/*
 * Copyright (C) 2015 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 ANDROID_SERVICE_UTILS_EVICTION_POLICY_MANAGER_H
#define ANDROID_SERVICE_UTILS_EVICTION_POLICY_MANAGER_H

#include <utils/Condition.h>
#include <utils/Mutex.h>
#include <utils/Timers.h>

#include <algorithm>
#include <utility>
#include <vector>
#include <set>
#include <map>
#include <memory>

namespace android {
namespace resource_policy {

// Values from frameworks/base/services/core/java/com/android/server/am/ProcessList.java
const int32_t INVALID_ADJ = -10000;
const int32_t UNKNOWN_ADJ = 1001;
const int32_t CACHED_APP_MAX_ADJ = 999;
const int32_t CACHED_APP_MIN_ADJ = 900;
const int32_t CACHED_APP_LMK_FIRST_ADJ = 950;
const int32_t CACHED_APP_IMPORTANCE_LEVELS = 5;
const int32_t SERVICE_B_ADJ = 800;
const int32_t PREVIOUS_APP_ADJ = 700;
const int32_t HOME_APP_ADJ = 600;
const int32_t SERVICE_ADJ = 500;
const int32_t HEAVY_WEIGHT_APP_ADJ = 400;
const int32_t BACKUP_APP_ADJ = 300;
const int32_t PERCEPTIBLE_LOW_APP_ADJ = 250;
const int32_t PERCEPTIBLE_MEDIUM_APP_ADJ = 225;
const int32_t PERCEPTIBLE_APP_ADJ = 200;
const int32_t VISIBLE_APP_ADJ = 100;
const int32_t VISIBLE_APP_LAYER_MAX = PERCEPTIBLE_APP_ADJ - VISIBLE_APP_ADJ - 1;
const int32_t PERCEPTIBLE_RECENT_FOREGROUND_APP_ADJ = 50;
const int32_t FOREGROUND_APP_ADJ = 0;
const int32_t PERSISTENT_SERVICE_ADJ = -700;
const int32_t PERSISTENT_PROC_ADJ = -800;
const int32_t SYSTEM_ADJ = -900;
const int32_t NATIVE_ADJ = -1000;

class ClientPriority {
public:
    /**
     * Choosing to set mIsVendorClient through a parameter instead of calling
     * getCurrentServingCall() == BinderCallType::HWBINDER to protect against the
     * case where the construction is offloaded to another thread which isn't a
     * hwbinder thread.
     */
    ClientPriority(int32_t score, int32_t state, bool isVendorClient, int32_t scoreOffset = 0) :
            mIsVendorClient(isVendorClient), mScoreOffset(scoreOffset) {
        setScore(score);
        setState(state);
    }

    int32_t getScore() const { return mScore; }
    int32_t getState() const { return mState; }
    int32_t isVendorClient() const { return mIsVendorClient; }

    void setScore(int32_t score) {
        // For vendor clients, the score is set once and for all during
        // construction. Otherwise, it can get reset each time cameraserver
        // queries ActivityManagerService for oom_adj scores / states .
        // For clients where the score offset is set by the app, add it to the
        // score provided by ActivityManagerService.
        if (score == INVALID_ADJ) {
            mScore = UNKNOWN_ADJ;
        } else {
            mScore = mScoreOffset + score;
        }
    }

    void setState(int32_t state) {
      // For vendor clients, the score is set once and for all during
      // construction. Otherwise, it can get reset each time cameraserver
      // queries ActivityManagerService for oom_adj scores / states
      // (ActivityManagerService returns a vendor process' state as
      // PROCESS_STATE_NONEXISTENT.
      mState = state;
    }

    bool operator==(const ClientPriority& rhs) const {
        return (this->mScore == rhs.mScore) && (this->mState == rhs.mState);
    }

    bool operator< (const ClientPriority& rhs)  const {
        if (this->mScore == rhs.mScore) {
            return this->mState < rhs.mState;
        } else {
            return this->mScore < rhs.mScore;
        }
    }

    bool operator> (const ClientPriority& rhs) const {
        return rhs < *this;
    }

    bool operator<=(const ClientPriority& rhs) const {
        return !(*this > rhs);
    }

    bool operator>=(const ClientPriority& rhs) const {
        return !(*this < rhs);
    }

