334 lines
12 KiB
C++
334 lines
12 KiB
C++
/*
|
|
* 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,
|
|
const PointerCaptureRequest& request)
|
|
: EventEntry(id, Type::POINTER_CAPTURE_CHANGED, eventTime, POLICY_FLAG_PASS_TO_USER),
|
|
pointerCaptureRequest(request) {}
|
|
|
|
PointerCaptureChangedEntry::~PointerCaptureChangedEntry() {}
|
|
|
|
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) {}
|
|
|
|
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,
|
|
uint32_t displayOrientation, int2 displaySize)
|
|
: seq(nextSeq()),
|
|
eventEntry(std::move(eventEntry)),
|
|
targetFlags(targetFlags),
|
|
transform(transform),
|
|
globalScaleFactor(globalScaleFactor),
|
|
displayOrientation(displayOrientation),
|
|
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) {}
|
|
|
|
CommandEntry::~CommandEntry() {}
|
|
|
|
} // namespace android::inputdispatcher
|