FileDocCategorySizeDatePackage
KeyInputQueue.javaAPI DocAndroid 1.5 API24522Wed May 06 22:42:00 BST 2009com.android.server

KeyInputQueue

public abstract class KeyInputQueue extends Object

Fields Summary
static final String
TAG
android.util.SparseArray
mDevices
int
mGlobalMetaState
boolean
mHaveGlobalMetaState
final QueuedEvent
mFirst
final QueuedEvent
mLast
QueuedEvent
mCache
int
mCacheCount
android.view.Display
mDisplay
int
mOrientation
int[]
mKeyRotationMap
PowerManager.WakeLock
mWakeLock
static final int[]
KEY_90_MAP
static final int[]
KEY_180_MAP
static final int[]
KEY_270_MAP
public static final int
FILTER_REMOVE
public static final int
FILTER_KEEP
public static final int
FILTER_ABORT
Thread
mThread
Constructors Summary
KeyInputQueue(android.content.Context context)

        PowerManager pm = (PowerManager)context.getSystemService(
                                                        Context.POWER_SERVICE);
        mWakeLock = pm.newWakeLock(PowerManager.PARTIAL_WAKE_LOCK,
                                                        "KeyInputQueue");
        mWakeLock.setReferenceCounted(false);

        mFirst = new QueuedEvent();
        mLast = new QueuedEvent();
        mFirst.next = mLast;
        mLast.prev = mFirst;

        mThread.start();
    
Methods Summary
private voidaddLocked(InputDevice device, long when, int flags, int classType, java.lang.Object event)

        boolean poke = mFirst.next == mLast;

        QueuedEvent ev = obtainLocked(device, when, flags, classType, event);
        QueuedEvent p = mLast.prev;
        while (p != mFirst && ev.when < p.when) {
            p = p.prev;
        }

        ev.next = p.next;
        ev.prev = p;
        p.next = ev;
        ev.next.prev = ev;
        ev.inQueue = true;

        if (poke) {
            mFirst.notify();
            mWakeLock.acquire();
        }
    
private voidcomputeGlobalMetaStateLocked()

        int i = mDevices.size();
        mGlobalMetaState = 0;
        while ((--i) >= 0) {
            mGlobalMetaState |= mDevices.valueAt(i).mMetaKeysState;
        }
        mHaveGlobalMetaState = true;
    
voidfilterQueue(com.android.server.KeyInputQueue$FilterCallback cb)

        synchronized (mFirst) {
            QueuedEvent cur = mLast.prev;
            while (cur.prev != null) {
                switch (cb.filterEvent(cur)) {
                    case FILTER_REMOVE:
                        cur.prev.next = cur.next;
                        cur.next.prev = cur.prev;
                        break;
                    case FILTER_ABORT:
                        return;
                }
                cur = cur.prev;
            }
        }
    
public static native booleangetAbsoluteInfo(int deviceId, int axis, InputDevice.AbsoluteInfo outInfo)

public static native intgetDeviceClasses(int deviceId)

public static native java.lang.StringgetDeviceName(int deviceId)

com.android.server.KeyInputQueue$QueuedEventgetEvent(long timeoutMS)

        long begin = SystemClock.uptimeMillis();
        final long end = begin+timeoutMS;
        long now = begin;
        synchronized (mFirst) {
            while (mFirst.next == mLast && end > now) {
                try {
                    mWakeLock.release();
                    mFirst.wait(end-now);
                }
                catch (InterruptedException e) {
                }
                now = SystemClock.uptimeMillis();
                if (begin > now) {
                    begin = now;
                }
            }
            if (mFirst.next == mLast) {
                return null;
            }
            QueuedEvent p = mFirst.next;
            mFirst.next = p.next;
            mFirst.next.prev = mFirst;
            p.inQueue = false;
            return p;
        }
    
