diff options
author | Mathias Agopian <mathias@google.com> | 2012-02-21 12:52:06 -0800 |
---|---|---|
committer | Android (Google) Code Review <android-gerrit@google.com> | 2012-02-21 12:52:06 -0800 |
commit | 6861d94d4c9dfe50aa7c2f4094665071b8e2f001 (patch) | |
tree | df517600cc246f5450fc5678bceea9076ef79aad /libs/ui | |
parent | f1e7d1174bae0581bdcffb27b7eb6c8e302ab01c (diff) | |
parent | 4f4c10104e8fbeed5dfeefb542e0bc5392daf9a5 (diff) | |
download | frameworks_native-6861d94d4c9dfe50aa7c2f4094665071b8e2f001.zip frameworks_native-6861d94d4c9dfe50aa7c2f4094665071b8e2f001.tar.gz frameworks_native-6861d94d4c9dfe50aa7c2f4094665071b8e2f001.tar.bz2 |
Merge "frameworks/base refactoring"
Diffstat (limited to 'libs/ui')
-rw-r--r-- | libs/ui/Android.mk | 35 | ||||
-rw-r--r-- | libs/ui/Input.cpp | 1223 | ||||
-rw-r--r-- | libs/ui/InputTransport.cpp | 611 | ||||
-rw-r--r-- | libs/ui/KeyCharacterMap.cpp | 838 | ||||
-rw-r--r-- | libs/ui/KeyLayoutMap.cpp | 341 | ||||
-rw-r--r-- | libs/ui/Keyboard.cpp | 303 | ||||
-rw-r--r-- | libs/ui/VirtualKeyMap.cpp | 171 | ||||
-rw-r--r-- | libs/ui/tests/Android.mk | 42 | ||||
-rw-r--r-- | libs/ui/tests/InputChannel_test.cpp | 158 | ||||
-rw-r--r-- | libs/ui/tests/InputEvent_test.cpp | 581 | ||||
-rw-r--r-- | libs/ui/tests/InputPublisherAndConsumer_test.cpp | 287 |
11 files changed, 1 insertions, 4589 deletions
diff --git a/libs/ui/Android.mk b/libs/ui/Android.mk index f8b4452..579c315 100644 --- a/libs/ui/Android.mk +++ b/libs/ui/Android.mk @@ -13,41 +13,14 @@ # limitations under the License. LOCAL_PATH:= $(call my-dir) - -# libui is partially built for the host (used by build time keymap validation tool) -# These files are common to host and target builds. -commonSources:= \ - Input.cpp \ - Keyboard.cpp \ - KeyLayoutMap.cpp \ - KeyCharacterMap.cpp \ - VirtualKeyMap.cpp - -# For the host -# ===================================================== - -include $(CLEAR_VARS) - -LOCAL_SRC_FILES:= $(commonSources) - -LOCAL_MODULE:= libui - -include $(BUILD_HOST_STATIC_LIBRARY) - - -# For the device -# ===================================================== - include $(CLEAR_VARS) LOCAL_SRC_FILES:= \ - $(commonSources) \ EGLUtils.cpp \ FramebufferNativeWindow.cpp \ GraphicBuffer.cpp \ GraphicBufferAllocator.cpp \ GraphicBufferMapper.cpp \ - InputTransport.cpp \ PixelFormat.cpp \ Rect.cpp \ Region.cpp @@ -57,13 +30,7 @@ LOCAL_SHARED_LIBRARIES := \ libutils \ libEGL \ libpixelflinger \ - libhardware \ - libhardware_legacy \ - libskia \ - libbinder - -LOCAL_C_INCLUDES := \ - external/skia/include/core + libhardware LOCAL_MODULE:= libui diff --git a/libs/ui/Input.cpp b/libs/ui/Input.cpp deleted file mode 100644 index ca09caf..0000000 --- a/libs/ui/Input.cpp +++ /dev/null @@ -1,1223 +0,0 @@ -// -// Copyright 2010 The Android Open Source Project -// -// Provides a pipe-based transport for native events in the NDK. -// -#define LOG_TAG "Input" - -//#define LOG_NDEBUG 0 - -// Log debug messages about keymap probing. -#define DEBUG_PROBE 0 - -// Log debug messages about velocity tracking. -#define DEBUG_VELOCITY 0 - -// Log debug messages about least squares fitting. -#define DEBUG_LEAST_SQUARES 0 - -// Log debug messages about acceleration. -#define DEBUG_ACCELERATION 0 - - -#include <stdlib.h> -#include <unistd.h> -#include <ctype.h> - -#include <androidfw/Input.h> - -#include <math.h> -#include <limits.h> - -#ifdef HAVE_ANDROID_OS -#include <binder/Parcel.h> - -#include "SkPoint.h" -#include "SkMatrix.h" -#include "SkScalar.h" -#endif - -namespace android { - -static const char* CONFIGURATION_FILE_DIR[] = { - "idc/", - "keylayout/", - "keychars/", -}; - -static const char* CONFIGURATION_FILE_EXTENSION[] = { - ".idc", - ".kl", - ".kcm", -}; - -static bool isValidNameChar(char ch) { - return isascii(ch) && (isdigit(ch) || isalpha(ch) || ch == '-' || ch == '_'); -} - -static void appendInputDeviceConfigurationFileRelativePath(String8& path, - const String8& name, InputDeviceConfigurationFileType type) { - path.append(CONFIGURATION_FILE_DIR[type]); - for (size_t i = 0; i < name.length(); i++) { - char ch = name[i]; - if (!isValidNameChar(ch)) { - ch = '_'; - } - path.append(&ch, 1); - } - path.append(CONFIGURATION_FILE_EXTENSION[type]); -} - -String8 getInputDeviceConfigurationFilePathByDeviceIdentifier( - const InputDeviceIdentifier& deviceIdentifier, - InputDeviceConfigurationFileType type) { - if (deviceIdentifier.vendor !=0 && deviceIdentifier.product != 0) { - if (deviceIdentifier.version != 0) { - // Try vendor product version. - String8 versionPath(getInputDeviceConfigurationFilePathByName( - String8::format("Vendor_%04x_Product_%04x_Version_%04x", - deviceIdentifier.vendor, deviceIdentifier.product, - deviceIdentifier.version), - type)); - if (!versionPath.isEmpty()) { - return versionPath; - } - } - - // Try vendor product. - String8 productPath(getInputDeviceConfigurationFilePathByName( - String8::format("Vendor_%04x_Product_%04x", - deviceIdentifier.vendor, deviceIdentifier.product), - type)); - if (!productPath.isEmpty()) { - return productPath; - } - } - - // Try device name. - return getInputDeviceConfigurationFilePathByName(deviceIdentifier.name, type); -} - -String8 getInputDeviceConfigurationFilePathByName( - const String8& name, InputDeviceConfigurationFileType type) { - // Search system repository. - String8 path; - path.setTo(getenv("ANDROID_ROOT")); - path.append("/usr/"); - appendInputDeviceConfigurationFileRelativePath(path, name, type); -#if DEBUG_PROBE - ALOGD("Probing for system provided input device configuration file: path='%s'", path.string()); -#endif - if (!access(path.string(), R_OK)) { -#if DEBUG_PROBE - ALOGD("Found"); -#endif - return path; - } - - // Search user repository. - // TODO Should only look here if not in safe mode. - path.setTo(getenv("ANDROID_DATA")); - path.append("/system/devices/"); - appendInputDeviceConfigurationFileRelativePath(path, name, type); -#if DEBUG_PROBE - ALOGD("Probing for system user input device configuration file: path='%s'", path.string()); -#endif - if (!access(path.string(), R_OK)) { -#if DEBUG_PROBE - ALOGD("Found"); -#endif - return path; - } - - // Not found. -#if DEBUG_PROBE - ALOGD("Probe failed to find input device configuration file: name='%s', type=%d", - name.string(), type); -#endif - return String8(); -} - - -// --- InputEvent --- - -void InputEvent::initialize(int32_t deviceId, int32_t source) { - mDeviceId = deviceId; - mSource = source; -} - -void InputEvent::initialize(const InputEvent& from) { - mDeviceId = from.mDeviceId; - mSource = from.mSource; -} - -// --- KeyEvent --- - -bool KeyEvent::hasDefaultAction(int32_t keyCode) { - switch (keyCode) { - case AKEYCODE_HOME: - case AKEYCODE_BACK: - case AKEYCODE_CALL: - case AKEYCODE_ENDCALL: - case AKEYCODE_VOLUME_UP: - case AKEYCODE_VOLUME_DOWN: - case AKEYCODE_VOLUME_MUTE: - case AKEYCODE_POWER: - case AKEYCODE_CAMERA: - case AKEYCODE_HEADSETHOOK: - case AKEYCODE_MENU: - case AKEYCODE_NOTIFICATION: - case AKEYCODE_FOCUS: - case AKEYCODE_SEARCH: - case AKEYCODE_MEDIA_PLAY: - case AKEYCODE_MEDIA_PAUSE: - case AKEYCODE_MEDIA_PLAY_PAUSE: - case AKEYCODE_MEDIA_STOP: - case AKEYCODE_MEDIA_NEXT: - case AKEYCODE_MEDIA_PREVIOUS: - case AKEYCODE_MEDIA_REWIND: - case AKEYCODE_MEDIA_RECORD: - case AKEYCODE_MEDIA_FAST_FORWARD: - case AKEYCODE_MUTE: - return true; - } - - return false; -} - -bool KeyEvent::hasDefaultAction() const { - return hasDefaultAction(getKeyCode()); -} - -bool KeyEvent::isSystemKey(int32_t keyCode) { - switch (keyCode) { - case AKEYCODE_MENU: - case AKEYCODE_SOFT_RIGHT: - case AKEYCODE_HOME: - case AKEYCODE_BACK: - case AKEYCODE_CALL: - case AKEYCODE_ENDCALL: - case AKEYCODE_VOLUME_UP: - case AKEYCODE_VOLUME_DOWN: - case AKEYCODE_VOLUME_MUTE: - case AKEYCODE_MUTE: - case AKEYCODE_POWER: - case AKEYCODE_HEADSETHOOK: - case AKEYCODE_MEDIA_PLAY: - case AKEYCODE_MEDIA_PAUSE: - case AKEYCODE_MEDIA_PLAY_PAUSE: - case AKEYCODE_MEDIA_STOP: - case AKEYCODE_MEDIA_NEXT: - case AKEYCODE_MEDIA_PREVIOUS: - case AKEYCODE_MEDIA_REWIND: - case AKEYCODE_MEDIA_RECORD: - case AKEYCODE_MEDIA_FAST_FORWARD: - case AKEYCODE_CAMERA: - case AKEYCODE_FOCUS: - case AKEYCODE_SEARCH: - return true; - } - - return false; -} - -bool KeyEvent::isSystemKey() const { - return isSystemKey(getKeyCode()); -} - -void KeyEvent::initialize( - int32_t deviceId, - int32_t source, - int32_t action, - int32_t flags, - int32_t keyCode, - int32_t scanCode, - int32_t metaState, - int32_t repeatCount, - nsecs_t downTime, - nsecs_t eventTime) { - InputEvent::initialize(deviceId, source); - mAction = action; - mFlags = flags; - mKeyCode = keyCode; - mScanCode = scanCode; - mMetaState = metaState; - mRepeatCount = repeatCount; - mDownTime = downTime; - mEventTime = eventTime; -} - -void KeyEvent::initialize(const KeyEvent& from) { - InputEvent::initialize(from); - mAction = from.mAction; - mFlags = from.mFlags; - mKeyCode = from.mKeyCode; - mScanCode = from.mScanCode; - mMetaState = from.mMetaState; - mRepeatCount = from.mRepeatCount; - mDownTime = from.mDownTime; - mEventTime = from.mEventTime; -} - - -// --- PointerCoords --- - -float PointerCoords::getAxisValue(int32_t axis) const { - if (axis < 0 || axis > 63) { - return 0; - } - - uint64_t axisBit = 1LL << axis; - if (!(bits & axisBit)) { - return 0; - } - uint32_t index = __builtin_popcountll(bits & (axisBit - 1LL)); - return values[index]; -} - -status_t PointerCoords::setAxisValue(int32_t axis, float value) { - if (axis < 0 || axis > 63) { - return NAME_NOT_FOUND; - } - - uint64_t axisBit = 1LL << axis; - uint32_t index = __builtin_popcountll(bits & (axisBit - 1LL)); - if (!(bits & axisBit)) { - if (value == 0) { - return OK; // axes with value 0 do not need to be stored - } - uint32_t count = __builtin_popcountll(bits); - if (count >= MAX_AXES) { - tooManyAxes(axis); - return NO_MEMORY; - } - bits |= axisBit; - for (uint32_t i = count; i > index; i--) { - values[i] = values[i - 1]; - } - } - values[index] = value; - return OK; -} - -static inline void scaleAxisValue(PointerCoords& c, int axis, float scaleFactor) { - float value = c.getAxisValue(axis); - if (value != 0) { - c.setAxisValue(axis, value * scaleFactor); - } -} - -void PointerCoords::scale(float scaleFactor) { - // No need to scale pressure or size since they are normalized. - // No need to scale orientation since it is meaningless to do so. - scaleAxisValue(*this, AMOTION_EVENT_AXIS_X, scaleFactor); - scaleAxisValue(*this, AMOTION_EVENT_AXIS_Y, scaleFactor); - scaleAxisValue(*this, AMOTION_EVENT_AXIS_TOUCH_MAJOR, scaleFactor); - scaleAxisValue(*this, AMOTION_EVENT_AXIS_TOUCH_MINOR, scaleFactor); - scaleAxisValue(*this, AMOTION_EVENT_AXIS_TOOL_MAJOR, scaleFactor); - scaleAxisValue(*this, AMOTION_EVENT_AXIS_TOOL_MINOR, scaleFactor); -} - -#ifdef HAVE_ANDROID_OS -status_t PointerCoords::readFromParcel(Parcel* parcel) { - bits = parcel->readInt64(); - - uint32_t count = __builtin_popcountll(bits); - if (count > MAX_AXES) { - return BAD_VALUE; - } - - for (uint32_t i = 0; i < count; i++) { - values[i] = parcel->readInt32(); - } - return OK; -} - -status_t PointerCoords::writeToParcel(Parcel* parcel) const { - parcel->writeInt64(bits); - - uint32_t count = __builtin_popcountll(bits); - for (uint32_t i = 0; i < count; i++) { - parcel->writeInt32(values[i]); - } - return OK; -} -#endif - -void PointerCoords::tooManyAxes(int axis) { - ALOGW("Could not set value for axis %d because the PointerCoords structure is full and " - "cannot contain more than %d axis values.", axis, int(MAX_AXES)); -} - -bool PointerCoords::operator==(const PointerCoords& other) const { - if (bits != other.bits) { - return false; - } - uint32_t count = __builtin_popcountll(bits); - for (uint32_t i = 0; i < count; i++) { - if (values[i] != other.values[i]) { - return false; - } - } - return true; -} - -void PointerCoords::copyFrom(const PointerCoords& other) { - bits = other.bits; - uint32_t count = __builtin_popcountll(bits); - for (uint32_t i = 0; i < count; i++) { - values[i] = other.values[i]; - } -} - - -// --- PointerProperties --- - -bool PointerProperties::operator==(const PointerProperties& other) const { - return id == other.id - && toolType == other.toolType; -} - -void PointerProperties::copyFrom(const PointerProperties& other) { - id = other.id; - toolType = other.toolType; -} - - -// --- MotionEvent --- - -void MotionEvent::initialize( - int32_t deviceId, - int32_t source, - int32_t action, - int32_t flags, - int32_t edgeFlags, - int32_t metaState, - int32_t buttonState, - float xOffset, - float yOffset, - float xPrecision, - float yPrecision, - nsecs_t downTime, - nsecs_t eventTime, - size_t pointerCount, - const PointerProperties* pointerProperties, - const PointerCoords* pointerCoords) { - InputEvent::initialize(deviceId, source); - mAction = action; - mFlags = flags; - mEdgeFlags = edgeFlags; - mMetaState = metaState; - mButtonState = buttonState; - mXOffset = xOffset; - mYOffset = yOffset; - mXPrecision = xPrecision; - mYPrecision = yPrecision; - mDownTime = downTime; - mPointerProperties.clear(); - mPointerProperties.appendArray(pointerProperties, pointerCount); - mSampleEventTimes.clear(); - mSamplePointerCoords.clear(); - addSample(eventTime, pointerCoords); -} - -void MotionEvent::copyFrom(const MotionEvent* other, bool keepHistory) { - InputEvent::initialize(other->mDeviceId, other->mSource); - mAction = other->mAction; - mFlags = other->mFlags; - mEdgeFlags = other->mEdgeFlags; - mMetaState = other->mMetaState; - mButtonState = other->mButtonState; - mXOffset = other->mXOffset; - mYOffset = other->mYOffset; - mXPrecision = other->mXPrecision; - mYPrecision = other->mYPrecision; - mDownTime = other->mDownTime; - mPointerProperties = other->mPointerProperties; - - if (keepHistory) { - mSampleEventTimes = other->mSampleEventTimes; - mSamplePointerCoords = other->mSamplePointerCoords; - } else { - mSampleEventTimes.clear(); - mSampleEventTimes.push(other->getEventTime()); - mSamplePointerCoords.clear(); - size_t pointerCount = other->getPointerCount(); - size_t historySize = other->getHistorySize(); - mSamplePointerCoords.appendArray(other->mSamplePointerCoords.array() - + (historySize * pointerCount), pointerCount); - } -} - -void MotionEvent::addSample( - int64_t eventTime, - const PointerCoords* pointerCoords) { - mSampleEventTimes.push(eventTime); - mSamplePointerCoords.appendArray(pointerCoords, getPointerCount()); -} - -const PointerCoords* MotionEvent::getRawPointerCoords(size_t pointerIndex) const { - return &mSamplePointerCoords[getHistorySize() * getPointerCount() + pointerIndex]; -} - -float MotionEvent::getRawAxisValue(int32_t axis, size_t pointerIndex) const { - return getRawPointerCoords(pointerIndex)->getAxisValue(axis); -} - -float MotionEvent::getAxisValue(int32_t axis, size_t pointerIndex) const { - float value = getRawPointerCoords(pointerIndex)->getAxisValue(axis); - switch (axis) { - case AMOTION_EVENT_AXIS_X: - return value + mXOffset; - case AMOTION_EVENT_AXIS_Y: - return value + mYOffset; - } - return value; -} - -const PointerCoords* MotionEvent::getHistoricalRawPointerCoords( - size_t pointerIndex, size_t historicalIndex) const { - return &mSamplePointerCoords[historicalIndex * getPointerCount() + pointerIndex]; -} - -float MotionEvent::getHistoricalRawAxisValue(int32_t axis, size_t pointerIndex, - size_t historicalIndex) const { - return getHistoricalRawPointerCoords(pointerIndex, historicalIndex)->getAxisValue(axis); -} - -float MotionEvent::getHistoricalAxisValue(int32_t axis, size_t pointerIndex, - size_t historicalIndex) const { - float value = getHistoricalRawPointerCoords(pointerIndex, historicalIndex)->getAxisValue(axis); - switch (axis) { - case AMOTION_EVENT_AXIS_X: - return value + mXOffset; - case AMOTION_EVENT_AXIS_Y: - return value + mYOffset; - } - return value; -} - -ssize_t MotionEvent::findPointerIndex(int32_t pointerId) const { - size_t pointerCount = mPointerProperties.size(); - for (size_t i = 0; i < pointerCount; i++) { - if (mPointerProperties.itemAt(i).id == pointerId) { - return i; - } - } - return -1; -} - -void MotionEvent::offsetLocation(float xOffset, float yOffset) { - mXOffset += xOffset; - mYOffset += yOffset; -} - -void MotionEvent::scale(float scaleFactor) { - mXOffset *= scaleFactor; - mYOffset *= scaleFactor; - mXPrecision *= scaleFactor; - mYPrecision *= scaleFactor; - - size_t numSamples = mSamplePointerCoords.size(); - for (size_t i = 0; i < numSamples; i++) { - mSamplePointerCoords.editItemAt(i).scale(scaleFactor); - } -} - -#ifdef HAVE_ANDROID_OS -static inline float transformAngle(const SkMatrix* matrix, float angleRadians) { - // Construct and transform a vector oriented at the specified clockwise angle from vertical. - // Coordinate system: down is increasing Y, right is increasing X. - SkPoint vector; - vector.fX = SkFloatToScalar(sinf(angleRadians)); - vector.fY = SkFloatToScalar(-cosf(angleRadians)); - matrix->mapVectors(& vector, 1); - - // Derive the transformed vector's clockwise angle from vertical. - float result = atan2f(SkScalarToFloat(vector.fX), SkScalarToFloat(-vector.fY)); - if (result < - M_PI_2) { - result += M_PI; - } else if (result > M_PI_2) { - result -= M_PI; - } - return result; -} - -void MotionEvent::transform(const SkMatrix* matrix) { - float oldXOffset = mXOffset; - float oldYOffset = mYOffset; - - // The tricky part of this implementation is to preserve the value of - // rawX and rawY. So we apply the transformation to the first point - // then derive an appropriate new X/Y offset that will preserve rawX and rawY. - SkPoint point; - float rawX = getRawX(0); - float rawY = getRawY(0); - matrix->mapXY(SkFloatToScalar(rawX + oldXOffset), SkFloatToScalar(rawY + oldYOffset), - & point); - float newX = SkScalarToFloat(point.fX); - float newY = SkScalarToFloat(point.fY); - float newXOffset = newX - rawX; - float newYOffset = newY - rawY; - - mXOffset = newXOffset; - mYOffset = newYOffset; - - // Apply the transformation to all samples. - size_t numSamples = mSamplePointerCoords.size(); - for (size_t i = 0; i < numSamples; i++) { - PointerCoords& c = mSamplePointerCoords.editItemAt(i); - float x = c.getAxisValue(AMOTION_EVENT_AXIS_X) + oldXOffset; - float y = c.getAxisValue(AMOTION_EVENT_AXIS_Y) + oldYOffset; - matrix->mapXY(SkFloatToScalar(x), SkFloatToScalar(y), &point); - c.setAxisValue(AMOTION_EVENT_AXIS_X, SkScalarToFloat(point.fX) - newXOffset); - c.setAxisValue(AMOTION_EVENT_AXIS_Y, SkScalarToFloat(point.fY) - newYOffset); - - float orientation = c.getAxisValue(AMOTION_EVENT_AXIS_ORIENTATION); - c.setAxisValue(AMOTION_EVENT_AXIS_ORIENTATION, transformAngle(matrix, orientation)); - } -} - -status_t MotionEvent::readFromParcel(Parcel* parcel) { - size_t pointerCount = parcel->readInt32(); - size_t sampleCount = parcel->readInt32(); - if (pointerCount == 0 || pointerCount > MAX_POINTERS || sampleCount == 0) { - return BAD_VALUE; - } - - mDeviceId = parcel->readInt32(); - mSource = parcel->readInt32(); - mAction = parcel->readInt32(); - mFlags = parcel->readInt32(); - mEdgeFlags = parcel->readInt32(); - mMetaState = parcel->readInt32(); - mButtonState = parcel->readInt32(); - mXOffset = parcel->readFloat(); - mYOffset = parcel->readFloat(); - mXPrecision = parcel->readFloat(); - mYPrecision = parcel->readFloat(); - mDownTime = parcel->readInt64(); - - mPointerProperties.clear(); - mPointerProperties.setCapacity(pointerCount); - mSampleEventTimes.clear(); - mSampleEventTimes.setCapacity(sampleCount); - mSamplePointerCoords.clear(); - mSamplePointerCoords.setCapacity(sampleCount * pointerCount); - - for (size_t i = 0; i < pointerCount; i++) { - mPointerProperties.push(); - PointerProperties& properties = mPointerProperties.editTop(); - properties.id = parcel->readInt32(); - properties.toolType = parcel->readInt32(); - } - - while (sampleCount-- > 0) { - mSampleEventTimes.push(parcel->readInt64()); - for (size_t i = 0; i < pointerCount; i++) { - mSamplePointerCoords.push(); - status_t status = mSamplePointerCoords.editTop().readFromParcel(parcel); - if (status) { - return status; - } - } - } - return OK; -} - -status_t MotionEvent::writeToParcel(Parcel* parcel) const { - size_t pointerCount = mPointerProperties.size(); - size_t sampleCount = mSampleEventTimes.size(); - - parcel->writeInt32(pointerCount); - parcel->writeInt32(sampleCount); - - parcel->writeInt32(mDeviceId); - parcel->writeInt32(mSource); - parcel->writeInt32(mAction); - parcel->writeInt32(mFlags); - parcel->writeInt32(mEdgeFlags); - parcel->writeInt32(mMetaState); - parcel->writeInt32(mButtonState); - parcel->writeFloat(mXOffset); - parcel->writeFloat(mYOffset); - parcel->writeFloat(mXPrecision); - parcel->writeFloat(mYPrecision); - parcel->writeInt64(mDownTime); - - for (size_t i = 0; i < pointerCount; i++) { - const PointerProperties& properties = mPointerProperties.itemAt(i); - parcel->writeInt32(properties.id); - parcel->writeInt32(properties.toolType); - } - - const PointerCoords* pc = mSamplePointerCoords.array(); - for (size_t h = 0; h < sampleCount; h++) { - parcel->writeInt64(mSampleEventTimes.itemAt(h)); - for (size_t i = 0; i < pointerCount; i++) { - status_t status = (pc++)->writeToParcel(parcel); - if (status) { - return status; - } - } - } - return OK; -} -#endif - -bool MotionEvent::isTouchEvent(int32_t source, int32_t action) { - if (source & AINPUT_SOURCE_CLASS_POINTER) { - // Specifically excludes HOVER_MOVE and SCROLL. - switch (action & AMOTION_EVENT_ACTION_MASK) { - case AMOTION_EVENT_ACTION_DOWN: - case AMOTION_EVENT_ACTION_MOVE: - case AMOTION_EVENT_ACTION_UP: - case AMOTION_EVENT_ACTION_POINTER_DOWN: - case AMOTION_EVENT_ACTION_POINTER_UP: - case AMOTION_EVENT_ACTION_CANCEL: - case AMOTION_EVENT_ACTION_OUTSIDE: - return true; - } - } - return false; -} - - -// --- VelocityTracker --- - -const uint32_t VelocityTracker::DEFAULT_DEGREE; -const nsecs_t VelocityTracker::DEFAULT_HORIZON; -const uint32_t VelocityTracker::HISTORY_SIZE; - -static inline float vectorDot(const float* a, const float* b, uint32_t m) { - float r = 0; - while (m--) { - r += *(a++) * *(b++); - } - return r; -} - -static inline float vectorNorm(const float* a, uint32_t m) { - float r = 0; - while (m--) { - float t = *(a++); - r += t * t; - } - return sqrtf(r); -} - -#if DEBUG_LEAST_SQUARES || DEBUG_VELOCITY -static String8 vectorToString(const float* a, uint32_t m) { - String8 str; - str.append("["); - while (m--) { - str.appendFormat(" %f", *(a++)); - if (m) { - str.append(","); - } - } - str.append(" ]"); - return str; -} - -static String8 matrixToString(const float* a, uint32_t m, uint32_t n, bool rowMajor) { - String8 str; - str.append("["); - for (size_t i = 0; i < m; i++) { - if (i) { - str.append(","); - } - str.append(" ["); - for (size_t j = 0; j < n; j++) { - if (j) { - str.append(","); - } - str.appendFormat(" %f", a[rowMajor ? i * n + j : j * m + i]); - } - str.append(" ]"); - } - str.append(" ]"); - return str; -} -#endif - -VelocityTracker::VelocityTracker() { - clear(); -} - -void VelocityTracker::clear() { - mIndex = 0; - mMovements[0].idBits.clear(); - mActivePointerId = -1; -} - -void VelocityTracker::clearPointers(BitSet32 idBits) { - BitSet32 remainingIdBits(mMovements[mIndex].idBits.value & ~idBits.value); - mMovements[mIndex].idBits = remainingIdBits; - - if (mActivePointerId >= 0 && idBits.hasBit(mActivePointerId)) { - mActivePointerId = !remainingIdBits.isEmpty() ? remainingIdBits.firstMarkedBit() : -1; - } -} - -void VelocityTracker::addMovement(nsecs_t eventTime, BitSet32 idBits, const Position* positions) { - if (++mIndex == HISTORY_SIZE) { - mIndex = 0; - } - - while (idBits.count() > MAX_POINTERS) { - idBits.clearLastMarkedBit(); - } - - Movement& movement = mMovements[mIndex]; - movement.eventTime = eventTime; - movement.idBits = idBits; - uint32_t count = idBits.count(); - for (uint32_t i = 0; i < count; i++) { - movement.positions[i] = positions[i]; - } - - if (mActivePointerId < 0 || !idBits.hasBit(mActivePointerId)) { - mActivePointerId = count != 0 ? idBits.firstMarkedBit() : -1; - } - -#if DEBUG_VELOCITY - ALOGD("VelocityTracker: addMovement eventTime=%lld, idBits=0x%08x, activePointerId=%d", - eventTime, idBits.value, mActivePointerId); - for (BitSet32 iterBits(idBits); !iterBits.isEmpty(); ) { - uint32_t id = iterBits.firstMarkedBit(); - uint32_t index = idBits.getIndexOfBit(id); - iterBits.clearBit(id); - Estimator estimator; - getEstimator(id, DEFAULT_DEGREE, DEFAULT_HORIZON, &estimator); - ALOGD(" %d: position (%0.3f, %0.3f), " - "estimator (degree=%d, xCoeff=%s, yCoeff=%s, confidence=%f)", - id, positions[index].x, positions[index].y, - int(estimator.degree), - vectorToString(estimator.xCoeff, estimator.degree).string(), - vectorToString(estimator.yCoeff, estimator.degree).string(), - estimator.confidence); - } -#endif -} - -void VelocityTracker::addMovement(const MotionEvent* event) { - int32_t actionMasked = event->getActionMasked(); - - switch (actionMasked) { - case AMOTION_EVENT_ACTION_DOWN: - case AMOTION_EVENT_ACTION_HOVER_ENTER: - // Clear all pointers on down before adding the new movement. - clear(); - break; - case AMOTION_EVENT_ACTION_POINTER_DOWN: { - // Start a new movement trace for a pointer that just went down. - // We do this on down instead of on up because the client may want to query the - // final velocity for a pointer that just went up. - BitSet32 downIdBits; - downIdBits.markBit(event->getPointerId(event->getActionIndex())); - clearPointers(downIdBits); - break; - } - case AMOTION_EVENT_ACTION_MOVE: - case AMOTION_EVENT_ACTION_HOVER_MOVE: - break; - default: - // Ignore all other actions because they do not convey any new information about - // pointer movement. We also want to preserve the last known velocity of the pointers. - // Note that ACTION_UP and ACTION_POINTER_UP always report the last known position - // of the pointers that went up. ACTION_POINTER_UP does include the new position of - // pointers that remained down but we will also receive an ACTION_MOVE with this - // information if any of them actually moved. Since we don't know how many pointers - // will be going up at once it makes sense to just wait for the following ACTION_MOVE - // before adding the movement. - return; - } - - size_t pointerCount = event->getPointerCount(); - if (pointerCount > MAX_POINTERS) { - pointerCount = MAX_POINTERS; - } - - BitSet32 idBits; - for (size_t i = 0; i < pointerCount; i++) { - idBits.markBit(event->getPointerId(i)); - } - - nsecs_t eventTime; - Position positions[pointerCount]; - - size_t historySize = event->getHistorySize(); - for (size_t h = 0; h < historySize; h++) { - eventTime = event->getHistoricalEventTime(h); - for (size_t i = 0; i < pointerCount; i++) { - positions[i].x = event->getHistoricalX(i, h); - positions[i].y = event->getHistoricalY(i, h); - } - addMovement(eventTime, idBits, positions); - } - - eventTime = event->getEventTime(); - for (size_t i = 0; i < pointerCount; i++) { - positions[i].x = event->getX(i); - positions[i].y = event->getY(i); - } - addMovement(eventTime, idBits, positions); -} - -/** - * Solves a linear least squares problem to obtain a N degree polynomial that fits - * the specified input data as nearly as possible. - * - * Returns true if a solution is found, false otherwise. - * - * The input consists of two vectors of data points X and Y with indices 0..m-1. - * The output is a vector B with indices 0..n-1 that describes a polynomial - * that fits the data, such the sum of abs(Y[i] - (B[0] + B[1] X[i] + B[2] X[i]^2 ... B[n] X[i]^n)) - * for all i between 0 and m-1 is minimized. - * - * That is to say, the function that generated the input data can be approximated - * by y(x) ~= B[0] + B[1] x + B[2] x^2 + ... + B[n] x^n. - * - * The coefficient of determination (R^2) is also returned to describe the goodness - * of fit of the model for the given data. It is a value between 0 and 1, where 1 - * indicates perfect correspondence. - * - * This function first expands the X vector to a m by n matrix A such that - * A[i][0] = 1, A[i][1] = X[i], A[i][2] = X[i]^2, ..., A[i][n] = X[i]^n. - * - * Then it calculates the QR decomposition of A yielding an m by m orthonormal matrix Q - * and an m by n upper triangular matrix R. Because R is upper triangular (lower - * part is all zeroes), we can simplify the decomposition into an m by n matrix - * Q1 and a n by n matrix R1 such that A = Q1 R1. - * - * Finally we solve the system of linear equations given by R1 B = (Qtranspose Y) - * to find B. - * - * For efficiency, we lay out A and Q column-wise in memory because we frequently - * operate on the column vectors. Conversely, we lay out R row-wise. - * - * http://en.wikipedia.org/wiki/Numerical_methods_for_linear_least_squares - * http://en.wikipedia.org/wiki/Gram-Schmidt - */ -static bool solveLeastSquares(const float* x, const float* y, uint32_t m, uint32_t n, - float* outB, float* outDet) { -#if DEBUG_LEAST_SQUARES - ALOGD("solveLeastSquares: m=%d, n=%d, x=%s, y=%s", int(m), int(n), - vectorToString(x, m).string(), vectorToString(y, m).string()); -#endif - - // Expand the X vector to a matrix A. - float a[n][m]; // column-major order - for (uint32_t h = 0; h < m; h++) { - a[0][h] = 1; - for (uint32_t i = 1; i < n; i++) { - a[i][h] = a[i - 1][h] * x[h]; - } - } -#if DEBUG_LEAST_SQUARES - ALOGD(" - a=%s", matrixToString(&a[0][0], m, n, false /*rowMajor*/).string()); -#endif - - // Apply the Gram-Schmidt process to A to obtain its QR decomposition. - float q[n][m]; // orthonormal basis, column-major order - float r[n][n]; // upper triangular matrix, row-major order - for (uint32_t j = 0; j < n; j++) { - for (uint32_t h = 0; h < m; h++) { - q[j][h] = a[j][h]; - } - for (uint32_t i = 0; i < j; i++) { - float dot = vectorDot(&q[j][0], &q[i][0], m); - for (uint32_t h = 0; h < m; h++) { - q[j][h] -= dot * q[i][h]; - } - } - - float norm = vectorNorm(&q[j][0], m); - if (norm < 0.000001f) { - // vectors are linearly dependent or zero so no solution -#if DEBUG_LEAST_SQUARES - ALOGD(" - no solution, norm=%f", norm); -#endif - return false; - } - - float invNorm = 1.0f / norm; - for (uint32_t h = 0; h < m; h++) { - q[j][h] *= invNorm; - } - for (uint32_t i = 0; i < n; i++) { - r[j][i] = i < j ? 0 : vectorDot(&q[j][0], &a[i][0], m); - } - } -#if DEBUG_LEAST_SQUARES - ALOGD(" - q=%s", matrixToString(&q[0][0], m, n, false /*rowMajor*/).string()); - ALOGD(" - r=%s", matrixToString(&r[0][0], n, n, true /*rowMajor*/).string()); - - // calculate QR, if we factored A correctly then QR should equal A - float qr[n][m]; - for (uint32_t h = 0; h < m; h++) { - for (uint32_t i = 0; i < n; i++) { - qr[i][h] = 0; - for (uint32_t j = 0; j < n; j++) { - qr[i][h] += q[j][h] * r[j][i]; - } - } - } - ALOGD(" - qr=%s", matrixToString(&qr[0][0], m, n, false /*rowMajor*/).string()); -#endif - - // Solve R B = Qt Y to find B. This is easy because R is upper triangular. - // We just work from bottom-right to top-left calculating B's coefficients. - for (uint32_t i = n; i-- != 0; ) { - outB[i] = vectorDot(&q[i][0], y, m); - for (uint32_t j = n - 1; j > i; j--) { - outB[i] -= r[i][j] * outB[j]; - } - outB[i] /= r[i][i]; - } -#if DEBUG_LEAST_SQUARES - ALOGD(" - b=%s", vectorToString(outB, n).string()); -#endif - - // Calculate the coefficient of determination as 1 - (SSerr / SStot) where - // SSerr is the residual sum of squares (squared variance of the error), - // and SStot is the total sum of squares (squared variance of the data). - float ymean = 0; - for (uint32_t h = 0; h < m; h++) { - ymean += y[h]; - } - ymean /= m; - - float sserr = 0; - float sstot = 0; - for (uint32_t h = 0; h < m; h++) { - float err = y[h] - outB[0]; - float term = 1; - for (uint32_t i = 1; i < n; i++) { - term *= x[h]; - err -= term * outB[i]; - } - sserr += err * err; - float var = y[h] - ymean; - sstot += var * var; - } - *outDet = sstot > 0.000001f ? 1.0f - (sserr / sstot) : 1; -#if DEBUG_LEAST_SQUARES - ALOGD(" - sserr=%f", sserr); - ALOGD(" - sstot=%f", sstot); - ALOGD(" - det=%f", *outDet); -#endif - return true; -} - -bool VelocityTracker::getVelocity(uint32_t id, float* outVx, float* outVy) const { - Estimator estimator; - if (getEstimator(id, DEFAULT_DEGREE, DEFAULT_HORIZON, &estimator)) { - if (estimator.degree >= 1) { - *outVx = estimator.xCoeff[1]; - *outVy = estimator.yCoeff[1]; - return true; - } - } - *outVx = 0; - *outVy = 0; - return false; -} - -bool VelocityTracker::getEstimator(uint32_t id, uint32_t degree, nsecs_t horizon, - Estimator* outEstimator) const { - outEstimator->clear(); - - // Iterate over movement samples in reverse time order and collect samples. - float x[HISTORY_SIZE]; - float y[HISTORY_SIZE]; - float time[HISTORY_SIZE]; - uint32_t m = 0; - uint32_t index = mIndex; - const Movement& newestMovement = mMovements[mIndex]; - do { - const Movement& movement = mMovements[index]; - if (!movement.idBits.hasBit(id)) { - break; - } - - nsecs_t age = newestMovement.eventTime - movement.eventTime; - if (age > horizon) { - break; - } - - const Position& position = movement.getPosition(id); - x[m] = position.x; - y[m] = position.y; - time[m] = -age * 0.000000001f; - index = (index == 0 ? HISTORY_SIZE : index) - 1; - } while (++m < HISTORY_SIZE); - - if (m == 0) { - return false; // no data - } - - // Calculate a least squares polynomial fit. - if (degree > Estimator::MAX_DEGREE) { - degree = Estimator::MAX_DEGREE; - } - if (degree > m - 1) { - degree = m - 1; - } - if (degree >= 1) { - float xdet, ydet; - uint32_t n = degree + 1; - if (solveLeastSquares(time, x, m, n, outEstimator->xCoeff, &xdet) - && solveLeastSquares(time, y, m, n, outEstimator->yCoeff, &ydet)) { - outEstimator->degree = degree; - outEstimator->confidence = xdet * ydet; -#if DEBUG_LEAST_SQUARES - ALOGD("estimate: degree=%d, xCoeff=%s, yCoeff=%s, confidence=%f", - int(outEstimator->degree), - vectorToString(outEstimator->xCoeff, n).string(), - vectorToString(outEstimator->yCoeff, n).string(), - outEstimator->confidence); -#endif - return true; - } - } - - // No velocity data available for this pointer, but we do have its current position. - outEstimator->xCoeff[0] = x[0]; - outEstimator->yCoeff[0] = y[0]; - outEstimator->degree = 0; - outEstimator->confidence = 1; - return true; -} - - -// --- VelocityControl --- - -const nsecs_t VelocityControl::STOP_TIME; - -VelocityControl::VelocityControl() { - reset(); -} - -void VelocityControl::setParameters(const VelocityControlParameters& parameters) { - mParameters = parameters; - reset(); -} - -void VelocityControl::reset() { - mLastMovementTime = LLONG_MIN; - mRawPosition.x = 0; - mRawPosition.y = 0; - mVelocityTracker.clear(); -} - -void VelocityControl::move(nsecs_t eventTime, float* deltaX, float* deltaY) { - if ((deltaX && *deltaX) || (deltaY && *deltaY)) { - if (eventTime >= mLastMovementTime + STOP_TIME) { -#if DEBUG_ACCELERATION - ALOGD("VelocityControl: stopped, last movement was %0.3fms ago", - (eventTime - mLastMovementTime) * 0.000001f); -#endif - reset(); - } - - mLastMovementTime = eventTime; - if (deltaX) { - mRawPosition.x += *deltaX; - } - if (deltaY) { - mRawPosition.y += *deltaY; - } - mVelocityTracker.addMovement(eventTime, BitSet32(BitSet32::valueForBit(0)), &mRawPosition); - - float vx, vy; - float scale = mParameters.scale; - if (mVelocityTracker.getVelocity(0, &vx, &vy)) { - float speed = hypotf(vx, vy) * scale; - if (speed >= mParameters.highThreshold) { - // Apply full acceleration above the high speed threshold. - scale *= mParameters.acceleration; - } else if (speed > mParameters.lowThreshold) { - // Linearly interpolate the acceleration to apply between the low and high - // speed thresholds. - scale *= 1 + (speed - mParameters.lowThreshold) - / (mParameters.highThreshold - mParameters.lowThreshold) - * (mParameters.acceleration - 1); - } - -#if DEBUG_ACCELERATION - ALOGD("VelocityControl(%0.3f, %0.3f, %0.3f, %0.3f): " - "vx=%0.3f, vy=%0.3f, speed=%0.3f, accel=%0.3f", - mParameters.scale, mParameters.lowThreshold, mParameters.highThreshold, - mParameters.acceleration, - vx, vy, speed, scale / mParameters.scale); -#endif - } else { -#if DEBUG_ACCELERATION - ALOGD("VelocityControl(%0.3f, %0.3f, %0.3f, %0.3f): unknown velocity", - mParameters.scale, mParameters.lowThreshold, mParameters.highThreshold, - mParameters.acceleration); -#endif - } - - if (deltaX) { - *deltaX *= scale; - } - if (deltaY) { - *deltaY *= scale; - } - } -} - - -// --- InputDeviceInfo --- - -InputDeviceInfo::InputDeviceInfo() { - initialize(-1, String8("uninitialized device info")); -} - -InputDeviceInfo::InputDeviceInfo(const InputDeviceInfo& other) : - mId(other.mId), mName(other.mName), mSources(other.mSources), - mKeyboardType(other.mKeyboardType), - mMotionRanges(other.mMotionRanges) { -} - -InputDeviceInfo::~InputDeviceInfo() { -} - -void InputDeviceInfo::initialize(int32_t id, const String8& name) { - mId = id; - mName = name; - mSources = 0; - mKeyboardType = AINPUT_KEYBOARD_TYPE_NONE; - mMotionRanges.clear(); -} - -const InputDeviceInfo::MotionRange* InputDeviceInfo::getMotionRange( - int32_t axis, uint32_t source) const { - size_t numRanges = mMotionRanges.size(); - for (size_t i = 0; i < numRanges; i++) { - const MotionRange& range = mMotionRanges.itemAt(i); - if (range.axis == axis && range.source == source) { - return ⦥ - } - } - return NULL; -} - -void InputDeviceInfo::addSource(uint32_t source) { - mSources |= source; -} - -void InputDeviceInfo::addMotionRange(int32_t axis, uint32_t source, float min, float max, - float flat, float fuzz) { - MotionRange range = { axis, source, min, max, flat, fuzz }; - mMotionRanges.add(range); -} - -void InputDeviceInfo::addMotionRange(const MotionRange& range) { - mMotionRanges.add(range); -} - -} // namespace android diff --git a/libs/ui/InputTransport.cpp b/libs/ui/InputTransport.cpp deleted file mode 100644 index 1ebd75c..0000000 --- a/libs/ui/InputTransport.cpp +++ /dev/null @@ -1,611 +0,0 @@ -// -// Copyright 2010 The Android Open Source Project -// -// Provides a shared memory transport for input events. -// -#define LOG_TAG "InputTransport" - -//#define LOG_NDEBUG 0 - -// Log debug messages about channel messages (send message, receive message) -#define DEBUG_CHANNEL_MESSAGES 0 - -// Log debug messages whenever InputChannel objects are created/destroyed -#define DEBUG_CHANNEL_LIFECYCLE 0 - -// Log debug messages about transport actions -#define DEBUG_TRANSPORT_ACTIONS 0 - - -#include <cutils/log.h> -#include <errno.h> -#include <fcntl.h> -#include <androidfw/InputTransport.h> -#include <unistd.h> -#include <sys/types.h> -#include <sys/socket.h> - - -namespace android { - -// Socket buffer size. The default is typically about 128KB, which is much larger than -// we really need. So we make it smaller. It just needs to be big enough to hold -// a few dozen large multi-finger motion events in the case where an application gets -// behind processing touches. -static const size_t SOCKET_BUFFER_SIZE = 32 * 1024; - - -// --- InputMessage --- - -bool InputMessage::isValid(size_t actualSize) const { - if (size() == actualSize) { - switch (header.type) { - case TYPE_KEY: - return true; - case TYPE_MOTION: - return body.motion.pointerCount > 0 - && body.motion.pointerCount <= MAX_POINTERS; - case TYPE_FINISHED: - return true; - } - } - return false; -} - -size_t InputMessage::size() const { - switch (header.type) { - case TYPE_KEY: - return sizeof(Header) + body.key.size(); - case TYPE_MOTION: - return sizeof(Header) + body.motion.size(); - case TYPE_FINISHED: - return sizeof(Header) + body.finished.size(); - } - return sizeof(Header); -} - - -// --- InputChannel --- - -InputChannel::InputChannel(const String8& name, int fd) : - mName(name), mFd(fd) { -#if DEBUG_CHANNEL_LIFECYCLE - ALOGD("Input channel constructed: name='%s', fd=%d", - mName.string(), fd); -#endif - - int result = fcntl(mFd, F_SETFL, O_NONBLOCK); - LOG_ALWAYS_FATAL_IF(result != 0, "channel '%s' ~ Could not make socket " - "non-blocking. errno=%d", mName.string(), errno); -} - -InputChannel::~InputChannel() { -#if DEBUG_CHANNEL_LIFECYCLE - ALOGD("Input channel destroyed: name='%s', fd=%d", - mName.string(), mFd); -#endif - - ::close(mFd); -} - -status_t InputChannel::openInputChannelPair(const String8& name, - sp<InputChannel>& outServerChannel, sp<InputChannel>& outClientChannel) { - int sockets[2]; - if (socketpair(AF_UNIX, SOCK_SEQPACKET, 0, sockets)) { - status_t result = -errno; - ALOGE("channel '%s' ~ Could not create socket pair. errno=%d", - name.string(), errno); - outServerChannel.clear(); - outClientChannel.clear(); - return result; - } - - int bufferSize = SOCKET_BUFFER_SIZE; - setsockopt(sockets[0], SOL_SOCKET, SO_SNDBUF, &bufferSize, sizeof(bufferSize)); - setsockopt(sockets[0], SOL_SOCKET, SO_RCVBUF, &bufferSize, sizeof(bufferSize)); - setsockopt(sockets[1], SOL_SOCKET, SO_SNDBUF, &bufferSize, sizeof(bufferSize)); - setsockopt(sockets[1], SOL_SOCKET, SO_RCVBUF, &bufferSize, sizeof(bufferSize)); - - String8 serverChannelName = name; - serverChannelName.append(" (server)"); - outServerChannel = new InputChannel(serverChannelName, sockets[0]); - - String8 clientChannelName = name; - clientChannelName.append(" (client)"); - outClientChannel = new InputChannel(clientChannelName, sockets[1]); - return OK; -} - -status_t InputChannel::sendMessage(const InputMessage* msg) { - size_t msgLength = msg->size(); - ssize_t nWrite; - do { - nWrite = ::send(mFd, msg, msgLength, MSG_DONTWAIT | MSG_NOSIGNAL); - } while (nWrite == -1 && errno == EINTR); - - if (nWrite < 0) { - int error = errno; -#if DEBUG_CHANNEL_MESSAGES - ALOGD("channel '%s' ~ error sending message of type %d, errno=%d", mName.string(), - msg->header.type, error); -#endif - if (error == EAGAIN || error == EWOULDBLOCK) { - return WOULD_BLOCK; - } - if (error == EPIPE || error == ENOTCONN) { - return DEAD_OBJECT; - } - return -error; - } - - if (size_t(nWrite) != msgLength) { -#if DEBUG_CHANNEL_MESSAGES - ALOGD("channel '%s' ~ error sending message type %d, send was incomplete", - mName.string(), msg->header.type); -#endif - return DEAD_OBJECT; - } - -#if DEBUG_CHANNEL_MESSAGES - ALOGD("channel '%s' ~ sent message of type %d", mName.string(), msg->header.type); -#endif - return OK; -} - -status_t InputChannel::receiveMessage(InputMessage* msg) { - ssize_t nRead; - do { - nRead = ::recv(mFd, msg, sizeof(InputMessage), MSG_DONTWAIT); - } while (nRead == -1 && errno == EINTR); - - if (nRead < 0) { - int error = errno; -#if DEBUG_CHANNEL_MESSAGES - ALOGD("channel '%s' ~ receive message failed, errno=%d", mName.string(), errno); -#endif - if (error == EAGAIN || error == EWOULDBLOCK) { - return WOULD_BLOCK; - } - if (error == EPIPE || error == ENOTCONN) { - return DEAD_OBJECT; - } - return -error; - } - - if (nRead == 0) { // check for EOF -#if DEBUG_CHANNEL_MESSAGES - ALOGD("channel '%s' ~ receive message failed because peer was closed", mName.string()); -#endif - return DEAD_OBJECT; - } - - if (!msg->isValid(nRead)) { -#if DEBUG_CHANNEL_MESSAGES - ALOGD("channel '%s' ~ received invalid message", mName.string()); -#endif - return BAD_VALUE; - } - -#if DEBUG_CHANNEL_MESSAGES - ALOGD("channel '%s' ~ received message of type %d", mName.string(), msg->header.type); -#endif - return OK; -} - - -// --- InputPublisher --- - -InputPublisher::InputPublisher(const sp<InputChannel>& channel) : - mChannel(channel) { -} - -InputPublisher::~InputPublisher() { -} - -status_t InputPublisher::publishKeyEvent( - uint32_t seq, - int32_t deviceId, - int32_t source, - int32_t action, - int32_t flags, - int32_t keyCode, - int32_t scanCode, - int32_t metaState, - int32_t repeatCount, - nsecs_t downTime, - nsecs_t eventTime) { -#if DEBUG_TRANSPORT_ACTIONS - ALOGD("channel '%s' publisher ~ publishKeyEvent: seq=%u, deviceId=%d, source=0x%x, " - "action=0x%x, flags=0x%x, keyCode=%d, scanCode=%d, metaState=0x%x, repeatCount=%d," - "downTime=%lld, eventTime=%lld", - mChannel->getName().string(), seq, - deviceId, source, action, flags, keyCode, scanCode, metaState, repeatCount, - downTime, eventTime); -#endif - - if (!seq) { - ALOGE("Attempted to publish a key event with sequence number 0."); - return BAD_VALUE; - } - - InputMessage msg; - msg.header.type = InputMessage::TYPE_KEY; - msg.body.key.seq = seq; - msg.body.key.deviceId = deviceId; - msg.body.key.source = source; - msg.body.key.action = action; - msg.body.key.flags = flags; - msg.body.key.keyCode = keyCode; - msg.body.key.scanCode = scanCode; - msg.body.key.metaState = metaState; - msg.body.key.repeatCount = repeatCount; - msg.body.key.downTime = downTime; - msg.body.key.eventTime = eventTime; - return mChannel->sendMessage(&msg); -} - -status_t InputPublisher::publishMotionEvent( - uint32_t seq, - int32_t deviceId, - int32_t source, - int32_t action, - int32_t flags, - int32_t edgeFlags, - int32_t metaState, - int32_t buttonState, - float xOffset, - float yOffset, - float xPrecision, - float yPrecision, - nsecs_t downTime, - nsecs_t eventTime, - size_t pointerCount, - const PointerProperties* pointerProperties, - const PointerCoords* pointerCoords) { -#if DEBUG_TRANSPORT_ACTIONS - ALOGD("channel '%s' publisher ~ publishMotionEvent: seq=%u, deviceId=%d, source=0x%x, " - "action=0x%x, flags=0x%x, edgeFlags=0x%x, metaState=0x%x, buttonState=0x%x, " - "xOffset=%f, yOffset=%f, " - "xPrecision=%f, yPrecision=%f, downTime=%lld, eventTime=%lld, " - "pointerCount=%d", - mChannel->getName().string(), seq, - deviceId, source, action, flags, edgeFlags, metaState, buttonState, - xOffset, yOffset, xPrecision, yPrecision, downTime, eventTime, pointerCount); -#endif - - if (!seq) { - ALOGE("Attempted to publish a motion event with sequence number 0."); - return BAD_VALUE; - } - - if (pointerCount > MAX_POINTERS || pointerCount < 1) { - ALOGE("channel '%s' publisher ~ Invalid number of pointers provided: %d.", - mChannel->getName().string(), pointerCount); - return BAD_VALUE; - } - - InputMessage msg; - msg.header.type = InputMessage::TYPE_MOTION; - msg.body.motion.seq = seq; - msg.body.motion.deviceId = deviceId; - msg.body.motion.source = source; - msg.body.motion.action = action; - msg.body.motion.flags = flags; - msg.body.motion.edgeFlags = edgeFlags; - msg.body.motion.metaState = metaState; - msg.body.motion.buttonState = buttonState; - msg.body.motion.xOffset = xOffset; - msg.body.motion.yOffset = yOffset; - msg.body.motion.xPrecision = xPrecision; - msg.body.motion.yPrecision = yPrecision; - msg.body.motion.downTime = downTime; - msg.body.motion.eventTime = eventTime; - msg.body.motion.pointerCount = pointerCount; - for (size_t i = 0; i < pointerCount; i++) { - msg.body.motion.pointers[i].properties.copyFrom(pointerProperties[i]); - msg.body.motion.pointers[i].coords.copyFrom(pointerCoords[i]); - } - return mChannel->sendMessage(&msg); -} - -status_t InputPublisher::receiveFinishedSignal(uint32_t* outSeq, bool* outHandled) { -#if DEBUG_TRANSPORT_ACTIONS - ALOGD("channel '%s' publisher ~ receiveFinishedSignal", - mChannel->getName().string()); -#endif - - InputMessage msg; - status_t result = mChannel->receiveMessage(&msg); - if (result) { - *outSeq = 0; - *outHandled = false; - return result; - } - if (msg.header.type != InputMessage::TYPE_FINISHED) { - ALOGE("channel '%s' publisher ~ Received unexpected message of type %d from consumer", - mChannel->getName().string(), msg.header.type); - return UNKNOWN_ERROR; - } - *outSeq = msg.body.finished.seq; - *outHandled = msg.body.finished.handled; - return OK; -} - -// --- InputConsumer --- - -InputConsumer::InputConsumer(const sp<InputChannel>& channel) : - mChannel(channel), mMsgDeferred(false) { -} - -InputConsumer::~InputConsumer() { -} - -status_t InputConsumer::consume(InputEventFactoryInterface* factory, - bool consumeBatches, uint32_t* outSeq, InputEvent** outEvent) { -#if DEBUG_TRANSPORT_ACTIONS - ALOGD("channel '%s' consumer ~ consume: consumeBatches=%s", - mChannel->getName().string(), consumeBatches ? "true" : "false"); -#endif - - *outSeq = 0; - *outEvent = NULL; - - // Fetch the next input message. - // Loop until an event can be returned or no additional events are received. - while (!*outEvent) { - if (mMsgDeferred) { - // mMsg contains a valid input message from the previous call to consume - // that has not yet been processed. - mMsgDeferred = false; - } else { - // Receive a fresh message. - status_t result = mChannel->receiveMessage(&mMsg); - if (result) { - // Consume the next batched event unless batches are being held for later. - if (!mBatches.isEmpty() && (consumeBatches || result != WOULD_BLOCK)) { - MotionEvent* motionEvent = factory->createMotionEvent(); - if (! motionEvent) return NO_MEMORY; - - const Batch& batch = mBatches.top(); - motionEvent->copyFrom(&batch.event, true /*keepHistory*/); - *outSeq = batch.seq; - *outEvent = motionEvent; - mBatches.pop(); -#if DEBUG_TRANSPORT_ACTIONS - ALOGD("channel '%s' consumer ~ consumed batch event, seq=%u", - mChannel->getName().string(), *outSeq); -#endif - break; - } - return result; - } - } - - switch (mMsg.header.type) { - case InputMessage::TYPE_KEY: { - KeyEvent* keyEvent = factory->createKeyEvent(); - if (!keyEvent) return NO_MEMORY; - - initializeKeyEvent(keyEvent, &mMsg); - *outSeq = mMsg.body.key.seq; - *outEvent = keyEvent; -#if DEBUG_TRANSPORT_ACTIONS - ALOGD("channel '%s' consumer ~ consumed key event, seq=%u", - mChannel->getName().string(), *outSeq); -#endif - break; - } - - case AINPUT_EVENT_TYPE_MOTION: { - ssize_t batchIndex = findBatch(mMsg.body.motion.deviceId, mMsg.body.motion.source); - if (batchIndex >= 0) { - Batch& batch = mBatches.editItemAt(batchIndex); - if (canAppendSamples(&batch.event, &mMsg)) { - // Append to the batch and save the new sequence number for the tail end. - uint32_t chain = batch.seq; - appendSamples(&batch.event, &mMsg); - batch.seq = mMsg.body.motion.seq; - - // Update the sequence number chain. - SeqChain seqChain; - seqChain.seq = batch.seq; - seqChain.chain = chain; - mSeqChains.push(seqChain); -#if DEBUG_TRANSPORT_ACTIONS - ALOGD("channel '%s' consumer ~ appended to batch event", - mChannel->getName().string()); -#endif - break; - } else { - MotionEvent* motionEvent = factory->createMotionEvent(); - if (! motionEvent) return NO_MEMORY; - - // We cannot append to the batch in progress, so we need to consume - // the previous batch right now and defer the new message until later. - mMsgDeferred = true; - - // Return the end of the previous batch. - motionEvent->copyFrom(&batch.event, true /*keepHistory*/); - *outSeq = batch.seq; - *outEvent = motionEvent; - mBatches.removeAt(batchIndex); -#if DEBUG_TRANSPORT_ACTIONS - ALOGD("channel '%s' consumer ~ consumed batch event and " - "deferred current event, seq=%u", - mChannel->getName().string(), *outSeq); -#endif - break; - } - } - - // Start a new batch if needed. - if (mMsg.body.motion.action == AMOTION_EVENT_ACTION_MOVE - || mMsg.body.motion.action == AMOTION_EVENT_ACTION_HOVER_MOVE) { - mBatches.push(); - Batch& batch = mBatches.editTop(); - batch.seq = mMsg.body.motion.seq; - initializeMotionEvent(&batch.event, &mMsg); -#if DEBUG_TRANSPORT_ACTIONS - ALOGD("channel '%s' consumer ~ started batch event", - mChannel->getName().string()); -#endif - break; - } - - MotionEvent* motionEvent = factory->createMotionEvent(); - if (! motionEvent) return NO_MEMORY; - - initializeMotionEvent(motionEvent, &mMsg); - *outSeq = mMsg.body.motion.seq; - *outEvent = motionEvent; -#if DEBUG_TRANSPORT_ACTIONS - ALOGD("channel '%s' consumer ~ consumed motion event, seq=%u", - mChannel->getName().string(), *outSeq); -#endif - break; - } - - default: - ALOGE("channel '%s' consumer ~ Received unexpected message of type %d", - mChannel->getName().string(), mMsg.header.type); - return UNKNOWN_ERROR; - } - } - return OK; -} - -status_t InputConsumer::sendFinishedSignal(uint32_t seq, bool handled) { -#if DEBUG_TRANSPORT_ACTIONS - ALOGD("channel '%s' consumer ~ sendFinishedSignal: seq=%u, handled=%s", - mChannel->getName().string(), seq, handled ? "true" : "false"); -#endif - - if (!seq) { - ALOGE("Attempted to send a finished signal with sequence number 0."); - return BAD_VALUE; - } - - // Send finished signals for the batch sequence chain first. - size_t seqChainCount = mSeqChains.size(); - if (seqChainCount) { - uint32_t currentSeq = seq; - uint32_t chainSeqs[seqChainCount]; - size_t chainIndex = 0; - for (size_t i = seqChainCount; i-- > 0; ) { - const SeqChain& seqChain = mSeqChains.itemAt(i); - if (seqChain.seq == currentSeq) { - currentSeq = seqChain.chain; - chainSeqs[chainIndex++] = currentSeq; - mSeqChains.removeAt(i); - } - } - status_t status = OK; - while (!status && chainIndex-- > 0) { - status = sendUnchainedFinishedSignal(chainSeqs[chainIndex], handled); - } - if (status) { - // An error occurred so at least one signal was not sent, reconstruct the chain. - do { - SeqChain seqChain; - seqChain.seq = chainIndex != 0 ? chainSeqs[chainIndex - 1] : seq; - seqChain.chain = chainSeqs[chainIndex]; - mSeqChains.push(seqChain); - } while (chainIndex-- > 0); - return status; - } - } - - // Send finished signal for the last message in the batch. - return sendUnchainedFinishedSignal(seq, handled); -} - -status_t InputConsumer::sendUnchainedFinishedSignal(uint32_t seq, bool handled) { - InputMessage msg; - msg.header.type = InputMessage::TYPE_FINISHED; - msg.body.finished.seq = seq; - msg.body.finished.handled = handled; - return mChannel->sendMessage(&msg); -} - -bool InputConsumer::hasPendingBatch() const { - return !mBatches.isEmpty(); -} - -ssize_t InputConsumer::findBatch(int32_t deviceId, int32_t source) const { - for (size_t i = 0; i < mBatches.size(); i++) { - const Batch& batch = mBatches.itemAt(i); - if (batch.event.getDeviceId() == deviceId && batch.event.getSource() == source) { - return i; - } - } - return -1; -} - -void InputConsumer::initializeKeyEvent(KeyEvent* event, const InputMessage* msg) { - event->initialize( - msg->body.key.deviceId, - msg->body.key.source, - msg->body.key.action, - msg->body.key.flags, - msg->body.key.keyCode, - msg->body.key.scanCode, - msg->body.key.metaState, - msg->body.key.repeatCount, - msg->body.key.downTime, - msg->body.key.eventTime); -} - -void InputConsumer::initializeMotionEvent(MotionEvent* event, const InputMessage* msg) { - size_t pointerCount = msg->body.motion.pointerCount; - PointerProperties pointerProperties[pointerCount]; - PointerCoords pointerCoords[pointerCount]; - for (size_t i = 0; i < pointerCount; i++) { - pointerProperties[i].copyFrom(msg->body.motion.pointers[i].properties); - pointerCoords[i].copyFrom(msg->body.motion.pointers[i].coords); - } - - event->initialize( - msg->body.motion.deviceId, - msg->body.motion.source, - msg->body.motion.action, - msg->body.motion.flags, - msg->body.motion.edgeFlags, - msg->body.motion.metaState, - msg->body.motion.buttonState, - msg->body.motion.xOffset, - msg->body.motion.yOffset, - msg->body.motion.xPrecision, - msg->body.motion.yPrecision, - msg->body.motion.downTime, - msg->body.motion.eventTime, - pointerCount, - pointerProperties, - pointerCoords); -} - -bool InputConsumer::canAppendSamples(const MotionEvent* event, const InputMessage *msg) { - size_t pointerCount = msg->body.motion.pointerCount; - if (event->getPointerCount() != pointerCount - || event->getAction() != msg->body.motion.action) { - return false; - } - for (size_t i = 0; i < pointerCount; i++) { - if (*event->getPointerProperties(i) != msg->body.motion.pointers[i].properties) { - return false; - } - } - return true; -} - -void InputConsumer::appendSamples(MotionEvent* event, const InputMessage* msg) { - size_t pointerCount = msg->body.motion.pointerCount; - PointerCoords pointerCoords[pointerCount]; - for (size_t i = 0; i < pointerCount; i++) { - pointerCoords[i].copyFrom(msg->body.motion.pointers[i].coords); - } - - event->setMetaState(event->getMetaState() | msg->body.motion.metaState); - event->addSample(msg->body.motion.eventTime, pointerCoords); -} - -} // namespace android diff --git a/libs/ui/KeyCharacterMap.cpp b/libs/ui/KeyCharacterMap.cpp deleted file mode 100644 index 6984084..0000000 --- a/libs/ui/KeyCharacterMap.cpp +++ /dev/null @@ -1,838 +0,0 @@ -/* - * Copyright (C) 2008 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 "KeyCharacterMap" - -#include <stdlib.h> -#include <string.h> -#include <android/keycodes.h> -#include <androidfw/Keyboard.h> -#include <androidfw/KeyCharacterMap.h> -#include <utils/Log.h> -#include <utils/Errors.h> -#include <utils/Tokenizer.h> -#include <utils/Timers.h> - -// Enables debug output for the parser. -#define DEBUG_PARSER 0 - -// Enables debug output for parser performance. -#define DEBUG_PARSER_PERFORMANCE 0 - -// Enables debug output for mapping. -#define DEBUG_MAPPING 0 - - -namespace android { - -static const char* WHITESPACE = " \t\r"; -static const char* WHITESPACE_OR_PROPERTY_DELIMITER = " \t\r,:"; - -struct Modifier { - const char* label; - int32_t metaState; -}; -static const Modifier modifiers[] = { - { "shift", AMETA_SHIFT_ON }, - { "lshift", AMETA_SHIFT_LEFT_ON }, - { "rshift", AMETA_SHIFT_RIGHT_ON }, - { "alt", AMETA_ALT_ON }, - { "lalt", AMETA_ALT_LEFT_ON }, - { "ralt", AMETA_ALT_RIGHT_ON }, - { "ctrl", AMETA_CTRL_ON }, - { "lctrl", AMETA_CTRL_LEFT_ON }, - { "rctrl", AMETA_CTRL_RIGHT_ON }, - { "meta", AMETA_META_ON }, - { "lmeta", AMETA_META_LEFT_ON }, - { "rmeta", AMETA_META_RIGHT_ON }, - { "sym", AMETA_SYM_ON }, - { "fn", AMETA_FUNCTION_ON }, - { "capslock", AMETA_CAPS_LOCK_ON }, - { "numlock", AMETA_NUM_LOCK_ON }, - { "scrolllock", AMETA_SCROLL_LOCK_ON }, -}; - -#if DEBUG_MAPPING -static String8 toString(const char16_t* chars, size_t numChars) { - String8 result; - for (size_t i = 0; i < numChars; i++) { - result.appendFormat(i == 0 ? "%d" : ", %d", chars[i]); - } - return result; -} -#endif - - -// --- KeyCharacterMap --- - -KeyCharacterMap::KeyCharacterMap() : - mType(KEYBOARD_TYPE_UNKNOWN) { -} - -KeyCharacterMap::~KeyCharacterMap() { - for (size_t i = 0; i < mKeys.size(); i++) { - Key* key = mKeys.editValueAt(i); - delete key; - } -} - -status_t KeyCharacterMap::load(const String8& filename, KeyCharacterMap** outMap) { - *outMap = NULL; - - Tokenizer* tokenizer; - status_t status = Tokenizer::open(filename, &tokenizer); - if (status) { - ALOGE("Error %d opening key character map file %s.", status, filename.string()); - } else { - KeyCharacterMap* map = new KeyCharacterMap(); - if (!map) { - ALOGE("Error allocating key character map."); - status = NO_MEMORY; - } else { -#if DEBUG_PARSER_PERFORMANCE - nsecs_t startTime = systemTime(SYSTEM_TIME_MONOTONIC); -#endif - Parser parser(map, tokenizer); - status = parser.parse(); -#if DEBUG_PARSER_PERFORMANCE - nsecs_t elapsedTime = systemTime(SYSTEM_TIME_MONOTONIC) - startTime; - ALOGD("Parsed key character map file '%s' %d lines in %0.3fms.", - tokenizer->getFilename().string(), tokenizer->getLineNumber(), - elapsedTime / 1000000.0); -#endif - if (status) { - delete map; - } else { - *outMap = map; - } - } - delete tokenizer; - } - return status; -} - -int32_t KeyCharacterMap::getKeyboardType() const { - return mType; -} - -char16_t KeyCharacterMap::getDisplayLabel(int32_t keyCode) const { - char16_t result = 0; - const Key* key; - if (getKey(keyCode, &key)) { - result = key->label; - } -#if DEBUG_MAPPING - ALOGD("getDisplayLabel: keyCode=%d ~ Result %d.", keyCode, result); -#endif - return result; -} - -char16_t KeyCharacterMap::getNumber(int32_t keyCode) const { - char16_t result = 0; - const Key* key; - if (getKey(keyCode, &key)) { - result = key->number; - } -#if DEBUG_MAPPING - ALOGD("getNumber: keyCode=%d ~ Result %d.", keyCode, result); -#endif - return result; -} - -char16_t KeyCharacterMap::getCharacter(int32_t keyCode, int32_t metaState) const { - char16_t result = 0; - const Key* key; - const Behavior* behavior; - if (getKeyBehavior(keyCode, metaState, &key, &behavior)) { - result = behavior->character; - } -#if DEBUG_MAPPING - ALOGD("getCharacter: keyCode=%d, metaState=0x%08x ~ Result %d.", keyCode, metaState, result); -#endif - return result; -} - -bool KeyCharacterMap::getFallbackAction(int32_t keyCode, int32_t metaState, - FallbackAction* outFallbackAction) const { - outFallbackAction->keyCode = 0; - outFallbackAction->metaState = 0; - - bool result = false; - const Key* key; - const Behavior* behavior; - if (getKeyBehavior(keyCode, metaState, &key, &behavior)) { - if (behavior->fallbackKeyCode) { - outFallbackAction->keyCode = behavior->fallbackKeyCode; - outFallbackAction->metaState = metaState & ~behavior->metaState; - result = true; - } - } -#if DEBUG_MAPPING - ALOGD("getFallbackKeyCode: keyCode=%d, metaState=0x%08x ~ Result %s, " - "fallback keyCode=%d, fallback metaState=0x%08x.", - keyCode, metaState, result ? "true" : "false", - outFallbackAction->keyCode, outFallbackAction->metaState); -#endif - return result; -} - -char16_t KeyCharacterMap::getMatch(int32_t keyCode, const char16_t* chars, size_t numChars, - int32_t metaState) const { - char16_t result = 0; - const Key* key; - if (getKey(keyCode, &key)) { - // Try to find the most general behavior that maps to this character. - // For example, the base key behavior will usually be last in the list. - // However, if we find a perfect meta state match for one behavior then use that one. - for (const Behavior* behavior = key->firstBehavior; behavior; behavior = behavior->next) { - if (behavior->character) { - for (size_t i = 0; i < numChars; i++) { - if (behavior->character == chars[i]) { - result = behavior->character; - if ((behavior->metaState & metaState) == behavior->metaState) { - goto ExactMatch; - } - break; - } - } - } - } - ExactMatch: ; - } -#if DEBUG_MAPPING - ALOGD("getMatch: keyCode=%d, chars=[%s], metaState=0x%08x ~ Result %d.", - keyCode, toString(chars, numChars).string(), metaState, result); -#endif - return result; -} - -bool KeyCharacterMap::getEvents(int32_t deviceId, const char16_t* chars, size_t numChars, - Vector<KeyEvent>& outEvents) const { - nsecs_t now = systemTime(SYSTEM_TIME_MONOTONIC); - - for (size_t i = 0; i < numChars; i++) { - int32_t keyCode, metaState; - char16_t ch = chars[i]; - if (!findKey(ch, &keyCode, &metaState)) { -#if DEBUG_MAPPING - ALOGD("getEvents: deviceId=%d, chars=[%s] ~ Failed to find mapping for character %d.", - deviceId, toString(chars, numChars).string(), ch); -#endif - return false; - } - - int32_t currentMetaState = 0; - addMetaKeys(outEvents, deviceId, metaState, true, now, ¤tMetaState); - addKey(outEvents, deviceId, keyCode, currentMetaState, true, now); - addKey(outEvents, deviceId, keyCode, currentMetaState, false, now); - addMetaKeys(outEvents, deviceId, metaState, false, now, ¤tMetaState); - } -#if DEBUG_MAPPING - ALOGD("getEvents: deviceId=%d, chars=[%s] ~ Generated %d events.", - deviceId, toString(chars, numChars).string(), int32_t(outEvents.size())); - for (size_t i = 0; i < outEvents.size(); i++) { - ALOGD(" Key: keyCode=%d, metaState=0x%08x, %s.", - outEvents[i].getKeyCode(), outEvents[i].getMetaState(), - outEvents[i].getAction() == AKEY_EVENT_ACTION_DOWN ? "down" : "up"); - } -#endif - return true; -} - -bool KeyCharacterMap::getKey(int32_t keyCode, const Key** outKey) const { - ssize_t index = mKeys.indexOfKey(keyCode); - if (index >= 0) { - *outKey = mKeys.valueAt(index); - return true; - } - return false; -} - -bool KeyCharacterMap::getKeyBehavior(int32_t keyCode, int32_t metaState, - const Key** outKey, const Behavior** outBehavior) const { - const Key* key; - if (getKey(keyCode, &key)) { - const Behavior* behavior = key->firstBehavior; - while (behavior) { - if ((behavior->metaState & metaState) == behavior->metaState) { - *outKey = key; - *outBehavior = behavior; - return true; - } - behavior = behavior->next; - } - } - return false; -} - -bool KeyCharacterMap::findKey(char16_t ch, int32_t* outKeyCode, int32_t* outMetaState) const { - if (!ch) { - return false; - } - - for (size_t i = 0; i < mKeys.size(); i++) { - const Key* key = mKeys.valueAt(i); - - // Try to find the most general behavior that maps to this character. - // For example, the base key behavior will usually be last in the list. - const Behavior* found = NULL; - for (const Behavior* behavior = key->firstBehavior; behavior; behavior = behavior->next) { - if (behavior->character == ch) { - found = behavior; - } - } - if (found) { - *outKeyCode = mKeys.keyAt(i); - *outMetaState = found->metaState; - return true; - } - } - return false; -} - -void KeyCharacterMap::addKey(Vector<KeyEvent>& outEvents, - int32_t deviceId, int32_t keyCode, int32_t metaState, bool down, nsecs_t time) { - outEvents.push(); - KeyEvent& event = outEvents.editTop(); - event.initialize(deviceId, AINPUT_SOURCE_KEYBOARD, - down ? AKEY_EVENT_ACTION_DOWN : AKEY_EVENT_ACTION_UP, - 0, keyCode, 0, metaState, 0, time, time); -} - -void KeyCharacterMap::addMetaKeys(Vector<KeyEvent>& outEvents, - int32_t deviceId, int32_t metaState, bool down, nsecs_t time, - int32_t* currentMetaState) { - // Add and remove meta keys symmetrically. - if (down) { - addLockedMetaKey(outEvents, deviceId, metaState, time, - AKEYCODE_CAPS_LOCK, AMETA_CAPS_LOCK_ON, currentMetaState); - addLockedMetaKey(outEvents, deviceId, metaState, time, - AKEYCODE_NUM_LOCK, AMETA_NUM_LOCK_ON, currentMetaState); - addLockedMetaKey(outEvents, deviceId, metaState, time, - AKEYCODE_SCROLL_LOCK, AMETA_SCROLL_LOCK_ON, currentMetaState); - - addDoubleEphemeralMetaKey(outEvents, deviceId, metaState, true, time, - AKEYCODE_SHIFT_LEFT, AMETA_SHIFT_LEFT_ON, - AKEYCODE_SHIFT_RIGHT, AMETA_SHIFT_RIGHT_ON, - AMETA_SHIFT_ON, currentMetaState); - addDoubleEphemeralMetaKey(outEvents, deviceId, metaState, true, time, - AKEYCODE_ALT_LEFT, AMETA_ALT_LEFT_ON, - AKEYCODE_ALT_RIGHT, AMETA_ALT_RIGHT_ON, - AMETA_ALT_ON, currentMetaState); - addDoubleEphemeralMetaKey(outEvents, deviceId, metaState, true, time, - AKEYCODE_CTRL_LEFT, AMETA_CTRL_LEFT_ON, - AKEYCODE_CTRL_RIGHT, AMETA_CTRL_RIGHT_ON, - AMETA_CTRL_ON, currentMetaState); - addDoubleEphemeralMetaKey(outEvents, deviceId, metaState, true, time, - AKEYCODE_META_LEFT, AMETA_META_LEFT_ON, - AKEYCODE_META_RIGHT, AMETA_META_RIGHT_ON, - AMETA_META_ON, currentMetaState); - - addSingleEphemeralMetaKey(outEvents, deviceId, metaState, true, time, - AKEYCODE_SYM, AMETA_SYM_ON, currentMetaState); - addSingleEphemeralMetaKey(outEvents, deviceId, metaState, true, time, - AKEYCODE_FUNCTION, AMETA_FUNCTION_ON, currentMetaState); - } else { - addSingleEphemeralMetaKey(outEvents, deviceId, metaState, false, time, - AKEYCODE_FUNCTION, AMETA_FUNCTION_ON, currentMetaState); - addSingleEphemeralMetaKey(outEvents, deviceId, metaState, false, time, - AKEYCODE_SYM, AMETA_SYM_ON, currentMetaState); - - addDoubleEphemeralMetaKey(outEvents, deviceId, metaState, false, time, - AKEYCODE_META_LEFT, AMETA_META_LEFT_ON, - AKEYCODE_META_RIGHT, AMETA_META_RIGHT_ON, - AMETA_META_ON, currentMetaState); - addDoubleEphemeralMetaKey(outEvents, deviceId, metaState, false, time, - AKEYCODE_CTRL_LEFT, AMETA_CTRL_LEFT_ON, - AKEYCODE_CTRL_RIGHT, AMETA_CTRL_RIGHT_ON, - AMETA_CTRL_ON, currentMetaState); - addDoubleEphemeralMetaKey(outEvents, deviceId, metaState, false, time, - AKEYCODE_ALT_LEFT, AMETA_ALT_LEFT_ON, - AKEYCODE_ALT_RIGHT, AMETA_ALT_RIGHT_ON, - AMETA_ALT_ON, currentMetaState); - addDoubleEphemeralMetaKey(outEvents, deviceId, metaState, false, time, - AKEYCODE_SHIFT_LEFT, AMETA_SHIFT_LEFT_ON, - AKEYCODE_SHIFT_RIGHT, AMETA_SHIFT_RIGHT_ON, - AMETA_SHIFT_ON, currentMetaState); - - addLockedMetaKey(outEvents, deviceId, metaState, time, - AKEYCODE_SCROLL_LOCK, AMETA_SCROLL_LOCK_ON, currentMetaState); - addLockedMetaKey(outEvents, deviceId, metaState, time, - AKEYCODE_NUM_LOCK, AMETA_NUM_LOCK_ON, currentMetaState); - addLockedMetaKey(outEvents, deviceId, metaState, time, - AKEYCODE_CAPS_LOCK, AMETA_CAPS_LOCK_ON, currentMetaState); - } -} - -bool KeyCharacterMap::addSingleEphemeralMetaKey(Vector<KeyEvent>& outEvents, - int32_t deviceId, int32_t metaState, bool down, nsecs_t time, - int32_t keyCode, int32_t keyMetaState, - int32_t* currentMetaState) { - if ((metaState & keyMetaState) == keyMetaState) { - *currentMetaState = updateMetaState(keyCode, down, *currentMetaState); - addKey(outEvents, deviceId, keyCode, *currentMetaState, down, time); - return true; - } - return false; -} - -void KeyCharacterMap::addDoubleEphemeralMetaKey(Vector<KeyEvent>& outEvents, - int32_t deviceId, int32_t metaState, bool down, nsecs_t time, - int32_t leftKeyCode, int32_t leftKeyMetaState, - int32_t rightKeyCode, int32_t rightKeyMetaState, - int32_t eitherKeyMetaState, - int32_t* currentMetaState) { - bool specific = false; - specific |= addSingleEphemeralMetaKey(outEvents, deviceId, metaState, down, time, - leftKeyCode, leftKeyMetaState, currentMetaState); - specific |= addSingleEphemeralMetaKey(outEvents, deviceId, metaState, down, time, - rightKeyCode, rightKeyMetaState, currentMetaState); - - if (!specific) { - addSingleEphemeralMetaKey(outEvents, deviceId, metaState, down, time, - leftKeyCode, eitherKeyMetaState, currentMetaState); - } -} - -void KeyCharacterMap::addLockedMetaKey(Vector<KeyEvent>& outEvents, - int32_t deviceId, int32_t metaState, nsecs_t time, - int32_t keyCode, int32_t keyMetaState, - int32_t* currentMetaState) { - if ((metaState & keyMetaState) == keyMetaState) { - *currentMetaState = updateMetaState(keyCode, true, *currentMetaState); - addKey(outEvents, deviceId, keyCode, *currentMetaState, true, time); - *currentMetaState = updateMetaState(keyCode, false, *currentMetaState); - addKey(outEvents, deviceId, keyCode, *currentMetaState, false, time); - } -} - - -// --- KeyCharacterMap::Key --- - -KeyCharacterMap::Key::Key() : - label(0), number(0), firstBehavior(NULL) { -} - -KeyCharacterMap::Key::~Key() { - Behavior* behavior = firstBehavior; - while (behavior) { - Behavior* next = behavior->next; - delete behavior; - behavior = next; - } -} - - -// --- KeyCharacterMap::Behavior --- - -KeyCharacterMap::Behavior::Behavior() : - next(NULL), metaState(0), character(0), fallbackKeyCode(0) { -} - - -// --- KeyCharacterMap::Parser --- - -KeyCharacterMap::Parser::Parser(KeyCharacterMap* map, Tokenizer* tokenizer) : - mMap(map), mTokenizer(tokenizer), mState(STATE_TOP) { -} - -KeyCharacterMap::Parser::~Parser() { -} - -status_t KeyCharacterMap::Parser::parse() { - while (!mTokenizer->isEof()) { -#if DEBUG_PARSER - ALOGD("Parsing %s: '%s'.", mTokenizer->getLocation().string(), - mTokenizer->peekRemainderOfLine().string()); -#endif - - mTokenizer->skipDelimiters(WHITESPACE); - - if (!mTokenizer->isEol() && mTokenizer->peekChar() != '#') { - switch (mState) { - case STATE_TOP: { - String8 keywordToken = mTokenizer->nextToken(WHITESPACE); - if (keywordToken == "type") { - mTokenizer->skipDelimiters(WHITESPACE); - status_t status = parseType(); - if (status) return status; - } else if (keywordToken == "key") { - mTokenizer->skipDelimiters(WHITESPACE); - status_t status = parseKey(); - if (status) return status; - } else { - ALOGE("%s: Expected keyword, got '%s'.", mTokenizer->getLocation().string(), - keywordToken.string()); - return BAD_VALUE; - } - break; - } - - case STATE_KEY: { - status_t status = parseKeyProperty(); - if (status) return status; - break; - } - } - - mTokenizer->skipDelimiters(WHITESPACE); - if (!mTokenizer->isEol()) { - ALOGE("%s: Expected end of line, got '%s'.", - mTokenizer->getLocation().string(), - mTokenizer->peekRemainderOfLine().string()); - return BAD_VALUE; - } - } - - mTokenizer->nextLine(); - } - - if (mState != STATE_TOP) { - ALOGE("%s: Unterminated key description at end of file.", - mTokenizer->getLocation().string()); - return BAD_VALUE; - } - - if (mMap->mType == KEYBOARD_TYPE_UNKNOWN) { - ALOGE("%s: Missing required keyboard 'type' declaration.", - mTokenizer->getLocation().string()); - return BAD_VALUE; - } - - return NO_ERROR; -} - -status_t KeyCharacterMap::Parser::parseType() { - if (mMap->mType != KEYBOARD_TYPE_UNKNOWN) { - ALOGE("%s: Duplicate keyboard 'type' declaration.", - mTokenizer->getLocation().string()); - return BAD_VALUE; - } - - KeyboardType type; - String8 typeToken = mTokenizer->nextToken(WHITESPACE); - if (typeToken == "NUMERIC") { - type = KEYBOARD_TYPE_NUMERIC; - } else if (typeToken == "PREDICTIVE") { - type = KEYBOARD_TYPE_PREDICTIVE; - } else if (typeToken == "ALPHA") { - type = KEYBOARD_TYPE_ALPHA; - } else if (typeToken == "FULL") { - type = KEYBOARD_TYPE_FULL; - } else if (typeToken == "SPECIAL_FUNCTION") { - type = KEYBOARD_TYPE_SPECIAL_FUNCTION; - } else { - ALOGE("%s: Expected keyboard type label, got '%s'.", mTokenizer->getLocation().string(), - typeToken.string()); - return BAD_VALUE; - } - -#if DEBUG_PARSER - ALOGD("Parsed type: type=%d.", type); -#endif - mMap->mType = type; - return NO_ERROR; -} - -status_t KeyCharacterMap::Parser::parseKey() { - String8 keyCodeToken = mTokenizer->nextToken(WHITESPACE); - int32_t keyCode = getKeyCodeByLabel(keyCodeToken.string()); - if (!keyCode) { - ALOGE("%s: Expected key code label, got '%s'.", mTokenizer->getLocation().string(), - keyCodeToken.string()); - return BAD_VALUE; - } - if (mMap->mKeys.indexOfKey(keyCode) >= 0) { - ALOGE("%s: Duplicate entry for key code '%s'.", mTokenizer->getLocation().string(), - keyCodeToken.string()); - return BAD_VALUE; - } - - mTokenizer->skipDelimiters(WHITESPACE); - String8 openBraceToken = mTokenizer->nextToken(WHITESPACE); - if (openBraceToken != "{") { - ALOGE("%s: Expected '{' after key code label, got '%s'.", - mTokenizer->getLocation().string(), openBraceToken.string()); - return BAD_VALUE; - } - -#if DEBUG_PARSER - ALOGD("Parsed beginning of key: keyCode=%d.", keyCode); -#endif - mKeyCode = keyCode; - mMap->mKeys.add(keyCode, new Key()); - mState = STATE_KEY; - return NO_ERROR; -} - -status_t KeyCharacterMap::Parser::parseKeyProperty() { - String8 token = mTokenizer->nextToken(WHITESPACE_OR_PROPERTY_DELIMITER); - if (token == "}") { - mState = STATE_TOP; - return NO_ERROR; - } - - Vector<Property> properties; - - // Parse all comma-delimited property names up to the first colon. - for (;;) { - if (token == "label") { - properties.add(Property(PROPERTY_LABEL)); - } else if (token == "number") { - properties.add(Property(PROPERTY_NUMBER)); - } else { - int32_t metaState; - status_t status = parseModifier(token, &metaState); - if (status) { - ALOGE("%s: Expected a property name or modifier, got '%s'.", - mTokenizer->getLocation().string(), token.string()); - return status; - } - properties.add(Property(PROPERTY_META, metaState)); - } - - mTokenizer->skipDelimiters(WHITESPACE); - if (!mTokenizer->isEol()) { - char ch = mTokenizer->nextChar(); - if (ch == ':') { - break; - } else if (ch == ',') { - mTokenizer->skipDelimiters(WHITESPACE); - token = mTokenizer->nextToken(WHITESPACE_OR_PROPERTY_DELIMITER); - continue; - } - } - - ALOGE("%s: Expected ',' or ':' after property name.", - mTokenizer->getLocation().string()); - return BAD_VALUE; - } - - // Parse behavior after the colon. - mTokenizer->skipDelimiters(WHITESPACE); - - Behavior behavior; - bool haveCharacter = false; - bool haveFallback = false; - - do { - char ch = mTokenizer->peekChar(); - if (ch == '\'') { - char16_t character; - status_t status = parseCharacterLiteral(&character); - if (status || !character) { - ALOGE("%s: Invalid character literal for key.", - mTokenizer->getLocation().string()); - return BAD_VALUE; - } - if (haveCharacter) { - ALOGE("%s: Cannot combine multiple character literals or 'none'.", - mTokenizer->getLocation().string()); - return BAD_VALUE; - } - behavior.character = character; - haveCharacter = true; - } else { - token = mTokenizer->nextToken(WHITESPACE); - if (token == "none") { - if (haveCharacter) { - ALOGE("%s: Cannot combine multiple character literals or 'none'.", - mTokenizer->getLocation().string()); - return BAD_VALUE; - } - haveCharacter = true; - } else if (token == "fallback") { - mTokenizer->skipDelimiters(WHITESPACE); - token = mTokenizer->nextToken(WHITESPACE); - int32_t keyCode = getKeyCodeByLabel(token.string()); - if (!keyCode) { - ALOGE("%s: Invalid key code label for fallback behavior, got '%s'.", - mTokenizer->getLocation().string(), - token.string()); - return BAD_VALUE; - } - if (haveFallback) { - ALOGE("%s: Cannot combine multiple fallback key codes.", - mTokenizer->getLocation().string()); - return BAD_VALUE; - } - behavior.fallbackKeyCode = keyCode; - haveFallback = true; - } else { - ALOGE("%s: Expected a key behavior after ':'.", - mTokenizer->getLocation().string()); - return BAD_VALUE; - } - } - - mTokenizer->skipDelimiters(WHITESPACE); - } while (!mTokenizer->isEol()); - - // Add the behavior. - Key* key = mMap->mKeys.valueFor(mKeyCode); - for (size_t i = 0; i < properties.size(); i++) { - const Property& property = properties.itemAt(i); - switch (property.property) { - case PROPERTY_LABEL: - if (key->label) { - ALOGE("%s: Duplicate label for key.", - mTokenizer->getLocation().string()); - return BAD_VALUE; - } - key->label = behavior.character; -#if DEBUG_PARSER - ALOGD("Parsed key label: keyCode=%d, label=%d.", mKeyCode, key->label); -#endif - break; - case PROPERTY_NUMBER: - if (key->number) { - ALOGE("%s: Duplicate number for key.", - mTokenizer->getLocation().string()); - return BAD_VALUE; - } - key->number = behavior.character; -#if DEBUG_PARSER - ALOGD("Parsed key number: keyCode=%d, number=%d.", mKeyCode, key->number); -#endif - break; - case PROPERTY_META: { - for (Behavior* b = key->firstBehavior; b; b = b->next) { - if (b->metaState == property.metaState) { - ALOGE("%s: Duplicate key behavior for modifier.", - mTokenizer->getLocation().string()); - return BAD_VALUE; - } - } - Behavior* newBehavior = new Behavior(behavior); - newBehavior->metaState = property.metaState; - newBehavior->next = key->firstBehavior; - key->firstBehavior = newBehavior; -#if DEBUG_PARSER - ALOGD("Parsed key meta: keyCode=%d, meta=0x%x, char=%d, fallback=%d.", mKeyCode, - newBehavior->metaState, newBehavior->character, newBehavior->fallbackKeyCode); -#endif - break; - } - } - } - return NO_ERROR; -} - -status_t KeyCharacterMap::Parser::parseModifier(const String8& token, int32_t* outMetaState) { - if (token == "base") { - *outMetaState = 0; - return NO_ERROR; - } - - int32_t combinedMeta = 0; - - const char* str = token.string(); - const char* start = str; - for (const char* cur = str; ; cur++) { - char ch = *cur; - if (ch == '+' || ch == '\0') { - size_t len = cur - start; - int32_t metaState = 0; - for (size_t i = 0; i < sizeof(modifiers) / sizeof(Modifier); i++) { - if (strlen(modifiers[i].label) == len - && strncmp(modifiers[i].label, start, len) == 0) { - metaState = modifiers[i].metaState; - break; - } - } - if (!metaState) { - return BAD_VALUE; - } - if (combinedMeta & metaState) { - ALOGE("%s: Duplicate modifier combination '%s'.", - mTokenizer->getLocation().string(), token.string()); - return BAD_VALUE; - } - - combinedMeta |= metaState; - start = cur + 1; - - if (ch == '\0') { - break; - } - } - } - *outMetaState = combinedMeta; - return NO_ERROR; -} - -status_t KeyCharacterMap::Parser::parseCharacterLiteral(char16_t* outCharacter) { - char ch = mTokenizer->nextChar(); - if (ch != '\'') { - goto Error; - } - - ch = mTokenizer->nextChar(); - if (ch == '\\') { - // Escape sequence. - ch = mTokenizer->nextChar(); - if (ch == 'n') { - *outCharacter = '\n'; - } else if (ch == 't') { - *outCharacter = '\t'; - } else if (ch == '\\') { - *outCharacter = '\\'; - } else if (ch == '\'') { - *outCharacter = '\''; - } else if (ch == '"') { - *outCharacter = '"'; - } else if (ch == 'u') { - *outCharacter = 0; - for (int i = 0; i < 4; i++) { - ch = mTokenizer->nextChar(); - int digit; - if (ch >= '0' && ch <= '9') { - digit = ch - '0'; - } else if (ch >= 'A' && ch <= 'F') { - digit = ch - 'A' + 10; - } else if (ch >= 'a' && ch <= 'f') { - digit = ch - 'a' + 10; - } else { - goto Error; - } - *outCharacter = (*outCharacter << 4) | digit; - } - } else { - goto Error; - } - } else if (ch >= 32 && ch <= 126 && ch != '\'') { - // ASCII literal character. - *outCharacter = ch; - } else { - goto Error; - } - - ch = mTokenizer->nextChar(); - if (ch != '\'') { - goto Error; - } - - // Ensure that we consumed the entire token. - if (mTokenizer->nextToken(WHITESPACE).isEmpty()) { - return NO_ERROR; - } - -Error: - ALOGE("%s: Malformed character literal.", mTokenizer->getLocation().string()); - return BAD_VALUE; -} - -} // namespace android diff --git a/libs/ui/KeyLayoutMap.cpp b/libs/ui/KeyLayoutMap.cpp deleted file mode 100644 index 15d81ee..0000000 --- a/libs/ui/KeyLayoutMap.cpp +++ /dev/null @@ -1,341 +0,0 @@ -/* - * Copyright (C) 2008 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 "KeyLayoutMap" - -#include <stdlib.h> -#include <android/keycodes.h> -#include <androidfw/Keyboard.h> -#include <androidfw/KeyLayoutMap.h> -#include <utils/Log.h> -#include <utils/Errors.h> -#include <utils/Tokenizer.h> -#include <utils/Timers.h> - -// Enables debug output for the parser. -#define DEBUG_PARSER 0 - -// Enables debug output for parser performance. -#define DEBUG_PARSER_PERFORMANCE 0 - -// Enables debug output for mapping. -#define DEBUG_MAPPING 0 - - -namespace android { - -static const char* WHITESPACE = " \t\r"; - -// --- KeyLayoutMap --- - -KeyLayoutMap::KeyLayoutMap() { -} - -KeyLayoutMap::~KeyLayoutMap() { -} - -status_t KeyLayoutMap::load(const String8& filename, KeyLayoutMap** outMap) { - *outMap = NULL; - - Tokenizer* tokenizer; - status_t status = Tokenizer::open(filename, &tokenizer); - if (status) { - ALOGE("Error %d opening key layout map file %s.", status, filename.string()); - } else { - KeyLayoutMap* map = new KeyLayoutMap(); - if (!map) { - ALOGE("Error allocating key layout map."); - status = NO_MEMORY; - } else { -#if DEBUG_PARSER_PERFORMANCE - nsecs_t startTime = systemTime(SYSTEM_TIME_MONOTONIC); -#endif - Parser parser(map, tokenizer); - status = parser.parse(); -#if DEBUG_PARSER_PERFORMANCE - nsecs_t elapsedTime = systemTime(SYSTEM_TIME_MONOTONIC) - startTime; - ALOGD("Parsed key layout map file '%s' %d lines in %0.3fms.", - tokenizer->getFilename().string(), tokenizer->getLineNumber(), - elapsedTime / 1000000.0); -#endif - if (status) { - delete map; - } else { - *outMap = map; - } - } - delete tokenizer; - } - return status; -} - -status_t KeyLayoutMap::mapKey(int32_t scanCode, int32_t* keyCode, uint32_t* flags) const { - ssize_t index = mKeys.indexOfKey(scanCode); - if (index < 0) { -#if DEBUG_MAPPING - ALOGD("mapKey: scanCode=%d ~ Failed.", scanCode); -#endif - *keyCode = AKEYCODE_UNKNOWN; - *flags = 0; - return NAME_NOT_FOUND; - } - - const Key& k = mKeys.valueAt(index); - *keyCode = k.keyCode; - *flags = k.flags; - -#if DEBUG_MAPPING - ALOGD("mapKey: scanCode=%d ~ Result keyCode=%d, flags=0x%08x.", scanCode, *keyCode, *flags); -#endif - return NO_ERROR; -} - -status_t KeyLayoutMap::findScanCodesForKey(int32_t keyCode, Vector<int32_t>* outScanCodes) const { - const size_t N = mKeys.size(); - for (size_t i=0; i<N; i++) { - if (mKeys.valueAt(i).keyCode == keyCode) { - outScanCodes->add(mKeys.keyAt(i)); - } - } - return NO_ERROR; -} - -status_t KeyLayoutMap::mapAxis(int32_t scanCode, AxisInfo* outAxisInfo) const { - ssize_t index = mAxes.indexOfKey(scanCode); - if (index < 0) { -#if DEBUG_MAPPING - ALOGD("mapAxis: scanCode=%d ~ Failed.", scanCode); -#endif - return NAME_NOT_FOUND; - } - - *outAxisInfo = mAxes.valueAt(index); - -#if DEBUG_MAPPING - ALOGD("mapAxis: scanCode=%d ~ Result mode=%d, axis=%d, highAxis=%d, " - "splitValue=%d, flatOverride=%d.", - scanCode, - outAxisInfo->mode, outAxisInfo->axis, outAxisInfo->highAxis, - outAxisInfo->splitValue, outAxisInfo->flatOverride); -#endif - return NO_ERROR; -} - - -// --- KeyLayoutMap::Parser --- - -KeyLayoutMap::Parser::Parser(KeyLayoutMap* map, Tokenizer* tokenizer) : - mMap(map), mTokenizer(tokenizer) { -} - -KeyLayoutMap::Parser::~Parser() { -} - -status_t KeyLayoutMap::Parser::parse() { - while (!mTokenizer->isEof()) { -#if DEBUG_PARSER - ALOGD("Parsing %s: '%s'.", mTokenizer->getLocation().string(), - mTokenizer->peekRemainderOfLine().string()); -#endif - - mTokenizer->skipDelimiters(WHITESPACE); - - if (!mTokenizer->isEol() && mTokenizer->peekChar() != '#') { - String8 keywordToken = mTokenizer->nextToken(WHITESPACE); - if (keywordToken == "key") { - mTokenizer->skipDelimiters(WHITESPACE); - status_t status = parseKey(); - if (status) return status; - } else if (keywordToken == "axis") { - mTokenizer->skipDelimiters(WHITESPACE); - status_t status = parseAxis(); - if (status) return status; - } else { - ALOGE("%s: Expected keyword, got '%s'.", mTokenizer->getLocation().string(), - keywordToken.string()); - return BAD_VALUE; - } - - mTokenizer->skipDelimiters(WHITESPACE); - if (!mTokenizer->isEol()) { - ALOGE("%s: Expected end of line, got '%s'.", - mTokenizer->getLocation().string(), - mTokenizer->peekRemainderOfLine().string()); - return BAD_VALUE; - } - } - - mTokenizer->nextLine(); - } - return NO_ERROR; -} - -status_t KeyLayoutMap::Parser::parseKey() { - String8 scanCodeToken = mTokenizer->nextToken(WHITESPACE); - char* end; - int32_t scanCode = int32_t(strtol(scanCodeToken.string(), &end, 0)); - if (*end) { - ALOGE("%s: Expected key scan code number, got '%s'.", mTokenizer->getLocation().string(), - scanCodeToken.string()); - return BAD_VALUE; - } - if (mMap->mKeys.indexOfKey(scanCode) >= 0) { - ALOGE("%s: Duplicate entry for key scan code '%s'.", mTokenizer->getLocation().string(), - scanCodeToken.string()); - return BAD_VALUE; - } - - mTokenizer->skipDelimiters(WHITESPACE); - String8 keyCodeToken = mTokenizer->nextToken(WHITESPACE); - int32_t keyCode = getKeyCodeByLabel(keyCodeToken.string()); - if (!keyCode) { - ALOGE("%s: Expected key code label, got '%s'.", mTokenizer->getLocation().string(), - keyCodeToken.string()); - return BAD_VALUE; - } - - uint32_t flags = 0; - for (;;) { - mTokenizer->skipDelimiters(WHITESPACE); - if (mTokenizer->isEol()) break; - - String8 flagToken = mTokenizer->nextToken(WHITESPACE); - uint32_t flag = getKeyFlagByLabel(flagToken.string()); - if (!flag) { - ALOGE("%s: Expected key flag label, got '%s'.", mTokenizer->getLocation().string(), - flagToken.string()); - return BAD_VALUE; - } - if (flags & flag) { - ALOGE("%s: Duplicate key flag '%s'.", mTokenizer->getLocation().string(), - flagToken.string()); - return BAD_VALUE; - } - flags |= flag; - } - -#if DEBUG_PARSER - ALOGD("Parsed key: scanCode=%d, keyCode=%d, flags=0x%08x.", scanCode, keyCode, flags); -#endif - Key key; - key.keyCode = keyCode; - key.flags = flags; - mMap->mKeys.add(scanCode, key); - return NO_ERROR; -} - -status_t KeyLayoutMap::Parser::parseAxis() { - String8 scanCodeToken = mTokenizer->nextToken(WHITESPACE); - char* end; - int32_t scanCode = int32_t(strtol(scanCodeToken.string(), &end, 0)); - if (*end) { - ALOGE("%s: Expected axis scan code number, got '%s'.", mTokenizer->getLocation().string(), - scanCodeToken.string()); - return BAD_VALUE; - } - if (mMap->mAxes.indexOfKey(scanCode) >= 0) { - ALOGE("%s: Duplicate entry for axis scan code '%s'.", mTokenizer->getLocation().string(), - scanCodeToken.string()); - return BAD_VALUE; - } - - AxisInfo axisInfo; - - mTokenizer->skipDelimiters(WHITESPACE); - String8 token = mTokenizer->nextToken(WHITESPACE); - if (token == "invert") { - axisInfo.mode = AxisInfo::MODE_INVERT; - - mTokenizer->skipDelimiters(WHITESPACE); - String8 axisToken = mTokenizer->nextToken(WHITESPACE); - axisInfo.axis = getAxisByLabel(axisToken.string()); - if (axisInfo.axis < 0) { - ALOGE("%s: Expected inverted axis label, got '%s'.", - mTokenizer->getLocation().string(), axisToken.string()); - return BAD_VALUE; - } - } else if (token == "split") { - axisInfo.mode = AxisInfo::MODE_SPLIT; - - mTokenizer->skipDelimiters(WHITESPACE); - String8 splitToken = mTokenizer->nextToken(WHITESPACE); - axisInfo.splitValue = int32_t(strtol(splitToken.string(), &end, 0)); - if (*end) { - ALOGE("%s: Expected split value, got '%s'.", - mTokenizer->getLocation().string(), splitToken.string()); - return BAD_VALUE; - } - - mTokenizer->skipDelimiters(WHITESPACE); - String8 lowAxisToken = mTokenizer->nextToken(WHITESPACE); - axisInfo.axis = getAxisByLabel(lowAxisToken.string()); - if (axisInfo.axis < 0) { - ALOGE("%s: Expected low axis label, got '%s'.", - mTokenizer->getLocation().string(), lowAxisToken.string()); - return BAD_VALUE; - } - - mTokenizer->skipDelimiters(WHITESPACE); - String8 highAxisToken = mTokenizer->nextToken(WHITESPACE); - axisInfo.highAxis = getAxisByLabel(highAxisToken.string()); - if (axisInfo.highAxis < 0) { - ALOGE("%s: Expected high axis label, got '%s'.", - mTokenizer->getLocation().string(), highAxisToken.string()); - return BAD_VALUE; - } - } else { - axisInfo.axis = getAxisByLabel(token.string()); - if (axisInfo.axis < 0) { - ALOGE("%s: Expected axis label, 'split' or 'invert', got '%s'.", - mTokenizer->getLocation().string(), token.string()); - return BAD_VALUE; - } - } - - for (;;) { - mTokenizer->skipDelimiters(WHITESPACE); - if (mTokenizer->isEol()) { - break; - } - String8 keywordToken = mTokenizer->nextToken(WHITESPACE); - if (keywordToken == "flat") { - mTokenizer->skipDelimiters(WHITESPACE); - String8 flatToken = mTokenizer->nextToken(WHITESPACE); - axisInfo.flatOverride = int32_t(strtol(flatToken.string(), &end, 0)); - if (*end) { - ALOGE("%s: Expected flat value, got '%s'.", - mTokenizer->getLocation().string(), flatToken.string()); - return BAD_VALUE; - } - } else { - ALOGE("%s: Expected keyword 'flat', got '%s'.", - mTokenizer->getLocation().string(), keywordToken.string()); - return BAD_VALUE; - } - } - -#if DEBUG_PARSER - ALOGD("Parsed axis: scanCode=%d, mode=%d, axis=%d, highAxis=%d, " - "splitValue=%d, flatOverride=%d.", - scanCode, - axisInfo.mode, axisInfo.axis, axisInfo.highAxis, - axisInfo.splitValue, axisInfo.flatOverride); -#endif - mMap->mAxes.add(scanCode, axisInfo); - return NO_ERROR; -} - -}; diff --git a/libs/ui/Keyboard.cpp b/libs/ui/Keyboard.cpp deleted file mode 100644 index e97a5eb..0000000 --- a/libs/ui/Keyboard.cpp +++ /dev/null @@ -1,303 +0,0 @@ -/* - * 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 "Keyboard" - -#include <stdlib.h> -#include <unistd.h> -#include <limits.h> - -#include <androidfw/Keyboard.h> -#include <androidfw/KeycodeLabels.h> -#include <androidfw/KeyLayoutMap.h> -#include <androidfw/KeyCharacterMap.h> -#include <utils/Errors.h> -#include <utils/Log.h> -#include <cutils/properties.h> - -namespace android { - -// --- KeyMap --- - -KeyMap::KeyMap() : - keyLayoutMap(NULL), keyCharacterMap(NULL) { -} - -KeyMap::~KeyMap() { - delete keyLayoutMap; - delete keyCharacterMap; -} - -status_t KeyMap::load(const InputDeviceIdentifier& deviceIdenfifier, - const PropertyMap* deviceConfiguration) { - // Use the configured key layout if available. - if (deviceConfiguration) { - String8 keyLayoutName; - if (deviceConfiguration->tryGetProperty(String8("keyboard.layout"), - keyLayoutName)) { - status_t status = loadKeyLayout(deviceIdenfifier, keyLayoutName); - if (status == NAME_NOT_FOUND) { - ALOGE("Configuration for keyboard device '%s' requested keyboard layout '%s' but " - "it was not found.", - deviceIdenfifier.name.string(), keyLayoutName.string()); - } - } - - String8 keyCharacterMapName; - if (deviceConfiguration->tryGetProperty(String8("keyboard.characterMap"), - keyCharacterMapName)) { - status_t status = loadKeyCharacterMap(deviceIdenfifier, keyCharacterMapName); - if (status == NAME_NOT_FOUND) { - ALOGE("Configuration for keyboard device '%s' requested keyboard character " - "map '%s' but it was not found.", - deviceIdenfifier.name.string(), keyLayoutName.string()); - } - } - - if (isComplete()) { - return OK; - } - } - - // Try searching by device identifier. - if (probeKeyMap(deviceIdenfifier, String8::empty())) { - return OK; - } - - // Fall back on the Generic key map. - // TODO Apply some additional heuristics here to figure out what kind of - // generic key map to use (US English, etc.) for typical external keyboards. - if (probeKeyMap(deviceIdenfifier, String8("Generic"))) { - return OK; - } - - // Try the Virtual key map as a last resort. - if (probeKeyMap(deviceIdenfifier, String8("Virtual"))) { - return OK; - } - - // Give up! - ALOGE("Could not determine key map for device '%s' and no default key maps were found!", - deviceIdenfifier.name.string()); - return NAME_NOT_FOUND; -} - -bool KeyMap::probeKeyMap(const InputDeviceIdentifier& deviceIdentifier, - const String8& keyMapName) { - if (!haveKeyLayout()) { - loadKeyLayout(deviceIdentifier, keyMapName); - } - if (!haveKeyCharacterMap()) { - loadKeyCharacterMap(deviceIdentifier, keyMapName); - } - return isComplete(); -} - -status_t KeyMap::loadKeyLayout(const InputDeviceIdentifier& deviceIdentifier, - const String8& name) { - String8 path(getPath(deviceIdentifier, name, - INPUT_DEVICE_CONFIGURATION_FILE_TYPE_KEY_LAYOUT)); - if (path.isEmpty()) { - return NAME_NOT_FOUND; - } - - KeyLayoutMap* map; - status_t status = KeyLayoutMap::load(path, &map); - if (status) { - return status; - } - - keyLayoutFile.setTo(path); - keyLayoutMap = map; - return OK; -} - -status_t KeyMap::loadKeyCharacterMap(const InputDeviceIdentifier& deviceIdentifier, - const String8& name) { - String8 path(getPath(deviceIdentifier, name, - INPUT_DEVICE_CONFIGURATION_FILE_TYPE_KEY_CHARACTER_MAP)); - if (path.isEmpty()) { - return NAME_NOT_FOUND; - } - - KeyCharacterMap* map; - status_t status = KeyCharacterMap::load(path, &map); - if (status) { - return status; - } - - keyCharacterMapFile.setTo(path); - keyCharacterMap = map; - return OK; -} - -String8 KeyMap::getPath(const InputDeviceIdentifier& deviceIdentifier, - const String8& name, InputDeviceConfigurationFileType type) { - return name.isEmpty() - ? getInputDeviceConfigurationFilePathByDeviceIdentifier(deviceIdentifier, type) - : getInputDeviceConfigurationFilePathByName(name, type); -} - - -// --- Global functions --- - -bool isEligibleBuiltInKeyboard(const InputDeviceIdentifier& deviceIdentifier, - const PropertyMap* deviceConfiguration, const KeyMap* keyMap) { - if (!keyMap->haveKeyCharacterMap() - || keyMap->keyCharacterMap->getKeyboardType() - == KeyCharacterMap::KEYBOARD_TYPE_SPECIAL_FUNCTION) { - return false; - } - - if (deviceConfiguration) { - bool builtIn = false; - if (deviceConfiguration->tryGetProperty(String8("keyboard.builtIn"), builtIn) - && builtIn) { - return true; - } - } - - return strstr(deviceIdentifier.name.string(), "-keypad"); -} - -static int lookupValueByLabel(const char* literal, const KeycodeLabel *list) { - while (list->literal) { - if (strcmp(literal, list->literal) == 0) { - return list->value; - } - list++; - } - return list->value; -} - -static const char* lookupLabelByValue(int value, const KeycodeLabel *list) { - while (list->literal) { - if (list->value == value) { - return list->literal; - } - list++; - } - return NULL; -} - -int32_t getKeyCodeByLabel(const char* label) { - return int32_t(lookupValueByLabel(label, KEYCODES)); -} - -uint32_t getKeyFlagByLabel(const char* label) { - return uint32_t(lookupValueByLabel(label, FLAGS)); -} - -int32_t getAxisByLabel(const char* label) { - return int32_t(lookupValueByLabel(label, AXES)); -} - -const char* getAxisLabel(int32_t axisId) { - return lookupLabelByValue(axisId, AXES); -} - -static int32_t setEphemeralMetaState(int32_t mask, bool down, int32_t oldMetaState) { - int32_t newMetaState; - if (down) { - newMetaState = oldMetaState | mask; - } else { - newMetaState = oldMetaState & - ~(mask | AMETA_ALT_ON | AMETA_SHIFT_ON | AMETA_CTRL_ON | AMETA_META_ON); - } - - if (newMetaState & (AMETA_ALT_LEFT_ON | AMETA_ALT_RIGHT_ON)) { - newMetaState |= AMETA_ALT_ON; - } - - if (newMetaState & (AMETA_SHIFT_LEFT_ON | AMETA_SHIFT_RIGHT_ON)) { - newMetaState |= AMETA_SHIFT_ON; - } - - if (newMetaState & (AMETA_CTRL_LEFT_ON | AMETA_CTRL_RIGHT_ON)) { - newMetaState |= AMETA_CTRL_ON; - } - - if (newMetaState & (AMETA_META_LEFT_ON | AMETA_META_RIGHT_ON)) { - newMetaState |= AMETA_META_ON; - } - return newMetaState; -} - -static int32_t toggleLockedMetaState(int32_t mask, bool down, int32_t oldMetaState) { - if (down) { - return oldMetaState; - } else { - return oldMetaState ^ mask; - } -} - -int32_t updateMetaState(int32_t keyCode, bool down, int32_t oldMetaState) { - int32_t mask; - switch (keyCode) { - case AKEYCODE_ALT_LEFT: - return setEphemeralMetaState(AMETA_ALT_LEFT_ON, down, oldMetaState); - case AKEYCODE_ALT_RIGHT: - return setEphemeralMetaState(AMETA_ALT_RIGHT_ON, down, oldMetaState); - case AKEYCODE_SHIFT_LEFT: - return setEphemeralMetaState(AMETA_SHIFT_LEFT_ON, down, oldMetaState); - case AKEYCODE_SHIFT_RIGHT: - return setEphemeralMetaState(AMETA_SHIFT_RIGHT_ON, down, oldMetaState); - case AKEYCODE_SYM: - return setEphemeralMetaState(AMETA_SYM_ON, down, oldMetaState); - case AKEYCODE_FUNCTION: - return setEphemeralMetaState(AMETA_FUNCTION_ON, down, oldMetaState); - case AKEYCODE_CTRL_LEFT: - return setEphemeralMetaState(AMETA_CTRL_LEFT_ON, down, oldMetaState); - case AKEYCODE_CTRL_RIGHT: - return setEphemeralMetaState(AMETA_CTRL_RIGHT_ON, down, oldMetaState); - case AKEYCODE_META_LEFT: - return setEphemeralMetaState(AMETA_META_LEFT_ON, down, oldMetaState); - case AKEYCODE_META_RIGHT: - return setEphemeralMetaState(AMETA_META_RIGHT_ON, down, oldMetaState); - case AKEYCODE_CAPS_LOCK: - return toggleLockedMetaState(AMETA_CAPS_LOCK_ON, down, oldMetaState); - case AKEYCODE_NUM_LOCK: - return toggleLockedMetaState(AMETA_NUM_LOCK_ON, down, oldMetaState); - case AKEYCODE_SCROLL_LOCK: - return toggleLockedMetaState(AMETA_SCROLL_LOCK_ON, down, oldMetaState); - default: - return oldMetaState; - } -} - -bool isMetaKey(int32_t keyCode) { - switch (keyCode) { - case AKEYCODE_ALT_LEFT: - case AKEYCODE_ALT_RIGHT: - case AKEYCODE_SHIFT_LEFT: - case AKEYCODE_SHIFT_RIGHT: - case AKEYCODE_SYM: - case AKEYCODE_FUNCTION: - case AKEYCODE_CTRL_LEFT: - case AKEYCODE_CTRL_RIGHT: - case AKEYCODE_META_LEFT: - case AKEYCODE_META_RIGHT: - case AKEYCODE_CAPS_LOCK: - case AKEYCODE_NUM_LOCK: - case AKEYCODE_SCROLL_LOCK: - return true; - default: - return false; - } -} - - -} // namespace android diff --git a/libs/ui/VirtualKeyMap.cpp b/libs/ui/VirtualKeyMap.cpp deleted file mode 100644 index 2ba1673..0000000 --- a/libs/ui/VirtualKeyMap.cpp +++ /dev/null @@ -1,171 +0,0 @@ -/* - * 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 "VirtualKeyMap" - -#include <stdlib.h> -#include <string.h> -#include <androidfw/VirtualKeyMap.h> -#include <utils/Log.h> -#include <utils/Errors.h> -#include <utils/Tokenizer.h> -#include <utils/Timers.h> - -// Enables debug output for the parser. -#define DEBUG_PARSER 0 - -// Enables debug output for parser performance. -#define DEBUG_PARSER_PERFORMANCE 0 - - -namespace android { - -static const char* WHITESPACE = " \t\r"; -static const char* WHITESPACE_OR_FIELD_DELIMITER = " \t\r:"; - - -// --- VirtualKeyMap --- - -VirtualKeyMap::VirtualKeyMap() { -} - -VirtualKeyMap::~VirtualKeyMap() { -} - -status_t VirtualKeyMap::load(const String8& filename, VirtualKeyMap** outMap) { - *outMap = NULL; - - Tokenizer* tokenizer; - status_t status = Tokenizer::open(filename, &tokenizer); - if (status) { - ALOGE("Error %d opening virtual key map file %s.", status, filename.string()); - } else { - VirtualKeyMap* map = new VirtualKeyMap(); - if (!map) { - ALOGE("Error allocating virtual key map."); - status = NO_MEMORY; - } else { -#if DEBUG_PARSER_PERFORMANCE - nsecs_t startTime = systemTime(SYSTEM_TIME_MONOTONIC); -#endif - Parser parser(map, tokenizer); - status = parser.parse(); -#if DEBUG_PARSER_PERFORMANCE - nsecs_t elapsedTime = systemTime(SYSTEM_TIME_MONOTONIC) - startTime; - ALOGD("Parsed key character map file '%s' %d lines in %0.3fms.", - tokenizer->getFilename().string(), tokenizer->getLineNumber(), - elapsedTime / 1000000.0); -#endif - if (status) { - delete map; - } else { - *outMap = map; - } - } - delete tokenizer; - } - return status; -} - - -// --- VirtualKeyMap::Parser --- - -VirtualKeyMap::Parser::Parser(VirtualKeyMap* map, Tokenizer* tokenizer) : - mMap(map), mTokenizer(tokenizer) { -} - -VirtualKeyMap::Parser::~Parser() { -} - -status_t VirtualKeyMap::Parser::parse() { - while (!mTokenizer->isEof()) { -#if DEBUG_PARSER - ALOGD("Parsing %s: '%s'.", mTokenizer->getLocation().string(), - mTokenizer->peekRemainderOfLine().string()); -#endif - - mTokenizer->skipDelimiters(WHITESPACE); - - if (!mTokenizer->isEol() && mTokenizer->peekChar() != '#') { - // Multiple keys can appear on one line or they can be broken up across multiple lines. - do { - String8 token = mTokenizer->nextToken(WHITESPACE_OR_FIELD_DELIMITER); - if (token != "0x01") { - ALOGE("%s: Unknown virtual key type, expected 0x01.", - mTokenizer->getLocation().string()); - return BAD_VALUE; - } - - VirtualKeyDefinition defn; - bool success = parseNextIntField(&defn.scanCode) - && parseNextIntField(&defn.centerX) - && parseNextIntField(&defn.centerY) - && parseNextIntField(&defn.width) - && parseNextIntField(&defn.height); - if (!success) { - ALOGE("%s: Expected 5 colon-delimited integers in virtual key definition.", - mTokenizer->getLocation().string()); - return BAD_VALUE; - } - -#if DEBUG_PARSER - ALOGD("Parsed virtual key: scanCode=%d, centerX=%d, centerY=%d, " - "width=%d, height=%d", - defn.scanCode, defn.centerX, defn.centerY, defn.width, defn.height); -#endif - mMap->mVirtualKeys.push(defn); - } while (consumeFieldDelimiterAndSkipWhitespace()); - - if (!mTokenizer->isEol()) { - ALOGE("%s: Expected end of line, got '%s'.", - mTokenizer->getLocation().string(), - mTokenizer->peekRemainderOfLine().string()); - return BAD_VALUE; - } - } - - mTokenizer->nextLine(); - } - - return NO_ERROR; -} - -bool VirtualKeyMap::Parser::consumeFieldDelimiterAndSkipWhitespace() { - mTokenizer->skipDelimiters(WHITESPACE); - if (mTokenizer->peekChar() == ':') { - mTokenizer->nextChar(); - mTokenizer->skipDelimiters(WHITESPACE); - return true; - } - return false; -} - -bool VirtualKeyMap::Parser::parseNextIntField(int32_t* outValue) { - if (!consumeFieldDelimiterAndSkipWhitespace()) { - return false; - } - - String8 token = mTokenizer->nextToken(WHITESPACE_OR_FIELD_DELIMITER); - char* end; - *outValue = strtol(token.string(), &end, 0); - if (token.isEmpty() || *end != '\0') { - ALOGE("Expected an integer, got '%s'.", token.string()); - return false; - } - return true; -} - -} // namespace android diff --git a/libs/ui/tests/Android.mk b/libs/ui/tests/Android.mk index 700b604..50cad36 100644 --- a/libs/ui/tests/Android.mk +++ b/libs/ui/tests/Android.mk @@ -2,47 +2,5 @@ LOCAL_PATH:= $(call my-dir) include $(CLEAR_VARS) -# Build the unit tests. -test_src_files := \ - InputChannel_test.cpp \ - InputEvent_test.cpp \ - InputPublisherAndConsumer_test.cpp - -shared_libraries := \ - libcutils \ - libutils \ - libEGL \ - libbinder \ - libpixelflinger \ - libhardware \ - libhardware_legacy \ - libui \ - libstlport \ - libskia - -static_libraries := \ - libgtest \ - libgtest_main - -c_includes := \ - bionic \ - bionic/libstdc++/include \ - external/gtest/include \ - external/stlport/stlport \ - external/skia/include/core - -module_tags := eng tests - -$(foreach file,$(test_src_files), \ - $(eval include $(CLEAR_VARS)) \ - $(eval LOCAL_SHARED_LIBRARIES := $(shared_libraries)) \ - $(eval LOCAL_STATIC_LIBRARIES := $(static_libraries)) \ - $(eval LOCAL_C_INCLUDES := $(c_includes)) \ - $(eval LOCAL_SRC_FILES := $(file)) \ - $(eval LOCAL_MODULE := $(notdir $(file:%.cpp=%))) \ - $(eval LOCAL_MODULE_TAGS := $(module_tags)) \ - $(eval include $(BUILD_EXECUTABLE)) \ -) - # Build the manual test programs. include $(call all-makefiles-under, $(LOCAL_PATH)) diff --git a/libs/ui/tests/InputChannel_test.cpp b/libs/ui/tests/InputChannel_test.cpp deleted file mode 100644 index 0e5d19d..0000000 --- a/libs/ui/tests/InputChannel_test.cpp +++ /dev/null @@ -1,158 +0,0 @@ -/* - * 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. - */ - -#include <androidfw/InputTransport.h> -#include <utils/Timers.h> -#include <utils/StopWatch.h> -#include <utils/StrongPointer.h> -#include <gtest/gtest.h> -#include <unistd.h> -#include <time.h> -#include <errno.h> - -#include "../../utils/tests/TestHelpers.h" - -namespace android { - -class InputChannelTest : public testing::Test { -protected: - virtual void SetUp() { } - virtual void TearDown() { } -}; - - -TEST_F(InputChannelTest, ConstructorAndDestructor_TakesOwnershipOfFileDescriptors) { - // Our purpose here is to verify that the input channel destructor closes the - // file descriptor provided to it. One easy way is to provide it with one end - // of a pipe and to check for EPIPE on the other end after the channel is destroyed. - Pipe pipe; - - sp<InputChannel> inputChannel = new InputChannel(String8("channel name"), pipe.sendFd); - - EXPECT_STREQ("channel name", inputChannel->getName().string()) - << "channel should have provided name"; - EXPECT_EQ(pipe.sendFd, inputChannel->getFd()) - << "channel should have provided fd"; - - inputChannel.clear(); // destroys input channel - - EXPECT_EQ(-EPIPE, pipe.readSignal()) - << "channel should have closed fd when destroyed"; - - // clean up fds of Pipe endpoints that were closed so we don't try to close them again - pipe.sendFd = -1; -} - -TEST_F(InputChannelTest, OpenInputChannelPair_ReturnsAPairOfConnectedChannels) { - sp<InputChannel> serverChannel, clientChannel; - - status_t result = InputChannel::openInputChannelPair(String8("channel name"), - serverChannel, clientChannel); - - ASSERT_EQ(OK, result) - << "should have successfully opened a channel pair"; - - // Name - EXPECT_STREQ("channel name (server)", serverChannel->getName().string()) - << "server channel should have suffixed name"; - EXPECT_STREQ("channel name (client)", clientChannel->getName().string()) - << "client channel should have suffixed name"; - - // Server->Client communication - InputMessage serverMsg; - memset(&serverMsg, 0, sizeof(InputMessage)); - serverMsg.header.type = InputMessage::TYPE_KEY; - serverMsg.body.key.action = AKEY_EVENT_ACTION_DOWN; - EXPECT_EQ(OK, serverChannel->sendMessage(&serverMsg)) - << "server channel should be able to send message to client channel"; - - InputMessage clientMsg; - EXPECT_EQ(OK, clientChannel->receiveMessage(&clientMsg)) - << "client channel should be able to receive message from server channel"; - EXPECT_EQ(serverMsg.header.type, clientMsg.header.type) - << "client channel should receive the correct message from server channel"; - EXPECT_EQ(serverMsg.body.key.action, clientMsg.body.key.action) - << "client channel should receive the correct message from server channel"; - - // Client->Server communication - InputMessage clientReply; - memset(&clientReply, 0, sizeof(InputMessage)); - clientReply.header.type = InputMessage::TYPE_FINISHED; - clientReply.body.finished.seq = 0x11223344; - clientReply.body.finished.handled = true; - EXPECT_EQ(OK, clientChannel->sendMessage(&clientReply)) - << "client channel should be able to send message to server channel"; - - InputMessage serverReply; - EXPECT_EQ(OK, serverChannel->receiveMessage(&serverReply)) - << "server channel should be able to receive message from client channel"; - EXPECT_EQ(clientReply.header.type, serverReply.header.type) - << "server channel should receive the correct message from client channel"; - EXPECT_EQ(clientReply.body.finished.seq, serverReply.body.finished.seq) - << "server channel should receive the correct message from client channel"; - EXPECT_EQ(clientReply.body.finished.handled, serverReply.body.finished.handled) - << "server channel should receive the correct message from client channel"; -} - -TEST_F(InputChannelTest, ReceiveSignal_WhenNoSignalPresent_ReturnsAnError) { - sp<InputChannel> serverChannel, clientChannel; - - status_t result = InputChannel::openInputChannelPair(String8("channel name"), - serverChannel, clientChannel); - - ASSERT_EQ(OK, result) - << "should have successfully opened a channel pair"; - - InputMessage msg; - EXPECT_EQ(WOULD_BLOCK, clientChannel->receiveMessage(&msg)) - << "receiveMessage should have returned WOULD_BLOCK"; -} - -TEST_F(InputChannelTest, ReceiveSignal_WhenPeerClosed_ReturnsAnError) { - sp<InputChannel> serverChannel, clientChannel; - - status_t result = InputChannel::openInputChannelPair(String8("channel name"), - serverChannel, clientChannel); - - ASSERT_EQ(OK, result) - << "should have successfully opened a channel pair"; - - serverChannel.clear(); // close server channel - - InputMessage msg; - EXPECT_EQ(DEAD_OBJECT, clientChannel->receiveMessage(&msg)) - << "receiveMessage should have returned DEAD_OBJECT"; -} - -TEST_F(InputChannelTest, SendSignal_WhenPeerClosed_ReturnsAnError) { - sp<InputChannel> serverChannel, clientChannel; - - status_t result = InputChannel::openInputChannelPair(String8("channel name"), - serverChannel, clientChannel); - - ASSERT_EQ(OK, result) - << "should have successfully opened a channel pair"; - - serverChannel.clear(); // close server channel - - InputMessage msg; - msg.header.type = InputMessage::TYPE_KEY; - EXPECT_EQ(DEAD_OBJECT, clientChannel->sendMessage(&msg)) - << "sendMessage should have returned DEAD_OBJECT"; -} - - -} // namespace android diff --git a/libs/ui/tests/InputEvent_test.cpp b/libs/ui/tests/InputEvent_test.cpp deleted file mode 100644 index ac5549c..0000000 --- a/libs/ui/tests/InputEvent_test.cpp +++ /dev/null @@ -1,581 +0,0 @@ -/* - * Copyright (C) 2011 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 <androidfw/Input.h> -#include <gtest/gtest.h> -#include <binder/Parcel.h> - -#include <math.h> -#include <SkMatrix.h> - -namespace android { - -class BaseTest : public testing::Test { -protected: - virtual void SetUp() { } - virtual void TearDown() { } -}; - -// --- PointerCoordsTest --- - -class PointerCoordsTest : public BaseTest { -}; - -TEST_F(PointerCoordsTest, ClearSetsBitsToZero) { - PointerCoords coords; - coords.clear(); - - ASSERT_EQ(0ULL, coords.bits); -} - -TEST_F(PointerCoordsTest, AxisValues) { - float* valuePtr; - PointerCoords coords; - coords.clear(); - - // Check invariants when no axes are present. - ASSERT_EQ(0, coords.getAxisValue(0)) - << "getAxisValue should return zero because axis is not present"; - ASSERT_EQ(0, coords.getAxisValue(1)) - << "getAxisValue should return zero because axis is not present"; - - // Set first axis. - ASSERT_EQ(OK, coords.setAxisValue(1, 5)); - ASSERT_EQ(0x00000002ULL, coords.bits); - ASSERT_EQ(5, coords.values[0]); - - ASSERT_EQ(0, coords.getAxisValue(0)) - << "getAxisValue should return zero because axis is not present"; - ASSERT_EQ(5, coords.getAxisValue(1)) - << "getAxisValue should return value of axis"; - - // Set an axis with a higher id than all others. (appending value at the end) - ASSERT_EQ(OK, coords.setAxisValue(3, 2)); - ASSERT_EQ(0x0000000aULL, coords.bits); - ASSERT_EQ(5, coords.values[0]); - ASSERT_EQ(2, coords.values[1]); - - ASSERT_EQ(0, coords.getAxisValue(0)) - << "getAxisValue should return zero because axis is not present"; - ASSERT_EQ(5, coords.getAxisValue(1)) - << "getAxisValue should return value of axis"; - ASSERT_EQ(0, coords.getAxisValue(2)) - << "getAxisValue should return zero because axis is not present"; - ASSERT_EQ(2, coords.getAxisValue(3)) - << "getAxisValue should return value of axis"; - - // Set an axis with an id lower than all others. (prepending value at beginning) - ASSERT_EQ(OK, coords.setAxisValue(0, 4)); - ASSERT_EQ(0x0000000bULL, coords.bits); - ASSERT_EQ(4, coords.values[0]); - ASSERT_EQ(5, coords.values[1]); - ASSERT_EQ(2, coords.values[2]); - - ASSERT_EQ(4, coords.getAxisValue(0)) - << "getAxisValue should return value of axis"; - ASSERT_EQ(5, coords.getAxisValue(1)) - << "getAxisValue should return value of axis"; - ASSERT_EQ(0, coords.getAxisValue(2)) - << "getAxisValue should return zero because axis is not present"; - ASSERT_EQ(2, coords.getAxisValue(3)) - << "getAxisValue should return value of axis"; - - // Set an axis with an id between the others. (inserting value in the middle) - ASSERT_EQ(OK, coords.setAxisValue(2, 1)); - ASSERT_EQ(0x0000000fULL, coords.bits); - ASSERT_EQ(4, coords.values[0]); - ASSERT_EQ(5, coords.values[1]); - ASSERT_EQ(1, coords.values[2]); - ASSERT_EQ(2, coords.values[3]); - - ASSERT_EQ(4, coords.getAxisValue(0)) - << "getAxisValue should return value of axis"; - ASSERT_EQ(5, coords.getAxisValue(1)) - << "getAxisValue should return value of axis"; - ASSERT_EQ(1, coords.getAxisValue(2)) - << "getAxisValue should return value of axis"; - ASSERT_EQ(2, coords.getAxisValue(3)) - << "getAxisValue should return value of axis"; - - // Set an existing axis value in place. - ASSERT_EQ(OK, coords.setAxisValue(1, 6)); - ASSERT_EQ(0x0000000fULL, coords.bits); - ASSERT_EQ(4, coords.values[0]); - ASSERT_EQ(6, coords.values[1]); - ASSERT_EQ(1, coords.values[2]); - ASSERT_EQ(2, coords.values[3]); - - ASSERT_EQ(4, coords.getAxisValue(0)) - << "getAxisValue should return value of axis"; - ASSERT_EQ(6, coords.getAxisValue(1)) - << "getAxisValue should return value of axis"; - ASSERT_EQ(1, coords.getAxisValue(2)) - << "getAxisValue should return value of axis"; - ASSERT_EQ(2, coords.getAxisValue(3)) - << "getAxisValue should return value of axis"; - - // Set maximum number of axes. - for (size_t axis = 4; axis < PointerCoords::MAX_AXES; axis++) { - ASSERT_EQ(OK, coords.setAxisValue(axis, axis)); - } - ASSERT_EQ(PointerCoords::MAX_AXES, __builtin_popcountll(coords.bits)); - - // Try to set one more axis beyond maximum number. - // Ensure bits are unchanged. - ASSERT_EQ(NO_MEMORY, coords.setAxisValue(PointerCoords::MAX_AXES, 100)); - ASSERT_EQ(PointerCoords::MAX_AXES, __builtin_popcountll(coords.bits)); -} - -TEST_F(PointerCoordsTest, Parcel) { - Parcel parcel; - - PointerCoords inCoords; - inCoords.clear(); - PointerCoords outCoords; - - // Round trip with empty coords. - inCoords.writeToParcel(&parcel); - parcel.setDataPosition(0); - outCoords.readFromParcel(&parcel); - - ASSERT_EQ(0ULL, outCoords.bits); - - // Round trip with some values. - parcel.freeData(); - inCoords.setAxisValue(2, 5); - inCoords.setAxisValue(5, 8); - - inCoords.writeToParcel(&parcel); - parcel.setDataPosition(0); - outCoords.readFromParcel(&parcel); - - ASSERT_EQ(outCoords.bits, inCoords.bits); - ASSERT_EQ(outCoords.values[0], inCoords.values[0]); - ASSERT_EQ(outCoords.values[1], inCoords.values[1]); -} - - -// --- KeyEventTest --- - -class KeyEventTest : public BaseTest { -}; - -TEST_F(KeyEventTest, Properties) { - KeyEvent event; - - // Initialize and get properties. - const nsecs_t ARBITRARY_DOWN_TIME = 1; - const nsecs_t ARBITRARY_EVENT_TIME = 2; - event.initialize(2, AINPUT_SOURCE_GAMEPAD, AKEY_EVENT_ACTION_DOWN, - AKEY_EVENT_FLAG_FROM_SYSTEM, AKEYCODE_BUTTON_X, 121, - AMETA_ALT_ON, 1, ARBITRARY_DOWN_TIME, ARBITRARY_EVENT_TIME); - - ASSERT_EQ(AINPUT_EVENT_TYPE_KEY, event.getType()); - ASSERT_EQ(2, event.getDeviceId()); - ASSERT_EQ(AINPUT_SOURCE_GAMEPAD, event.getSource()); - ASSERT_EQ(AKEY_EVENT_ACTION_DOWN, event.getAction()); - ASSERT_EQ(AKEY_EVENT_FLAG_FROM_SYSTEM, event.getFlags()); - ASSERT_EQ(AKEYCODE_BUTTON_X, event.getKeyCode()); - ASSERT_EQ(121, event.getScanCode()); - ASSERT_EQ(AMETA_ALT_ON, event.getMetaState()); - ASSERT_EQ(1, event.getRepeatCount()); - ASSERT_EQ(ARBITRARY_DOWN_TIME, event.getDownTime()); - ASSERT_EQ(ARBITRARY_EVENT_TIME, event.getEventTime()); - - // Set source. - event.setSource(AINPUT_SOURCE_JOYSTICK); - ASSERT_EQ(AINPUT_SOURCE_JOYSTICK, event.getSource()); -} - - -// --- MotionEventTest --- - -class MotionEventTest : public BaseTest { -protected: - static const nsecs_t ARBITRARY_DOWN_TIME; - static const nsecs_t ARBITRARY_EVENT_TIME; - static const float X_OFFSET; - static const float Y_OFFSET; - - void initializeEventWithHistory(MotionEvent* event); - void assertEqualsEventWithHistory(const MotionEvent* event); -}; - -const nsecs_t MotionEventTest::ARBITRARY_DOWN_TIME = 1; -const nsecs_t MotionEventTest::ARBITRARY_EVENT_TIME = 2; -const float MotionEventTest::X_OFFSET = 1.0f; -const float MotionEventTest::Y_OFFSET = 1.1f; - -void MotionEventTest::initializeEventWithHistory(MotionEvent* event) { - PointerProperties pointerProperties[2]; - pointerProperties[0].clear(); - pointerProperties[0].id = 1; - pointerProperties[0].toolType = AMOTION_EVENT_TOOL_TYPE_FINGER; - pointerProperties[1].clear(); - pointerProperties[1].id = 2; - pointerProperties[1].toolType = AMOTION_EVENT_TOOL_TYPE_STYLUS; - - PointerCoords pointerCoords[2]; - pointerCoords[0].clear(); - pointerCoords[0].setAxisValue(AMOTION_EVENT_AXIS_X, 10); - pointerCoords[0].setAxisValue(AMOTION_EVENT_AXIS_Y, 11); - pointerCoords[0].setAxisValue(AMOTION_EVENT_AXIS_PRESSURE, 12); - pointerCoords[0].setAxisValue(AMOTION_EVENT_AXIS_SIZE, 13); - pointerCoords[0].setAxisValue(AMOTION_EVENT_AXIS_TOUCH_MAJOR, 14); - pointerCoords[0].setAxisValue(AMOTION_EVENT_AXIS_TOUCH_MINOR, 15); - pointerCoords[0].setAxisValue(AMOTION_EVENT_AXIS_TOOL_MAJOR, 16); - pointerCoords[0].setAxisValue(AMOTION_EVENT_AXIS_TOOL_MINOR, 17); - pointerCoords[0].setAxisValue(AMOTION_EVENT_AXIS_ORIENTATION, 18); - pointerCoords[1].clear(); - pointerCoords[1].setAxisValue(AMOTION_EVENT_AXIS_X, 20); - pointerCoords[1].setAxisValue(AMOTION_EVENT_AXIS_Y, 21); - pointerCoords[1].setAxisValue(AMOTION_EVENT_AXIS_PRESSURE, 22); - pointerCoords[1].setAxisValue(AMOTION_EVENT_AXIS_SIZE, 23); - pointerCoords[1].setAxisValue(AMOTION_EVENT_AXIS_TOUCH_MAJOR, 24); - pointerCoords[1].setAxisValue(AMOTION_EVENT_AXIS_TOUCH_MINOR, 25); - pointerCoords[1].setAxisValue(AMOTION_EVENT_AXIS_TOOL_MAJOR, 26); - pointerCoords[1].setAxisValue(AMOTION_EVENT_AXIS_TOOL_MINOR, 27); - pointerCoords[1].setAxisValue(AMOTION_EVENT_AXIS_ORIENTATION, 28); - event->initialize(2, AINPUT_SOURCE_TOUCHSCREEN, AMOTION_EVENT_ACTION_MOVE, - AMOTION_EVENT_FLAG_WINDOW_IS_OBSCURED, - AMOTION_EVENT_EDGE_FLAG_TOP, AMETA_ALT_ON, AMOTION_EVENT_BUTTON_PRIMARY, - X_OFFSET, Y_OFFSET, 2.0f, 2.1f, - ARBITRARY_DOWN_TIME, ARBITRARY_EVENT_TIME, - 2, pointerProperties, pointerCoords); - - pointerCoords[0].setAxisValue(AMOTION_EVENT_AXIS_X, 110); - pointerCoords[0].setAxisValue(AMOTION_EVENT_AXIS_Y, 111); - pointerCoords[0].setAxisValue(AMOTION_EVENT_AXIS_PRESSURE, 112); - pointerCoords[0].setAxisValue(AMOTION_EVENT_AXIS_SIZE, 113); - pointerCoords[0].setAxisValue(AMOTION_EVENT_AXIS_TOUCH_MAJOR, 114); - pointerCoords[0].setAxisValue(AMOTION_EVENT_AXIS_TOUCH_MINOR, 115); - pointerCoords[0].setAxisValue(AMOTION_EVENT_AXIS_TOOL_MAJOR, 116); - pointerCoords[0].setAxisValue(AMOTION_EVENT_AXIS_TOOL_MINOR, 117); - pointerCoords[0].setAxisValue(AMOTION_EVENT_AXIS_ORIENTATION, 118); - pointerCoords[1].setAxisValue(AMOTION_EVENT_AXIS_X, 120); - pointerCoords[1].setAxisValue(AMOTION_EVENT_AXIS_Y, 121); - pointerCoords[1].setAxisValue(AMOTION_EVENT_AXIS_PRESSURE, 122); - pointerCoords[1].setAxisValue(AMOTION_EVENT_AXIS_SIZE, 123); - pointerCoords[1].setAxisValue(AMOTION_EVENT_AXIS_TOUCH_MAJOR, 124); - pointerCoords[1].setAxisValue(AMOTION_EVENT_AXIS_TOUCH_MINOR, 125); - pointerCoords[1].setAxisValue(AMOTION_EVENT_AXIS_TOOL_MAJOR, 126); - pointerCoords[1].setAxisValue(AMOTION_EVENT_AXIS_TOOL_MINOR, 127); - pointerCoords[1].setAxisValue(AMOTION_EVENT_AXIS_ORIENTATION, 128); - event->addSample(ARBITRARY_EVENT_TIME + 1, pointerCoords); - - pointerCoords[0].setAxisValue(AMOTION_EVENT_AXIS_X, 210); - pointerCoords[0].setAxisValue(AMOTION_EVENT_AXIS_Y, 211); - pointerCoords[0].setAxisValue(AMOTION_EVENT_AXIS_PRESSURE, 212); - pointerCoords[0].setAxisValue(AMOTION_EVENT_AXIS_SIZE, 213); - pointerCoords[0].setAxisValue(AMOTION_EVENT_AXIS_TOUCH_MAJOR, 214); - pointerCoords[0].setAxisValue(AMOTION_EVENT_AXIS_TOUCH_MINOR, 215); - pointerCoords[0].setAxisValue(AMOTION_EVENT_AXIS_TOOL_MAJOR, 216); - pointerCoords[0].setAxisValue(AMOTION_EVENT_AXIS_TOOL_MINOR, 217); - pointerCoords[0].setAxisValue(AMOTION_EVENT_AXIS_ORIENTATION, 218); - pointerCoords[1].setAxisValue(AMOTION_EVENT_AXIS_X, 220); - pointerCoords[1].setAxisValue(AMOTION_EVENT_AXIS_Y, 221); - pointerCoords[1].setAxisValue(AMOTION_EVENT_AXIS_PRESSURE, 222); - pointerCoords[1].setAxisValue(AMOTION_EVENT_AXIS_SIZE, 223); - pointerCoords[1].setAxisValue(AMOTION_EVENT_AXIS_TOUCH_MAJOR, 224); - pointerCoords[1].setAxisValue(AMOTION_EVENT_AXIS_TOUCH_MINOR, 225); - pointerCoords[1].setAxisValue(AMOTION_EVENT_AXIS_TOOL_MAJOR, 226); - pointerCoords[1].setAxisValue(AMOTION_EVENT_AXIS_TOOL_MINOR, 227); - pointerCoords[1].setAxisValue(AMOTION_EVENT_AXIS_ORIENTATION, 228); - event->addSample(ARBITRARY_EVENT_TIME + 2, pointerCoords); -} - -void MotionEventTest::assertEqualsEventWithHistory(const MotionEvent* event) { - // Check properties. - ASSERT_EQ(AINPUT_EVENT_TYPE_MOTION, event->getType()); - ASSERT_EQ(2, event->getDeviceId()); - ASSERT_EQ(AINPUT_SOURCE_TOUCHSCREEN, event->getSource()); - ASSERT_EQ(AMOTION_EVENT_ACTION_MOVE, event->getAction()); - ASSERT_EQ(AMOTION_EVENT_FLAG_WINDOW_IS_OBSCURED, event->getFlags()); - ASSERT_EQ(AMOTION_EVENT_EDGE_FLAG_TOP, event->getEdgeFlags()); - ASSERT_EQ(AMETA_ALT_ON, event->getMetaState()); - ASSERT_EQ(AMOTION_EVENT_BUTTON_PRIMARY, event->getButtonState()); - ASSERT_EQ(X_OFFSET, event->getXOffset()); - ASSERT_EQ(Y_OFFSET, event->getYOffset()); - ASSERT_EQ(2.0f, event->getXPrecision()); - ASSERT_EQ(2.1f, event->getYPrecision()); - ASSERT_EQ(ARBITRARY_DOWN_TIME, event->getDownTime()); - - ASSERT_EQ(2U, event->getPointerCount()); - ASSERT_EQ(1, event->getPointerId(0)); - ASSERT_EQ(AMOTION_EVENT_TOOL_TYPE_FINGER, event->getToolType(0)); - ASSERT_EQ(2, event->getPointerId(1)); - ASSERT_EQ(AMOTION_EVENT_TOOL_TYPE_STYLUS, event->getToolType(1)); - - ASSERT_EQ(2U, event->getHistorySize()); - - // Check data. - ASSERT_EQ(ARBITRARY_EVENT_TIME, event->getHistoricalEventTime(0)); - ASSERT_EQ(ARBITRARY_EVENT_TIME + 1, event->getHistoricalEventTime(1)); - ASSERT_EQ(ARBITRARY_EVENT_TIME + 2, event->getEventTime()); - - ASSERT_EQ(11, event->getHistoricalRawPointerCoords(0, 0)-> - getAxisValue(AMOTION_EVENT_AXIS_Y)); - ASSERT_EQ(21, event->getHistoricalRawPointerCoords(1, 0)-> - getAxisValue(AMOTION_EVENT_AXIS_Y)); - ASSERT_EQ(111, event->getHistoricalRawPointerCoords(0, 1)-> - getAxisValue(AMOTION_EVENT_AXIS_Y)); - ASSERT_EQ(121, event->getHistoricalRawPointerCoords(1, 1)-> - getAxisValue(AMOTION_EVENT_AXIS_Y)); - ASSERT_EQ(211, event->getRawPointerCoords(0)-> - getAxisValue(AMOTION_EVENT_AXIS_Y)); - ASSERT_EQ(221, event->getRawPointerCoords(1)-> - getAxisValue(AMOTION_EVENT_AXIS_Y)); - - ASSERT_EQ(11, event->getHistoricalRawAxisValue(AMOTION_EVENT_AXIS_Y, 0, 0)); - ASSERT_EQ(21, event->getHistoricalRawAxisValue(AMOTION_EVENT_AXIS_Y, 1, 0)); - ASSERT_EQ(111, event->getHistoricalRawAxisValue(AMOTION_EVENT_AXIS_Y, 0, 1)); - ASSERT_EQ(121, event->getHistoricalRawAxisValue(AMOTION_EVENT_AXIS_Y, 1, 1)); - ASSERT_EQ(211, event->getRawAxisValue(AMOTION_EVENT_AXIS_Y, 0)); - ASSERT_EQ(221, event->getRawAxisValue(AMOTION_EVENT_AXIS_Y, 1)); - - ASSERT_EQ(10, event->getHistoricalRawX(0, 0)); - ASSERT_EQ(20, event->getHistoricalRawX(1, 0)); - ASSERT_EQ(110, event->getHistoricalRawX(0, 1)); - ASSERT_EQ(120, event->getHistoricalRawX(1, 1)); - ASSERT_EQ(210, event->getRawX(0)); - ASSERT_EQ(220, event->getRawX(1)); - - ASSERT_EQ(11, event->getHistoricalRawY(0, 0)); - ASSERT_EQ(21, event->getHistoricalRawY(1, 0)); - ASSERT_EQ(111, event->getHistoricalRawY(0, 1)); - ASSERT_EQ(121, event->getHistoricalRawY(1, 1)); - ASSERT_EQ(211, event->getRawY(0)); - ASSERT_EQ(221, event->getRawY(1)); - - ASSERT_EQ(X_OFFSET + 10, event->getHistoricalX(0, 0)); - ASSERT_EQ(X_OFFSET + 20, event->getHistoricalX(1, 0)); - ASSERT_EQ(X_OFFSET + 110, event->getHistoricalX(0, 1)); - ASSERT_EQ(X_OFFSET + 120, event->getHistoricalX(1, 1)); - ASSERT_EQ(X_OFFSET + 210, event->getX(0)); - ASSERT_EQ(X_OFFSET + 220, event->getX(1)); - - ASSERT_EQ(Y_OFFSET + 11, event->getHistoricalY(0, 0)); - ASSERT_EQ(Y_OFFSET + 21, event->getHistoricalY(1, 0)); - ASSERT_EQ(Y_OFFSET + 111, event->getHistoricalY(0, 1)); - ASSERT_EQ(Y_OFFSET + 121, event->getHistoricalY(1, 1)); - ASSERT_EQ(Y_OFFSET + 211, event->getY(0)); - ASSERT_EQ(Y_OFFSET + 221, event->getY(1)); - - ASSERT_EQ(12, event->getHistoricalPressure(0, 0)); - ASSERT_EQ(22, event->getHistoricalPressure(1, 0)); - ASSERT_EQ(112, event->getHistoricalPressure(0, 1)); - ASSERT_EQ(122, event->getHistoricalPressure(1, 1)); - ASSERT_EQ(212, event->getPressure(0)); - ASSERT_EQ(222, event->getPressure(1)); - - ASSERT_EQ(13, event->getHistoricalSize(0, 0)); - ASSERT_EQ(23, event->getHistoricalSize(1, 0)); - ASSERT_EQ(113, event->getHistoricalSize(0, 1)); - ASSERT_EQ(123, event->getHistoricalSize(1, 1)); - ASSERT_EQ(213, event->getSize(0)); - ASSERT_EQ(223, event->getSize(1)); - - ASSERT_EQ(14, event->getHistoricalTouchMajor(0, 0)); - ASSERT_EQ(24, event->getHistoricalTouchMajor(1, 0)); - ASSERT_EQ(114, event->getHistoricalTouchMajor(0, 1)); - ASSERT_EQ(124, event->getHistoricalTouchMajor(1, 1)); - ASSERT_EQ(214, event->getTouchMajor(0)); - ASSERT_EQ(224, event->getTouchMajor(1)); - - ASSERT_EQ(15, event->getHistoricalTouchMinor(0, 0)); - ASSERT_EQ(25, event->getHistoricalTouchMinor(1, 0)); - ASSERT_EQ(115, event->getHistoricalTouchMinor(0, 1)); - ASSERT_EQ(125, event->getHistoricalTouchMinor(1, 1)); - ASSERT_EQ(215, event->getTouchMinor(0)); - ASSERT_EQ(225, event->getTouchMinor(1)); - - ASSERT_EQ(16, event->getHistoricalToolMajor(0, 0)); - ASSERT_EQ(26, event->getHistoricalToolMajor(1, 0)); - ASSERT_EQ(116, event->getHistoricalToolMajor(0, 1)); - ASSERT_EQ(126, event->getHistoricalToolMajor(1, 1)); - ASSERT_EQ(216, event->getToolMajor(0)); - ASSERT_EQ(226, event->getToolMajor(1)); - - ASSERT_EQ(17, event->getHistoricalToolMinor(0, 0)); - ASSERT_EQ(27, event->getHistoricalToolMinor(1, 0)); - ASSERT_EQ(117, event->getHistoricalToolMinor(0, 1)); - ASSERT_EQ(127, event->getHistoricalToolMinor(1, 1)); - ASSERT_EQ(217, event->getToolMinor(0)); - ASSERT_EQ(227, event->getToolMinor(1)); - - ASSERT_EQ(18, event->getHistoricalOrientation(0, 0)); - ASSERT_EQ(28, event->getHistoricalOrientation(1, 0)); - ASSERT_EQ(118, event->getHistoricalOrientation(0, 1)); - ASSERT_EQ(128, event->getHistoricalOrientation(1, 1)); - ASSERT_EQ(218, event->getOrientation(0)); - ASSERT_EQ(228, event->getOrientation(1)); -} - -TEST_F(MotionEventTest, Properties) { - MotionEvent event; - - // Initialize, add samples and check properties. - initializeEventWithHistory(&event); - ASSERT_NO_FATAL_FAILURE(assertEqualsEventWithHistory(&event)); - - // Set source. - event.setSource(AINPUT_SOURCE_JOYSTICK); - ASSERT_EQ(AINPUT_SOURCE_JOYSTICK, event.getSource()); - - // Set action. - event.setAction(AMOTION_EVENT_ACTION_CANCEL); - ASSERT_EQ(AMOTION_EVENT_ACTION_CANCEL, event.getAction()); - - // Set meta state. - event.setMetaState(AMETA_CTRL_ON); - ASSERT_EQ(AMETA_CTRL_ON, event.getMetaState()); -} - -TEST_F(MotionEventTest, CopyFrom_KeepHistory) { - MotionEvent event; - initializeEventWithHistory(&event); - - MotionEvent copy; - copy.copyFrom(&event, true /*keepHistory*/); - - ASSERT_NO_FATAL_FAILURE(assertEqualsEventWithHistory(&event)); -} - -TEST_F(MotionEventTest, CopyFrom_DoNotKeepHistory) { - MotionEvent event; - initializeEventWithHistory(&event); - - MotionEvent copy; - copy.copyFrom(&event, false /*keepHistory*/); - - ASSERT_EQ(event.getPointerCount(), copy.getPointerCount()); - ASSERT_EQ(0U, copy.getHistorySize()); - - ASSERT_EQ(event.getPointerId(0), copy.getPointerId(0)); - ASSERT_EQ(event.getPointerId(1), copy.getPointerId(1)); - - ASSERT_EQ(event.getEventTime(), copy.getEventTime()); - - ASSERT_EQ(event.getX(0), copy.getX(0)); -} - -TEST_F(MotionEventTest, OffsetLocation) { - MotionEvent event; - initializeEventWithHistory(&event); - - event.offsetLocation(5.0f, -2.0f); - - ASSERT_EQ(X_OFFSET + 5.0f, event.getXOffset()); - ASSERT_EQ(Y_OFFSET - 2.0f, event.getYOffset()); -} - -TEST_F(MotionEventTest, Scale) { - MotionEvent event; - initializeEventWithHistory(&event); - - event.scale(2.0f); - - ASSERT_EQ(X_OFFSET * 2, event.getXOffset()); - ASSERT_EQ(Y_OFFSET * 2, event.getYOffset()); - - ASSERT_EQ(210 * 2, event.getRawX(0)); - ASSERT_EQ(211 * 2, event.getRawY(0)); - ASSERT_EQ((X_OFFSET + 210) * 2, event.getX(0)); - ASSERT_EQ((Y_OFFSET + 211) * 2, event.getY(0)); - ASSERT_EQ(212, event.getPressure(0)); - ASSERT_EQ(213, event.getSize(0)); - ASSERT_EQ(214 * 2, event.getTouchMajor(0)); - ASSERT_EQ(215 * 2, event.getTouchMinor(0)); - ASSERT_EQ(216 * 2, event.getToolMajor(0)); - ASSERT_EQ(217 * 2, event.getToolMinor(0)); - ASSERT_EQ(218, event.getOrientation(0)); -} - -TEST_F(MotionEventTest, Parcel) { - Parcel parcel; - - MotionEvent inEvent; - initializeEventWithHistory(&inEvent); - MotionEvent outEvent; - - // Round trip. - inEvent.writeToParcel(&parcel); - parcel.setDataPosition(0); - outEvent.readFromParcel(&parcel); - - ASSERT_NO_FATAL_FAILURE(assertEqualsEventWithHistory(&outEvent)); -} - -TEST_F(MotionEventTest, Transform) { - // Generate some points on a circle. - // Each point 'i' is a point on a circle of radius ROTATION centered at (3,2) at an angle - // of ARC * i degrees clockwise relative to the Y axis. - // The geometrical representation is irrelevant to the test, it's just easy to generate - // and check rotation. We set the orientation to the same angle. - // Coordinate system: down is increasing Y, right is increasing X. - const float PI_180 = float(M_PI / 180); - const float RADIUS = 10; - const float ARC = 36; - const float ROTATION = ARC * 2; - - const size_t pointerCount = 11; - PointerProperties pointerProperties[pointerCount]; - PointerCoords pointerCoords[pointerCount]; - for (size_t i = 0; i < pointerCount; i++) { - float angle = float(i * ARC * PI_180); - pointerProperties[i].clear(); - pointerProperties[i].id = i; - pointerCoords[i].clear(); - pointerCoords[i].setAxisValue(AMOTION_EVENT_AXIS_X, sinf(angle) * RADIUS + 3); - pointerCoords[i].setAxisValue(AMOTION_EVENT_AXIS_Y, -cosf(angle) * RADIUS + 2); - pointerCoords[i].setAxisValue(AMOTION_EVENT_AXIS_ORIENTATION, angle); - } - MotionEvent event; - event.initialize(0, 0, AMOTION_EVENT_ACTION_MOVE, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, pointerCount, pointerProperties, pointerCoords); - float originalRawX = 0 + 3; - float originalRawY = -RADIUS + 2; - - // Check original raw X and Y assumption. - ASSERT_NEAR(originalRawX, event.getRawX(0), 0.001); - ASSERT_NEAR(originalRawY, event.getRawY(0), 0.001); - - // Now translate the motion event so the circle's origin is at (0,0). - event.offsetLocation(-3, -2); - - // Offsetting the location should preserve the raw X and Y of the first point. - ASSERT_NEAR(originalRawX, event.getRawX(0), 0.001); - ASSERT_NEAR(originalRawY, event.getRawY(0), 0.001); - - // Apply a rotation about the origin by ROTATION degrees clockwise. - SkMatrix matrix; - matrix.setRotate(ROTATION); - event.transform(&matrix); - - // Check the points. - for (size_t i = 0; i < pointerCount; i++) { - float angle = float((i * ARC + ROTATION) * PI_180); - ASSERT_NEAR(sinf(angle) * RADIUS, event.getX(i), 0.001); - ASSERT_NEAR(-cosf(angle) * RADIUS, event.getY(i), 0.001); - ASSERT_NEAR(tanf(angle), tanf(event.getOrientation(i)), 0.1); - } - - // Applying the transformation should preserve the raw X and Y of the first point. - ASSERT_NEAR(originalRawX, event.getRawX(0), 0.001); - ASSERT_NEAR(originalRawY, event.getRawY(0), 0.001); -} - -} // namespace android diff --git a/libs/ui/tests/InputPublisherAndConsumer_test.cpp b/libs/ui/tests/InputPublisherAndConsumer_test.cpp deleted file mode 100644 index bb45247..0000000 --- a/libs/ui/tests/InputPublisherAndConsumer_test.cpp +++ /dev/null @@ -1,287 +0,0 @@ -/* - * 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. - */ - -#include <androidfw/InputTransport.h> -#include <utils/Timers.h> -#include <utils/StopWatch.h> -#include <gtest/gtest.h> -#include <unistd.h> -#include <time.h> -#include <sys/mman.h> -#include <cutils/ashmem.h> - -#include "../../utils/tests/TestHelpers.h" - -namespace android { - -class InputPublisherAndConsumerTest : public testing::Test { -protected: - sp<InputChannel> serverChannel, clientChannel; - InputPublisher* mPublisher; - InputConsumer* mConsumer; - PreallocatedInputEventFactory mEventFactory; - - virtual void SetUp() { - status_t result = InputChannel::openInputChannelPair(String8("channel name"), - serverChannel, clientChannel); - - mPublisher = new InputPublisher(serverChannel); - mConsumer = new InputConsumer(clientChannel); - } - - virtual void TearDown() { - if (mPublisher) { - delete mPublisher; - mPublisher = NULL; - } - - if (mConsumer) { - delete mConsumer; - mConsumer = NULL; - } - - serverChannel.clear(); - clientChannel.clear(); - } - - void PublishAndConsumeKeyEvent(); - void PublishAndConsumeMotionEvent(); -}; - -TEST_F(InputPublisherAndConsumerTest, GetChannel_ReturnsTheChannel) { - EXPECT_EQ(serverChannel.get(), mPublisher->getChannel().get()); - EXPECT_EQ(clientChannel.get(), mConsumer->getChannel().get()); -} - -void InputPublisherAndConsumerTest::PublishAndConsumeKeyEvent() { - status_t status; - - const uint32_t seq = 15; - const int32_t deviceId = 1; - const int32_t source = AINPUT_SOURCE_KEYBOARD; - const int32_t action = AKEY_EVENT_ACTION_DOWN; - const int32_t flags = AKEY_EVENT_FLAG_FROM_SYSTEM; - const int32_t keyCode = AKEYCODE_ENTER; - const int32_t scanCode = 13; - const int32_t metaState = AMETA_ALT_LEFT_ON | AMETA_ALT_ON; - const int32_t repeatCount = 1; - const nsecs_t downTime = 3; - const nsecs_t eventTime = 4; - - status = mPublisher->publishKeyEvent(seq, deviceId, source, action, flags, - keyCode, scanCode, metaState, repeatCount, downTime, eventTime); - ASSERT_EQ(OK, status) - << "publisher publishKeyEvent should return OK"; - - uint32_t consumeSeq; - InputEvent* event; - status = mConsumer->consume(&mEventFactory, true /*consumeBatches*/, &consumeSeq, &event); - ASSERT_EQ(OK, status) - << "consumer consume should return OK"; - - ASSERT_TRUE(event != NULL) - << "consumer should have returned non-NULL event"; - ASSERT_EQ(AINPUT_EVENT_TYPE_KEY, event->getType()) - << "consumer should have returned a key event"; - - KeyEvent* keyEvent = static_cast<KeyEvent*>(event); - EXPECT_EQ(seq, consumeSeq); - EXPECT_EQ(deviceId, keyEvent->getDeviceId()); - EXPECT_EQ(source, keyEvent->getSource()); - EXPECT_EQ(action, keyEvent->getAction()); - EXPECT_EQ(flags, keyEvent->getFlags()); - EXPECT_EQ(keyCode, keyEvent->getKeyCode()); - EXPECT_EQ(scanCode, keyEvent->getScanCode()); - EXPECT_EQ(metaState, keyEvent->getMetaState()); - EXPECT_EQ(repeatCount, keyEvent->getRepeatCount()); - EXPECT_EQ(downTime, keyEvent->getDownTime()); - EXPECT_EQ(eventTime, keyEvent->getEventTime()); - - status = mConsumer->sendFinishedSignal(seq, true); - ASSERT_EQ(OK, status) - << "consumer sendFinishedSignal should return OK"; - - uint32_t finishedSeq = 0; - bool handled = false; - status = mPublisher->receiveFinishedSignal(&finishedSeq, &handled); - ASSERT_EQ(OK, status) - << "publisher receiveFinishedSignal should return OK"; - ASSERT_EQ(seq, finishedSeq) - << "publisher receiveFinishedSignal should have returned the original sequence number"; - ASSERT_TRUE(handled) - << "publisher receiveFinishedSignal should have set handled to consumer's reply"; -} - -void InputPublisherAndConsumerTest::PublishAndConsumeMotionEvent() { - status_t status; - - const uint32_t seq = 15; - const int32_t deviceId = 1; - const int32_t source = AINPUT_SOURCE_TOUCHSCREEN; - const int32_t action = AMOTION_EVENT_ACTION_MOVE; - const int32_t flags = AMOTION_EVENT_FLAG_WINDOW_IS_OBSCURED; - const int32_t edgeFlags = AMOTION_EVENT_EDGE_FLAG_TOP; - const int32_t metaState = AMETA_ALT_LEFT_ON | AMETA_ALT_ON; - const int32_t buttonState = AMOTION_EVENT_BUTTON_PRIMARY; - const float xOffset = -10; - const float yOffset = -20; - const float xPrecision = 0.25; - const float yPrecision = 0.5; - const nsecs_t downTime = 3; - const size_t pointerCount = 3; - const nsecs_t eventTime = 4; - PointerProperties pointerProperties[pointerCount]; - PointerCoords pointerCoords[pointerCount]; - for (size_t i = 0; i < pointerCount; i++) { - pointerProperties[i].clear(); - pointerProperties[i].id = (i + 2) % pointerCount; - pointerProperties[i].toolType = AMOTION_EVENT_TOOL_TYPE_FINGER; - - pointerCoords[i].clear(); - pointerCoords[i].setAxisValue(AMOTION_EVENT_AXIS_X, 100 * i); - pointerCoords[i].setAxisValue(AMOTION_EVENT_AXIS_Y, 200 * i); - pointerCoords[i].setAxisValue(AMOTION_EVENT_AXIS_PRESSURE, 0.5 * i); - pointerCoords[i].setAxisValue(AMOTION_EVENT_AXIS_SIZE, 0.7 * i); - pointerCoords[i].setAxisValue(AMOTION_EVENT_AXIS_TOUCH_MAJOR, 1.5 * i); - pointerCoords[i].setAxisValue(AMOTION_EVENT_AXIS_TOUCH_MINOR, 1.7 * i); - pointerCoords[i].setAxisValue(AMOTION_EVENT_AXIS_TOOL_MAJOR, 2.5 * i); - pointerCoords[i].setAxisValue(AMOTION_EVENT_AXIS_TOOL_MAJOR, 2.7 * i); - pointerCoords[i].setAxisValue(AMOTION_EVENT_AXIS_ORIENTATION, 3.5 * i); - } - - status = mPublisher->publishMotionEvent(seq, deviceId, source, action, flags, edgeFlags, - metaState, buttonState, xOffset, yOffset, xPrecision, yPrecision, - downTime, eventTime, pointerCount, - pointerProperties, pointerCoords); - ASSERT_EQ(OK, status) - << "publisher publishMotionEvent should return OK"; - - uint32_t consumeSeq; - InputEvent* event; - status = mConsumer->consume(&mEventFactory, true /*consumeBatches*/, &consumeSeq, &event); - ASSERT_EQ(OK, status) - << "consumer consume should return OK"; - - ASSERT_TRUE(event != NULL) - << "consumer should have returned non-NULL event"; - ASSERT_EQ(AINPUT_EVENT_TYPE_MOTION, event->getType()) - << "consumer should have returned a motion event"; - - MotionEvent* motionEvent = static_cast<MotionEvent*>(event); - EXPECT_EQ(seq, consumeSeq); - EXPECT_EQ(deviceId, motionEvent->getDeviceId()); - EXPECT_EQ(source, motionEvent->getSource()); - EXPECT_EQ(action, motionEvent->getAction()); - EXPECT_EQ(flags, motionEvent->getFlags()); - EXPECT_EQ(edgeFlags, motionEvent->getEdgeFlags()); - EXPECT_EQ(metaState, motionEvent->getMetaState()); - EXPECT_EQ(buttonState, motionEvent->getButtonState()); - EXPECT_EQ(xPrecision, motionEvent->getXPrecision()); - EXPECT_EQ(yPrecision, motionEvent->getYPrecision()); - EXPECT_EQ(downTime, motionEvent->getDownTime()); - EXPECT_EQ(eventTime, motionEvent->getEventTime()); - EXPECT_EQ(pointerCount, motionEvent->getPointerCount()); - EXPECT_EQ(0U, motionEvent->getHistorySize()); - - for (size_t i = 0; i < pointerCount; i++) { - SCOPED_TRACE(i); - EXPECT_EQ(pointerProperties[i].id, motionEvent->getPointerId(i)); - EXPECT_EQ(pointerProperties[i].toolType, motionEvent->getToolType(i)); - - EXPECT_EQ(pointerCoords[i].getAxisValue(AMOTION_EVENT_AXIS_X), - motionEvent->getRawX(i)); - EXPECT_EQ(pointerCoords[i].getAxisValue(AMOTION_EVENT_AXIS_Y), - motionEvent->getRawY(i)); - EXPECT_EQ(pointerCoords[i].getAxisValue(AMOTION_EVENT_AXIS_X) + xOffset, - motionEvent->getX(i)); - EXPECT_EQ(pointerCoords[i].getAxisValue(AMOTION_EVENT_AXIS_Y) + yOffset, - motionEvent->getY(i)); - EXPECT_EQ(pointerCoords[i].getAxisValue(AMOTION_EVENT_AXIS_PRESSURE), - motionEvent->getPressure(i)); - EXPECT_EQ(pointerCoords[i].getAxisValue(AMOTION_EVENT_AXIS_SIZE), - motionEvent->getSize(i)); - EXPECT_EQ(pointerCoords[i].getAxisValue(AMOTION_EVENT_AXIS_TOUCH_MAJOR), - motionEvent->getTouchMajor(i)); - EXPECT_EQ(pointerCoords[i].getAxisValue(AMOTION_EVENT_AXIS_TOUCH_MINOR), - motionEvent->getTouchMinor(i)); - EXPECT_EQ(pointerCoords[i].getAxisValue(AMOTION_EVENT_AXIS_TOOL_MAJOR), - motionEvent->getToolMajor(i)); - EXPECT_EQ(pointerCoords[i].getAxisValue(AMOTION_EVENT_AXIS_TOOL_MINOR), - motionEvent->getToolMinor(i)); - EXPECT_EQ(pointerCoords[i].getAxisValue(AMOTION_EVENT_AXIS_ORIENTATION), - motionEvent->getOrientation(i)); - } - - status = mConsumer->sendFinishedSignal(seq, false); - ASSERT_EQ(OK, status) - << "consumer sendFinishedSignal should return OK"; - - uint32_t finishedSeq = 0; - bool handled = true; - status = mPublisher->receiveFinishedSignal(&finishedSeq, &handled); - ASSERT_EQ(OK, status) - << "publisher receiveFinishedSignal should return OK"; - ASSERT_EQ(seq, finishedSeq) - << "publisher receiveFinishedSignal should have returned the original sequence number"; - ASSERT_FALSE(handled) - << "publisher receiveFinishedSignal should have set handled to consumer's reply"; -} - -TEST_F(InputPublisherAndConsumerTest, PublishKeyEvent_EndToEnd) { - ASSERT_NO_FATAL_FAILURE(PublishAndConsumeKeyEvent()); -} - -TEST_F(InputPublisherAndConsumerTest, PublishMotionEvent_EndToEnd) { - ASSERT_NO_FATAL_FAILURE(PublishAndConsumeMotionEvent()); -} - -TEST_F(InputPublisherAndConsumerTest, PublishMotionEvent_WhenPointerCountLessThan1_ReturnsError) { - status_t status; - const size_t pointerCount = 0; - PointerProperties pointerProperties[pointerCount]; - PointerCoords pointerCoords[pointerCount]; - - status = mPublisher->publishMotionEvent(0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - pointerCount, pointerProperties, pointerCoords); - ASSERT_EQ(BAD_VALUE, status) - << "publisher publishMotionEvent should return BAD_VALUE"; -} - -TEST_F(InputPublisherAndConsumerTest, PublishMotionEvent_WhenPointerCountGreaterThanMax_ReturnsError) { - status_t status; - const size_t pointerCount = MAX_POINTERS + 1; - PointerProperties pointerProperties[pointerCount]; - PointerCoords pointerCoords[pointerCount]; - for (size_t i = 0; i < pointerCount; i++) { - pointerProperties[i].clear(); - pointerCoords[i].clear(); - } - - status = mPublisher->publishMotionEvent(0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - pointerCount, pointerProperties, pointerCoords); - ASSERT_EQ(BAD_VALUE, status) - << "publisher publishMotionEvent should return BAD_VALUE"; -} - -TEST_F(InputPublisherAndConsumerTest, PublishMultipleEvents_EndToEnd) { - ASSERT_NO_FATAL_FAILURE(PublishAndConsumeMotionEvent()); - ASSERT_NO_FATAL_FAILURE(PublishAndConsumeKeyEvent()); - ASSERT_NO_FATAL_FAILURE(PublishAndConsumeMotionEvent()); - ASSERT_NO_FATAL_FAILURE(PublishAndConsumeMotionEvent()); - ASSERT_NO_FATAL_FAILURE(PublishAndConsumeKeyEvent()); -} - -} // namespace android |