private:
        int32_t mScore;
        int32_t mState;
        bool mIsVendorClient = false;
        int32_t mScoreOffset = 0;
};

// --------------------------------------------------------------------------------

/**
 * The ClientDescriptor class is a container for a given key/value pair identifying a shared
 * resource, and the corresponding cost, priority, owner ID, and conflicting keys list used
 * in determining eviction behavior.
 *
 * Aside from the priority, these values are immutable once the ClientDescriptor has been
 * constructed.
 */
template<class KEY, class VALUE>
class ClientDescriptor final {
public:
    ClientDescriptor(const KEY& key, const VALUE& value, int32_t cost,
            const std::set<KEY>& conflictingKeys, int32_t score, int32_t ownerId, int32_t state,
            bool isVendorClient, int32_t oomScoreOffset);
    ClientDescriptor(KEY&& key, VALUE&& value, int32_t cost, std::set<KEY>&& conflictingKeys,
            int32_t score, int32_t ownerId, int32_t state, bool isVendorClient,
            int32_t oomScoreOffset);

    ~ClientDescriptor();

    /**
     * Return the key for this descriptor.
     */
    const KEY& getKey() const;

    /**
     * Return the value for this descriptor.
     */
    const VALUE& getValue() const;

    /**
     * Return the cost for this descriptor.
     */
    int32_t getCost() const;

    /**
     * Return the priority for this descriptor.
     */
    const ClientPriority &getPriority() const;

    /**
     * Return the owner ID for this descriptor.
     */
    int32_t getOwnerId() const;

    /**
     * Return true if the given key is in this descriptor's conflicting keys list.
     */
    bool isConflicting(const KEY& key) const;

    /**
     * Return the set of all conflicting keys for this descriptor.
     */
    std::set<KEY> getConflicting() const;

    /**
     * Set the proirity for this descriptor.
     */
    void setPriority(const ClientPriority& priority);

    // This class is ordered by key
    template<class K, class V>
    friend bool operator < (const ClientDescriptor<K, V>& a, const ClientDescriptor<K, V>& b);

private:
    KEY mKey;
    VALUE mValue;
    int32_t mCost;
    std::set<KEY> mConflicting;
    ClientPriority mPriority;
    int32_t mOwnerId;
}; // class ClientDescriptor

template<class K, class V>
bool operator < (const ClientDescriptor<K, V>& a, const ClientDescriptor<K, V>& b) {
    return a.mKey < b.mKey;
}

template<class KEY, class VALUE>
ClientDescriptor<KEY, VALUE>::ClientDescriptor(const KEY& key, const VALUE& value, int32_t cost,
        const std::set<KEY>& conflictingKeys, int32_t score, int32_t ownerId, int32_t state,
        bool isVendorClient, int32_t scoreOffset) :
        mKey{key}, mValue{value}, mCost{cost}, mConflicting{conflictingKeys},
        mPriority(score, state, isVendorClient, scoreOffset),
        mOwnerId{ownerId} {}

template<class KEY, class VALUE>
ClientDescriptor<KEY, VALUE>::ClientDescriptor(KEY&& key, VALUE&& value, int32_t cost,
        std::set<KEY>&& conflictingKeys, int32_t score, int32_t ownerId, int32_t state,
        bool isVendorClient, int32_t scoreOffset) :
        mKey{std::forward<KEY>(key)}, mValue{std::forward<VALUE>(value)}, mCost{cost},
        mConflicting{std::forward<std::set<KEY>>(conflictingKeys)},
        mPriority(score, state, isVendorClient, scoreOffset), mOwnerId{ownerId} {}

template<class KEY, class VALUE>
ClientDescriptor<KEY, VALUE>::~ClientDescriptor() {}

template<class KEY, class VALUE>
const KEY& ClientDescriptor<KEY, VALUE>::getKey() const {
    return mKey;
}