public voidgetInputConfiguration(android.content.res.Configuration config)

        synchronized (mFirst) {
            config.touchscreen = Configuration.TOUCHSCREEN_NOTOUCH;
            config.keyboard = Configuration.KEYBOARD_NOKEYS;
            config.navigation = Configuration.NAVIGATION_NONAV;
            
            final int N = mDevices.size();
            for (int i=0; i<N; i++) {
                InputDevice d = mDevices.valueAt(i);
                if (d != null) {
                    if ((d.classes&RawInputEvent.CLASS_TOUCHSCREEN) != 0) {
                        config.touchscreen
                                = Configuration.TOUCHSCREEN_FINGER;
                        //Log.i("foo", "***** HAVE TOUCHSCREEN!");
                    }
                    if ((d.classes&RawInputEvent.CLASS_ALPHAKEY) != 0) {
                        config.keyboard
                                = Configuration.KEYBOARD_QWERTY;
                        //Log.i("foo", "***** HAVE QWERTY!");
                    }
                    if ((d.classes&RawInputEvent.CLASS_TRACKBALL) != 0) {
                        config.navigation
                                = Configuration.NAVIGATION_TRACKBALL;
                        //Log.i("foo", "***** HAVE TRACKBALL!");
                    }
                }
            }
        }
    
InputDevicegetInputDevice(int deviceId)

        synchronized (mFirst) {
            return getInputDeviceLocked(deviceId);
        }
    
private InputDevicegetInputDeviceLocked(int deviceId)

        return mDevices.get(deviceId);
    
public static native intgetKeycodeState(int sw)

public static native intgetKeycodeState(int deviceId, int sw)

public static native intgetScancodeState(int deviceId, int sw)

public static native intgetScancodeState(int sw)

public static native intgetSwitchState(int sw)

public static native intgetSwitchState(int deviceId, int sw)

booleanhasEvents()

        synchronized (mFirst) {
            return mFirst.next != mLast;
        }
    
public static native booleanhasKeys(int[] keycodes, boolean[] keyExists)

private InputDevice.AbsoluteInfoloadAbsoluteInfo(int id, int channel, java.lang.String name)

        InputDevice.AbsoluteInfo info = new InputDevice.AbsoluteInfo();
        if (getAbsoluteInfo(id, channel, info)
                && info.minValue != info.maxValue) {
            Log.i(TAG, "  " + name + ": min=" + info.minValue
                    + " max=" + info.maxValue
                    + " flat=" + info.flat
                    + " fuzz=" + info.fuzz);
            info.range = info.maxValue-info.minValue;
            return info;
        }
        Log.i(TAG, "  " + name + ": unknown values");
        return null;
    
private static final intmakeMetaState(int keycode, boolean down, int old)
Returns a new meta state for the given keys and old state.


                     
              
        int mask;
        switch (keycode) {
        case KeyEvent.KEYCODE_ALT_LEFT:
            mask = KeyEvent.META_ALT_LEFT_ON;
            break;
        case KeyEvent.KEYCODE_ALT_RIGHT:
            mask = KeyEvent.META_ALT_RIGHT_ON;
            break;
        case KeyEvent.KEYCODE_SHIFT_LEFT:
            mask = KeyEvent.META_SHIFT_LEFT_ON;
            break;
        case KeyEvent.KEYCODE_SHIFT_RIGHT:
            mask = KeyEvent.META_SHIFT_RIGHT_ON;
            break;
        case KeyEvent.KEYCODE_SYM:
            mask = KeyEvent.META_SYM_ON;
            break;
        default:
            return old;
        }
        int result = ~(KeyEvent.META_ALT_ON | KeyEvent.META_SHIFT_ON)
                    & (down ? (old | mask) : (old & ~mask));
        if (0 != (result & (KeyEvent.META_ALT_LEFT_ON | KeyEvent.META_ALT_RIGHT_ON))) {
            result |= KeyEvent.META_ALT_ON;
        }
        if (0 != (result & (KeyEvent.META_SHIFT_LEFT_ON | KeyEvent.META_SHIFT_RIGHT_ON))) {
            result |= KeyEvent.META_SHIFT_ON;
        }
        return result;
    
