/*
 * 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.
 */
#define LOG_TAG "KeystoreOperation"

#include "operation.h"

#include <algorithm>

namespace keystore {

OperationMap::OperationMap(IBinder::DeathRecipient* deathRecipient)
    : mDeathRecipient(deathRecipient) {}

sp<IBinder> OperationMap::addOperation(uint64_t handle, uint64_t keyid, KeyPurpose purpose,
                                       const sp<Keymaster>& dev, const sp<IBinder>& appToken,
                                       KeyCharacteristics&& characteristics, bool pruneable) {
    sp<IBinder> token = new ::android::BBinder();
    mMap.emplace(token,
                 Operation(handle, keyid, purpose, dev, std::move(characteristics), appToken));
    if (pruneable) mLru.push_back(token);
    if (mAppTokenMap.find(appToken) == mAppTokenMap.end()) appToken->linkToDeath(mDeathRecipient);
    mAppTokenMap[appToken].push_back(token);

    return token;
}

NullOr<const OperationMap::Operation&> OperationMap::getOperation(const sp<IBinder>& token) {
    auto entry = mMap.find(token);
    if (entry == mMap.end()) return {};

    updateLru(token);
    return entry->second;
}

void OperationMap::updateLru(const sp<IBinder>& token) {
    auto lruEntry = std::find(mLru.begin(), mLru.end(), token);
    if (lruEntry != mLru.end()) {
        mLru.erase(lruEntry);
        mLru.push_back(token);
    }
}

NullOr<OperationMap::Operation> OperationMap::removeOperation(const sp<IBinder>& token) {
    auto entry = mMap.find(token);
    if (entry == mMap.end()) return {};

    Operation op = std::move(entry->second);
    mMap.erase(entry);

    auto lruEntry = std::find(mLru.begin(), mLru.end(), token);
    if (lruEntry != mLru.end()) mLru.erase(lruEntry);
    removeOperationTracking(token, op.appToken);

    return op;
}

void OperationMap::removeOperationTracking(const sp<IBinder>& token, const sp<IBinder>& appToken) {
    auto appEntry = mAppTokenMap.find(appToken);
    if (appEntry == mAppTokenMap.end()) {
        ALOGE("Entry for %p contains unmapped application token %p", token.get(), appToken.get());
        return;
    }
    auto tokenEntry = std::find(appEntry->second.begin(), appEntry->second.end(), token);
    appEntry->second.erase(tokenEntry);
    // Stop listening for death if all operations tied to the token have finished.
    if (appEntry->second.size() == 0) {
        appToken->unlinkToDeath(mDeathRecipient);
        mAppTokenMap.erase(appEntry);
    }
}

bool OperationMap::hasPruneableOperation() const {
    return !mLru.empty();
}

size_t OperationMap::getPruneableOperationCount() const {
    return mLru.size();
}

sp<IBinder> OperationMap::getOldestPruneableOperation() {
    if (!hasPruneableOperation()) return sp<IBinder>(nullptr);
    return mLru.front();
}

bool OperationMap::setOperationAuthToken(const sp<IBinder>& token, HardwareAuthToken authToken) {
    auto entry = mMap.find(token);
    if (entry == mMap.end()) return false;

    entry->second.authToken = std::move(authToken);
    return true;
}

std::vector<sp<IBinder>> OperationMap::getOperationsForToken(const sp<IBinder>& appToken) {
    auto appEntry = mAppTokenMap.find(appToken);
    if (appEntry == mAppTokenMap.end()) return {};
    return appEntry->second;
}

OperationMap::Operation::Operation(uint64_t handle_, uint64_t keyid_, KeyPurpose purpose_,
                                   const sp<Keymaster>& device_,
                                   KeyCharacteristics&& characteristics_, sp<IBinder> appToken_)
    : handle(handle_), keyid(keyid_), purpose(purpose_), device(device_),
      characteristics(characteristics_), appToken(appToken_) {}

}  // namespace keystore
