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

Commit fe984ebf authored by Treehugger Robot's avatar Treehugger Robot Committed by Automerger Merge Worker
Browse files

Merge "Keep track of DeathMonitor cookies" into tm-dev am: 74770054 am: 3ebbbd99

parents 2d035d54 3ebbbd99
Loading
Loading
Loading
Loading
+11 −0
Original line number Original line Diff line number Diff line
@@ -56,6 +56,8 @@ class IProtectedCallback {
// Thread safe class
// Thread safe class
class DeathMonitor final {
class DeathMonitor final {
  public:
  public:
    explicit DeathMonitor(uintptr_t cookieKey) : kCookieKey(cookieKey) {}

    static void serviceDied(void* cookie);
    static void serviceDied(void* cookie);
    void serviceDied();
    void serviceDied();
    // Precondition: `killable` must be non-null.
    // Precondition: `killable` must be non-null.
@@ -63,9 +65,18 @@ class DeathMonitor final {
    // Precondition: `killable` must be non-null.
    // Precondition: `killable` must be non-null.
    void remove(IProtectedCallback* killable) const;
    void remove(IProtectedCallback* killable) const;


    uintptr_t getCookieKey() const { return kCookieKey; }

    ~DeathMonitor();
    DeathMonitor(const DeathMonitor&) = delete;
    DeathMonitor(DeathMonitor&&) noexcept = delete;
    DeathMonitor& operator=(const DeathMonitor&) = delete;
    DeathMonitor& operator=(DeathMonitor&&) noexcept = delete;

  private:
  private:
    mutable std::mutex mMutex;
    mutable std::mutex mMutex;
    mutable std::vector<IProtectedCallback*> mObjects GUARDED_BY(mMutex);
    mutable std::vector<IProtectedCallback*> mObjects GUARDED_BY(mMutex);
    const uintptr_t kCookieKey;
};
};


class DeathHandler final {
class DeathHandler final {
+49 −7
Original line number Original line Diff line number Diff line
@@ -25,6 +25,7 @@


#include <algorithm>
#include <algorithm>
#include <functional>
#include <functional>
#include <map>
#include <memory>
#include <memory>
#include <mutex>
#include <mutex>
#include <vector>
#include <vector>
@@ -33,6 +34,16 @@


namespace aidl::android::hardware::neuralnetworks::utils {
namespace aidl::android::hardware::neuralnetworks::utils {


namespace {

// Only dereference the cookie if it's valid (if it's in this set)
// Only used with ndk
std::mutex sCookiesMutex;
uintptr_t sCookieKeyCounter GUARDED_BY(sCookiesMutex) = 0;
std::map<uintptr_t, std::weak_ptr<DeathMonitor>> sCookies GUARDED_BY(sCookiesMutex);

}  // namespace

void DeathMonitor::serviceDied() {
void DeathMonitor::serviceDied() {
    std::lock_guard guard(mMutex);
    std::lock_guard guard(mMutex);
    std::for_each(mObjects.begin(), mObjects.end(),
    std::for_each(mObjects.begin(), mObjects.end(),
@@ -40,8 +51,24 @@ void DeathMonitor::serviceDied() {
}
}


void DeathMonitor::serviceDied(void* cookie) {
void DeathMonitor::serviceDied(void* cookie) {
    auto deathMonitor = static_cast<DeathMonitor*>(cookie);
    std::shared_ptr<DeathMonitor> monitor;
    deathMonitor->serviceDied();
    {
        std::lock_guard<std::mutex> guard(sCookiesMutex);
        if (auto it = sCookies.find(reinterpret_cast<uintptr_t>(cookie)); it != sCookies.end()) {
            monitor = it->second.lock();
            sCookies.erase(it);
        } else {
            LOG(INFO)
                    << "Service died, but cookie is no longer valid so there is nothing to notify.";
            return;
        }
    }
    if (monitor) {
        LOG(INFO) << "Notifying DeathMonitor from serviceDied.";
        monitor->serviceDied();
    } else {
        LOG(INFO) << "Tried to notify DeathMonitor from serviceDied but could not promote.";
    }
}
}


void DeathMonitor::add(IProtectedCallback* killable) const {
void DeathMonitor::add(IProtectedCallback* killable) const {
@@ -57,12 +84,25 @@ void DeathMonitor::remove(IProtectedCallback* killable) const {
    mObjects.erase(removedIter);
    mObjects.erase(removedIter);
}
}


DeathMonitor::~DeathMonitor() {
    // lock must be taken so object is not used in OnBinderDied"
    std::lock_guard<std::mutex> guard(sCookiesMutex);
    sCookies.erase(kCookieKey);
}

nn::GeneralResult<DeathHandler> DeathHandler::create(std::shared_ptr<ndk::ICInterface> object) {
nn::GeneralResult<DeathHandler> DeathHandler::create(std::shared_ptr<ndk::ICInterface> object) {
    if (object == nullptr) {
    if (object == nullptr) {
        return NN_ERROR(nn::ErrorStatus::INVALID_ARGUMENT)
        return NN_ERROR(nn::ErrorStatus::INVALID_ARGUMENT)
               << "utils::DeathHandler::create must have non-null object";
               << "utils::DeathHandler::create must have non-null object";
    }
    }
    auto deathMonitor = std::make_shared<DeathMonitor>();

    std::shared_ptr<DeathMonitor> deathMonitor;
    {
        std::lock_guard<std::mutex> guard(sCookiesMutex);
        deathMonitor = std::make_shared<DeathMonitor>(sCookieKeyCounter++);
        sCookies[deathMonitor->getCookieKey()] = deathMonitor;
    }

    auto deathRecipient = ndk::ScopedAIBinder_DeathRecipient(
    auto deathRecipient = ndk::ScopedAIBinder_DeathRecipient(
            AIBinder_DeathRecipient_new(DeathMonitor::serviceDied));
            AIBinder_DeathRecipient_new(DeathMonitor::serviceDied));


@@ -70,8 +110,9 @@ nn::GeneralResult<DeathHandler> DeathHandler::create(std::shared_ptr<ndk::ICInte
    // STATUS_INVALID_OPERATION. We ignore this case because we only use local binders in tests
    // STATUS_INVALID_OPERATION. We ignore this case because we only use local binders in tests
    // where this is not an error.
    // where this is not an error.
    if (object->isRemote()) {
    if (object->isRemote()) {
        const auto ret = ndk::ScopedAStatus::fromStatus(AIBinder_linkToDeath(
        const auto ret = ndk::ScopedAStatus::fromStatus(
                object->asBinder().get(), deathRecipient.get(), deathMonitor.get()));
                AIBinder_linkToDeath(object->asBinder().get(), deathRecipient.get(),
                                     reinterpret_cast<void*>(deathMonitor->getCookieKey())));
        HANDLE_ASTATUS(ret) << "AIBinder_linkToDeath failed";
        HANDLE_ASTATUS(ret) << "AIBinder_linkToDeath failed";
    }
    }


@@ -91,8 +132,9 @@ DeathHandler::DeathHandler(std::shared_ptr<ndk::ICInterface> object,


DeathHandler::~DeathHandler() {
DeathHandler::~DeathHandler() {
    if (kObject != nullptr && kDeathRecipient.get() != nullptr && kDeathMonitor != nullptr) {
    if (kObject != nullptr && kDeathRecipient.get() != nullptr && kDeathMonitor != nullptr) {
        const auto ret = ndk::ScopedAStatus::fromStatus(AIBinder_unlinkToDeath(
        const auto ret = ndk::ScopedAStatus::fromStatus(
                kObject->asBinder().get(), kDeathRecipient.get(), kDeathMonitor.get()));
                AIBinder_unlinkToDeath(kObject->asBinder().get(), kDeathRecipient.get(),
                                       reinterpret_cast<void*>(kDeathMonitor->getCookieKey())));
        const auto maybeSuccess = handleTransportError(ret);
        const auto maybeSuccess = handleTransportError(ret);
        if (!maybeSuccess.ok()) {
        if (!maybeSuccess.ok()) {
            LOG(ERROR) << maybeSuccess.error().message;
            LOG(ERROR) << maybeSuccess.error().message;
+6 −3
Original line number Original line Diff line number Diff line
@@ -697,7 +697,8 @@ TEST_P(DeviceTest, prepareModelAsyncCrash) {
    const auto mockDevice = createMockDevice();
    const auto mockDevice = createMockDevice();
    const auto device = Device::create(kName, mockDevice, kVersion).value();
    const auto device = Device::create(kName, mockDevice, kVersion).value();
    const auto ret = [&device]() {
    const auto ret = [&device]() {
        DeathMonitor::serviceDied(device->getDeathMonitor());
        DeathMonitor::serviceDied(
                reinterpret_cast<void*>(device->getDeathMonitor()->getCookieKey()));
        return ndk::ScopedAStatus::ok();
        return ndk::ScopedAStatus::ok();
    };
    };
    EXPECT_CALL(*mockDevice, prepareModel(_, _, _, _, _, _, _, _))
    EXPECT_CALL(*mockDevice, prepareModel(_, _, _, _, _, _, _, _))
@@ -846,7 +847,8 @@ TEST_P(DeviceTest, prepareModelWithConfigAsyncCrash) {
    const auto mockDevice = createMockDevice();
    const auto mockDevice = createMockDevice();
    const auto device = Device::create(kName, mockDevice, kVersion).value();
    const auto device = Device::create(kName, mockDevice, kVersion).value();
    const auto ret = [&device]() {
    const auto ret = [&device]() {
        DeathMonitor::serviceDied(device->getDeathMonitor());
        DeathMonitor::serviceDied(
                reinterpret_cast<void*>(device->getDeathMonitor()->getCookieKey()));
        return ndk::ScopedAStatus::ok();
        return ndk::ScopedAStatus::ok();
    };
    };
    EXPECT_CALL(*mockDevice, prepareModelWithConfig(_, _, _))
    EXPECT_CALL(*mockDevice, prepareModelWithConfig(_, _, _))
@@ -970,7 +972,8 @@ TEST_P(DeviceTest, prepareModelFromCacheAsyncCrash) {
    const auto mockDevice = createMockDevice();
    const auto mockDevice = createMockDevice();
    const auto device = Device::create(kName, mockDevice, kVersion).value();
    const auto device = Device::create(kName, mockDevice, kVersion).value();
    const auto ret = [&device]() {
    const auto ret = [&device]() {
        DeathMonitor::serviceDied(device->getDeathMonitor());
        DeathMonitor::serviceDied(
                reinterpret_cast<void*>(device->getDeathMonitor()->getCookieKey()));
        return ndk::ScopedAStatus::ok();
        return ndk::ScopedAStatus::ok();
    };
    };
    EXPECT_CALL(*mockDevice, prepareModelFromCache(_, _, _, _, _))
    EXPECT_CALL(*mockDevice, prepareModelFromCache(_, _, _, _, _))