template<class KEY, class VALUE>
const VALUE& ClientDescriptor<KEY, VALUE>::getValue() const {
    return mValue;
}

template<class KEY, class VALUE>
int32_t ClientDescriptor<KEY, VALUE>::getCost() const {
    return mCost;
}

template<class KEY, class VALUE>
const ClientPriority& ClientDescriptor<KEY, VALUE>::getPriority() const {
    return mPriority;
}

template<class KEY, class VALUE>
int32_t ClientDescriptor<KEY, VALUE>::getOwnerId() const {
    return mOwnerId;
}

template<class KEY, class VALUE>
bool ClientDescriptor<KEY, VALUE>::isConflicting(const KEY& key) const {
    if (key == mKey) return true;
    for (const auto& x : mConflicting) {
        if (key == x) return true;
    }
    return false;
}

template<class KEY, class VALUE>
std::set<KEY> ClientDescriptor<KEY, VALUE>::getConflicting() const {
    return mConflicting;
}

template<class KEY, class VALUE>
void ClientDescriptor<KEY, VALUE>::setPriority(const ClientPriority& priority) {
    // We don't use the usual copy constructor here since we want to remember
    // whether a client is a vendor client or not. This could have been wiped
    // off in the incoming priority argument since an AIDL thread might have
    // called getCurrentServingCall() == BinderCallType::HWBINDER after refreshing
    // priorities for old clients through ProcessInfoService::getProcessStatesScoresFromPids().
    if (mPriority.isVendorClient()) {
        return;
    }
    mPriority.setScore(priority.getScore());
    mPriority.setState(priority.getState());
}

// --------------------------------------------------------------------------------

/**
 * A default class implementing the LISTENER interface used by ClientManager.
 */
template<class KEY, class VALUE>
class DefaultEventListener {
public:
    void onClientAdded(const ClientDescriptor<KEY, VALUE>& descriptor);
    void onClientRemoved(const ClientDescriptor<KEY, VALUE>& descriptor);
};

template<class KEY, class VALUE>
void DefaultEventListener<KEY, VALUE>::onClientAdded(
        const ClientDescriptor<KEY, VALUE>& /*descriptor*/) {}

template<class KEY, class VALUE>
void DefaultEventListener<KEY, VALUE>::onClientRemoved(
        const ClientDescriptor<KEY, VALUE>& /*descriptor*/) {}

// --------------------------------------------------------------------------------

/**
 * The ClientManager class wraps an LRU-ordered list of active clients and implements eviction
 * behavior for handling shared resource access.
 *
 * When adding a new descriptor, eviction behavior is as follows:
 *   - Keys are unique, adding a descriptor with the same key as an existing descriptor will
 *     result in the lower-priority of the two being removed.  Priority ties result in the
 *     LRU descriptor being evicted (this means the incoming descriptor be added in this case).
 *   - Any descriptors with keys that are in the incoming descriptor's 'conflicting keys' list
 *     will be removed if they have an equal or lower priority than the incoming descriptor;
 *     if any have a higher priority, the incoming descriptor is removed instead.
 *   - If the sum of all descriptors' costs, including the incoming descriptor's, is more than
 *     the max cost allowed for this ClientManager, descriptors with non-zero cost, equal or lower
 *     priority, and a different owner will be evicted in LRU order until either the cost is less
 *     than the max cost, or all descriptors meeting this criteria have been evicted and the
 *     incoming descriptor has the highest priority.  Otherwise, the incoming descriptor is
 *     removed instead.
 */
template<class KEY, class VALUE, class LISTENER=DefaultEventListener<KEY, VALUE>>
class ClientManager {
public:
    // The default maximum "cost" allowed before evicting
    static constexpr int32_t DEFAULT_MAX_COST = 100;

    ClientManager();
    explicit ClientManager(int32_t totalCost);

