| /* |
| * 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 |