Loading include/ui/EventHub.h +4 −1 Original line number Diff line number Diff line Loading @@ -73,6 +73,9 @@ public: int getKeycodeState(int key) const; int getKeycodeState(int32_t deviceId, int key) const; status_t scancodeToKeycode(int32_t deviceId, int scancode, int32_t* outKeycode, uint32_t* outFlags) const; // special type codes when devices are added/removed. enum { DEVICE_ADDED = 0x10000000, Loading Loading @@ -121,7 +124,7 @@ private: mutable Mutex mLock; bool mHaveFirstKeyboard; int32_t mFirstKeyboardId; // the API is that the build in keyboard is id 0, so map it int32_t mFirstKeyboardId; // the API is that the built-in keyboard is id 0, so map it struct device_ent { device_t* device; Loading libs/ui/EventHub.cpp +29 −0 Original line number Diff line number Diff line Loading @@ -240,6 +240,35 @@ int EventHub::getKeycodeState(int32_t deviceId, int code) const return 0; } status_t EventHub::scancodeToKeycode(int32_t deviceId, int scancode, int32_t* outKeycode, uint32_t* outFlags) const { AutoMutex _l(mLock); device_t* device = getDevice(deviceId); if (device != NULL && device->layoutMap != NULL) { status_t err = device->layoutMap->map(scancode, outKeycode, outFlags); if (err == NO_ERROR) { return NO_ERROR; } } if (mHaveFirstKeyboard) { device = getDevice(mFirstKeyboardId); if (device != NULL && device->layoutMap != NULL) { status_t err = device->layoutMap->map(scancode, outKeycode, outFlags); if (err == NO_ERROR) { return NO_ERROR; } } } *outKeycode = 0; *outFlags = 0; return NAME_NOT_FOUND; } EventHub::device_t* EventHub::getDevice(int32_t deviceId) const { if (deviceId == 0) deviceId = mFirstKeyboardId; Loading services/java/com/android/server/InputDevice.java +70 −48 Original line number Diff line number Diff line Loading @@ -66,19 +66,56 @@ public class InputDevice { MotionEvent generateMotion(InputDevice device, long curTime, long curTimeNano, boolean isAbs, Display display, int orientation, int metaState) { if (!changed) { return null; } float scaledX = x; float scaledY = y; float temp; float scaledPressure = 1.0f; float scaledSize = 0; int edgeFlags = 0; int action; if (down != lastDown) { if (isAbs) { int w = display.getWidth()-1; int h = display.getHeight()-1; final AbsoluteInfo absX = device.absX; final AbsoluteInfo absY = device.absY; if (down && absX != null && absY != null) { // We don't let downs start unless we are // inside of the screen. There are two reasons for // this: to avoid spurious touches when holding // the edges of the device near the touchscreen, // and to avoid reporting events if there are virtual // keys on the touchscreen outside of the display // area. if (scaledX < absX.minValue || scaledX > absX.maxValue || scaledY < absY.minValue || scaledY > absY.maxValue) { if (false) Log.v("InputDevice", "Rejecting (" + scaledX + "," + scaledY + "): outside of (" + absX.minValue + "," + absY.minValue + ")-(" + absX.maxValue + "," + absY.maxValue + ")"); return null; } } } else { x = y = 0; } lastDown = down; if (down) { action = MotionEvent.ACTION_DOWN; downTime = curTime; } else { action = MotionEvent.ACTION_UP; } currentMove = null; } else { action = MotionEvent.ACTION_MOVE; } if (isAbs) { final int dispW = display.getWidth()-1; final int dispH = display.getHeight()-1; int w = dispW; int h = dispH; if (orientation == Surface.ROTATION_90 || orientation == Surface.ROTATION_270) { int tmp = w; Loading Loading @@ -120,17 +157,18 @@ public class InputDevice { break; } if (scaledX == 0) { if (action != MotionEvent.ACTION_DOWN) { if (scaledX <= 0) { edgeFlags += MotionEvent.EDGE_LEFT; } else if (scaledX == display.getWidth() - 1.0f) { } else if (scaledX >= dispW) { edgeFlags += MotionEvent.EDGE_RIGHT; } if (scaledY == 0) { if (scaledY <= 0) { edgeFlags += MotionEvent.EDGE_TOP; } else if (scaledY == display.getHeight() - 1.0f) { } else if (scaledY >= dispH) { edgeFlags += MotionEvent.EDGE_BOTTOM; } } } else { scaledX *= xMoveScale; Loading @@ -153,24 +191,6 @@ public class InputDevice { } } changed = false; if (down != lastDown) { int action; lastDown = down; if (down) { action = MotionEvent.ACTION_DOWN; downTime = curTime; } else { action = MotionEvent.ACTION_UP; } currentMove = null; if (!isAbs) { x = y = 0; } return MotionEvent.obtainNano(downTime, curTime, curTimeNano, action, scaledX, scaledY, scaledPressure, scaledSize, metaState, xPrecision, yPrecision, device.id, edgeFlags); } else { if (currentMove != null) { if (false) Log.i("InputDevice", "Adding batch x=" + scaledX + " y=" + scaledY + " to " + currentMove); Loading @@ -181,13 +201,15 @@ public class InputDevice { } return null; } MotionEvent me = MotionEvent.obtainNano(downTime, curTime, curTimeNano, MotionEvent.ACTION_MOVE, scaledX, scaledY, MotionEvent me = MotionEvent.obtainNano(downTime, curTime, curTimeNano, action, scaledX, scaledY, scaledPressure, scaledSize, metaState, xPrecision, yPrecision, device.id, edgeFlags); if (action == MotionEvent.ACTION_MOVE) { currentMove = me; return me; } return me; } } Loading services/java/com/android/server/KeyInputQueue.java +226 −19 Original line number Diff line number Diff line Loading @@ -30,10 +30,20 @@ import android.view.RawInputEvent; import android.view.Surface; import android.view.WindowManagerPolicy; import java.io.BufferedReader; import java.io.FileInputStream; import java.io.FileNotFoundException; import java.io.IOException; import java.io.InputStreamReader; import java.util.ArrayList; public abstract class KeyInputQueue { static final String TAG = "KeyInputQueue"; SparseArray<InputDevice> mDevices = new SparseArray<InputDevice>(); static final boolean DEBUG_VIRTUAL_KEYS = false; final SparseArray<InputDevice> mDevices = new SparseArray<InputDevice>(); final ArrayList<VirtualKey> mVirtualKeys = new ArrayList<VirtualKey>(); int mGlobalMetaState = 0; boolean mHaveGlobalMetaState = false; Loading @@ -44,10 +54,14 @@ public abstract class KeyInputQueue { int mCacheCount; Display mDisplay = null; int mDisplayWidth; int mDisplayHeight; int mOrientation = Surface.ROTATION_0; int[] mKeyRotationMap = null; VirtualKey mPressedVirtualKey = null; PowerManager.WakeLock mWakeLock; static final int[] KEY_90_MAP = new int[] { Loading Loading @@ -110,11 +124,106 @@ public abstract class KeyInputQueue { QueuedEvent next; } /** * A key that exists as a part of the touch-screen, outside of the normal * display area of the screen. */ static class VirtualKey { int scancode; int centerx; int centery; int width; int height; int hitLeft; int hitTop; int hitRight; int hitBottom; InputDevice lastDevice; int lastKeycode; boolean checkHit(int x, int y) { return (x >= hitLeft && x <= hitRight && y >= hitTop && y <= hitBottom); } void computeHitRect(InputDevice dev, int dw, int dh) { if (dev == lastDevice) { return; } if (DEBUG_VIRTUAL_KEYS) Log.v(TAG, "computeHitRect for " + scancode + ": dev=" + dev + " absX=" + dev.absX + " absY=" + dev.absY); lastDevice = dev; int minx = dev.absX.minValue; int maxx = dev.absX.maxValue; int halfw = width/2; int left = centerx - halfw; int right = centerx + halfw; hitLeft = minx + ((left*maxx-minx)/dw); hitRight = minx + ((right*maxx-minx)/dw); int miny = dev.absY.minValue; int maxy = dev.absY.maxValue; int halfh = height/2; int top = centery - halfh; int bottom = centery + halfh; hitTop = miny + ((top*maxy-miny)/dh); hitBottom = miny + ((bottom*maxy-miny)/dh); } } KeyInputQueue(Context context) { if (MEASURE_LATENCY) { lt = new LatencyTimer(100, 1000); } try { FileInputStream fis = new FileInputStream( "/sys/board_properties/virtualkeys.synaptics-rmi-touchscreen"); InputStreamReader isr = new InputStreamReader(fis); BufferedReader br = new BufferedReader(isr); String str = br.readLine(); if (str != null) { String[] it = str.split(":"); if (DEBUG_VIRTUAL_KEYS) Log.v(TAG, "***** VIRTUAL KEYS: " + it); final int N = it.length-6; for (int i=0; i<=N; i+=6) { if (!"0x01".equals(it[i])) { Log.w(TAG, "Unknown virtual key type at elem #" + i + ": " + it[i]); continue; } try { VirtualKey sb = new VirtualKey(); sb.scancode = Integer.parseInt(it[i+1]); sb.centerx = Integer.parseInt(it[i+2]); sb.centery = Integer.parseInt(it[i+3]); sb.width = Integer.parseInt(it[i+4]); sb.height = Integer.parseInt(it[i+5]); if (DEBUG_VIRTUAL_KEYS) Log.v(TAG, "Virtual key " + sb.scancode + ": center=" + sb.centerx + "," + sb.centery + " size=" + sb.width + "x" + sb.height); mVirtualKeys.add(sb); } catch (NumberFormatException e) { Log.w(TAG, "Bad number at region " + i + " in: " + str, e); } } } br.close(); } catch (FileNotFoundException e) { Log.i(TAG, "No virtual keys found"); } catch (IOException e) { Log.w(TAG, "Error reading virtual keys", e); } PowerManager pm = (PowerManager)context.getSystemService( Context.POWER_SERVICE); mWakeLock = pm.newWakeLock(PowerManager.PARTIAL_WAKE_LOCK, Loading @@ -131,6 +240,12 @@ public abstract class KeyInputQueue { public void setDisplay(Display display) { mDisplay = display; // We assume at this point that the display dimensions reflect the // natural, unrotated display. We will perform hit tests for soft // buttons based on that display. mDisplayWidth = display.getWidth(); mDisplayHeight = display.getHeight(); } public void getInputConfiguration(Configuration config) { Loading Loading @@ -173,6 +288,7 @@ public abstract class KeyInputQueue { public static native int getScancodeState(int deviceId, int sw); public static native int getKeycodeState(int sw); public static native int getKeycodeState(int deviceId, int sw); public static native int scancodeToKeycode(int deviceId, int scancode); public static native boolean hasKeys(int[] keycodes, boolean[] keyExists); public static KeyEvent newKeyEvent(InputDevice device, long downTime, Loading Loading @@ -339,8 +455,54 @@ public abstract class KeyInputQueue { } MotionEvent me; me = di.mAbs.generateMotion(di, curTime, curTimeNano, true, mDisplay, mOrientation, mGlobalMetaState); InputDevice.MotionState ms = di.mAbs; if (ms.changed) { ms.changed = false; boolean doMotion = true; // Look for virtual buttons. VirtualKey vk = mPressedVirtualKey; if (vk != null) { doMotion = false; if (!ms.down) { mPressedVirtualKey = null; ms.lastDown = ms.down; if (DEBUG_VIRTUAL_KEYS) Log.v(TAG, "Generate key up for: " + vk.scancode); addLocked(di, curTimeNano, ev.flags, RawInputEvent.CLASS_KEYBOARD, newKeyEvent(di, di.mDownTime, curTime, false, vk.lastKeycode, 0, vk.scancode, 0)); } } else if (ms.down && !ms.lastDown) { vk = findSoftButton(di); if (vk != null) { doMotion = false; mPressedVirtualKey = vk; vk.lastKeycode = scancodeToKeycode( di.id, vk.scancode); ms.lastDown = ms.down; di.mDownTime = curTime; if (DEBUG_VIRTUAL_KEYS) Log.v(TAG, "Generate key down for: " + vk.scancode + " (keycode=" + vk.lastKeycode + ")"); addLocked(di, curTimeNano, ev.flags, RawInputEvent.CLASS_KEYBOARD, newKeyEvent(di, di.mDownTime, curTime, true, vk.lastKeycode, 0, vk.scancode, 0)); } } if (doMotion) { me = ms.generateMotion(di, curTime, curTimeNano, true, mDisplay, mOrientation, mGlobalMetaState); if (false) Log.v(TAG, "Absolute: x=" + di.mAbs.x + " y=" + di.mAbs.y + " ev=" + me); if (me != null) { Loading @@ -350,8 +512,16 @@ public abstract class KeyInputQueue { addLocked(di, curTimeNano, ev.flags, RawInputEvent.CLASS_TOUCHSCREEN, me); } me = di.mRel.generateMotion(di, curTime, curTimeNano, false, mDisplay, mOrientation, mGlobalMetaState); } } ms = di.mRel; if (ms.changed) { ms.changed = false; me = ms.generateMotion(di, curTime, curTimeNano, false, mDisplay, mOrientation, mGlobalMetaState); if (false) Log.v(TAG, "Relative: x=" + di.mRel.x + " y=" + di.mRel.y + " ev=" + me); if (me != null) { Loading @@ -363,12 +533,49 @@ public abstract class KeyInputQueue { } } } catch (RuntimeException exc) { } catch (RuntimeException exc) { Log.e(TAG, "InputReaderThread uncaught exception", exc); } } }; private VirtualKey findSoftButton(InputDevice dev) { final int N = mVirtualKeys.size(); if (N <= 0) { return null; } final InputDevice.AbsoluteInfo absx = dev.absX; final InputDevice.AbsoluteInfo absy = dev.absY; final InputDevice.MotionState absm = dev.mAbs; if (absx == null || absy == null || absm == null) { return null; } if (absm.x >= absx.minValue && absm.x <= absx.maxValue && absm.y >= absy.minValue && absm.y <= absy.maxValue) { if (DEBUG_VIRTUAL_KEYS) Log.v(TAG, "Input (" + absm.x + "," + absm.y + ") inside of display"); return null; } for (int i=0; i<N; i++) { VirtualKey sb = mVirtualKeys.get(i); sb.computeHitRect(dev, mDisplayWidth, mDisplayHeight); if (DEBUG_VIRTUAL_KEYS) Log.v(TAG, "Hit test (" + absm.x + "," + absm.y + ") in code " + sb.scancode + " - (" + sb.hitLeft + "," + sb.hitTop + ")-(" + sb.hitRight + "," + sb.hitBottom + ")"); if (sb.checkHit(absm.x, absm.y)) { if (DEBUG_VIRTUAL_KEYS) Log.v(TAG, "Hit!"); return sb; } } return null; } /** * Returns a new meta state for the given keys and old state. */ Loading services/jni/com_android_server_KeyInputQueue.cpp +19 −0 Original line number Diff line number Diff line Loading @@ -205,6 +205,23 @@ android_server_KeyInputQueue_getKeycodeStateDevice(JNIEnv* env, jobject clazz, return st; } static jint android_server_KeyInputQueue_scancodeToKeycode(JNIEnv* env, jobject clazz, jint deviceId, jint scancode) { jint res = 0; gLock.lock(); if (gHub != NULL) { int32_t keycode; uint32_t flags; gHub->scancodeToKeycode(deviceId, scancode, &keycode, &flags); res = keycode; } gLock.unlock(); return res; } static jboolean android_server_KeyInputQueue_hasKeys(JNIEnv* env, jobject clazz, jintArray keyCodes, jbooleanArray outFlags) Loading Loading @@ -254,6 +271,8 @@ static JNINativeMethod gInputMethods[] = { (void*) android_server_KeyInputQueue_getKeycodeStateDevice }, { "hasKeys", "([I[Z)Z", (void*) android_server_KeyInputQueue_hasKeys }, { "scancodeToKeycode", "(II)I", (void*) android_server_KeyInputQueue_scancodeToKeycode }, }; int register_android_server_KeyInputQueue(JNIEnv* env) Loading Loading
include/ui/EventHub.h +4 −1 Original line number Diff line number Diff line Loading @@ -73,6 +73,9 @@ public: int getKeycodeState(int key) const; int getKeycodeState(int32_t deviceId, int key) const; status_t scancodeToKeycode(int32_t deviceId, int scancode, int32_t* outKeycode, uint32_t* outFlags) const; // special type codes when devices are added/removed. enum { DEVICE_ADDED = 0x10000000, Loading Loading @@ -121,7 +124,7 @@ private: mutable Mutex mLock; bool mHaveFirstKeyboard; int32_t mFirstKeyboardId; // the API is that the build in keyboard is id 0, so map it int32_t mFirstKeyboardId; // the API is that the built-in keyboard is id 0, so map it struct device_ent { device_t* device; Loading
libs/ui/EventHub.cpp +29 −0 Original line number Diff line number Diff line Loading @@ -240,6 +240,35 @@ int EventHub::getKeycodeState(int32_t deviceId, int code) const return 0; } status_t EventHub::scancodeToKeycode(int32_t deviceId, int scancode, int32_t* outKeycode, uint32_t* outFlags) const { AutoMutex _l(mLock); device_t* device = getDevice(deviceId); if (device != NULL && device->layoutMap != NULL) { status_t err = device->layoutMap->map(scancode, outKeycode, outFlags); if (err == NO_ERROR) { return NO_ERROR; } } if (mHaveFirstKeyboard) { device = getDevice(mFirstKeyboardId); if (device != NULL && device->layoutMap != NULL) { status_t err = device->layoutMap->map(scancode, outKeycode, outFlags); if (err == NO_ERROR) { return NO_ERROR; } } } *outKeycode = 0; *outFlags = 0; return NAME_NOT_FOUND; } EventHub::device_t* EventHub::getDevice(int32_t deviceId) const { if (deviceId == 0) deviceId = mFirstKeyboardId; Loading
services/java/com/android/server/InputDevice.java +70 −48 Original line number Diff line number Diff line Loading @@ -66,19 +66,56 @@ public class InputDevice { MotionEvent generateMotion(InputDevice device, long curTime, long curTimeNano, boolean isAbs, Display display, int orientation, int metaState) { if (!changed) { return null; } float scaledX = x; float scaledY = y; float temp; float scaledPressure = 1.0f; float scaledSize = 0; int edgeFlags = 0; int action; if (down != lastDown) { if (isAbs) { int w = display.getWidth()-1; int h = display.getHeight()-1; final AbsoluteInfo absX = device.absX; final AbsoluteInfo absY = device.absY; if (down && absX != null && absY != null) { // We don't let downs start unless we are // inside of the screen. There are two reasons for // this: to avoid spurious touches when holding // the edges of the device near the touchscreen, // and to avoid reporting events if there are virtual // keys on the touchscreen outside of the display // area. if (scaledX < absX.minValue || scaledX > absX.maxValue || scaledY < absY.minValue || scaledY > absY.maxValue) { if (false) Log.v("InputDevice", "Rejecting (" + scaledX + "," + scaledY + "): outside of (" + absX.minValue + "," + absY.minValue + ")-(" + absX.maxValue + "," + absY.maxValue + ")"); return null; } } } else { x = y = 0; } lastDown = down; if (down) { action = MotionEvent.ACTION_DOWN; downTime = curTime; } else { action = MotionEvent.ACTION_UP; } currentMove = null; } else { action = MotionEvent.ACTION_MOVE; } if (isAbs) { final int dispW = display.getWidth()-1; final int dispH = display.getHeight()-1; int w = dispW; int h = dispH; if (orientation == Surface.ROTATION_90 || orientation == Surface.ROTATION_270) { int tmp = w; Loading Loading @@ -120,17 +157,18 @@ public class InputDevice { break; } if (scaledX == 0) { if (action != MotionEvent.ACTION_DOWN) { if (scaledX <= 0) { edgeFlags += MotionEvent.EDGE_LEFT; } else if (scaledX == display.getWidth() - 1.0f) { } else if (scaledX >= dispW) { edgeFlags += MotionEvent.EDGE_RIGHT; } if (scaledY == 0) { if (scaledY <= 0) { edgeFlags += MotionEvent.EDGE_TOP; } else if (scaledY == display.getHeight() - 1.0f) { } else if (scaledY >= dispH) { edgeFlags += MotionEvent.EDGE_BOTTOM; } } } else { scaledX *= xMoveScale; Loading @@ -153,24 +191,6 @@ public class InputDevice { } } changed = false; if (down != lastDown) { int action; lastDown = down; if (down) { action = MotionEvent.ACTION_DOWN; downTime = curTime; } else { action = MotionEvent.ACTION_UP; } currentMove = null; if (!isAbs) { x = y = 0; } return MotionEvent.obtainNano(downTime, curTime, curTimeNano, action, scaledX, scaledY, scaledPressure, scaledSize, metaState, xPrecision, yPrecision, device.id, edgeFlags); } else { if (currentMove != null) { if (false) Log.i("InputDevice", "Adding batch x=" + scaledX + " y=" + scaledY + " to " + currentMove); Loading @@ -181,13 +201,15 @@ public class InputDevice { } return null; } MotionEvent me = MotionEvent.obtainNano(downTime, curTime, curTimeNano, MotionEvent.ACTION_MOVE, scaledX, scaledY, MotionEvent me = MotionEvent.obtainNano(downTime, curTime, curTimeNano, action, scaledX, scaledY, scaledPressure, scaledSize, metaState, xPrecision, yPrecision, device.id, edgeFlags); if (action == MotionEvent.ACTION_MOVE) { currentMove = me; return me; } return me; } } Loading
services/java/com/android/server/KeyInputQueue.java +226 −19 Original line number Diff line number Diff line Loading @@ -30,10 +30,20 @@ import android.view.RawInputEvent; import android.view.Surface; import android.view.WindowManagerPolicy; import java.io.BufferedReader; import java.io.FileInputStream; import java.io.FileNotFoundException; import java.io.IOException; import java.io.InputStreamReader; import java.util.ArrayList; public abstract class KeyInputQueue { static final String TAG = "KeyInputQueue"; SparseArray<InputDevice> mDevices = new SparseArray<InputDevice>(); static final boolean DEBUG_VIRTUAL_KEYS = false; final SparseArray<InputDevice> mDevices = new SparseArray<InputDevice>(); final ArrayList<VirtualKey> mVirtualKeys = new ArrayList<VirtualKey>(); int mGlobalMetaState = 0; boolean mHaveGlobalMetaState = false; Loading @@ -44,10 +54,14 @@ public abstract class KeyInputQueue { int mCacheCount; Display mDisplay = null; int mDisplayWidth; int mDisplayHeight; int mOrientation = Surface.ROTATION_0; int[] mKeyRotationMap = null; VirtualKey mPressedVirtualKey = null; PowerManager.WakeLock mWakeLock; static final int[] KEY_90_MAP = new int[] { Loading Loading @@ -110,11 +124,106 @@ public abstract class KeyInputQueue { QueuedEvent next; } /** * A key that exists as a part of the touch-screen, outside of the normal * display area of the screen. */ static class VirtualKey { int scancode; int centerx; int centery; int width; int height; int hitLeft; int hitTop; int hitRight; int hitBottom; InputDevice lastDevice; int lastKeycode; boolean checkHit(int x, int y) { return (x >= hitLeft && x <= hitRight && y >= hitTop && y <= hitBottom); } void computeHitRect(InputDevice dev, int dw, int dh) { if (dev == lastDevice) { return; } if (DEBUG_VIRTUAL_KEYS) Log.v(TAG, "computeHitRect for " + scancode + ": dev=" + dev + " absX=" + dev.absX + " absY=" + dev.absY); lastDevice = dev; int minx = dev.absX.minValue; int maxx = dev.absX.maxValue; int halfw = width/2; int left = centerx - halfw; int right = centerx + halfw; hitLeft = minx + ((left*maxx-minx)/dw); hitRight = minx + ((right*maxx-minx)/dw); int miny = dev.absY.minValue; int maxy = dev.absY.maxValue; int halfh = height/2; int top = centery - halfh; int bottom = centery + halfh; hitTop = miny + ((top*maxy-miny)/dh); hitBottom = miny + ((bottom*maxy-miny)/dh); } } KeyInputQueue(Context context) { if (MEASURE_LATENCY) { lt = new LatencyTimer(100, 1000); } try { FileInputStream fis = new FileInputStream( "/sys/board_properties/virtualkeys.synaptics-rmi-touchscreen"); InputStreamReader isr = new InputStreamReader(fis); BufferedReader br = new BufferedReader(isr); String str = br.readLine(); if (str != null) { String[] it = str.split(":"); if (DEBUG_VIRTUAL_KEYS) Log.v(TAG, "***** VIRTUAL KEYS: " + it); final int N = it.length-6; for (int i=0; i<=N; i+=6) { if (!"0x01".equals(it[i])) { Log.w(TAG, "Unknown virtual key type at elem #" + i + ": " + it[i]); continue; } try { VirtualKey sb = new VirtualKey(); sb.scancode = Integer.parseInt(it[i+1]); sb.centerx = Integer.parseInt(it[i+2]); sb.centery = Integer.parseInt(it[i+3]); sb.width = Integer.parseInt(it[i+4]); sb.height = Integer.parseInt(it[i+5]); if (DEBUG_VIRTUAL_KEYS) Log.v(TAG, "Virtual key " + sb.scancode + ": center=" + sb.centerx + "," + sb.centery + " size=" + sb.width + "x" + sb.height); mVirtualKeys.add(sb); } catch (NumberFormatException e) { Log.w(TAG, "Bad number at region " + i + " in: " + str, e); } } } br.close(); } catch (FileNotFoundException e) { Log.i(TAG, "No virtual keys found"); } catch (IOException e) { Log.w(TAG, "Error reading virtual keys", e); } PowerManager pm = (PowerManager)context.getSystemService( Context.POWER_SERVICE); mWakeLock = pm.newWakeLock(PowerManager.PARTIAL_WAKE_LOCK, Loading @@ -131,6 +240,12 @@ public abstract class KeyInputQueue { public void setDisplay(Display display) { mDisplay = display; // We assume at this point that the display dimensions reflect the // natural, unrotated display. We will perform hit tests for soft // buttons based on that display. mDisplayWidth = display.getWidth(); mDisplayHeight = display.getHeight(); } public void getInputConfiguration(Configuration config) { Loading Loading @@ -173,6 +288,7 @@ public abstract class KeyInputQueue { public static native int getScancodeState(int deviceId, int sw); public static native int getKeycodeState(int sw); public static native int getKeycodeState(int deviceId, int sw); public static native int scancodeToKeycode(int deviceId, int scancode); public static native boolean hasKeys(int[] keycodes, boolean[] keyExists); public static KeyEvent newKeyEvent(InputDevice device, long downTime, Loading Loading @@ -339,8 +455,54 @@ public abstract class KeyInputQueue { } MotionEvent me; me = di.mAbs.generateMotion(di, curTime, curTimeNano, true, mDisplay, mOrientation, mGlobalMetaState); InputDevice.MotionState ms = di.mAbs; if (ms.changed) { ms.changed = false; boolean doMotion = true; // Look for virtual buttons. VirtualKey vk = mPressedVirtualKey; if (vk != null) { doMotion = false; if (!ms.down) { mPressedVirtualKey = null; ms.lastDown = ms.down; if (DEBUG_VIRTUAL_KEYS) Log.v(TAG, "Generate key up for: " + vk.scancode); addLocked(di, curTimeNano, ev.flags, RawInputEvent.CLASS_KEYBOARD, newKeyEvent(di, di.mDownTime, curTime, false, vk.lastKeycode, 0, vk.scancode, 0)); } } else if (ms.down && !ms.lastDown) { vk = findSoftButton(di); if (vk != null) { doMotion = false; mPressedVirtualKey = vk; vk.lastKeycode = scancodeToKeycode( di.id, vk.scancode); ms.lastDown = ms.down; di.mDownTime = curTime; if (DEBUG_VIRTUAL_KEYS) Log.v(TAG, "Generate key down for: " + vk.scancode + " (keycode=" + vk.lastKeycode + ")"); addLocked(di, curTimeNano, ev.flags, RawInputEvent.CLASS_KEYBOARD, newKeyEvent(di, di.mDownTime, curTime, true, vk.lastKeycode, 0, vk.scancode, 0)); } } if (doMotion) { me = ms.generateMotion(di, curTime, curTimeNano, true, mDisplay, mOrientation, mGlobalMetaState); if (false) Log.v(TAG, "Absolute: x=" + di.mAbs.x + " y=" + di.mAbs.y + " ev=" + me); if (me != null) { Loading @@ -350,8 +512,16 @@ public abstract class KeyInputQueue { addLocked(di, curTimeNano, ev.flags, RawInputEvent.CLASS_TOUCHSCREEN, me); } me = di.mRel.generateMotion(di, curTime, curTimeNano, false, mDisplay, mOrientation, mGlobalMetaState); } } ms = di.mRel; if (ms.changed) { ms.changed = false; me = ms.generateMotion(di, curTime, curTimeNano, false, mDisplay, mOrientation, mGlobalMetaState); if (false) Log.v(TAG, "Relative: x=" + di.mRel.x + " y=" + di.mRel.y + " ev=" + me); if (me != null) { Loading @@ -363,12 +533,49 @@ public abstract class KeyInputQueue { } } } catch (RuntimeException exc) { } catch (RuntimeException exc) { Log.e(TAG, "InputReaderThread uncaught exception", exc); } } }; private VirtualKey findSoftButton(InputDevice dev) { final int N = mVirtualKeys.size(); if (N <= 0) { return null; } final InputDevice.AbsoluteInfo absx = dev.absX; final InputDevice.AbsoluteInfo absy = dev.absY; final InputDevice.MotionState absm = dev.mAbs; if (absx == null || absy == null || absm == null) { return null; } if (absm.x >= absx.minValue && absm.x <= absx.maxValue && absm.y >= absy.minValue && absm.y <= absy.maxValue) { if (DEBUG_VIRTUAL_KEYS) Log.v(TAG, "Input (" + absm.x + "," + absm.y + ") inside of display"); return null; } for (int i=0; i<N; i++) { VirtualKey sb = mVirtualKeys.get(i); sb.computeHitRect(dev, mDisplayWidth, mDisplayHeight); if (DEBUG_VIRTUAL_KEYS) Log.v(TAG, "Hit test (" + absm.x + "," + absm.y + ") in code " + sb.scancode + " - (" + sb.hitLeft + "," + sb.hitTop + ")-(" + sb.hitRight + "," + sb.hitBottom + ")"); if (sb.checkHit(absm.x, absm.y)) { if (DEBUG_VIRTUAL_KEYS) Log.v(TAG, "Hit!"); return sb; } } return null; } /** * Returns a new meta state for the given keys and old state. */ Loading
services/jni/com_android_server_KeyInputQueue.cpp +19 −0 Original line number Diff line number Diff line Loading @@ -205,6 +205,23 @@ android_server_KeyInputQueue_getKeycodeStateDevice(JNIEnv* env, jobject clazz, return st; } static jint android_server_KeyInputQueue_scancodeToKeycode(JNIEnv* env, jobject clazz, jint deviceId, jint scancode) { jint res = 0; gLock.lock(); if (gHub != NULL) { int32_t keycode; uint32_t flags; gHub->scancodeToKeycode(deviceId, scancode, &keycode, &flags); res = keycode; } gLock.unlock(); return res; } static jboolean android_server_KeyInputQueue_hasKeys(JNIEnv* env, jobject clazz, jintArray keyCodes, jbooleanArray outFlags) Loading Loading @@ -254,6 +271,8 @@ static JNINativeMethod gInputMethods[] = { (void*) android_server_KeyInputQueue_getKeycodeStateDevice }, { "hasKeys", "([I[Z)Z", (void*) android_server_KeyInputQueue_hasKeys }, { "scancodeToKeycode", "(II)I", (void*) android_server_KeyInputQueue_scancodeToKeycode }, }; int register_android_server_KeyInputQueue(JNIEnv* env) Loading