/*
 * 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 "key_operation_log_handler.h"

#include <algorithm>
#include <android-base/logging.h>
#include <mutex>

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,
                                       const hidl_vec<KeyParameter>& params, bool pruneable) {
    sp<IBinder> token = new ::android::BBinder();
    mMap.emplace(token, std::make_shared<Operation>(handle, keyid, purpose, dev,
                                                    std::move(characteristics), appToken, params));
    if (pruneable) mLru.push_back(token);
    if (mAppTokenMap.find(appToken) == mAppTokenMap.end()) appToken->linkToDeath(mDeathRecipient);
    mAppTokenMap[appToken].push_back(token);
    return token;
}

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

    auto op = entry->second;

    updateLru(token);
    return op;
}

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);
    }
}

std::shared_ptr<Operation> OperationMap::removeOperation(const sp<IBinder>& token,
                                                         bool wasSuccessful, int32_t responseCode) {
    auto entry = mMap.find(token);
    if (entry == mMap.end()) return {};

    auto op = entry->second;
    logKeystoreKeyOperationEvent(*op, wasSuccessful, responseCode);
    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);
    }
}

sp<IBinder> OperationMap::getOldestPruneableOperation() {
    if (mLru.size() == 0) return {};

    return {mLru.front()};
}

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

}  // namespace keystore