    /**
     * Add a given ClientDescriptor to the managed list.  ClientDescriptors for clients that
     * are evicted by this action are returned in a vector.
     *
     * This may return the ClientDescriptor passed in if it would be evicted.
     */
    std::vector<std::shared_ptr<ClientDescriptor<KEY, VALUE>>> addAndEvict(
            const std::shared_ptr<ClientDescriptor<KEY, VALUE>>& client);

    /**
     * Given a map containing owner (pid) -> priority mappings, update the priority of each
     * ClientDescriptor with an owner in this mapping.
     */
    void updatePriorities(const std::map<int32_t,ClientPriority>& ownerPriorityList);

    /**
     * Remove all ClientDescriptors.
     */
    void removeAll();

    /**
     * Remove and return the ClientDescriptor with a given key.
     */
    std::shared_ptr<ClientDescriptor<KEY, VALUE>> remove(const KEY& key);

    /**
     * Remove the given ClientDescriptor.
     */
    void remove(const std::shared_ptr<ClientDescriptor<KEY, VALUE>>& value);

    /**
     * Return a vector of the ClientDescriptors that would be evicted by adding the given
     * ClientDescriptor.
     *
     * This may return the ClientDescriptor passed in if it would be evicted.
     */
    std::vector<std::shared_ptr<ClientDescriptor<KEY, VALUE>>> wouldEvict(
            const std::shared_ptr<ClientDescriptor<KEY, VALUE>>& client) const;

    /**
     * Return a vector of active ClientDescriptors that prevent this client from being added.
     */
    std::vector<std::shared_ptr<ClientDescriptor<KEY, VALUE>>> getIncompatibleClients(
            const std::shared_ptr<ClientDescriptor<KEY, VALUE>>& client) const;

    /**
     * Return a vector containing all currently active ClientDescriptors.
     */
    std::vector<std::shared_ptr<ClientDescriptor<KEY, VALUE>>> getAll() const;

    /**
     * Return a vector containing all keys of currently active ClientDescriptors.
     */
    std::vector<KEY> getAllKeys() const;

    /**
     * Return a vector of the owner tags of all currently active ClientDescriptors (duplicates
     * will be removed).
     */
    std::vector<int32_t> getAllOwners() const;

    /**
     * Return the ClientDescriptor corresponding to the given key, or an empty shared pointer
     * if none exists.
     */
    std::shared_ptr<ClientDescriptor<KEY, VALUE>> get(const KEY& key) const;

    /**
     * Block until the given client is no longer in the active clients list, or the timeout
     * occurred.
     *
     * Returns NO_ERROR if this succeeded, -ETIMEDOUT on a timeout, or a negative error code on
     * failure.
     */
    status_t waitUntilRemoved(const std::shared_ptr<ClientDescriptor<KEY, VALUE>> client,
            nsecs_t timeout) const;

    /**
     * Set the current listener for client add/remove events.
     *
     * The listener instance must inherit from the LISTENER class and implement the following
     * methods:
     *    void onClientRemoved(const ClientDescriptor<KEY, VALUE>& descriptor);
     *    void onClientAdded(const ClientDescriptor<KEY, VALUE>& descriptor);
     *
     * These callback methods will be called with the ClientManager's lock held, and should
     * not call any further ClientManager methods.
     *
     * The onClientRemoved method will be called when the client has been removed or evicted
     * from the ClientManager that this event listener has been added to. The onClientAdded
     * method will be called when the client has been added to the ClientManager that this
     * event listener has been added to.
     */
    void setListener(const std::shared_ptr<LISTENER>& listener);

protected:
    ~ClientManager();

private:

    /**
     * Return a vector of the ClientDescriptors that would be evicted by adding the given
     * ClientDescriptor.  If returnIncompatibleClients is set to true, instead, return the
     * vector of ClientDescriptors that are higher priority than the incoming client and
     * either conflict with this client, or contribute to the resource cost if that would
     * prevent the incoming client from being added.
     *
     * This may return the ClientDescriptor passed in.
     */
    std::vector<std::shared_ptr<ClientDescriptor<KEY, VALUE>>> wouldEvictLocked(
            const std::shared_ptr<ClientDescriptor<KEY, VALUE>>& client,
            bool returnIncompatibleClients = false) const;

