diff options
Diffstat (limited to 'services')
-rw-r--r-- | services/input/InputDispatcher.cpp | 1 | ||||
-rw-r--r-- | services/input/InputReader.cpp | 455 | ||||
-rw-r--r-- | services/input/InputReader.h | 45 | ||||
-rw-r--r-- | services/input/InputWindow.h | 5 | ||||
-rw-r--r-- | services/input/tests/InputReader_test.cpp | 19 | ||||
-rw-r--r-- | services/java/com/android/server/wm/InputMonitor.java | 5 | ||||
-rw-r--r-- | services/java/com/android/server/wm/InputWindow.java | 3 | ||||
-rw-r--r-- | services/jni/com_android_server_InputManager.cpp | 37 | ||||
-rw-r--r-- | services/jni/com_android_server_InputWindow.cpp | 6 |
9 files changed, 344 insertions, 232 deletions
diff --git a/services/input/InputDispatcher.cpp b/services/input/InputDispatcher.cpp index 28df3fb..4a50d8a 100644 --- a/services/input/InputDispatcher.cpp +++ b/services/input/InputDispatcher.cpp @@ -3395,6 +3395,7 @@ void InputDispatcher::dumpDispatchStateLocked(String8& dump) { window.frameRight, window.frameBottom, window.scaleFactor); dumpRegion(dump, window.touchableRegion); + dump.appendFormat(", inputFeatures=0x%08x", window.inputFeatures); dump.appendFormat(", ownerPid=%d, ownerUid=%d, dispatchingTimeout=%0.3fms\n", window.ownerPid, window.ownerUid, window.dispatchingTimeout / 1000000.0); diff --git a/services/input/InputReader.cpp b/services/input/InputReader.cpp index 2b61570..3e4c666 100644 --- a/services/input/InputReader.cpp +++ b/services/input/InputReader.cpp @@ -38,7 +38,6 @@ #include "InputReader.h" -#include <cutils/atomic.h> #include <cutils/log.h> #include <ui/Keyboard.h> #include <ui/VirtualKeyMap.h> @@ -245,8 +244,8 @@ InputReader::InputReader(const sp<EventHubInterface>& eventHub, const sp<InputDispatcherInterface>& dispatcher) : mEventHub(eventHub), mPolicy(policy), mDispatcher(dispatcher), mGlobalMetaState(0), mDisableVirtualKeysTimeout(LLONG_MIN), mNextTimeout(LLONG_MAX), - mRefreshConfiguration(0) { - configure(true /*firstTime*/); + mConfigurationChangesToRefresh(0) { + refreshConfiguration(0); updateGlobalMetaState(); updateInputConfiguration(); } @@ -258,9 +257,16 @@ InputReader::~InputReader() { } void InputReader::loopOnce() { - if (android_atomic_acquire_load(&mRefreshConfiguration)) { - android_atomic_release_store(0, &mRefreshConfiguration); - configure(false /*firstTime*/); + uint32_t changes; + { // acquire lock + AutoMutex _l(mStateLock); + + changes = mConfigurationChangesToRefresh; + mConfigurationChangesToRefresh = 0; + } // release lock + + if (changes) { + refreshConfiguration(changes); } int32_t timeoutMillis = -1; @@ -326,7 +332,7 @@ void InputReader::addDevice(int32_t deviceId) { uint32_t classes = mEventHub->getDeviceClasses(deviceId); InputDevice* device = createDevice(deviceId, name, classes); - device->configure(); + device->configure(&mConfig, 0); if (device->isIgnored()) { LOGI("Device added: id=%d, name='%s' (ignored non-input device)", deviceId, name.string()); @@ -483,12 +489,25 @@ void InputReader::handleConfigurationChanged(nsecs_t when) { mDispatcher->notifyConfigurationChanged(when); } -void InputReader::configure(bool firstTime) { +void InputReader::refreshConfiguration(uint32_t changes) { mPolicy->getReaderConfiguration(&mConfig); mEventHub->setExcludedDevices(mConfig.excludedDeviceNames); - if (!firstTime) { - mEventHub->requestReopenDevices(); + if (changes) { + LOGI("Reconfiguring input devices. changes=0x%08x", changes); + + if (changes & InputReaderConfiguration::CHANGE_MUST_REOPEN) { + mEventHub->requestReopenDevices(); + } else { + { // acquire device registry reader lock + RWLock::AutoRLock _rl(mDeviceRegistryLock); + + for (size_t i = 0; i < mDevices.size(); i++) { + InputDevice* device = mDevices.valueAt(i); + device->configure(&mConfig, changes); + } + } // release device registry reader lock + } } } @@ -709,10 +728,20 @@ bool InputReader::markSupportedKeyCodes(int32_t deviceId, uint32_t sourceMask, s } // release device registy reader lock } -void InputReader::refreshConfiguration() { - android_atomic_release_store(1, &mRefreshConfiguration); +void InputReader::requestRefreshConfiguration(uint32_t changes) { + if (changes) { + bool needWake; + { // acquire lock + AutoMutex _l(mStateLock); + + needWake = !mConfigurationChangesToRefresh; + mConfigurationChangesToRefresh |= changes; + } // release lock - mEventHub->wake(); + if (needWake) { + mEventHub->wake(); + } + } } void InputReader::dump(String8& dump) { @@ -760,6 +789,8 @@ void InputReader::dump(String8& dump) { mConfig.wheelVelocityControlParameters.acceleration); dump.appendFormat(INDENT2 "PointerGesture:\n"); + dump.appendFormat(INDENT3 "Enabled: %s\n", + toString(mConfig.pointerGesturesEnabled)); dump.appendFormat(INDENT3 "QuietInterval: %0.1fms\n", mConfig.pointerGestureQuietInterval * 0.000001f); dump.appendFormat(INDENT3 "DragMinSwitchSpeed: %0.1fpx/s\n", @@ -855,18 +886,20 @@ void InputDevice::addMapper(InputMapper* mapper) { mMappers.add(mapper); } -void InputDevice::configure() { - if (! isIgnored()) { - mContext->getEventHub()->getConfiguration(mId, &mConfiguration); - } - +void InputDevice::configure(const InputReaderConfiguration* config, uint32_t changes) { mSources = 0; - size_t numMappers = mMappers.size(); - for (size_t i = 0; i < numMappers; i++) { - InputMapper* mapper = mMappers[i]; - mapper->configure(); - mSources |= mapper->getSources(); + if (!isIgnored()) { + if (!changes) { // first time only + mContext->getEventHub()->getConfiguration(mId, &mConfiguration); + } + + size_t numMappers = mMappers.size(); + for (size_t i = 0; i < numMappers; i++) { + InputMapper* mapper = mMappers[i]; + mapper->configure(config, changes); + mSources |= mapper->getSources(); + } } } @@ -1010,7 +1043,7 @@ void InputMapper::populateDeviceInfo(InputDeviceInfo* info) { void InputMapper::dump(String8& dump) { } -void InputMapper::configure() { +void InputMapper::configure(const InputReaderConfiguration* config, uint32_t changes) { } void InputMapper::reset() { @@ -1124,16 +1157,18 @@ void KeyboardInputMapper::dump(String8& dump) { } -void KeyboardInputMapper::configure() { - InputMapper::configure(); +void KeyboardInputMapper::configure(const InputReaderConfiguration* config, uint32_t changes) { + InputMapper::configure(config, changes); - // Configure basic parameters. - configureParameters(); + if (!changes) { // first time only + // Configure basic parameters. + configureParameters(); - // Reset LEDs. - { - AutoMutex _l(mLock); - resetLedStateLocked(); + // Reset LEDs. + { + AutoMutex _l(mLock); + resetLedStateLocked(); + } } } @@ -1411,40 +1446,44 @@ void CursorInputMapper::dump(String8& dump) { } // release lock } -void CursorInputMapper::configure() { - InputMapper::configure(); +void CursorInputMapper::configure(const InputReaderConfiguration* config, uint32_t changes) { + InputMapper::configure(config, changes); - // Configure basic parameters. - configureParameters(); + if (!changes) { // first time only + // Configure basic parameters. + configureParameters(); - // Configure device mode. - switch (mParameters.mode) { - case Parameters::MODE_POINTER: - mSource = AINPUT_SOURCE_MOUSE; - mXPrecision = 1.0f; - mYPrecision = 1.0f; - mXScale = 1.0f; - mYScale = 1.0f; - mPointerController = getPolicy()->obtainPointerController(getDeviceId()); - break; - case Parameters::MODE_NAVIGATION: - mSource = AINPUT_SOURCE_TRACKBALL; - mXPrecision = TRACKBALL_MOVEMENT_THRESHOLD; - mYPrecision = TRACKBALL_MOVEMENT_THRESHOLD; - mXScale = 1.0f / TRACKBALL_MOVEMENT_THRESHOLD; - mYScale = 1.0f / TRACKBALL_MOVEMENT_THRESHOLD; - break; - } + // Configure device mode. + switch (mParameters.mode) { + case Parameters::MODE_POINTER: + mSource = AINPUT_SOURCE_MOUSE; + mXPrecision = 1.0f; + mYPrecision = 1.0f; + mXScale = 1.0f; + mYScale = 1.0f; + mPointerController = getPolicy()->obtainPointerController(getDeviceId()); + break; + case Parameters::MODE_NAVIGATION: + mSource = AINPUT_SOURCE_TRACKBALL; + mXPrecision = TRACKBALL_MOVEMENT_THRESHOLD; + mYPrecision = TRACKBALL_MOVEMENT_THRESHOLD; + mXScale = 1.0f / TRACKBALL_MOVEMENT_THRESHOLD; + mYScale = 1.0f / TRACKBALL_MOVEMENT_THRESHOLD; + break; + } - mVWheelScale = 1.0f; - mHWheelScale = 1.0f; + mVWheelScale = 1.0f; + mHWheelScale = 1.0f; - mHaveVWheel = getEventHub()->hasRelativeAxis(getDeviceId(), REL_WHEEL); - mHaveHWheel = getEventHub()->hasRelativeAxis(getDeviceId(), REL_HWHEEL); + mHaveVWheel = getEventHub()->hasRelativeAxis(getDeviceId(), REL_WHEEL); + mHaveHWheel = getEventHub()->hasRelativeAxis(getDeviceId(), REL_HWHEEL); + } - mPointerVelocityControl.setParameters(getConfig()->pointerVelocityControlParameters); - mWheelXVelocityControl.setParameters(getConfig()->wheelVelocityControlParameters); - mWheelYVelocityControl.setParameters(getConfig()->wheelVelocityControlParameters); + if (!changes || (changes & InputReaderConfiguration::CHANGE_POINTER_SPEED)) { + mPointerVelocityControl.setParameters(config->pointerVelocityControlParameters); + mWheelXVelocityControl.setParameters(config->wheelVelocityControlParameters); + mWheelYVelocityControl.setParameters(config->wheelVelocityControlParameters); + } } void CursorInputMapper::configureParameters() { @@ -1787,8 +1826,6 @@ void CursorInputMapper::fadePointer() { TouchInputMapper::TouchInputMapper(InputDevice* device) : InputMapper(device) { - mConfig = getConfig(); - mLocked.surfaceOrientation = -1; mLocked.surfaceWidth = -1; mLocked.surfaceHeight = -1; @@ -1925,52 +1962,65 @@ void TouchInputMapper::initializeLocked() { mLocked.orientedRanges.haveDistance = false; mPointerGesture.reset(); - mPointerGesture.pointerVelocityControl.setParameters(mConfig->pointerVelocityControlParameters); } -void TouchInputMapper::configure() { - InputMapper::configure(); +void TouchInputMapper::configure(const InputReaderConfiguration* config, uint32_t changes) { + InputMapper::configure(config, changes); - // Configure basic parameters. - configureParameters(); + mConfig = *config; - // Configure sources. - switch (mParameters.deviceType) { - case Parameters::DEVICE_TYPE_TOUCH_SCREEN: - mTouchSource = AINPUT_SOURCE_TOUCHSCREEN; - mPointerSource = 0; - break; - case Parameters::DEVICE_TYPE_TOUCH_PAD: - mTouchSource = AINPUT_SOURCE_TOUCHPAD; - mPointerSource = 0; - break; - case Parameters::DEVICE_TYPE_POINTER: - mTouchSource = AINPUT_SOURCE_TOUCHPAD; - mPointerSource = AINPUT_SOURCE_MOUSE; - break; - default: - LOG_ASSERT(false); - } + if (!changes) { // first time only + // Configure basic parameters. + configureParameters(); + + // Configure sources. + switch (mParameters.deviceType) { + case Parameters::DEVICE_TYPE_TOUCH_SCREEN: + mTouchSource = AINPUT_SOURCE_TOUCHSCREEN; + mPointerSource = 0; + break; + case Parameters::DEVICE_TYPE_TOUCH_PAD: + mTouchSource = AINPUT_SOURCE_TOUCHPAD; + mPointerSource = 0; + break; + case Parameters::DEVICE_TYPE_POINTER: + mTouchSource = AINPUT_SOURCE_TOUCHPAD; + mPointerSource = AINPUT_SOURCE_MOUSE; + break; + default: + LOG_ASSERT(false); + } - // Configure absolute axis information. - configureRawAxes(); + // Configure absolute axis information. + configureRawAxes(); - // Prepare input device calibration. - parseCalibration(); - resolveCalibration(); + // Prepare input device calibration. + parseCalibration(); + resolveCalibration(); - { // acquire lock - AutoMutex _l(mLock); + { // acquire lock + AutoMutex _l(mLock); - // Configure surface dimensions and orientation. - configureSurfaceLocked(); - } // release lock + // Configure surface dimensions and orientation. + configureSurfaceLocked(); + } // release lock + } + + if (!changes || (changes & InputReaderConfiguration::CHANGE_POINTER_SPEED)) { + mPointerGesture.pointerVelocityControl.setParameters( + mConfig.pointerVelocityControlParameters); + } + + if (!changes || (changes & InputReaderConfiguration::CHANGE_POINTER_GESTURE_ENABLEMENT)) { + // Reset the touch screen when pointer gesture enablement changes. + reset(); + } } void TouchInputMapper::configureParameters() { - mParameters.useBadTouchFilter = mConfig->filterTouchEvents; - mParameters.useAveragingTouchFilter = mConfig->filterTouchEvents; - mParameters.useJumpyTouchFilter = mConfig->filterJumpyTouchEvents; + mParameters.useBadTouchFilter = mConfig.filterTouchEvents; + mParameters.useAveragingTouchFilter = mConfig.filterTouchEvents; + mParameters.useJumpyTouchFilter = mConfig.filterJumpyTouchEvents; // Use the pointer presentation mode for devices that do not support distinct // multitouch. The spot-based presentation relies on being able to accurately @@ -2401,14 +2451,14 @@ bool TouchInputMapper::configureSurfaceLocked() { // is applied. // Assume that the touch pad has a square aspect ratio such that movements in // X and Y of the same number of raw units cover the same physical distance. - mLocked.pointerGestureXMovementScale = mConfig->pointerGestureMovementSpeedRatio + mLocked.pointerGestureXMovementScale = mConfig.pointerGestureMovementSpeedRatio * displayDiagonal / rawDiagonal; mLocked.pointerGestureYMovementScale = mLocked.pointerGestureXMovementScale; // Scale zooms to cover a smaller range of the display than movements do. // This value determines the area around the pointer that is affected by freeform // pointer gestures. - mLocked.pointerGestureXZoomScale = mConfig->pointerGestureZoomSpeedRatio + mLocked.pointerGestureXZoomScale = mConfig.pointerGestureZoomSpeedRatio * displayDiagonal / rawDiagonal; mLocked.pointerGestureYZoomScale = mLocked.pointerGestureXZoomScale; @@ -2416,7 +2466,7 @@ bool TouchInputMapper::configureSurfaceLocked() { // of the diagonal axis of the touch pad. Touches that are wider than this are // translated into freeform gestures. mLocked.pointerGestureMaxSwipeWidth = - mConfig->pointerGestureSwipeMaxWidthRatio * rawDiagonal; + mConfig.pointerGestureSwipeMaxWidthRatio * rawDiagonal; // Reset the current pointer gesture. mPointerGesture.reset(); @@ -2902,6 +2952,7 @@ void TouchInputMapper::reset() { if (mPointerController != NULL && mParameters.gestureMode == Parameters::GESTURE_MODE_SPOTS) { + mPointerController->fade(PointerControllerInterface::TRANSITION_GRADUAL); mPointerController->clearSpots(); } } // release lock @@ -2982,7 +3033,7 @@ void TouchInputMapper::syncTouch(nsecs_t when, bool havePointerIds) { touchResult = consumeOffScreenTouches(when, policyFlags); if (touchResult == DISPATCH_TOUCH) { suppressSwipeOntoVirtualKeys(when); - if (mPointerController != NULL) { + if (mPointerController != NULL && mConfig.pointerGesturesEnabled) { dispatchPointerGestures(when, policyFlags, false /*isTimeout*/); } dispatchTouches(when, policyFlags); @@ -3139,8 +3190,8 @@ void TouchInputMapper::suppressSwipeOntoVirtualKeys(nsecs_t when) { // area and accidentally triggers a virtual key. This often happens when virtual keys // are layed out below the screen near to where the on screen keyboard's space bar // is displayed. - if (mConfig->virtualKeyQuietTime > 0 && mCurrentTouch.pointerCount != 0) { - mContext->disableVirtualKeysUntil(when + mConfig->virtualKeyQuietTime); + if (mConfig.virtualKeyQuietTime > 0 && mCurrentTouch.pointerCount != 0) { + mContext->disableVirtualKeysUntil(when + mConfig.virtualKeyQuietTime); } } @@ -3688,10 +3739,10 @@ bool TouchInputMapper::preparePointerGestures(nsecs_t when, #endif if (mPointerGesture.lastGestureMode == PointerGesture::TAP) { - if (when <= mPointerGesture.tapUpTime + mConfig->pointerGestureTapDragInterval) { + if (when <= mPointerGesture.tapUpTime + mConfig.pointerGestureTapDragInterval) { // The tap/drag timeout has not yet expired. getContext()->requestTimeoutAtTime(mPointerGesture.tapUpTime - + mConfig->pointerGestureTapDragInterval); + + mConfig.pointerGestureTapDragInterval); } else { // The tap is finished. #if DEBUG_GESTURES @@ -3756,7 +3807,7 @@ bool TouchInputMapper::preparePointerGestures(nsecs_t when, if (activeTouchId < 0) { mPointerGesture.resetQuietTime(); } else { - isQuietTime = when < mPointerGesture.quietTime + mConfig->pointerGestureQuietInterval; + isQuietTime = when < mPointerGesture.quietTime + mConfig.pointerGestureQuietInterval; if (!isQuietTime) { if ((mPointerGesture.lastGestureMode == PointerGesture::PRESS || mPointerGesture.lastGestureMode == PointerGesture::SWIPE @@ -3785,7 +3836,7 @@ bool TouchInputMapper::preparePointerGestures(nsecs_t when, // Case 1: Quiet time. (QUIET) #if DEBUG_GESTURES LOGD("Gestures: QUIET for next %0.3fms", (mPointerGesture.quietTime - + mConfig->pointerGestureQuietInterval - when) * 0.000001f); + + mConfig.pointerGestureQuietInterval - when) * 0.000001f); #endif if (mPointerGesture.lastGestureMode != PointerGesture::QUIET) { *outFinishPreviousGesture = true; @@ -3824,7 +3875,7 @@ bool TouchInputMapper::preparePointerGestures(nsecs_t when, // Find the fastest pointer and follow it. if (activeTouchId >= 0 && mCurrentTouch.pointerCount > 1) { int32_t bestId = -1; - float bestSpeed = mConfig->pointerGestureDragMinSwitchSpeed; + float bestSpeed = mConfig.pointerGestureDragMinSwitchSpeed; for (uint32_t i = 0; i < mCurrentTouch.pointerCount; i++) { uint32_t id = mCurrentTouch.pointers[i].id; float vx, vy; @@ -3893,18 +3944,18 @@ bool TouchInputMapper::preparePointerGestures(nsecs_t when, if ((mPointerGesture.lastGestureMode == PointerGesture::HOVER || mPointerGesture.lastGestureMode == PointerGesture::TAP_DRAG) && mLastTouch.pointerCount == 1) { - if (when <= mPointerGesture.tapDownTime + mConfig->pointerGestureTapInterval) { + if (when <= mPointerGesture.tapDownTime + mConfig.pointerGestureTapInterval) { float x, y; mPointerController->getPosition(&x, &y); - if (fabs(x - mPointerGesture.tapX) <= mConfig->pointerGestureTapSlop - && fabs(y - mPointerGesture.tapY) <= mConfig->pointerGestureTapSlop) { + if (fabs(x - mPointerGesture.tapX) <= mConfig.pointerGestureTapSlop + && fabs(y - mPointerGesture.tapY) <= mConfig.pointerGestureTapSlop) { #if DEBUG_GESTURES LOGD("Gestures: TAP"); #endif mPointerGesture.tapUpTime = when; getContext()->requestTimeoutAtTime(when - + mConfig->pointerGestureTapDragInterval); + + mConfig.pointerGestureTapDragInterval); mPointerGesture.activeGestureId = 0; mPointerGesture.currentGestureMode = PointerGesture::TAP; @@ -3961,11 +4012,11 @@ bool TouchInputMapper::preparePointerGestures(nsecs_t when, mPointerGesture.currentGestureMode = PointerGesture::HOVER; if (mPointerGesture.lastGestureMode == PointerGesture::TAP) { - if (when <= mPointerGesture.tapUpTime + mConfig->pointerGestureTapDragInterval) { + if (when <= mPointerGesture.tapUpTime + mConfig.pointerGestureTapDragInterval) { float x, y; mPointerController->getPosition(&x, &y); - if (fabs(x - mPointerGesture.tapX) <= mConfig->pointerGestureTapSlop - && fabs(y - mPointerGesture.tapY) <= mConfig->pointerGestureTapSlop) { + if (fabs(x - mPointerGesture.tapX) <= mConfig.pointerGestureTapSlop + && fabs(y - mPointerGesture.tapY) <= mConfig.pointerGestureTapSlop) { mPointerGesture.currentGestureMode = PointerGesture::TAP_DRAG; } else { #if DEBUG_GESTURES @@ -4059,7 +4110,7 @@ bool TouchInputMapper::preparePointerGestures(nsecs_t when, LOG_ASSERT(activeTouchId >= 0); bool settled = when >= mPointerGesture.firstTouchTime - + mConfig->pointerGestureMultitouchSettleInterval; + + mConfig.pointerGestureMultitouchSettleInterval; if (mPointerGesture.lastGestureMode != PointerGesture::PRESS && mPointerGesture.lastGestureMode != PointerGesture::SWIPE && mPointerGesture.lastGestureMode != PointerGesture::FREEFORM) { @@ -4070,7 +4121,7 @@ bool TouchInputMapper::preparePointerGestures(nsecs_t when, #if DEBUG_GESTURES LOGD("Gestures: Resetting gesture since additional pointers went down for MULTITOUCH, " "settle time remaining %0.3fms", (mPointerGesture.firstTouchTime - + mConfig->pointerGestureMultitouchSettleInterval - when) + + mConfig.pointerGestureMultitouchSettleInterval - when) * 0.000001f); #endif *outCancelPreviousGesture = true; @@ -4089,7 +4140,7 @@ bool TouchInputMapper::preparePointerGestures(nsecs_t when, #if DEBUG_GESTURES LOGD("Gestures: Using centroid as reference for MULTITOUCH, " "settle time remaining %0.3fms", (mPointerGesture.firstTouchTime - + mConfig->pointerGestureMultitouchSettleInterval - when) + + mConfig.pointerGestureMultitouchSettleInterval - when) * 0.000001f); #endif mCurrentTouch.getCentroid(&mPointerGesture.referenceTouchX, @@ -4143,7 +4194,7 @@ bool TouchInputMapper::preparePointerGestures(nsecs_t when, PointerGesture::Delta& delta = mPointerGesture.referenceDeltas[id]; dist[id] = hypotf(delta.dx * mLocked.pointerGestureXZoomScale, delta.dy * mLocked.pointerGestureYZoomScale); - if (dist[id] > mConfig->pointerGestureMultitouchMinDistance) { + if (dist[id] > mConfig.pointerGestureMultitouchMinDistance) { distOverThreshold += 1; } } @@ -4179,8 +4230,8 @@ bool TouchInputMapper::preparePointerGestures(nsecs_t when, uint32_t id2 = mCurrentTouch.pointers[1].id; float dist1 = dist[id1]; float dist2 = dist[id2]; - if (dist1 >= mConfig->pointerGestureMultitouchMinDistance - && dist2 >= mConfig->pointerGestureMultitouchMinDistance) { + if (dist1 >= mConfig.pointerGestureMultitouchMinDistance + && dist2 >= mConfig.pointerGestureMultitouchMinDistance) { // Calculate the dot product of the displacement vectors. // When the vectors are oriented in approximately the same direction, // the angle betweeen them is near zero and the cosine of the angle @@ -4193,15 +4244,15 @@ bool TouchInputMapper::preparePointerGestures(nsecs_t when, float dy2 = delta2.dy * mLocked.pointerGestureYZoomScale; float dot = dx1 * dx2 + dy1 * dy2; float cosine = dot / (dist1 * dist2); // denominator always > 0 - if (cosine >= mConfig->pointerGestureSwipeTransitionAngleCosine) { + if (cosine >= mConfig.pointerGestureSwipeTransitionAngleCosine) { // Pointers are moving in the same direction. Switch to SWIPE. #if DEBUG_GESTURES LOGD("Gestures: PRESS transitioned to SWIPE, " "dist1 %0.3f >= %0.3f, dist2 %0.3f >= %0.3f, " "cosine %0.3f >= %0.3f", - dist1, mConfig->pointerGestureMultitouchMinDistance, - dist2, mConfig->pointerGestureMultitouchMinDistance, - cosine, mConfig->pointerGestureSwipeTransitionAngleCosine); + dist1, mConfig.pointerGestureMultitouchMinDistance, + dist2, mConfig.pointerGestureMultitouchMinDistance, + cosine, mConfig.pointerGestureSwipeTransitionAngleCosine); #endif mPointerGesture.currentGestureMode = PointerGesture::SWIPE; } else { @@ -4210,9 +4261,9 @@ bool TouchInputMapper::preparePointerGestures(nsecs_t when, LOGD("Gestures: PRESS transitioned to FREEFORM, " "dist1 %0.3f >= %0.3f, dist2 %0.3f >= %0.3f, " "cosine %0.3f < %0.3f", - dist1, mConfig->pointerGestureMultitouchMinDistance, - dist2, mConfig->pointerGestureMultitouchMinDistance, - cosine, mConfig->pointerGestureSwipeTransitionAngleCosine); + dist1, mConfig.pointerGestureMultitouchMinDistance, + dist2, mConfig.pointerGestureMultitouchMinDistance, + cosine, mConfig.pointerGestureSwipeTransitionAngleCosine); #endif *outCancelPreviousGesture = true; mPointerGesture.currentGestureMode = PointerGesture::FREEFORM; @@ -5665,85 +5716,87 @@ void JoystickInputMapper::dump(String8& dump) { } } -void JoystickInputMapper::configure() { - InputMapper::configure(); +void JoystickInputMapper::configure(const InputReaderConfiguration* config, uint32_t changes) { + InputMapper::configure(config, changes); - // Collect all axes. - for (int32_t abs = 0; abs <= ABS_MAX; abs++) { - RawAbsoluteAxisInfo rawAxisInfo; - getEventHub()->getAbsoluteAxisInfo(getDeviceId(), abs, &rawAxisInfo); - if (rawAxisInfo.valid) { - // Map axis. - AxisInfo axisInfo; - bool explicitlyMapped = !getEventHub()->mapAxis(getDeviceId(), abs, &axisInfo); - if (!explicitlyMapped) { - // Axis is not explicitly mapped, will choose a generic axis later. - axisInfo.mode = AxisInfo::MODE_NORMAL; - axisInfo.axis = -1; - } + if (!changes) { // first time only + // Collect all axes. + for (int32_t abs = 0; abs <= ABS_MAX; abs++) { + RawAbsoluteAxisInfo rawAxisInfo; + getEventHub()->getAbsoluteAxisInfo(getDeviceId(), abs, &rawAxisInfo); + if (rawAxisInfo.valid) { + // Map axis. + AxisInfo axisInfo; + bool explicitlyMapped = !getEventHub()->mapAxis(getDeviceId(), abs, &axisInfo); + if (!explicitlyMapped) { + // Axis is not explicitly mapped, will choose a generic axis later. + axisInfo.mode = AxisInfo::MODE_NORMAL; + axisInfo.axis = -1; + } - // Apply flat override. - int32_t rawFlat = axisInfo.flatOverride < 0 - ? rawAxisInfo.flat : axisInfo.flatOverride; - - // Calculate scaling factors and limits. - Axis axis; - if (axisInfo.mode == AxisInfo::MODE_SPLIT) { - float scale = 1.0f / (axisInfo.splitValue - rawAxisInfo.minValue); - float highScale = 1.0f / (rawAxisInfo.maxValue - axisInfo.splitValue); - axis.initialize(rawAxisInfo, axisInfo, explicitlyMapped, - scale, 0.0f, highScale, 0.0f, - 0.0f, 1.0f, rawFlat * scale, rawAxisInfo.fuzz * scale); - } else if (isCenteredAxis(axisInfo.axis)) { - float scale = 2.0f / (rawAxisInfo.maxValue - rawAxisInfo.minValue); - float offset = avg(rawAxisInfo.minValue, rawAxisInfo.maxValue) * -scale; - axis.initialize(rawAxisInfo, axisInfo, explicitlyMapped, - scale, offset, scale, offset, - -1.0f, 1.0f, rawFlat * scale, rawAxisInfo.fuzz * scale); - } else { - float scale = 1.0f / (rawAxisInfo.maxValue - rawAxisInfo.minValue); - axis.initialize(rawAxisInfo, axisInfo, explicitlyMapped, - scale, 0.0f, scale, 0.0f, - 0.0f, 1.0f, rawFlat * scale, rawAxisInfo.fuzz * scale); - } + // Apply flat override. + int32_t rawFlat = axisInfo.flatOverride < 0 + ? rawAxisInfo.flat : axisInfo.flatOverride; + + // Calculate scaling factors and limits. + Axis axis; + if (axisInfo.mode == AxisInfo::MODE_SPLIT) { + float scale = 1.0f / (axisInfo.splitValue - rawAxisInfo.minValue); + float highScale = 1.0f / (rawAxisInfo.maxValue - axisInfo.splitValue); + axis.initialize(rawAxisInfo, axisInfo, explicitlyMapped, + scale, 0.0f, highScale, 0.0f, + 0.0f, 1.0f, rawFlat * scale, rawAxisInfo.fuzz * scale); + } else if (isCenteredAxis(axisInfo.axis)) { + float scale = 2.0f / (rawAxisInfo.maxValue - rawAxisInfo.minValue); + float offset = avg(rawAxisInfo.minValue, rawAxisInfo.maxValue) * -scale; + axis.initialize(rawAxisInfo, axisInfo, explicitlyMapped, + scale, offset, scale, offset, + -1.0f, 1.0f, rawFlat * scale, rawAxisInfo.fuzz * scale); + } else { + float scale = 1.0f / (rawAxisInfo.maxValue - rawAxisInfo.minValue); + axis.initialize(rawAxisInfo, axisInfo, explicitlyMapped, + scale, 0.0f, scale, 0.0f, + 0.0f, 1.0f, rawFlat * scale, rawAxisInfo.fuzz * scale); + } - // To eliminate noise while the joystick is at rest, filter out small variations - // in axis values up front. - axis.filter = axis.flat * 0.25f; + // To eliminate noise while the joystick is at rest, filter out small variations + // in axis values up front. + axis.filter = axis.flat * 0.25f; - mAxes.add(abs, axis); + mAxes.add(abs, axis); + } } - } - // If there are too many axes, start dropping them. - // Prefer to keep explicitly mapped axes. - if (mAxes.size() > PointerCoords::MAX_AXES) { - LOGI("Joystick '%s' has %d axes but the framework only supports a maximum of %d.", - getDeviceName().string(), mAxes.size(), PointerCoords::MAX_AXES); - pruneAxes(true); - pruneAxes(false); - } - - // Assign generic axis ids to remaining axes. - int32_t nextGenericAxisId = AMOTION_EVENT_AXIS_GENERIC_1; - size_t numAxes = mAxes.size(); - for (size_t i = 0; i < numAxes; i++) { - Axis& axis = mAxes.editValueAt(i); - if (axis.axisInfo.axis < 0) { - while (nextGenericAxisId <= AMOTION_EVENT_AXIS_GENERIC_16 - && haveAxis(nextGenericAxisId)) { - nextGenericAxisId += 1; - } + // If there are too many axes, start dropping them. + // Prefer to keep explicitly mapped axes. + if (mAxes.size() > PointerCoords::MAX_AXES) { + LOGI("Joystick '%s' has %d axes but the framework only supports a maximum of %d.", + getDeviceName().string(), mAxes.size(), PointerCoords::MAX_AXES); + pruneAxes(true); + pruneAxes(false); + } + + // Assign generic axis ids to remaining axes. + int32_t nextGenericAxisId = AMOTION_EVENT_AXIS_GENERIC_1; + size_t numAxes = mAxes.size(); + for (size_t i = 0; i < numAxes; i++) { + Axis& axis = mAxes.editValueAt(i); + if (axis.axisInfo.axis < 0) { + while (nextGenericAxisId <= AMOTION_EVENT_AXIS_GENERIC_16 + && haveAxis(nextGenericAxisId)) { + nextGenericAxisId += 1; + } - if (nextGenericAxisId <= AMOTION_EVENT_AXIS_GENERIC_16) { - axis.axisInfo.axis = nextGenericAxisId; - nextGenericAxisId += 1; - } else { - LOGI("Ignoring joystick '%s' axis %d because all of the generic axis ids " - "have already been assigned to other axes.", - getDeviceName().string(), mAxes.keyAt(i)); - mAxes.removeItemsAt(i--); - numAxes -= 1; + if (nextGenericAxisId <= AMOTION_EVENT_AXIS_GENERIC_16) { + axis.axisInfo.axis = nextGenericAxisId; + nextGenericAxisId += 1; + } else { + LOGI("Ignoring joystick '%s' axis %d because all of the generic axis ids " + "have already been assigned to other axes.", + getDeviceName().string(), mAxes.keyAt(i)); + mAxes.removeItemsAt(i--); + numAxes -= 1; + } } } } diff --git a/services/input/InputReader.h b/services/input/InputReader.h index 55315f7..288ff4e 100644 --- a/services/input/InputReader.h +++ b/services/input/InputReader.h @@ -45,6 +45,18 @@ class InputMapper; * Specifies various options that modify the behavior of the input reader. */ struct InputReaderConfiguration { + // Describes changes that have occurred. + enum { + // The pointer speed changed. + CHANGE_POINTER_SPEED = 1 << 0, + + // The pointer gesture control changed. + CHANGE_POINTER_GESTURE_ENABLEMENT = 1 << 1, + + // All devices must be reopened. + CHANGE_MUST_REOPEN = 1 << 31, + }; + // Determines whether to turn on some hacks we have to improve the touch interaction with a // certain device whose screen currently is not all that good. bool filterTouchEvents; @@ -68,6 +80,9 @@ struct InputReaderConfiguration { // Velocity control parameters for mouse wheel movements. VelocityControlParameters wheelVelocityControlParameters; + // True if pointer gestures are enabled. + bool pointerGesturesEnabled; + // Quiet time between certain pointer gesture transitions. // Time to allow for all fingers or buttons to settle into a stable state before // starting a new gesture. @@ -136,6 +151,7 @@ struct InputReaderConfiguration { virtualKeyQuietTime(0), pointerVelocityControlParameters(1.0f, 500.0f, 3000.0f, 3.0f), wheelVelocityControlParameters(1.0f, 15.0f, 50.0f, 4.0f), + pointerGesturesEnabled(true), pointerGestureQuietInterval(100 * 1000000LL), // 100 ms pointerGestureDragMinSwitchSpeed(50), // 50 pixels per second pointerGestureTapInterval(150 * 1000000LL), // 150 ms @@ -235,8 +251,10 @@ public: virtual bool hasKeys(int32_t deviceId, uint32_t sourceMask, size_t numCodes, const int32_t* keyCodes, uint8_t* outFlags) = 0; - /* Reopens and reconfigures all input devices. */ - virtual void refreshConfiguration() = 0; + /* Requests that a reconfiguration of all input devices. + * The changes flag is a bitfield that indicates what has changed and whether + * the input devices must all be reopened. */ + virtual void requestRefreshConfiguration(uint32_t changes) = 0; }; @@ -260,7 +278,6 @@ public: virtual void requestTimeoutAtTime(nsecs_t when) = 0; virtual InputReaderPolicyInterface* getPolicy() = 0; - virtual const InputReaderConfiguration* getConfig() = 0; virtual InputDispatcherInterface* getDispatcher() = 0; virtual EventHubInterface* getEventHub() = 0; }; @@ -301,7 +318,7 @@ public: virtual bool hasKeys(int32_t deviceId, uint32_t sourceMask, size_t numCodes, const int32_t* keyCodes, uint8_t* outFlags); - virtual void refreshConfiguration(); + virtual void requestRefreshConfiguration(uint32_t changes); protected: // These methods are protected virtual so they can be overridden and instrumented @@ -316,7 +333,6 @@ private: InputReaderConfiguration mConfig; virtual InputReaderPolicyInterface* getPolicy() { return mPolicy.get(); } - virtual const InputReaderConfiguration* getConfig() { return &mConfig; } virtual InputDispatcherInterface* getDispatcher() { return mDispatcher.get(); } virtual EventHubInterface* getEventHub() { return mEventHub.get(); } @@ -365,8 +381,8 @@ private: nsecs_t mNextTimeout; // only accessed by reader thread, not guarded virtual void requestTimeoutAtTime(nsecs_t when); - volatile int32_t mRefreshConfiguration; // atomic - void configure(bool firstTime); + uint32_t mConfigurationChangesToRefresh; // guarded by mStateLock + void refreshConfiguration(uint32_t changes); // state queries typedef int32_t (InputDevice::*GetStateFunc)(uint32_t sourceMask, int32_t code); @@ -408,7 +424,7 @@ public: void dump(String8& dump); void addMapper(InputMapper* mapper); - void configure(); + void configure(const InputReaderConfiguration* config, uint32_t changes); void reset(); void process(const RawEvent* rawEvents, size_t count); void timeoutExpired(nsecs_t when); @@ -460,14 +476,13 @@ public: inline const String8 getDeviceName() { return mDevice->getName(); } inline InputReaderContext* getContext() { return mContext; } inline InputReaderPolicyInterface* getPolicy() { return mContext->getPolicy(); } - inline const InputReaderConfiguration* getConfig() { return mContext->getConfig(); } inline InputDispatcherInterface* getDispatcher() { return mContext->getDispatcher(); } inline EventHubInterface* getEventHub() { return mContext->getEventHub(); } virtual uint32_t getSources() = 0; virtual void populateDeviceInfo(InputDeviceInfo* deviceInfo); virtual void dump(String8& dump); - virtual void configure(); + virtual void configure(const InputReaderConfiguration* config, uint32_t changes); virtual void reset(); virtual void process(const RawEvent* rawEvent) = 0; virtual void timeoutExpired(nsecs_t when); @@ -514,7 +529,7 @@ public: virtual uint32_t getSources(); virtual void populateDeviceInfo(InputDeviceInfo* deviceInfo); virtual void dump(String8& dump); - virtual void configure(); + virtual void configure(const InputReaderConfiguration* config, uint32_t changes); virtual void reset(); virtual void process(const RawEvent* rawEvent); @@ -584,7 +599,7 @@ public: virtual uint32_t getSources(); virtual void populateDeviceInfo(InputDeviceInfo* deviceInfo); virtual void dump(String8& dump); - virtual void configure(); + virtual void configure(const InputReaderConfiguration* config, uint32_t changes); virtual void reset(); virtual void process(const RawEvent* rawEvent); @@ -675,7 +690,7 @@ public: virtual uint32_t getSources(); virtual void populateDeviceInfo(InputDeviceInfo* deviceInfo); virtual void dump(String8& dump); - virtual void configure(); + virtual void configure(const InputReaderConfiguration* config, uint32_t changes); virtual void reset(); virtual int32_t getKeyCodeState(uint32_t sourceMask, int32_t keyCode); @@ -783,7 +798,7 @@ protected: uint32_t mPointerSource; // sources when reporting pointer gestures // The reader's configuration. - const InputReaderConfiguration* mConfig; + InputReaderConfiguration mConfig; // Immutable configuration parameters. struct Parameters { @@ -1400,7 +1415,7 @@ public: virtual uint32_t getSources(); virtual void populateDeviceInfo(InputDeviceInfo* deviceInfo); virtual void dump(String8& dump); - virtual void configure(); + virtual void configure(const InputReaderConfiguration* config, uint32_t changes); virtual void reset(); virtual void process(const RawEvent* rawEvent); diff --git a/services/input/InputWindow.h b/services/input/InputWindow.h index 93c9b5f..d166ad4 100644 --- a/services/input/InputWindow.h +++ b/services/input/InputWindow.h @@ -127,6 +127,10 @@ struct InputWindow { LAST_SYSTEM_WINDOW = 2999, }; + enum { + INPUT_FEATURE_DISABLE_TOUCH_PAD_GESTURES = 0x00000001, + }; + sp<InputWindowHandle> inputWindowHandle; sp<InputChannel> inputChannel; String8 name; @@ -147,6 +151,7 @@ struct InputWindow { int32_t layer; int32_t ownerPid; int32_t ownerUid; + int32_t inputFeatures; bool touchableRegionContainsPoint(int32_t x, int32_t y) const; bool frameContainsPoint(int32_t x, int32_t y) const; diff --git a/services/input/tests/InputReader_test.cpp b/services/input/tests/InputReader_test.cpp index 4a32341..e349248 100644 --- a/services/input/tests/InputReader_test.cpp +++ b/services/input/tests/InputReader_test.cpp @@ -747,8 +747,6 @@ class FakeInputReaderContext : public InputReaderContext { int32_t mGlobalMetaState; bool mUpdateGlobalMetaStateWasCalled; - InputReaderConfiguration mConfig; - public: FakeInputReaderContext(const sp<EventHubInterface>& eventHub, const sp<InputReaderPolicyInterface>& policy, @@ -786,11 +784,6 @@ private: return mPolicy.get(); } - virtual const InputReaderConfiguration* getConfig() { - mPolicy->getReaderConfiguration(&mConfig); - return &mConfig; - } - virtual InputDispatcherInterface* getDispatcher() { return mDispatcher.get(); } @@ -895,7 +888,7 @@ private: } } - virtual void configure() { + virtual void configure(const InputReaderConfiguration* config, uint32_t changes) { mConfigureWasCalled = true; } @@ -1359,7 +1352,8 @@ TEST_F(InputDeviceTest, ImmutableProperties) { TEST_F(InputDeviceTest, WhenNoMappersAreRegistered_DeviceIsIgnored) { // Configuration. - mDevice->configure(); + InputReaderConfiguration config; + mDevice->configure(&config, 0); // Metadata. ASSERT_TRUE(mDevice->isIgnored()); @@ -1413,7 +1407,8 @@ TEST_F(InputDeviceTest, WhenMappersAreRegistered_DeviceIsNotIgnoredAndForwardsRe mapper2->setMetaState(AMETA_SHIFT_ON); mDevice->addMapper(mapper2); - mDevice->configure(); + InputReaderConfiguration config; + mDevice->configure(&config, 0); String8 propertyValue; ASSERT_TRUE(mDevice->getConfiguration().tryGetProperty(String8("key"), propertyValue)) @@ -1519,8 +1514,10 @@ protected: } void addMapperAndConfigure(InputMapper* mapper) { + InputReaderConfiguration config; + mDevice->addMapper(mapper); - mDevice->configure(); + mDevice->configure(&config, 0); } static void process(InputMapper* mapper, nsecs_t when, int32_t deviceId, int32_t type, diff --git a/services/java/com/android/server/wm/InputMonitor.java b/services/java/com/android/server/wm/InputMonitor.java index 9dc92d3..3be8af6 100644 --- a/services/java/com/android/server/wm/InputMonitor.java +++ b/services/java/com/android/server/wm/InputMonitor.java @@ -128,6 +128,8 @@ final class InputMonitor { inputWindow.layer = mService.mDragState.getDragLayerLw(); inputWindow.ownerPid = Process.myPid(); inputWindow.ownerUid = Process.myUid(); + inputWindow.inputFeatures = 0; + inputWindow.scaleFactor = 1.0f; // The drag window covers the entire display inputWindow.frameLeft = 0; @@ -204,7 +206,8 @@ final class InputMonitor { inputWindow.layer = child.mLayer; inputWindow.ownerPid = child.mSession.mPid; inputWindow.ownerUid = child.mSession.mUid; - + inputWindow.inputFeatures = child.mAttrs.inputFeatures; + final Rect frame = child.mFrame; inputWindow.frameLeft = frame.left; inputWindow.frameTop = frame.top; diff --git a/services/java/com/android/server/wm/InputWindow.java b/services/java/com/android/server/wm/InputWindow.java index 578120e..655d734 100644 --- a/services/java/com/android/server/wm/InputWindow.java +++ b/services/java/com/android/server/wm/InputWindow.java @@ -75,6 +75,9 @@ public final class InputWindow { public int ownerPid; public int ownerUid; + // Window input features. + public int inputFeatures; + public void recycle() { inputWindowHandle = null; inputChannel = null; diff --git a/services/jni/com_android_server_InputManager.cpp b/services/jni/com_android_server_InputManager.cpp index 7c5084f..8a46ab0 100644 --- a/services/jni/com_android_server_InputManager.cpp +++ b/services/jni/com_android_server_InputManager.cpp @@ -234,6 +234,9 @@ private: // Pointer speed. int32_t pointerSpeed; + // True if pointer gestures are enabled. + bool pointerGesturesEnabled; + // Sprite controller singleton, created on first use. sp<SpriteController> spriteController; @@ -274,6 +277,7 @@ NativeInputManager::NativeInputManager(jobject contextObj, mLocked.systemUiVisibility = ASYSTEM_UI_VISIBILITY_STATUS_BAR_VISIBLE; mLocked.pointerSpeed = 0; + mLocked.pointerGesturesEnabled = true; } sp<EventHub> eventHub = new EventHub(); @@ -443,6 +447,7 @@ void NativeInputManager::getReaderConfiguration(InputReaderConfiguration* outCon outConfig->pointerVelocityControlParameters.scale = exp2f(mLocked.pointerSpeed * POINTER_SPEED_EXPONENT); + outConfig->pointerGesturesEnabled = mLocked.pointerGesturesEnabled; } // release lock } @@ -594,6 +599,7 @@ bool NativeInputManager::isKeyRepeatEnabled() { void NativeInputManager::setInputWindows(JNIEnv* env, jobjectArray windowObjArray) { Vector<InputWindow> windows; + bool newPointerGesturesEnabled = true; jsize length = env->GetArrayLength(windowObjArray); for (jsize i = 0; i < length; i++) { jobject windowObj = env->GetObjectArrayElement(windowObjArray, i); @@ -606,11 +612,29 @@ void NativeInputManager::setInputWindows(JNIEnv* env, jobjectArray windowObjArra android_server_InputWindow_toNative(env, windowObj, &window); if (window.inputChannel == NULL) { windows.pop(); + } else if (window.hasFocus) { + if (window.inputFeatures & InputWindow::INPUT_FEATURE_DISABLE_TOUCH_PAD_GESTURES) { + newPointerGesturesEnabled = false; + } } env->DeleteLocalRef(windowObj); } mInputManager->getDispatcher()->setInputWindows(windows); + + uint32_t changes = 0; + { // acquire lock + AutoMutex _l(mLock); + + if (mLocked.pointerGesturesEnabled != newPointerGesturesEnabled) { + mLocked.pointerGesturesEnabled = newPointerGesturesEnabled; + changes |= InputReaderConfiguration::CHANGE_POINTER_GESTURE_ENABLEMENT; + } + } // release lock + + if (changes) { + mInputManager->getReader()->requestRefreshConfiguration(changes); + } } void NativeInputManager::setFocusedApplication(JNIEnv* env, jobject applicationObj) { @@ -650,14 +674,19 @@ void NativeInputManager::updateInactivityTimeoutLocked(const sp<PointerControlle } void NativeInputManager::setPointerSpeed(int32_t speed) { - AutoMutex _l(mLock); + { // acquire lock + AutoMutex _l(mLock); + + if (mLocked.pointerSpeed == speed) { + return; + } - if (mLocked.pointerSpeed != speed) { LOGI("Setting pointer speed to %d.", speed); mLocked.pointerSpeed = speed; + } // release lock - mInputManager->getReader()->refreshConfiguration(); - } + mInputManager->getReader()->requestRefreshConfiguration( + InputReaderConfiguration::CHANGE_POINTER_SPEED); } bool NativeInputManager::isScreenOn() { diff --git a/services/jni/com_android_server_InputWindow.cpp b/services/jni/com_android_server_InputWindow.cpp index 012ce21..0426f63 100644 --- a/services/jni/com_android_server_InputWindow.cpp +++ b/services/jni/com_android_server_InputWindow.cpp @@ -48,6 +48,7 @@ static struct { jfieldID layer; jfieldID ownerPid; jfieldID ownerUid; + jfieldID inputFeatures; } gInputWindowClassInfo; @@ -130,6 +131,8 @@ void android_server_InputWindow_toNative( gInputWindowClassInfo.ownerPid); outInputWindow->ownerUid = env->GetIntField(inputWindowObj, gInputWindowClassInfo.ownerUid); + outInputWindow->inputFeatures = env->GetIntField(inputWindowObj, + gInputWindowClassInfo.inputFeatures); } @@ -206,6 +209,9 @@ int register_android_server_InputWindow(JNIEnv* env) { GET_FIELD_ID(gInputWindowClassInfo.ownerUid, clazz, "ownerUid", "I"); + + GET_FIELD_ID(gInputWindowClassInfo.inputFeatures, clazz, + "inputFeatures", "I"); return 0; } |