blob: 264dc03e702f2bf8f300efe9e1adfbfe84f80a42 [file] [log] [blame]
/*
* 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.
*/
#define LOG_TAG "InputDispatcher"
#include "Entry.h"
#include "Connection.h"
#include "DebugConfig.h"
#include <android-base/stringprintf.h>
#include <cutils/atomic.h>
#include <inttypes.h>
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.flags & VERIFIED_KEY_EVENT_FLAGS,
entry.downTime,
entry.keyCode,
entry.scanCode,
entry.metaState,
entry.repeatCount};
}
VerifiedMotionEvent verifiedMotionEventFromMotionEntry(const MotionEntry& entry,
const ui::Transform& rawTransform) {
const vec2 rawXY = MotionEvent::calculateTransformedXY(entry.source, rawTransform,
entry.pointerCoords[0].getXYValue());
const int actionMasked = entry.action & AMOTION_EVENT_ACTION_MASK;
return {{VerifiedInputEvent::Type::MOTION, entry.deviceId, entry.eventTime, entry.source,
entry.displayId},
rawXY.x,
rawXY.y,
actionMasked,
entry.flags & VERIFIED_MOTION_EVENT_FLAGS,
entry.downTime,
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) {}
// --- ConfigurationChangedEntry ---
ConfigurationChangedEntry::ConfigurationChangedEntry(int32_t id, nsecs_t eventTime)
: EventEntry(id, Type::CONFIGURATION_CHANGED, eventTime, 0) {}
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) {}
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) {}
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,
const PointerCaptureRequest& request)
: EventEntry(id, Type::POINTER_CAPTURE_CHANGED, eventTime, POLICY_FLAG_PASS_TO_USER),
pointerCaptureRequest(request) {}
std::string PointerCaptureChangedEntry::getDescription() const {
return StringPrintf("PointerCaptureChangedEvent(pointerCaptureEnabled=%s)",
pointerCaptureRequest.enable ? "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) {}
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, std::shared_ptr<InjectionState> injectionState, 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),
keyCode(keyCode),
scanCode(scanCode),
metaState(metaState),
downTime(downTime),
syntheticRepeat(false),
interceptKeyResult(KeyEntry::InterceptKeyResult::UNKNOWN),
interceptKeyWakeupTime(0),
flags(flags),
repeatCount(repeatCount) {
EventEntry::injectionState = std::move(injectionState);
}
std::string KeyEntry::getDescription() const {
if (!IS_DEBUGGABLE_BUILD) {
return "KeyEvent";
}
return StringPrintf("KeyEvent(deviceId=%d, eventTime=%" PRIu64 ", source=%s, displayId=%" PRId32
", action=%s, "
"flags=0x%08x, keyCode=%s(%d), scanCode=%d, metaState=0x%08x, "
"repeatCount=%d), policyFlags=0x%08x",
deviceId, eventTime, inputEventSourceToString(source).c_str(), displayId,
KeyEvent::actionToString(action), flags, KeyEvent::getLabel(keyCode),
keyCode, scanCode, metaState, repeatCount, policyFlags);
}
std::ostream& operator<<(std::ostream& out, const KeyEntry& keyEntry) {
out << keyEntry.getDescription();
return out;
}
// --- TouchModeEntry ---
TouchModeEntry::TouchModeEntry(int32_t id, nsecs_t eventTime, bool inTouchMode, int displayId)
: EventEntry(id, Type::TOUCH_MODE_CHANGED, eventTime, POLICY_FLAG_PASS_TO_USER),
inTouchMode(inTouchMode),
displayId(displayId) {}
std::string TouchModeEntry::getDescription() const {
return StringPrintf("TouchModeEvent(inTouchMode=%s)", inTouchMode ? "true" : "false");
}
// --- MotionEntry ---
MotionEntry::MotionEntry(int32_t id, std::shared_ptr<InjectionState> injectionState,
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, const std::vector<PointerProperties>& pointerProperties,
const std::vector<PointerCoords>& pointerCoords)
: 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),
pointerProperties(pointerProperties),
pointerCoords(pointerCoords) {
EventEntry::injectionState = std::move(injectionState);
}
std::string MotionEntry::getDescription() const {
if (!IS_DEBUGGABLE_BUILD) {
return "MotionEvent";
}
std::string msg;
msg += StringPrintf("MotionEvent(deviceId=%d, eventTime=%" PRIu64
", source=%s, 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, inputEventSourceToString(source).c_str(), displayId,
MotionEvent::actionToString(action).c_str(), actionButton, flags, metaState,
buttonState, motionClassificationToString(classification), edgeFlags,
xPrecision, yPrecision, xCursorPosition, yCursorPosition);
for (uint32_t i = 0; i < getPointerCount(); 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;
}
std::ostream& operator<<(std::ostream& out, const MotionEntry& motionEntry) {
out << motionEntry.getDescription();
return out;
}
// --- 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)) {}
std::string SensorEntry::getDescription() const {
std::string msg;
msg += StringPrintf("SensorEntry(deviceId=%d, source=%s, sensorType=%s, "
"accuracy=0x%08x, hwTimestamp=%" PRId64,
deviceId, inputEventSourceToString(source).c_str(),
ftl::enum_string(sensorType).c_str(), accuracy, hwTimestamp);
if (IS_DEBUGGABLE_BUILD) {
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<const EventEntry> eventEntry,
ftl::Flags<InputTargetFlags> targetFlags,
const ui::Transform& transform, const ui::Transform& rawTransform,
float globalScaleFactor, gui::Uid targetUid, int64_t vsyncId,
std::optional<int32_t> windowId)
: seq(nextSeq()),
eventEntry(std::move(eventEntry)),
targetFlags(targetFlags),
transform(transform),
rawTransform(rawTransform),
globalScaleFactor(globalScaleFactor),
deliveryTime(0),
resolvedFlags(0),
targetUid(targetUid),
vsyncId(vsyncId),
windowId(windowId) {
switch (this->eventEntry->type) {
case EventEntry::Type::KEY: {
const KeyEntry& keyEntry = static_cast<const KeyEntry&>(*this->eventEntry);
resolvedFlags = keyEntry.flags;
break;
}
case EventEntry::Type::MOTION: {
const MotionEntry& motionEntry = static_cast<const MotionEntry&>(*this->eventEntry);
resolvedFlags = motionEntry.flags;
break;
}
default: {
break;
}
}
}
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;
}
std::ostream& operator<<(std::ostream& out, const DispatchEntry& entry) {
std::string transform;
entry.transform.dump(transform, "transform");
out << "DispatchEntry{resolvedFlags=" << entry.resolvedFlags
<< ", targetFlags=" << entry.targetFlags.string() << ", transform=" << transform
<< "} original: " << entry.eventEntry->getDescription();
return out;
}
} // namespace android::inputdispatcher