    int64_t getCurrentCostLocked() const;

    mutable Mutex mLock;
    mutable Condition mRemovedCondition;
    int32_t mMaxCost;
    // LRU ordered, most recent at end
    std::vector<std::shared_ptr<ClientDescriptor<KEY, VALUE>>> mClients;
    std::shared_ptr<LISTENER> mListener;
}; // class ClientManager

template<class KEY, class VALUE, class LISTENER>
ClientManager<KEY, VALUE, LISTENER>::ClientManager() :
        ClientManager(DEFAULT_MAX_COST) {}

template<class KEY, class VALUE, class LISTENER>
ClientManager<KEY, VALUE, LISTENER>::ClientManager(int32_t totalCost) : mMaxCost(totalCost) {}

template<class KEY, class VALUE, class LISTENER>
ClientManager<KEY, VALUE, LISTENER>::~ClientManager() {}

template<class KEY, class VALUE, class LISTENER>
std::vector<std::shared_ptr<ClientDescriptor<KEY, VALUE>>>
ClientManager<KEY, VALUE, LISTENER>::wouldEvict(
        const std::shared_ptr<ClientDescriptor<KEY, VALUE>>& client) const {
    Mutex::Autolock lock(mLock);
    return wouldEvictLocked(client);
}

template<class KEY, class VALUE, class LISTENER>
std::vector<std::shared_ptr<ClientDescriptor<KEY, VALUE>>>
ClientManager<KEY, VALUE, LISTENER>::getIncompatibleClients(
        const std::shared_ptr<ClientDescriptor<KEY, VALUE>>& client) const {
    Mutex::Autolock lock(mLock);
    return wouldEvictLocked(client, /*returnIncompatibleClients*/true);
}

template<class KEY, class VALUE, class LISTENER>
std::vector<std::shared_ptr<ClientDescriptor<KEY, VALUE>>>
ClientManager<KEY, VALUE, LISTENER>::wouldEvictLocked(
        const std::shared_ptr<ClientDescriptor<KEY, VALUE>>& client,
        bool returnIncompatibleClients) const {

    std::vector<std::shared_ptr<ClientDescriptor<KEY, VALUE>>> evictList;

    // Disallow null clients, return input
    if (client == nullptr) {
        evictList.push_back(client);
        return evictList;
    }

    const KEY& key = client->getKey();
    int32_t cost = client->getCost();
    ClientPriority priority = client->getPriority();
    int32_t owner = client->getOwnerId();

    int64_t totalCost = getCurrentCostLocked() + cost;

    // Determine the MRU of the owners tied for having the highest priority
    int32_t highestPriorityOwner = owner;
    ClientPriority highestPriority = priority;
    for (const auto& i : mClients) {
        ClientPriority curPriority = i->getPriority();
        if (curPriority <= highestPriority) {
            highestPriority = curPriority;
            highestPriorityOwner = i->getOwnerId();
        }
    }

    if (highestPriority == priority) {
        // Switch back owner if the incoming client has the highest priority, as it is MRU
        highestPriorityOwner = owner;
    }

    // Build eviction list of clients to remove
    for (const auto& i : mClients) {
        const KEY& curKey = i->getKey();
        int32_t curCost = i->getCost();
        ClientPriority curPriority = i->getPriority();
        int32_t curOwner = i->getOwnerId();

        bool conflicting = (curKey == key || i->isConflicting(key) ||
                client->isConflicting(curKey));

        if (!returnIncompatibleClients) {
            // Find evicted clients

            if (conflicting && owner == curOwner) {
                // Pre-existing conflicting client with the same client owner exists
                // Open the same device twice -> most recent open wins
                // Otherwise let the existing client wins to avoid behaviors difference
                // due to how HAL advertising conflicting devices (which is hidden from
                // application)
                if (curKey == key) {
                    evictList.push_back(i);
                    totalCost -= curCost;
                } else {
                    evictList.clear();
                    evictList.push_back(client);
                    return evictList;
                }
            } else if (conflicting && curPriority < priority) {
                // Pre-existing conflicting client with higher priority exists
                evictList.clear();
                evictList.push_back(client);
                return evictList;
            } else if (conflicting || ((totalCost > mMaxCost && curCost > 0) &&
                    (curPriority >= priority) &&
                    !(highestPriorityOwner == owner && owner == curOwner))) {
                // Add a pre-existing client to the eviction list if:
                // - We are adding a client with higher priority that conflicts with this one.
                // - The total cost including the incoming client's is more than the allowable
                //   maximum, and the client has a non-zero cost, lower priority, and a different
                //   owner than the incoming client when the incoming client has the
                //   highest priority.
                evictList.push_back(i);
                totalCost -= curCost;
            }
        } else {
            // Find clients preventing the incoming client from being added

            if (curPriority < priority && (conflicting || (totalCost > mMaxCost && curCost > 0))) {
                // Pre-existing conflicting client with higher priority exists
                evictList.push_back(i);
            }
        }
    }

    // Immediately return the incompatible clients if we are calculating these instead
    if (returnIncompatibleClients) {
        return evictList;
    }

    // If the total cost is too high, return the input unless the input has the highest priority
    if (totalCost > mMaxCost && highestPriorityOwner != owner) {
        evictList.clear();
        evictList.push_back(client);
        return evictList;
    }

    return evictList;

}

