/*
 * Copyright (C) 2010 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 "InputManager"

//#define LOG_NDEBUG 0

#include <memory>

#include "InputManager.h"
#include "InputReader.h"
#include "InputTracingThreadedBackend.h"
#include "InteractionReporter.h"
#include "UnwantedInteractionBlocker.h"
#include "dispatcher/InputDispatcher.h"

#include <aidl/com/android/server/inputflinger/IInputFlingerRust.h>
#include <android-base/properties.h>
#include <android/binder_interface_utils.h>
#include <android/sysprop/InputProperties.sysprop.h>
#include <binder/IPCThreadState.h>
#include <com_android_input_flags.h>
#include <inputflinger_bootstrap.rs.h>
#include <jni.h>
#include <log/log.h>
#include <private/android_filesystem_config.h>

namespace input_flags = com::android::input::flags;

namespace android {

namespace {

const bool ENABLE_INPUT_DEVICE_USAGE_METRICS =
        sysprop::InputProperties::enable_input_device_usage_metrics().value_or(true);

int32_t exceptionCodeFromStatusT(status_t status) {
    switch (status) {
        case OK:
            return binder::Status::EX_NONE;
        case INVALID_OPERATION:
            return binder::Status::EX_UNSUPPORTED_OPERATION;
        case BAD_VALUE:
        case BAD_TYPE:
        case NAME_NOT_FOUND:
            return binder::Status::EX_ILLEGAL_ARGUMENT;
        case NO_INIT:
            return binder::Status::EX_ILLEGAL_STATE;
        case PERMISSION_DENIED:
            return binder::Status::EX_SECURITY;
        default:
            return binder::Status::EX_TRANSACTION_FAILED;
    }
}

// Convert a binder interface into a raw pointer to an AIBinder.
using IInputFlingerRustBootstrapCallback = aidl::com::android::server::inputflinger::
        IInputFlingerRust::IInputFlingerRustBootstrapCallback;
IInputFlingerRustBootstrapCallbackAIBinder* binderToPointer(
        IInputFlingerRustBootstrapCallback& interface) {
    ndk::SpAIBinder spAIBinder = interface.asBinder();
    auto* ptr = spAIBinder.get();
    AIBinder_incStrong(ptr);
    return ptr;
}

// Create the Rust component of InputFlinger that uses AIDL interfaces as a the foreign function
// interface (FFI). The bootstraping process for IInputFlingerRust is as follows:
//   - Create BnInputFlingerRustBootstrapCallback in C++.
//   - Use the cxxbridge ffi interface to call the Rust function `create_inputflinger_rust()`, and
//     pass the callback binder object as a raw pointer.
//   - The Rust implementation will create the implementation of IInputFlingerRust, and pass it
//     to C++ through the callback.
//   - After the Rust function returns, the binder interface provided to the callback will be the
//     only strong reference to the IInputFlingerRust.
std::shared_ptr<IInputFlingerRust> createInputFlingerRust() {
    using namespace aidl::com::android::server::inputflinger;

    class Callback : public IInputFlingerRust::BnInputFlingerRustBootstrapCallback {
        ndk::ScopedAStatus onProvideInputFlingerRust(
                const std::shared_ptr<IInputFlingerRust>& inputFlingerRust) override {
            mService = inputFlingerRust;
            return ndk::ScopedAStatus::ok();
        }

    public:
        std::shared_ptr<IInputFlingerRust> consumeInputFlingerRust() {
            auto service = mService;
            mService.reset();
            return service;
        }

    private:
        std::shared_ptr<IInputFlingerRust> mService;
    };

    auto callback = ndk::SharedRefBase::make<Callback>();
    create_inputflinger_rust(binderToPointer(*callback));
    auto service = callback->consumeInputFlingerRust();
    LOG_ALWAYS_FATAL_IF(!service,
                        "create_inputflinger_rust did not provide the IInputFlingerRust "
                        "implementation through the callback.");
    return service;
}

} // namespace

/**
 * The event flow is via the "InputListener" interface, as follows:
 *   InputReader
 *     -> UnwantedInteractionBlocker
 *     -> InputFilter
 *     -> PointerChoreographer
 *     -> InputProcessor
 *     -> InputDeviceMetricsCollector
 *     -> InteractionReporter
 *     -> InputDispatcher
 */