private InputDevicenewInputDevice(int deviceId)

        int classes = getDeviceClasses(deviceId);
        String name = getDeviceName(deviceId);
        Log.i(TAG, "Device added: id=0x" + Integer.toHexString(deviceId)
                + ", name=" + name
                + ", classes=" + Integer.toHexString(classes));
        InputDevice.AbsoluteInfo absX;
        InputDevice.AbsoluteInfo absY;
        InputDevice.AbsoluteInfo absPressure;
        InputDevice.AbsoluteInfo absSize;
        if ((classes&RawInputEvent.CLASS_TOUCHSCREEN) != 0) {
            absX = loadAbsoluteInfo(deviceId, RawInputEvent.ABS_X, "X");
            absY = loadAbsoluteInfo(deviceId, RawInputEvent.ABS_Y, "Y");
            absPressure = loadAbsoluteInfo(deviceId, RawInputEvent.ABS_PRESSURE, "Pressure");
            absSize = loadAbsoluteInfo(deviceId, RawInputEvent.ABS_TOOL_WIDTH, "Size");
        } else {
            absX = null;
            absY = null;
            absPressure = null;
            absSize = null;
        }
        
        return new InputDevice(deviceId, classes, name, absX, absY, absPressure, absSize);
    
public static android.view.KeyEventnewKeyEvent(InputDevice device, long downTime, long eventTime, boolean down, int keycode, int repeatCount, int scancode, int flags)

        return new KeyEvent(
                downTime, eventTime,
                down ? KeyEvent.ACTION_DOWN : KeyEvent.ACTION_UP,
                keycode, repeatCount,
                device != null ? device.mMetaKeysState : 0,
                device != null ? device.id : -1, scancode,
                flags | KeyEvent.FLAG_FROM_SYSTEM);
    
private com.android.server.KeyInputQueue$QueuedEventobtainLocked(InputDevice device, long when, int flags, int classType, java.lang.Object event)

        QueuedEvent ev;
        if (mCacheCount == 0) {
            ev = new QueuedEvent();
        } else {
            ev = mCache;
            ev.inQueue = false;
            mCache = ev.next;
            mCacheCount--;
        }
        ev.inputDevice = device;
        ev.when = when;
        ev.flags = flags;
        ev.classType = classType;
        ev.event = event;
        return ev;
    
abstract booleanpreprocessEvent(InputDevice device, android.view.RawInputEvent event)

private static native booleanreadEvent(android.view.RawInputEvent outEvent)

voidrecycleEvent(com.android.server.KeyInputQueue$QueuedEvent ev)

        synchronized (mFirst) {
            //Log.i(TAG, "Recycle event: " + ev);
            if (ev.event == ev.inputDevice.mAbs.currentMove) {
                ev.inputDevice.mAbs.currentMove = null;
            }
            if (ev.event == ev.inputDevice.mRel.currentMove) {
                if (false) Log.i(TAG, "Detach rel " + ev.event);
                ev.inputDevice.mRel.currentMove = null;
                ev.inputDevice.mRel.x = 0;
                ev.inputDevice.mRel.y = 0;
            }
            recycleLocked(ev);
        }
    
private voidrecycleLocked(com.android.server.KeyInputQueue$QueuedEvent ev)

        if (ev.inQueue) {
            throw new RuntimeException("Event already in queue!");
        }
        if (mCacheCount < 10) {
            mCacheCount++;
            ev.next = mCache;
            mCache = ev;
            ev.inQueue = true;
        }
    
public introtateKeyCode(int keyCode)

        synchronized(mFirst) {
            return rotateKeyCodeLocked(keyCode);
        }
    
private introtateKeyCodeLocked(int keyCode)

        int[] map = mKeyRotationMap;
        if (map != null) {
            final int N = map.length;
            for (int i=0; i<N; i+=2) {
                if (map[i] == keyCode) {
                    return map[i+1];
                }
            }
        }
        return keyCode;
    
public voidsetDisplay(android.view.Display display)

        mDisplay = display;
    
public voidsetOrientation(int orientation)

        synchronized(mFirst) {
            mOrientation = orientation;
            switch (orientation) {
                case Surface.ROTATION_90:
                    mKeyRotationMap = KEY_90_MAP;
                    break;
                case Surface.ROTATION_180:
                    mKeyRotationMap = KEY_180_MAP;
                    break;
                case Surface.ROTATION_270:
                    mKeyRotationMap = KEY_270_MAP;
                    break;
                default:
                    mKeyRotationMap = null;
                    break;
            }
        }