/*
 * Copyright (C) 2019 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.
 */

#include "Entry.h"

#include "Connection.h"

#include <android-base/properties.h>
#include <android-base/stringprintf.h>
#include <cutils/atomic.h>
#include <inttypes.h>

using android::base::GetBoolProperty;
using android::base::StringPrintf;

namespace android::inputdispatcher {

VerifiedKeyEvent verifiedKeyEventFromKeyEntry(const KeyEntry& entry) {
    return {{VerifiedInputEvent::Type::KEY, entry.deviceId, entry.eventTime, entry.source,
             entry.displayId},
            entry.action,
            entry.downTime,
            entry.flags & VERIFIED_KEY_EVENT_FLAGS,
            entry.keyCode,
            entry.scanCode,
            entry.metaState,
            entry.repeatCount};
}

VerifiedMotionEvent verifiedMotionEventFromMotionEntry(const MotionEntry& entry) {
    const float rawX = entry.pointerCoords[0].getAxisValue(AMOTION_EVENT_AXIS_X);
    const float rawY = entry.pointerCoords[0].getAxisValue(AMOTION_EVENT_AXIS_Y);
    const int actionMasked = entry.action & AMOTION_EVENT_ACTION_MASK;
    return {{VerifiedInputEvent::Type::MOTION, entry.deviceId, entry.eventTime, entry.source,
             entry.displayId},
            rawX,
            rawY,
            actionMasked,
            entry.downTime,
            entry.flags & VERIFIED_MOTION_EVENT_FLAGS,
            entry.metaState,
            entry.buttonState};
}

// --- EventEntry ---

EventEntry::EventEntry(int32_t id, Type type, nsecs_t eventTime, uint32_t policyFlags)
      : id(id),
        type(type),
        eventTime(eventTime),
        policyFlags(policyFlags),
        injectionState(nullptr),
        dispatchInProgress(false) {}

EventEntry::~EventEntry() {
    releaseInjectionState();
}

void EventEntry::releaseInjectionState() {
    if (injectionState) {
        injectionState->release();
        injectionState = nullptr;
    }
}

// --- ConfigurationChangedEntry ---

ConfigurationChangedEntry::ConfigurationChangedEntry(int32_t id, nsecs_t eventTime)
      : EventEntry(id, Type::CONFIGURATION_CHANGED, eventTime, 0) {}

ConfigurationChangedEntry::~ConfigurationChangedEntry() {}

std::string ConfigurationChangedEntry::getDescription() const {
    return StringPrintf("ConfigurationChangedEvent(), policyFlags=0x%08x", policyFlags);
}

// --- DeviceResetEntry ---

DeviceResetEntry::DeviceResetEntry(int32_t id, nsecs_t eventTime, int32_t deviceId)
      : EventEntry(id, Type::DEVICE_RESET, eventTime, 0), deviceId(deviceId) {}

DeviceResetEntry::~DeviceResetEntry() {}

std::string DeviceResetEntry::getDescription() const {
    return StringPrintf("DeviceResetEvent(deviceId=%d), policyFlags=0x%08x", deviceId, policyFlags);
}

// --- FocusEntry ---

// Focus notifications always go to apps, so set the flag POLICY_FLAG_PASS_TO_USER for all entries
FocusEntry::FocusEntry(int32_t id, nsecs_t eventTime, sp<IBinder> connectionToken, bool hasFocus,
                       const std::string& reason)
      : EventEntry(id, Type::FOCUS, eventTime, POLICY_FLAG_PASS_TO_USER),
        connectionToken(connectionToken),
        hasFocus(hasFocus),
        reason(reason) {}

FocusEntry::~FocusEntry() {}

std::string FocusEntry::getDescription() const {
    return StringPrintf("FocusEvent(hasFocus=%s)", hasFocus ? "true" : "false");
}

// --- PointerCaptureChangedEntry ---

// PointerCaptureChanged notifications always go to apps, so set the flag POLICY_FLAG_PASS_TO_USER
// for all entries.
PointerCaptureChangedEntry::PointerCaptureChangedEntry(int32_t id, nsecs_t eventTime,
                                                       bool hasPointerCapture)
      : EventEntry(id, Type::POINTER_CAPTURE_CHANGED, eventTime, POLICY_FLAG_PASS_TO_USER),
        pointerCaptureEnabled(hasPointerCapture) {}

PointerCaptureChangedEntry::~PointerCaptureChangedEntry() {}

std::string PointerCaptureChangedEntry::getDescription() const {
    return StringPrintf("PointerCaptureChangedEvent(pointerCaptureEnabled=%s)",
                        pointerCaptureEnabled ? "true" : "false");
}

// --- DragEntry ---

// Drag notifications always go to apps, so set the flag POLICY_FLAG_PASS_TO_USER for all entries
DragEntry::DragEntry(int32_t id, nsecs_t eventTime, sp<IBinder> connectionToken, bool isExiting,
                     float x, float y)
      : EventEntry(id, Type::DRAG, eventTime, POLICY_FLAG_PASS_TO_USER),
        connectionToken(connectionToken),
        isExiting(isExiting),
        x(x),
        y(y) {}

DragEntry::~DragEntry() {}

std::string DragEntry::getDescription() const {
    return StringPrintf("DragEntry(isExiting=%s, x=%f, y=%f)", isExiting ? "true" : "false", x, y);
}

// --- KeyEntry ---

KeyEntry::KeyEntry(int32_t id, nsecs_t eventTime, int32_t deviceId, uint32_t source,
                   int32_t displayId, uint32_t policyFlags, int32_t action, int32_t flags,
                   int32_t keyCode, int32_t scanCode, int32_t metaState, int32_t repeatCount,
                   nsecs_t downTime)
      : EventEntry(id, Type::KEY, eventTime, policyFlags),
        deviceId(deviceId),
        source(source),
        displayId(displayId),
        action(action),
        flags(flags),
        keyCode(keyCode),
        scanCode(scanCode),
        metaState(metaState),
        repeatCount(repeatCount),
        downTime(downTime),
        syntheticRepeat(false),
        interceptKeyResult(KeyEntry::INTERCEPT_KEY_RESULT_UNKNOWN),
        interceptKeyWakeupTime(0) {}

KeyEntry::~KeyEntry() {}

std::string KeyEntry::getDescription() const {
    if (!GetBoolProperty("ro.debuggable", false)) {
        return "KeyEvent";
    }
    return StringPrintf("KeyEvent(deviceId=%d, eventTime=%" PRIu64
                        ", source=0x%08x, displayId=%" PRId32 ", action=%s, "
                        "flags=0x%08x, keyCode=%d, scanCode=%d, metaState=0x%08x, "
                        "repeatCount=%d), policyFlags=0x%08x",
                        deviceId, eventTime, source, displayId, KeyEvent::actionToString(action),
                        flags, keyCode, scanCode, metaState, repeatCount, policyFlags);
}

void KeyEntry::recycle() {
    releaseInjectionState();

    dispatchInProgress = false;
    syntheticRepeat = false;
    interceptKeyResult = KeyEntry::INTERCEPT_KEY_RESULT_UNKNOWN;
    interceptKeyWakeupTime = 0;
}

// --- MotionEntry ---

MotionEntry::MotionEntry(int32_t id, nsecs_t eventTime, int32_t deviceId, uint32_t source,
                         int32_t displayId, uint32_t policyFlags, int32_t action,
                         int32_t actionButton, int32_t flags, int32_t metaState,
                         int32_t buttonState, MotionClassification classification,
                         int32_t edgeFlags, float xPrecision, float yPrecision,
                         float xCursorPosition, float yCursorPosition, nsecs_t downTime,
                         uint32_t pointerCount, const PointerProperties* pointerProperties,
                         const PointerCoords* pointerCoords, float xOffset, float yOffset)
      : EventEntry(id, Type::MOTION, eventTime, policyFlags),
        deviceId(deviceId),
        source(source),
        displayId(displayId),
        action(action),
        actionButton(actionButton),
        flags(flags),
        metaState(metaState),
        buttonState(buttonState),
        classification(classification),
        edgeFlags(edgeFlags),
        xPrecision(xPrecision),
        yPrecision(yPrecision),
        xCursorPosition(xCursorPosition),
        yCursorPosition(yCursorPosition),
        downTime(downTime),
        pointerCount(pointerCount) {
    for (uint32_t i = 0; i < pointerCount; i++) {
        this->pointerProperties[i].copyFrom(pointerProperties[i]);
        this->pointerCoords[i].copyFrom(pointerCoords[i]);
        if (xOffset || yOffset) {
            this->pointerCoords[i].applyOffset(xOffset, yOffset);
        }
    }
}

MotionEntry::~MotionEntry() {}

std::string MotionEntry::getDescription() const {
    if (!GetBoolProperty("ro.debuggable", false)) {
        return "MotionEvent";
    }
    std::string msg;
    msg += StringPrintf("MotionEvent(deviceId=%d, eventTime=%" PRIu64
                        ", source=0x%08x, displayId=%" PRId32
                        ", action=%s, actionButton=0x%08x, flags=0x%08x, metaState=0x%08x, "
                        "buttonState=0x%08x, "
                        "classification=%s, edgeFlags=0x%08x, xPrecision=%.1f, yPrecision=%.1f, "
                        "xCursorPosition=%0.1f, yCursorPosition=%0.1f, pointers=[",
                        deviceId, eventTime, source, displayId,
                        MotionEvent::actionToString(action).c_str(), actionButton, flags, metaState,
                        buttonState, motionClassificationToString(classification), edgeFlags,
                        xPrecision, yPrecision, xCursorPosition, yCursorPosition);

    for (uint32_t i = 0; i < pointerCount; i++) {
        if (i) {
            msg += ", ";
        }
        msg += StringPrintf("%d: (%.1f, %.1f)", pointerProperties[i].id, pointerCoords[i].getX(),
                            pointerCoords[i].getY());
    }
    msg += StringPrintf("]), policyFlags=0x%08x", policyFlags);
    return msg;
}

// --- SensorEntry ---

SensorEntry::SensorEntry(int32_t id, nsecs_t eventTime, int32_t deviceId, uint32_t source,
                         uint32_t policyFlags, nsecs_t hwTimestamp,
                         InputDeviceSensorType sensorType, InputDeviceSensorAccuracy accuracy,
                         bool accuracyChanged, std::vector<float> values)
      : EventEntry(id, Type::SENSOR, eventTime, policyFlags),
        deviceId(deviceId),
        source(source),
        sensorType(sensorType),
        accuracy(accuracy),
        accuracyChanged(accuracyChanged),
        hwTimestamp(hwTimestamp),
        values(std::move(values)) {}

SensorEntry::~SensorEntry() {}

std::string SensorEntry::getDescription() const {
    std::string msg;
    msg += StringPrintf("SensorEntry(deviceId=%d, source=0x%08x, sensorType=0x%08x, "
                        "accuracy=0x%08x, hwTimestamp=%" PRId64,
                        deviceId, source, sensorType, accuracy, hwTimestamp);

    if (!GetBoolProperty("ro.debuggable", false)) {
        for (size_t i = 0; i < values.size(); i++) {
            if (i > 0) {
                msg += ", ";
            }
            msg += StringPrintf("(%.3f)", values[i]);
        }
    }
    msg += StringPrintf(", policyFlags=0x%08x", policyFlags);
    return msg;
}

// --- DispatchEntry ---

volatile int32_t DispatchEntry::sNextSeqAtomic;

DispatchEntry::DispatchEntry(std::shared_ptr<EventEntry> eventEntry, int32_t targetFlags,
                             ui::Transform transform, float globalScaleFactor, int2 displaySize)
      : seq(nextSeq()),
        eventEntry(std::move(eventEntry)),
        targetFlags(targetFlags),
        transform(transform),
        globalScaleFactor(globalScaleFactor),
        displaySize(displaySize),
        deliveryTime(0),
        resolvedAction(0),
        resolvedFlags(0) {}

uint32_t DispatchEntry::nextSeq() {
    // Sequence number 0 is reserved and will never be returned.
    uint32_t seq;
    do {
        seq = android_atomic_inc(&sNextSeqAtomic);
    } while (!seq);
    return seq;
}

// --- CommandEntry ---

CommandEntry::CommandEntry(Command command)
      : command(command),
        eventTime(0),
        keyEntry(nullptr),
        userActivityEventType(0),
        seq(0),
        handled(false),
        enabled(false) {}

CommandEntry::~CommandEntry() {}

} // namespace android::inputdispatcher