template<class KEY, class VALUE, class LISTENER>
std::vector<std::shared_ptr<ClientDescriptor<KEY, VALUE>>>
ClientManager<KEY, VALUE, LISTENER>::addAndEvict(
        const std::shared_ptr<ClientDescriptor<KEY, VALUE>>& client) {
    Mutex::Autolock lock(mLock);
    auto evicted = wouldEvictLocked(client);
    auto it = evicted.begin();
    if (it != evicted.end() && *it == client) {
        return evicted;
    }

    auto iter = evicted.cbegin();

    if (iter != evicted.cend()) {

        if (mListener != nullptr) mListener->onClientRemoved(**iter);

        // Remove evicted clients from list
        mClients.erase(std::remove_if(mClients.begin(), mClients.end(),
            [&iter] (std::shared_ptr<ClientDescriptor<KEY, VALUE>>& curClientPtr) {
                if (curClientPtr->getKey() == (*iter)->getKey()) {
                    iter++;
                    return true;
                }
                return false;
            }), mClients.end());
    }

    if (mListener != nullptr) mListener->onClientAdded(*client);
    mClients.push_back(client);
    mRemovedCondition.broadcast();

    return evicted;
}

template<class KEY, class VALUE, class LISTENER>
std::vector<std::shared_ptr<ClientDescriptor<KEY, VALUE>>>
ClientManager<KEY, VALUE, LISTENER>::getAll() const {
    Mutex::Autolock lock(mLock);
    return mClients;
}

template<class KEY, class VALUE, class LISTENER>
std::vector<KEY> ClientManager<KEY, VALUE, LISTENER>::getAllKeys() const {
    Mutex::Autolock lock(mLock);
    std::vector<KEY> keys(mClients.size());
    for (const auto& i : mClients) {
        keys.push_back(i->getKey());
    }
    return keys;
}

template<class KEY, class VALUE, class LISTENER>
std::vector<int32_t> ClientManager<KEY, VALUE, LISTENER>::getAllOwners() const {
    Mutex::Autolock lock(mLock);
    std::set<int32_t> owners;
    for (const auto& i : mClients) {
        owners.emplace(i->getOwnerId());
    }
    return std::vector<int32_t>(owners.begin(), owners.end());
}

template<class KEY, class VALUE, class LISTENER>
void ClientManager<KEY, VALUE, LISTENER>::updatePriorities(
        const std::map<int32_t,ClientPriority>& ownerPriorityList) {
    Mutex::Autolock lock(mLock);
    for (auto& i : mClients) {
        auto j = ownerPriorityList.find(i->getOwnerId());
        if (j != ownerPriorityList.end()) {
            i->setPriority(j->second);
        }
    }
}