InputManager::InputManager(const sp<InputReaderPolicyInterface>& readerPolicy,
                           InputDispatcherPolicyInterface& dispatcherPolicy,
                           PointerChoreographerPolicyInterface& choreographerPolicy,
                           InputFilterPolicyInterface& inputFilterPolicy, JavaVM* vm,
                           bool createInteractionReporter) {
    mInputFlingerRust = createInputFlingerRust();

    std::shared_ptr<input_trace::InputTracingBackendInterface> tracingBackend =
            input_trace::impl::createInputTracingBackendIfEnabled(vm);
    mDispatcher = std::make_unique<inputdispatcher::InputDispatcher>(dispatcherPolicy,
                                                                     tracingBackend, vm);
    mTracingStages.emplace_back(
            std::make_unique<TracedInputListener>("InputDispatcher", *mDispatcher));

    if (createInteractionReporter) {
        // On devices without the Attention service, we can skip the InteractionReporter stage.
        mInteractionReporter = std::make_unique<InteractionReporter>(*mTracingStages.back());
        mTracingStages.emplace_back(std::make_unique<TracedInputListener>("InteractionReporter",
                                                                          *mInteractionReporter));
    }

    mInputFilter = std::make_unique<InputFilter>(*mTracingStages.back(), *mInputFlingerRust,
                                                 inputFilterPolicy, vm);
    mTracingStages.emplace_back(
            std::make_unique<TracedInputListener>("InputFilter", *mInputFilter));

    if (ENABLE_INPUT_DEVICE_USAGE_METRICS) {
        mCollector = std::make_unique<InputDeviceMetricsCollector>(*mTracingStages.back());
        mTracingStages.emplace_back(
                std::make_unique<TracedInputListener>("MetricsCollector", *mCollector));
    }

    mProcessor = std::make_unique<InputProcessor>(*mTracingStages.back());
    mTracingStages.emplace_back(
            std::make_unique<TracedInputListener>("InputProcessor", *mProcessor));

    mChoreographer =
            std::make_unique<PointerChoreographer>(*mTracingStages.back(), choreographerPolicy);
    mTracingStages.emplace_back(
            std::make_unique<TracedInputListener>("PointerChoreographer", *mChoreographer));

    mBlocker = std::make_unique<UnwantedInteractionBlocker>(*mTracingStages.back());
    mTracingStages.emplace_back(
            std::make_unique<TracedInputListener>("UnwantedInteractionBlocker", *mBlocker));

    mReader = std::make_unique<InputReader>(std::make_unique<EventHub>(), readerPolicy,
                                            *mTracingStages.back(), vm, tracingBackend);
}

InputManager::~InputManager() {
    stop();
}

status_t InputManager::start() {
    status_t result = mDispatcher->start();
    if (result) {
        ALOGE("Could not start InputDispatcher thread due to error %d.", result);
        return result;
    }

    result = mReader->start();
    if (result) {
        ALOGE("Could not start InputReader due to error %d.", result);

        mDispatcher->stop();
        return result;
    }

    return OK;
}

status_t InputManager::stop() {
    status_t status = OK;

    status_t result = mReader->stop();
    if (result) {
        ALOGW("Could not stop InputReader due to error %d.", result);
        status = result;
    }

    result = mDispatcher->stop();
    if (result) {
        ALOGW("Could not stop InputDispatcher thread due to error %d.", result);
        status = result;
    }

    return status;
}

InputReaderInterface& InputManager::getReader() {
    return *mReader;
}

PointerChoreographerInterface& InputManager::getChoreographer() {
    return *mChoreographer;
}

InputProcessorInterface& InputManager::getProcessor() {
    return *mProcessor;
}

InputDeviceMetricsCollectorInterface& InputManager::getMetricsCollector() {
    return *mCollector;
}

InputDispatcherInterface& InputManager::getDispatcher() {
    return *mDispatcher;
}

InputFilterInterface& InputManager::getInputFilter() {
    return *mInputFilter;
}

InteractionReporterInterface& InputManager::getInteractionReporter() {
    return *mInteractionReporter;
}

void InputManager::monitor() {
    mReader->monitor();
    mBlocker->monitor();
    mProcessor->monitor();
    if (ENABLE_INPUT_DEVICE_USAGE_METRICS) {
        mCollector->monitor();
    }
    mDispatcher->monitor();
}

void InputManager::dump(std::string& dump) {
    mReader->dump(dump);
    dump += '\n';
    mBlocker->dump(dump);
    dump += '\n';
    mChoreographer->dump(dump);
    dump += '\n';
    mProcessor->dump(dump);
    dump += '\n';
    if (ENABLE_INPUT_DEVICE_USAGE_METRICS) {
        mCollector->dump(dump);
        dump += '\n';
    }
    mInputFilter->dump(dump);
    dump += '\n';
    mDispatcher->dump(dump);
    dump += '\n';
}

// Used by tests only.
binder::Status InputManager::createInputChannel(const std::string& name,
                                                android::os::InputChannelCore* outChannel) {
    IPCThreadState* ipc = IPCThreadState::self();
    const uid_t uid = ipc->getCallingUid();
    if (uid != AID_SHELL && uid != AID_ROOT) {
        LOG(ERROR) << __func__ << " can only be called by SHELL or ROOT users, "
                   << "but was called from UID " << uid;
        return binder::Status::
                fromExceptionCode(EX_SECURITY,
                                  "This uid is not allowed to call createInputChannel");
    }

    base::Result<std::unique_ptr<InputChannel>> channel = mDispatcher->createInputChannel(name);
    if (!channel.ok()) {
        return binder::Status::fromExceptionCode(exceptionCodeFromStatusT(channel.error().code()),
                                                 channel.error().message().c_str());
    }
    InputChannel::moveChannel(std::move(*channel), *outChannel);
    return binder::Status::ok();
}

binder::Status InputManager::removeInputChannel(const sp<IBinder>& connectionToken) {
    mDispatcher->removeInputChannel(connectionToken);
    return binder::Status::ok();
}

status_t InputManager::dump(int fd, const Vector<String16>& args) {
    std::string dump;

    dump += " InputFlinger dump\n";

    TEMP_FAILURE_RETRY(::write(fd, dump.c_str(), dump.size()));
    return NO_ERROR;
}

binder::Status InputManager::setFocusedWindow(const gui::FocusRequest& request) {
    mDispatcher->setFocusedWindow(request);
    return binder::Status::ok();
}

} // namespace android