template<class KEY, class VALUE, class LISTENER>
std::shared_ptr<ClientDescriptor<KEY, VALUE>> ClientManager<KEY, VALUE, LISTENER>::get(
        const KEY& key) const {
    Mutex::Autolock lock(mLock);
    for (const auto& i : mClients) {
        if (i->getKey() == key) return i;
    }
    return std::shared_ptr<ClientDescriptor<KEY, VALUE>>(nullptr);
}

template<class KEY, class VALUE, class LISTENER>
void ClientManager<KEY, VALUE, LISTENER>::removeAll() {
    Mutex::Autolock lock(mLock);
    if (mListener != nullptr) {
        for (const auto& i : mClients) {
            mListener->onClientRemoved(*i);
        }
    }
    mClients.clear();
    mRemovedCondition.broadcast();
}

template<class KEY, class VALUE, class LISTENER>
std::shared_ptr<ClientDescriptor<KEY, VALUE>> ClientManager<KEY, VALUE, LISTENER>::remove(
    const KEY& key) {
    Mutex::Autolock lock(mLock);

    std::shared_ptr<ClientDescriptor<KEY, VALUE>> ret;

    // Remove evicted clients from list
    mClients.erase(std::remove_if(mClients.begin(), mClients.end(),
        [this, &key, &ret] (std::shared_ptr<ClientDescriptor<KEY, VALUE>>& curClientPtr) {
            if (curClientPtr->getKey() == key) {
                if (mListener != nullptr) mListener->onClientRemoved(*curClientPtr);
                ret = curClientPtr;
                return true;
            }
            return false;
        }), mClients.end());

    mRemovedCondition.broadcast();
    return ret;
}

template<class KEY, class VALUE, class LISTENER>
status_t ClientManager<KEY, VALUE, LISTENER>::waitUntilRemoved(
        const std::shared_ptr<ClientDescriptor<KEY, VALUE>> client,
        nsecs_t timeout) const {
    status_t ret = NO_ERROR;
    Mutex::Autolock lock(mLock);

    bool isRemoved = false;

    // Figure out what time in the future we should hit the timeout
    nsecs_t failTime = systemTime(SYSTEM_TIME_MONOTONIC) + timeout;

    while (!isRemoved) {
        isRemoved = true;
        for (const auto& i : mClients) {
            if (i == client) {
                isRemoved = false;
            }
        }

        if (!isRemoved) {
            ret = mRemovedCondition.waitRelative(mLock, timeout);
            if (ret != NO_ERROR) {
                break;
            }
            timeout = failTime - systemTime(SYSTEM_TIME_MONOTONIC);
        }
    }

    return ret;
}

template<class KEY, class VALUE, class LISTENER>
void ClientManager<KEY, VALUE, LISTENER>::setListener(const std::shared_ptr<LISTENER>& listener) {
    Mutex::Autolock lock(mLock);
    mListener = listener;
}

template<class KEY, class VALUE, class LISTENER>
void ClientManager<KEY, VALUE, LISTENER>::remove(
        const std::shared_ptr<ClientDescriptor<KEY, VALUE>>& value) {
    Mutex::Autolock lock(mLock);
    // Remove evicted clients from list
    mClients.erase(std::remove_if(mClients.begin(), mClients.end(),
        [this, &value] (std::shared_ptr<ClientDescriptor<KEY, VALUE>>& curClientPtr) {
            if (curClientPtr == value) {
                if (mListener != nullptr) mListener->onClientRemoved(*curClientPtr);
                return true;
            }
            return false;
        }), mClients.end());
    mRemovedCondition.broadcast();
}

template<class KEY, class VALUE, class LISTENER>
int64_t ClientManager<KEY, VALUE, LISTENER>::getCurrentCostLocked() const {
    int64_t totalCost = 0;
    for (const auto& x : mClients) {
            totalCost += x->getCost();
    }
    return totalCost;
}

// --------------------------------------------------------------------------------

}; // namespace resource_policy
}; // namespace android

#endif // ANDROID_SERVICE_UTILS_EVICTION_POLICY_MANAGER_H
