diff options
author | Jeff Brown <jeffbrown@google.com> | 2010-07-02 15:37:36 -0700 |
---|---|---|
committer | Jeff Brown <jeffbrown@google.com> | 2010-07-03 19:23:01 -0700 |
commit | 00fa7bdd69f0868fd17ea7c881c771d785b2fbbd (patch) | |
tree | 6fff8ad404e57af316c6ce5a20020dc209eb3cc6 /services | |
parent | 8ecfb60a8e74dfcd51bbf3f236d5f414a4d5ac7d (diff) | |
download | frameworks_base-00fa7bdd69f0868fd17ea7c881c771d785b2fbbd.zip frameworks_base-00fa7bdd69f0868fd17ea7c881c771d785b2fbbd.tar.gz frameworks_base-00fa7bdd69f0868fd17ea7c881c771d785b2fbbd.tar.bz2 |
More native input dispatch work.
Removed old input dispatch code.
Refactored the policy callbacks.
Pushed a tiny bit of the power manager state down to native.
Fixed long press on MENU.
Made the virtual key detection and cancelation a bit more precise.
Change-Id: I5d8c1062f7ea0ab3b54c6fadb058c4d5f5a9e02e
Diffstat (limited to 'services')
-rw-r--r-- | services/java/com/android/server/InputDevice.java | 1025 | ||||
-rw-r--r-- | services/java/com/android/server/InputManager.java | 50 | ||||
-rw-r--r-- | services/java/com/android/server/KeyInputQueue.java | 1388 | ||||
-rw-r--r-- | services/java/com/android/server/PowerManagerService.java | 16 | ||||
-rw-r--r-- | services/java/com/android/server/WindowManagerService.java | 2093 | ||||
-rw-r--r-- | services/jni/Android.mk | 2 | ||||
-rw-r--r-- | services/jni/com_android_server_InputManager.cpp | 164 | ||||
-rw-r--r-- | services/jni/com_android_server_KeyInputQueue.cpp | 358 | ||||
-rw-r--r-- | services/jni/com_android_server_PowerManagerService.cpp | 142 | ||||
-rw-r--r-- | services/jni/com_android_server_PowerManagerService.h | 42 | ||||
-rw-r--r-- | services/jni/onload.cpp | 4 |
11 files changed, 387 insertions, 4897 deletions
diff --git a/services/java/com/android/server/InputDevice.java b/services/java/com/android/server/InputDevice.java deleted file mode 100644 index 414b69f..0000000 --- a/services/java/com/android/server/InputDevice.java +++ /dev/null @@ -1,1025 +0,0 @@ -/* - * Copyright (C) 2007 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. - */ - -package com.android.server; - -import android.util.Slog; -import android.view.Display; -import android.view.MotionEvent; -import android.view.Surface; -import android.view.WindowManagerPolicy; - -import java.io.PrintWriter; - -public class InputDevice { - static final boolean DEBUG_POINTERS = false; - static final boolean DEBUG_HACKS = false; - - /** Amount that trackball needs to move in order to generate a key event. */ - static final int TRACKBALL_MOVEMENT_THRESHOLD = 6; - - /** Maximum number of pointers we will track and report. */ - static final int MAX_POINTERS = 10; - - /** - * Slop distance for jumpy pointer detection. - * The vertical range of the screen divided by this is our epsilon value. - */ - private static final int JUMPY_EPSILON_DIVISOR = 212; - - /** Number of jumpy points to drop for touchscreens that need it. */ - private static final int JUMPY_TRANSITION_DROPS = 3; - private static final int JUMPY_DROP_LIMIT = 3; - - final int id; - final int classes; - final String name; - final AbsoluteInfo absX; - final AbsoluteInfo absY; - final AbsoluteInfo absPressure; - final AbsoluteInfo absSize; - - long mKeyDownTime = 0; - int mMetaKeysState = 0; - - // For use by KeyInputQueue for keeping track of the current touch - // data in the old non-multi-touch protocol. - final int[] curTouchVals = new int[MotionEvent.NUM_SAMPLE_DATA * 2]; - - final MotionState mAbs = new MotionState(0, 0); - final MotionState mRel = new MotionState(TRACKBALL_MOVEMENT_THRESHOLD, - TRACKBALL_MOVEMENT_THRESHOLD); - - static class MotionState { - int xPrecision; - int yPrecision; - float xMoveScale; - float yMoveScale; - MotionEvent currentMove = null; - boolean changed = false; - boolean everChanged = false; - long mDownTime = 0; - - // The currently assigned pointer IDs, corresponding to the last data. - int[] mPointerIds = new int[MAX_POINTERS]; - - // This is the last generated pointer data, ordered to match - // mPointerIds. - boolean mSkipLastPointers; - int mLastNumPointers = 0; - final int[] mLastData = new int[MotionEvent.NUM_SAMPLE_DATA * MAX_POINTERS]; - - // This is the next set of pointer data being generated. It is not - // in any known order, and will be propagated in to mLastData - // as part of mapping it to the appropriate pointer IDs. - // Note that we have one extra sample of data here, to help clients - // avoid doing bounds checking. - int mNextNumPointers = 0; - final int[] mNextData = new int[(MotionEvent.NUM_SAMPLE_DATA * MAX_POINTERS) - + MotionEvent.NUM_SAMPLE_DATA]; - - // Used to determine whether we dropped bad data, to avoid doing - // it repeatedly. - final boolean[] mDroppedBadPoint = new boolean[MAX_POINTERS]; - - // Used to count the number of jumpy points dropped. - private int mJumpyPointsDropped = 0; - - // Used to perform averaging of reported coordinates, to smooth - // the data and filter out transients during a release. - static final int HISTORY_SIZE = 5; - int[] mHistoryDataStart = new int[MAX_POINTERS]; - int[] mHistoryDataEnd = new int[MAX_POINTERS]; - final int[] mHistoryData = new int[(MotionEvent.NUM_SAMPLE_DATA * MAX_POINTERS) - * HISTORY_SIZE]; - final int[] mAveragedData = new int[MotionEvent.NUM_SAMPLE_DATA * MAX_POINTERS]; - - // Temporary data structures for doing the pointer ID mapping. - final int[] mLast2Next = new int[MAX_POINTERS]; - final int[] mNext2Last = new int[MAX_POINTERS]; - final long[] mNext2LastDistance = new long[MAX_POINTERS]; - - // Temporary data structure for generating the final motion data. - final float[] mReportData = new float[MotionEvent.NUM_SAMPLE_DATA * MAX_POINTERS]; - - // This is not used here, but can be used by callers for state tracking. - int mAddingPointerOffset = 0; - final boolean[] mDown = new boolean[MAX_POINTERS]; - - void dumpIntArray(PrintWriter pw, int[] array) { - pw.print("["); - for (int i=0; i<array.length; i++) { - if (i > 0) pw.print(", "); - pw.print(array[i]); - } - pw.print("]"); - } - - void dumpBooleanArray(PrintWriter pw, boolean[] array) { - pw.print("["); - for (int i=0; i<array.length; i++) { - if (i > 0) pw.print(", "); - pw.print(array[i] ? "true" : "false"); - } - pw.print("]"); - } - - void dump(PrintWriter pw, String prefix) { - pw.print(prefix); pw.print("xPrecision="); pw.print(xPrecision); - pw.print(" yPrecision="); pw.println(yPrecision); - pw.print(prefix); pw.print("xMoveScale="); pw.print(xMoveScale); - pw.print(" yMoveScale="); pw.println(yMoveScale); - if (currentMove != null) { - pw.print(prefix); pw.print("currentMove="); pw.println(currentMove); - } - if (changed || mDownTime != 0) { - pw.print(prefix); pw.print("changed="); pw.print(changed); - pw.print(" mDownTime="); pw.println(mDownTime); - } - pw.print(prefix); pw.print("mPointerIds="); dumpIntArray(pw, mPointerIds); - pw.println(""); - if (mSkipLastPointers || mLastNumPointers != 0) { - pw.print(prefix); pw.print("mSkipLastPointers="); pw.print(mSkipLastPointers); - pw.print(" mLastNumPointers="); pw.println(mLastNumPointers); - pw.print(prefix); pw.print("mLastData="); dumpIntArray(pw, mLastData); - pw.println(""); - } - if (mNextNumPointers != 0) { - pw.print(prefix); pw.print("mNextNumPointers="); pw.println(mNextNumPointers); - pw.print(prefix); pw.print("mNextData="); dumpIntArray(pw, mNextData); - pw.println(""); - } - pw.print(prefix); pw.print("mDroppedBadPoint="); - dumpBooleanArray(pw, mDroppedBadPoint); pw.println(""); - pw.print(prefix); pw.print("mAddingPointerOffset="); pw.println(mAddingPointerOffset); - pw.print(prefix); pw.print("mDown="); - dumpBooleanArray(pw, mDown); pw.println(""); - } - - MotionState(int mx, int my) { - xPrecision = mx; - yPrecision = my; - xMoveScale = mx != 0 ? (1.0f/mx) : 1.0f; - yMoveScale = my != 0 ? (1.0f/my) : 1.0f; - for (int i=0; i<MAX_POINTERS; i++) { - mPointerIds[i] = i; - } - } - - /** - * Special hack for devices that have bad screen data: if one of the - * points has moved more than a screen height from the last position, - * then drop it. - */ - void dropBadPoint(InputDevice dev) { - // We should always have absY, but let's be paranoid. - if (dev.absY == null) { - return; - } - // Don't do anything if a finger is going down or up. We run - // here before assigning pointer IDs, so there isn't a good - // way to do per-finger matching. - if (mNextNumPointers != mLastNumPointers) { - return; - } - - // We consider a single movement across more than a 7/16 of - // the long size of the screen to be bad. This was a magic value - // determined by looking at the maximum distance it is feasible - // to actually move in one sample. - final int maxDy = ((dev.absY.maxValue-dev.absY.minValue)*7)/16; - - // Look through all new points and see if any are farther than - // acceptable from all previous points. - for (int i=mNextNumPointers-1; i>=0; i--) { - final int ioff = i * MotionEvent.NUM_SAMPLE_DATA; - //final int x = mNextData[ioff + MotionEvent.SAMPLE_X]; - final int y = mNextData[ioff + MotionEvent.SAMPLE_Y]; - if (DEBUG_HACKS) Slog.v("InputDevice", "Looking at next point #" + i + ": y=" + y); - boolean dropped = false; - if (!mDroppedBadPoint[i] && mLastNumPointers > 0) { - dropped = true; - int closestDy = -1; - int closestY = -1; - // We will drop this new point if it is sufficiently - // far away from -all- last points. - for (int j=mLastNumPointers-1; j>=0; j--) { - final int joff = j * MotionEvent.NUM_SAMPLE_DATA; - //int dx = x - mLastData[joff + MotionEvent.SAMPLE_X]; - int dy = y - mLastData[joff + MotionEvent.SAMPLE_Y]; - //if (dx < 0) dx = -dx; - if (dy < 0) dy = -dy; - if (DEBUG_HACKS) Slog.v("InputDevice", "Comparing with last point #" + j - + ": y=" + mLastData[joff] + " dy=" + dy); - if (dy < maxDy) { - dropped = false; - break; - } else if (closestDy < 0 || dy < closestDy) { - closestDy = dy; - closestY = mLastData[joff + MotionEvent.SAMPLE_Y]; - } - } - if (dropped) { - dropped = true; - Slog.i("InputDevice", "Dropping bad point #" + i - + ": newY=" + y + " closestDy=" + closestDy - + " maxDy=" + maxDy); - mNextData[ioff + MotionEvent.SAMPLE_Y] = closestY; - break; - } - } - mDroppedBadPoint[i] = dropped; - } - } - - void dropJumpyPoint(InputDevice dev) { - // We should always have absY, but let's be paranoid. - if (dev.absY == null) { - return; - } - final int jumpyEpsilon = dev.absY.range / JUMPY_EPSILON_DIVISOR; - - final int nextNumPointers = mNextNumPointers; - final int lastNumPointers = mLastNumPointers; - final int[] nextData = mNextData; - final int[] lastData = mLastData; - - if (nextNumPointers != mLastNumPointers) { - if (DEBUG_HACKS) { - Slog.d("InputDevice", "Different pointer count " + lastNumPointers + - " -> " + nextNumPointers); - for (int i = 0; i < nextNumPointers; i++) { - int ioff = i * MotionEvent.NUM_SAMPLE_DATA; - Slog.d("InputDevice", "Pointer " + i + " (" + - mNextData[ioff + MotionEvent.SAMPLE_X] + ", " + - mNextData[ioff + MotionEvent.SAMPLE_Y] + ")"); - } - } - - // Just drop the first few events going from 1 to 2 pointers. - // They're bad often enough that they're not worth considering. - if (lastNumPointers == 1 && nextNumPointers == 2 - && mJumpyPointsDropped < JUMPY_TRANSITION_DROPS) { - mNextNumPointers = 1; - mJumpyPointsDropped++; - } else if (lastNumPointers == 2 && nextNumPointers == 1 - && mJumpyPointsDropped < JUMPY_TRANSITION_DROPS) { - // The event when we go from 2 -> 1 tends to be messed up too - System.arraycopy(lastData, 0, nextData, 0, - lastNumPointers * MotionEvent.NUM_SAMPLE_DATA); - mNextNumPointers = lastNumPointers; - mJumpyPointsDropped++; - - if (DEBUG_HACKS) { - for (int i = 0; i < mNextNumPointers; i++) { - int ioff = i * MotionEvent.NUM_SAMPLE_DATA; - Slog.d("InputDevice", "Pointer " + i + " replaced (" + - mNextData[ioff + MotionEvent.SAMPLE_X] + ", " + - mNextData[ioff + MotionEvent.SAMPLE_Y] + ")"); - } - } - } else { - mJumpyPointsDropped = 0; - - if (DEBUG_HACKS) { - Slog.d("InputDevice", "Transition - drop limit reset"); - } - } - return; - } - - // A 'jumpy' point is one where the coordinate value for one axis - // has jumped to the other pointer's location. No need to do anything - // else if we only have one pointer. - if (nextNumPointers < 2) { - return; - } - - int badPointerIndex = -1; - int badPointerReplaceXWith = 0; - int badPointerReplaceYWith = 0; - int badPointerDistance = Integer.MIN_VALUE; - for (int i = nextNumPointers - 1; i >= 0; i--) { - boolean dropx = false; - boolean dropy = false; - - // Limit how many times a jumpy point can get dropped. - if (mJumpyPointsDropped < JUMPY_DROP_LIMIT) { - final int ioff = i * MotionEvent.NUM_SAMPLE_DATA; - final int x = nextData[ioff + MotionEvent.SAMPLE_X]; - final int y = nextData[ioff + MotionEvent.SAMPLE_Y]; - - if (DEBUG_HACKS) { - Slog.d("InputDevice", "Point " + i + " (" + x + ", " + y + ")"); - } - - // Check if a touch point is too close to another's coordinates - for (int j = 0; j < nextNumPointers && !dropx && !dropy; j++) { - if (j == i) { - continue; - } - - final int joff = j * MotionEvent.NUM_SAMPLE_DATA; - final int xOther = nextData[joff + MotionEvent.SAMPLE_X]; - final int yOther = nextData[joff + MotionEvent.SAMPLE_Y]; - - dropx = Math.abs(x - xOther) <= jumpyEpsilon; - dropy = Math.abs(y - yOther) <= jumpyEpsilon; - } - - if (dropx) { - int xreplace = lastData[MotionEvent.SAMPLE_X]; - int yreplace = lastData[MotionEvent.SAMPLE_Y]; - int distance = Math.abs(yreplace - y); - for (int j = 1; j < lastNumPointers; j++) { - final int joff = j * MotionEvent.NUM_SAMPLE_DATA; - int lasty = lastData[joff + MotionEvent.SAMPLE_Y]; - int currDist = Math.abs(lasty - y); - if (currDist < distance) { - xreplace = lastData[joff + MotionEvent.SAMPLE_X]; - yreplace = lasty; - distance = currDist; - } - } - - int badXDelta = Math.abs(xreplace - x); - if (badXDelta > badPointerDistance) { - badPointerDistance = badXDelta; - badPointerIndex = i; - badPointerReplaceXWith = xreplace; - badPointerReplaceYWith = yreplace; - } - } else if (dropy) { - int xreplace = lastData[MotionEvent.SAMPLE_X]; - int yreplace = lastData[MotionEvent.SAMPLE_Y]; - int distance = Math.abs(xreplace - x); - for (int j = 1; j < lastNumPointers; j++) { - final int joff = j * MotionEvent.NUM_SAMPLE_DATA; - int lastx = lastData[joff + MotionEvent.SAMPLE_X]; - int currDist = Math.abs(lastx - x); - if (currDist < distance) { - xreplace = lastx; - yreplace = lastData[joff + MotionEvent.SAMPLE_Y]; - distance = currDist; - } - } - - int badYDelta = Math.abs(yreplace - y); - if (badYDelta > badPointerDistance) { - badPointerDistance = badYDelta; - badPointerIndex = i; - badPointerReplaceXWith = xreplace; - badPointerReplaceYWith = yreplace; - } - } - } - } - if (badPointerIndex >= 0) { - if (DEBUG_HACKS) { - Slog.d("InputDevice", "Replacing bad pointer " + badPointerIndex + - " with (" + badPointerReplaceXWith + ", " + badPointerReplaceYWith + - ")"); - } - - final int offset = badPointerIndex * MotionEvent.NUM_SAMPLE_DATA; - nextData[offset + MotionEvent.SAMPLE_X] = badPointerReplaceXWith; - nextData[offset + MotionEvent.SAMPLE_Y] = badPointerReplaceYWith; - mJumpyPointsDropped++; - } else { - mJumpyPointsDropped = 0; - } - } - - /** - * Special hack for devices that have bad screen data: aggregate and - * compute averages of the coordinate data, to reduce the amount of - * jitter seen by applications. - */ - int[] generateAveragedData(int upOrDownPointer, int lastNumPointers, - int nextNumPointers) { - final int numPointers = mLastNumPointers; - final int[] rawData = mLastData; - if (DEBUG_HACKS) Slog.v("InputDevice", "lastNumPointers=" + lastNumPointers - + " nextNumPointers=" + nextNumPointers - + " numPointers=" + numPointers); - for (int i=0; i<numPointers; i++) { - final int ioff = i * MotionEvent.NUM_SAMPLE_DATA; - // We keep the average data in offsets based on the pointer - // ID, so we don't need to move it around as fingers are - // pressed and released. - final int p = mPointerIds[i]; - final int poff = p * MotionEvent.NUM_SAMPLE_DATA * HISTORY_SIZE; - if (i == upOrDownPointer && lastNumPointers != nextNumPointers) { - if (lastNumPointers < nextNumPointers) { - // This pointer is going down. Clear its history - // and start fresh. - if (DEBUG_HACKS) Slog.v("InputDevice", "Pointer down @ index " - + upOrDownPointer + " id " + mPointerIds[i]); - mHistoryDataStart[i] = 0; - mHistoryDataEnd[i] = 0; - System.arraycopy(rawData, ioff, mHistoryData, poff, - MotionEvent.NUM_SAMPLE_DATA); - System.arraycopy(rawData, ioff, mAveragedData, ioff, - MotionEvent.NUM_SAMPLE_DATA); - continue; - } else { - // The pointer is going up. Just fall through to - // recompute the last averaged point (and don't add - // it as a new point to include in the average). - if (DEBUG_HACKS) Slog.v("InputDevice", "Pointer up @ index " - + upOrDownPointer + " id " + mPointerIds[i]); - } - } else { - int end = mHistoryDataEnd[i]; - int eoff = poff + (end*MotionEvent.NUM_SAMPLE_DATA); - int oldX = mHistoryData[eoff + MotionEvent.SAMPLE_X]; - int oldY = mHistoryData[eoff + MotionEvent.SAMPLE_Y]; - int newX = rawData[ioff + MotionEvent.SAMPLE_X]; - int newY = rawData[ioff + MotionEvent.SAMPLE_Y]; - int dx = newX-oldX; - int dy = newY-oldY; - int delta = dx*dx + dy*dy; - if (DEBUG_HACKS) Slog.v("InputDevice", "Delta from last: " + delta); - if (delta >= (75*75)) { - // Magic number, if moving farther than this, turn - // off filtering to avoid lag in response. - mHistoryDataStart[i] = 0; - mHistoryDataEnd[i] = 0; - System.arraycopy(rawData, ioff, mHistoryData, poff, - MotionEvent.NUM_SAMPLE_DATA); - System.arraycopy(rawData, ioff, mAveragedData, ioff, - MotionEvent.NUM_SAMPLE_DATA); - continue; - } else { - end++; - if (end >= HISTORY_SIZE) { - end -= HISTORY_SIZE; - } - mHistoryDataEnd[i] = end; - int noff = poff + (end*MotionEvent.NUM_SAMPLE_DATA); - mHistoryData[noff + MotionEvent.SAMPLE_X] = newX; - mHistoryData[noff + MotionEvent.SAMPLE_Y] = newY; - mHistoryData[noff + MotionEvent.SAMPLE_PRESSURE] - = rawData[ioff + MotionEvent.SAMPLE_PRESSURE]; - int start = mHistoryDataStart[i]; - if (end == start) { - start++; - if (start >= HISTORY_SIZE) { - start -= HISTORY_SIZE; - } - mHistoryDataStart[i] = start; - } - } - } - - // Now compute the average. - int start = mHistoryDataStart[i]; - int end = mHistoryDataEnd[i]; - int x=0, y=0; - int totalPressure = 0; - while (start != end) { - int soff = poff + (start*MotionEvent.NUM_SAMPLE_DATA); - int pressure = mHistoryData[soff + MotionEvent.SAMPLE_PRESSURE]; - if (pressure <= 0) pressure = 1; - x += mHistoryData[soff + MotionEvent.SAMPLE_X] * pressure; - y += mHistoryData[soff + MotionEvent.SAMPLE_Y] * pressure; - totalPressure += pressure; - start++; - if (start >= HISTORY_SIZE) start = 0; - } - int eoff = poff + (end*MotionEvent.NUM_SAMPLE_DATA); - int pressure = mHistoryData[eoff + MotionEvent.SAMPLE_PRESSURE]; - if (pressure <= 0) pressure = 1; - x += mHistoryData[eoff + MotionEvent.SAMPLE_X] * pressure; - y += mHistoryData[eoff + MotionEvent.SAMPLE_Y] * pressure; - totalPressure += pressure; - x /= totalPressure; - y /= totalPressure; - if (DEBUG_HACKS) Slog.v("InputDevice", "Averaging " + totalPressure - + " weight: (" + x + "," + y + ")"); - mAveragedData[ioff + MotionEvent.SAMPLE_X] = x; - mAveragedData[ioff + MotionEvent.SAMPLE_Y] = y; - mAveragedData[ioff + MotionEvent.SAMPLE_PRESSURE] = - rawData[ioff + MotionEvent.SAMPLE_PRESSURE]; - mAveragedData[ioff + MotionEvent.SAMPLE_SIZE] = - rawData[ioff + MotionEvent.SAMPLE_SIZE]; - } - return mAveragedData; - } - - private boolean assignPointer(int nextIndex, boolean allowOverlap) { - final int lastNumPointers = mLastNumPointers; - final int[] next2Last = mNext2Last; - final long[] next2LastDistance = mNext2LastDistance; - final int[] last2Next = mLast2Next; - final int[] lastData = mLastData; - final int[] nextData = mNextData; - final int id = nextIndex * MotionEvent.NUM_SAMPLE_DATA; - - if (DEBUG_POINTERS) Slog.v("InputDevice", "assignPointer: nextIndex=" - + nextIndex + " dataOff=" + id); - final int x1 = nextData[id + MotionEvent.SAMPLE_X]; - final int y1 = nextData[id + MotionEvent.SAMPLE_Y]; - - long bestDistance = -1; - int bestIndex = -1; - for (int j=0; j<lastNumPointers; j++) { - // If we are not allowing multiple new points to be assigned - // to the same old pointer, then skip this one if it is already - // detected as a conflict (-2). - if (!allowOverlap && last2Next[j] < -1) { - continue; - } - final int jd = j * MotionEvent.NUM_SAMPLE_DATA; - final int xd = lastData[jd + MotionEvent.SAMPLE_X] - x1; - final int yd = lastData[jd + MotionEvent.SAMPLE_Y] - y1; - final long distance = xd*(long)xd + yd*(long)yd; - if (bestDistance == -1 || distance < bestDistance) { - bestDistance = distance; - bestIndex = j; - } - } - - if (DEBUG_POINTERS) Slog.v("InputDevice", "New index " + nextIndex - + " best old index=" + bestIndex + " (distance=" - + bestDistance + ")"); - next2Last[nextIndex] = bestIndex; - next2LastDistance[nextIndex] = bestDistance; - - if (bestIndex < 0) { - return true; - } - - if (last2Next[bestIndex] == -1) { - last2Next[bestIndex] = nextIndex; - return false; - } - - if (DEBUG_POINTERS) Slog.v("InputDevice", "Old index " + bestIndex - + " has multiple best new pointers!"); - - last2Next[bestIndex] = -2; - return true; - } - - private int updatePointerIdentifiers() { - final int[] lastData = mLastData; - final int[] nextData = mNextData; - final int nextNumPointers = mNextNumPointers; - final int lastNumPointers = mLastNumPointers; - - if (nextNumPointers == 1 && lastNumPointers == 1) { - System.arraycopy(nextData, 0, lastData, 0, - MotionEvent.NUM_SAMPLE_DATA); - return -1; - } - - // Clear our old state. - final int[] last2Next = mLast2Next; - for (int i=0; i<lastNumPointers; i++) { - last2Next[i] = -1; - } - - if (DEBUG_POINTERS) Slog.v("InputDevice", - "Update pointers: lastNumPointers=" + lastNumPointers - + " nextNumPointers=" + nextNumPointers); - - // Figure out the closes new points to the previous points. - final int[] next2Last = mNext2Last; - final long[] next2LastDistance = mNext2LastDistance; - boolean conflicts = false; - for (int i=0; i<nextNumPointers; i++) { - conflicts |= assignPointer(i, true); - } - - // Resolve ambiguities in pointer mappings, when two or more - // new pointer locations find their best previous location is - // the same. - if (conflicts) { - if (DEBUG_POINTERS) Slog.v("InputDevice", "Resolving conflicts"); - - for (int i=0; i<lastNumPointers; i++) { - if (last2Next[i] != -2) { - continue; - } - - // Note that this algorithm is far from perfect. Ideally - // we should do something like the one described at - // http://portal.acm.org/citation.cfm?id=997856 - - if (DEBUG_POINTERS) Slog.v("InputDevice", - "Resolving last index #" + i); - - int numFound; - do { - numFound = 0; - long worstDistance = 0; - int worstJ = -1; - for (int j=0; j<nextNumPointers; j++) { - if (next2Last[j] != i) { - continue; - } - numFound++; - if (worstDistance < next2LastDistance[j]) { - worstDistance = next2LastDistance[j]; - worstJ = j; - } - } - - if (worstJ >= 0) { - if (DEBUG_POINTERS) Slog.v("InputDevice", - "Worst new pointer: " + worstJ - + " (distance=" + worstDistance + ")"); - if (assignPointer(worstJ, false)) { - // In this case there is no last pointer - // remaining for this new one! - next2Last[worstJ] = -1; - } - } - } while (numFound > 2); - } - } - - int retIndex = -1; - - if (lastNumPointers < nextNumPointers) { - // We have one or more new pointers that are down. Create a - // new pointer identifier for one of them. - if (DEBUG_POINTERS) Slog.v("InputDevice", "Adding new pointer"); - int nextId = 0; - int i=0; - while (i < lastNumPointers) { - if (mPointerIds[i] > nextId) { - // Found a hole, insert the pointer here. - if (DEBUG_POINTERS) Slog.v("InputDevice", - "Inserting new pointer at hole " + i); - System.arraycopy(mPointerIds, i, mPointerIds, - i+1, lastNumPointers-i); - System.arraycopy(lastData, i*MotionEvent.NUM_SAMPLE_DATA, - lastData, (i+1)*MotionEvent.NUM_SAMPLE_DATA, - (lastNumPointers-i)*MotionEvent.NUM_SAMPLE_DATA); - System.arraycopy(next2Last, i, next2Last, - i+1, lastNumPointers-i); - break; - } - i++; - nextId++; - } - - if (DEBUG_POINTERS) Slog.v("InputDevice", - "New pointer id " + nextId + " at index " + i); - - mLastNumPointers++; - retIndex = i; - mPointerIds[i] = nextId; - - // And assign this identifier to the first new pointer. - for (int j=0; j<nextNumPointers; j++) { - if (next2Last[j] < 0) { - if (DEBUG_POINTERS) Slog.v("InputDevice", - "Assigning new id to new pointer index " + j); - next2Last[j] = i; - break; - } - } - } - - // Propagate all of the current data into the appropriate - // location in the old data to match the pointer ID that was - // assigned to it. - for (int i=0; i<nextNumPointers; i++) { - int lastIndex = next2Last[i]; - if (lastIndex >= 0) { - if (DEBUG_POINTERS) Slog.v("InputDevice", - "Copying next pointer index " + i - + " to last index " + lastIndex); - System.arraycopy(nextData, i*MotionEvent.NUM_SAMPLE_DATA, - lastData, lastIndex*MotionEvent.NUM_SAMPLE_DATA, - MotionEvent.NUM_SAMPLE_DATA); - } - } - - if (lastNumPointers > nextNumPointers) { - // One or more pointers has gone up. Find the first one, - // and adjust accordingly. - if (DEBUG_POINTERS) Slog.v("InputDevice", "Removing old pointer"); - for (int i=0; i<lastNumPointers; i++) { - if (last2Next[i] == -1) { - if (DEBUG_POINTERS) Slog.v("InputDevice", - "Removing old pointer at index " + i); - retIndex = i; - break; - } - } - } - - return retIndex; - } - - void removeOldPointer(int index) { - final int lastNumPointers = mLastNumPointers; - if (index >= 0 && index < lastNumPointers) { - System.arraycopy(mPointerIds, index+1, mPointerIds, - index, lastNumPointers-index-1); - System.arraycopy(mLastData, (index+1)*MotionEvent.NUM_SAMPLE_DATA, - mLastData, (index)*MotionEvent.NUM_SAMPLE_DATA, - (lastNumPointers-index-1)*MotionEvent.NUM_SAMPLE_DATA); - mLastNumPointers--; - } - } - - MotionEvent generateAbsMotion(InputDevice device, long curTime, - long curTimeNano, Display display, int orientation, - int metaState) { - - if (mSkipLastPointers) { - mSkipLastPointers = false; - mLastNumPointers = 0; - } - - if (mNextNumPointers <= 0 && mLastNumPointers <= 0) { - return null; - } - - final int lastNumPointers = mLastNumPointers; - final int nextNumPointers = mNextNumPointers; - if (mNextNumPointers > MAX_POINTERS) { - Slog.w("InputDevice", "Number of pointers " + mNextNumPointers - + " exceeded maximum of " + MAX_POINTERS); - mNextNumPointers = MAX_POINTERS; - } - - int upOrDownPointer = updatePointerIdentifiers(); - - final float[] reportData = mReportData; - final int[] rawData; - if (KeyInputQueue.BAD_TOUCH_HACK) { - rawData = generateAveragedData(upOrDownPointer, lastNumPointers, - nextNumPointers); - } else { - rawData = mLastData; - } - - final int numPointers = mLastNumPointers; - - if (DEBUG_POINTERS) Slog.v("InputDevice", "Processing " - + numPointers + " pointers (going from " + lastNumPointers - + " to " + nextNumPointers + ")"); - - for (int i=0; i<numPointers; i++) { - final int pos = i * MotionEvent.NUM_SAMPLE_DATA; - reportData[pos + MotionEvent.SAMPLE_X] = rawData[pos + MotionEvent.SAMPLE_X]; - reportData[pos + MotionEvent.SAMPLE_Y] = rawData[pos + MotionEvent.SAMPLE_Y]; - reportData[pos + MotionEvent.SAMPLE_PRESSURE] = rawData[pos + MotionEvent.SAMPLE_PRESSURE]; - reportData[pos + MotionEvent.SAMPLE_SIZE] = rawData[pos + MotionEvent.SAMPLE_SIZE]; - } - - int action; - int edgeFlags = 0; - if (nextNumPointers != lastNumPointers) { - if (nextNumPointers > lastNumPointers) { - if (lastNumPointers == 0) { - action = MotionEvent.ACTION_DOWN; - mDownTime = curTime; - } else { - action = MotionEvent.ACTION_POINTER_DOWN - | (upOrDownPointer << MotionEvent.ACTION_POINTER_INDEX_SHIFT); - } - } else { - if (numPointers == 1) { - action = MotionEvent.ACTION_UP; - } else { - action = MotionEvent.ACTION_POINTER_UP - | (upOrDownPointer << MotionEvent.ACTION_POINTER_INDEX_SHIFT); - } - } - currentMove = null; - } else { - action = MotionEvent.ACTION_MOVE; - } - - 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; - w = h; - h = tmp; - } - - final AbsoluteInfo absX = device.absX; - final AbsoluteInfo absY = device.absY; - final AbsoluteInfo absPressure = device.absPressure; - final AbsoluteInfo absSize = device.absSize; - for (int i=0; i<numPointers; i++) { - final int j = i * MotionEvent.NUM_SAMPLE_DATA; - - if (absX != null) { - reportData[j + MotionEvent.SAMPLE_X] = - ((reportData[j + MotionEvent.SAMPLE_X]-absX.minValue) - / absX.range) * w; - } - if (absY != null) { - reportData[j + MotionEvent.SAMPLE_Y] = - ((reportData[j + MotionEvent.SAMPLE_Y]-absY.minValue) - / absY.range) * h; - } - if (absPressure != null) { - reportData[j + MotionEvent.SAMPLE_PRESSURE] = - ((reportData[j + MotionEvent.SAMPLE_PRESSURE]-absPressure.minValue) - / (float)absPressure.range); - } - if (absSize != null) { - reportData[j + MotionEvent.SAMPLE_SIZE] = - ((reportData[j + MotionEvent.SAMPLE_SIZE]-absSize.minValue) - / (float)absSize.range); - } - - switch (orientation) { - case Surface.ROTATION_90: { - final float temp = reportData[j + MotionEvent.SAMPLE_X]; - reportData[j + MotionEvent.SAMPLE_X] = reportData[j + MotionEvent.SAMPLE_Y]; - reportData[j + MotionEvent.SAMPLE_Y] = w-temp; - break; - } - case Surface.ROTATION_180: { - reportData[j + MotionEvent.SAMPLE_X] = w-reportData[j + MotionEvent.SAMPLE_X]; - reportData[j + MotionEvent.SAMPLE_Y] = h-reportData[j + MotionEvent.SAMPLE_Y]; - break; - } - case Surface.ROTATION_270: { - final float temp = reportData[j + MotionEvent.SAMPLE_X]; - reportData[j + MotionEvent.SAMPLE_X] = h-reportData[j + MotionEvent.SAMPLE_Y]; - reportData[j + MotionEvent.SAMPLE_Y] = temp; - break; - } - } - } - - // We only consider the first pointer when computing the edge - // flags, since they are global to the event. - if (action == MotionEvent.ACTION_DOWN) { - if (reportData[MotionEvent.SAMPLE_X] <= 0) { - edgeFlags |= MotionEvent.EDGE_LEFT; - } else if (reportData[MotionEvent.SAMPLE_X] >= dispW) { - edgeFlags |= MotionEvent.EDGE_RIGHT; - } - if (reportData[MotionEvent.SAMPLE_Y] <= 0) { - edgeFlags |= MotionEvent.EDGE_TOP; - } else if (reportData[MotionEvent.SAMPLE_Y] >= dispH) { - edgeFlags |= MotionEvent.EDGE_BOTTOM; - } - } - - if (currentMove != null) { - if (false) Slog.i("InputDevice", "Adding batch x=" - + reportData[MotionEvent.SAMPLE_X] - + " y=" + reportData[MotionEvent.SAMPLE_Y] - + " to " + currentMove); - currentMove.addBatch(curTime, reportData, metaState); - if (WindowManagerPolicy.WATCH_POINTER) { - Slog.i("KeyInputQueue", "Updating: " + currentMove); - } - return null; - } - - MotionEvent me = MotionEvent.obtainNano(mDownTime, curTime, - curTimeNano, action, numPointers, mPointerIds, reportData, - metaState, xPrecision, yPrecision, device.id, edgeFlags); - if (action == MotionEvent.ACTION_MOVE) { - currentMove = me; - } - - if (nextNumPointers < lastNumPointers) { - removeOldPointer(upOrDownPointer); - } - - return me; - } - - boolean hasMore() { - return mLastNumPointers != mNextNumPointers; - } - - void finish() { - mNextNumPointers = mAddingPointerOffset = 0; - mNextData[MotionEvent.SAMPLE_PRESSURE] = 0; - } - - MotionEvent generateRelMotion(InputDevice device, long curTime, - long curTimeNano, int orientation, int metaState) { - - final float[] scaled = mReportData; - - // For now we only support 1 pointer with relative motions. - scaled[MotionEvent.SAMPLE_X] = mNextData[MotionEvent.SAMPLE_X]; - scaled[MotionEvent.SAMPLE_Y] = mNextData[MotionEvent.SAMPLE_Y]; - scaled[MotionEvent.SAMPLE_PRESSURE] = 1.0f; - scaled[MotionEvent.SAMPLE_SIZE] = 0; - int edgeFlags = 0; - - int action; - if (mNextNumPointers != mLastNumPointers) { - mNextData[MotionEvent.SAMPLE_X] = - mNextData[MotionEvent.SAMPLE_Y] = 0; - if (mNextNumPointers > 0 && mLastNumPointers == 0) { - action = MotionEvent.ACTION_DOWN; - mDownTime = curTime; - } else if (mNextNumPointers == 0) { - action = MotionEvent.ACTION_UP; - } else { - action = MotionEvent.ACTION_MOVE; - } - mLastNumPointers = mNextNumPointers; - currentMove = null; - } else { - action = MotionEvent.ACTION_MOVE; - } - - scaled[MotionEvent.SAMPLE_X] *= xMoveScale; - scaled[MotionEvent.SAMPLE_Y] *= yMoveScale; - switch (orientation) { - case Surface.ROTATION_90: { - final float temp = scaled[MotionEvent.SAMPLE_X]; - scaled[MotionEvent.SAMPLE_X] = scaled[MotionEvent.SAMPLE_Y]; - scaled[MotionEvent.SAMPLE_Y] = -temp; - break; - } - case Surface.ROTATION_180: { - scaled[MotionEvent.SAMPLE_X] = -scaled[MotionEvent.SAMPLE_X]; - scaled[MotionEvent.SAMPLE_Y] = -scaled[MotionEvent.SAMPLE_Y]; - break; - } - case Surface.ROTATION_270: { - final float temp = scaled[MotionEvent.SAMPLE_X]; - scaled[MotionEvent.SAMPLE_X] = -scaled[MotionEvent.SAMPLE_Y]; - scaled[MotionEvent.SAMPLE_Y] = temp; - break; - } - } - - if (currentMove != null) { - if (false) Slog.i("InputDevice", "Adding batch x=" - + scaled[MotionEvent.SAMPLE_X] - + " y=" + scaled[MotionEvent.SAMPLE_Y] - + " to " + currentMove); - currentMove.addBatch(curTime, scaled, metaState); - if (WindowManagerPolicy.WATCH_POINTER) { - Slog.i("KeyInputQueue", "Updating: " + currentMove); - } - return null; - } - - MotionEvent me = MotionEvent.obtainNano(mDownTime, curTime, - curTimeNano, action, 1, mPointerIds, scaled, metaState, - xPrecision, yPrecision, device.id, edgeFlags); - if (action == MotionEvent.ACTION_MOVE) { - currentMove = me; - } - return me; - } - } - - static class AbsoluteInfo { - int minValue; - int maxValue; - int range; - int flat; - int fuzz; - - final void dump(PrintWriter pw) { - pw.print("minValue="); pw.print(minValue); - pw.print(" maxValue="); pw.print(maxValue); - pw.print(" range="); pw.print(range); - pw.print(" flat="); pw.print(flat); - pw.print(" fuzz="); pw.print(fuzz); - } - }; - - InputDevice(int _id, int _classes, String _name, - AbsoluteInfo _absX, AbsoluteInfo _absY, - AbsoluteInfo _absPressure, AbsoluteInfo _absSize) { - id = _id; - classes = _classes; - name = _name; - absX = _absX; - absY = _absY; - absPressure = _absPressure; - absSize = _absSize; - } -}; diff --git a/services/java/com/android/server/InputManager.java b/services/java/com/android/server/InputManager.java index 2ba2914..cdae27c 100644 --- a/services/java/com/android/server/InputManager.java +++ b/services/java/com/android/server/InputManager.java @@ -56,7 +56,6 @@ public class InputManager { private final Callbacks mCallbacks; private final Context mContext; private final WindowManagerService mWindowManagerService; - private final WindowManagerPolicy mWindowManagerPolicy; private final PowerManager mPowerManager; private final PowerManagerService mPowerManagerService; @@ -103,12 +102,10 @@ public class InputManager { public InputManager(Context context, WindowManagerService windowManagerService, - WindowManagerPolicy windowManagerPolicy, PowerManager powerManager, PowerManagerService powerManagerService) { this.mContext = context; this.mWindowManagerService = windowManagerService; - this.mWindowManagerPolicy = windowManagerPolicy; this.mPowerManager = powerManager; this.mPowerManagerService = powerManagerService; @@ -325,23 +322,8 @@ public class InputManager { private static final String EXCLUDED_DEVICES_PATH = "etc/excluded-input-devices.xml"; @SuppressWarnings("unused") - public boolean isScreenOn() { - return mPowerManagerService.isScreenOn(); - } - - @SuppressWarnings("unused") - public boolean isScreenBright() { - return mPowerManagerService.isScreenBright(); - } - - @SuppressWarnings("unused") - public void virtualKeyFeedback(long whenNanos, int deviceId, int action, int flags, - int keyCode, int scanCode, int metaState, long downTimeNanos) { - KeyEvent keyEvent = new KeyEvent(downTimeNanos / 1000000, - whenNanos / 1000000, action, keyCode, 0, metaState, scanCode, deviceId, - flags); - - mWindowManagerService.virtualKeyFeedback(keyEvent); + public void virtualKeyDownFeedback() { + mWindowManagerService.mInputMonitor.virtualKeyDownFeedback(); } @SuppressWarnings("unused") @@ -356,7 +338,7 @@ public class InputManager { @SuppressWarnings("unused") public void notifyLidSwitchChanged(long whenNanos, boolean lidOpen) { - mWindowManagerPolicy.notifyLidSwitchChanged(whenNanos, lidOpen); + mWindowManagerService.mInputMonitor.notifyLidSwitchChanged(whenNanos, lidOpen); } @SuppressWarnings("unused") @@ -380,17 +362,17 @@ public class InputManager { } @SuppressWarnings("unused") - public int interceptKeyBeforeQueueing(int deviceId, int type, int scanCode, - int keyCode, int policyFlags, int value, long whenNanos, boolean isScreenOn) { - return mWindowManagerService.mInputMonitor.interceptKeyBeforeQueueing(deviceId, type, - scanCode, keyCode, policyFlags, value, whenNanos, isScreenOn); + public int interceptKeyBeforeQueueing(long whenNanos, int keyCode, boolean down, + int policyFlags, boolean isScreenOn) { + return mWindowManagerService.mInputMonitor.interceptKeyBeforeQueueing( + whenNanos, keyCode, down, policyFlags, isScreenOn); } @SuppressWarnings("unused") - public boolean interceptKeyBeforeDispatching(InputChannel focus, int keyCode, - int metaState, boolean down, int repeatCount, int policyFlags) { + public boolean interceptKeyBeforeDispatching(InputChannel focus, int action, + int flags, int keyCode, int metaState, int repeatCount, int policyFlags) { return mWindowManagerService.mInputMonitor.interceptKeyBeforeDispatching(focus, - keyCode, metaState, down, repeatCount, policyFlags); + action, flags, keyCode, metaState, repeatCount, policyFlags); } @SuppressWarnings("unused") @@ -401,18 +383,6 @@ public class InputManager { } @SuppressWarnings("unused") - public void goToSleep(long whenNanos) { - long when = whenNanos / 1000000; - mPowerManager.goToSleep(when); - } - - @SuppressWarnings("unused") - public void pokeUserActivity(long eventTimeNanos, int eventType) { - long eventTime = eventTimeNanos / 1000000; - mPowerManagerService.userActivity(eventTime, false, eventType, false); - } - - @SuppressWarnings("unused") public void notifyAppSwitchComing() { mWindowManagerService.mInputMonitor.notifyAppSwitchComing(); } diff --git a/services/java/com/android/server/KeyInputQueue.java b/services/java/com/android/server/KeyInputQueue.java deleted file mode 100644 index f62c7ee..0000000 --- a/services/java/com/android/server/KeyInputQueue.java +++ /dev/null @@ -1,1388 +0,0 @@ -/* - * Copyright (C) 2007 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. - */ - -package com.android.server; - -import android.content.Context; -import android.content.res.Configuration; -import android.content.res.Resources; -import android.os.Environment; -import android.os.LatencyTimer; -import android.os.PowerManager; -import android.os.SystemClock; -import android.os.SystemProperties; -import android.util.Slog; -import android.util.SparseArray; -import android.util.Xml; -import android.view.Display; -import android.view.KeyEvent; -import android.view.MotionEvent; -import android.view.RawInputEvent; -import android.view.Surface; -import android.view.WindowManagerPolicy; - -import com.android.internal.util.XmlUtils; - -import org.xmlpull.v1.XmlPullParser; - -import java.io.BufferedReader; -import java.io.File; -import java.io.FileInputStream; -import java.io.FileNotFoundException; -import java.io.FileReader; -import java.io.IOException; -import java.io.InputStreamReader; -import java.io.PrintWriter; -import java.util.ArrayList; - -public abstract class KeyInputQueue { - static final String TAG = "KeyInputQueue"; - - static final boolean DEBUG = false; - static final boolean DEBUG_VIRTUAL_KEYS = false; - static final boolean DEBUG_POINTERS = false; - - /** - * Turn on some hacks we have to improve the touch interaction with a - * certain device whose screen currently is not all that good. - */ - static boolean BAD_TOUCH_HACK = false; - - /** - * Turn on some hacks to improve touch interaction with another device - * where touch coordinate data can get corrupted. - */ - static boolean JUMPY_TOUCH_HACK = false; - - private static final String EXCLUDED_DEVICES_PATH = "etc/excluded-input-devices.xml"; - - final SparseArray<InputDevice> mDevices = new SparseArray<InputDevice>(); - final SparseArray<InputDevice> mIgnoredDevices = new SparseArray<InputDevice>(); - final ArrayList<VirtualKey> mVirtualKeys = new ArrayList<VirtualKey>(); - final HapticFeedbackCallback mHapticFeedbackCallback; - - int mGlobalMetaState = 0; - boolean mHaveGlobalMetaState = false; - - final QueuedEvent mFirst; - final QueuedEvent mLast; - QueuedEvent mCache; - 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[] { - KeyEvent.KEYCODE_DPAD_DOWN, KeyEvent.KEYCODE_DPAD_RIGHT, - KeyEvent.KEYCODE_DPAD_RIGHT, KeyEvent.KEYCODE_DPAD_UP, - KeyEvent.KEYCODE_DPAD_UP, KeyEvent.KEYCODE_DPAD_LEFT, - KeyEvent.KEYCODE_DPAD_LEFT, KeyEvent.KEYCODE_DPAD_DOWN, - }; - - static final int[] KEY_180_MAP = new int[] { - KeyEvent.KEYCODE_DPAD_DOWN, KeyEvent.KEYCODE_DPAD_UP, - KeyEvent.KEYCODE_DPAD_RIGHT, KeyEvent.KEYCODE_DPAD_LEFT, - KeyEvent.KEYCODE_DPAD_UP, KeyEvent.KEYCODE_DPAD_DOWN, - KeyEvent.KEYCODE_DPAD_LEFT, KeyEvent.KEYCODE_DPAD_RIGHT, - }; - - static final int[] KEY_270_MAP = new int[] { - KeyEvent.KEYCODE_DPAD_DOWN, KeyEvent.KEYCODE_DPAD_LEFT, - KeyEvent.KEYCODE_DPAD_LEFT, KeyEvent.KEYCODE_DPAD_UP, - KeyEvent.KEYCODE_DPAD_UP, KeyEvent.KEYCODE_DPAD_RIGHT, - KeyEvent.KEYCODE_DPAD_RIGHT, KeyEvent.KEYCODE_DPAD_DOWN, - }; - - public static final int FILTER_REMOVE = 0; - public static final int FILTER_KEEP = 1; - public static final int FILTER_ABORT = -1; - - private static final boolean MEASURE_LATENCY = false; - private LatencyTimer lt; - - public interface FilterCallback { - int filterEvent(QueuedEvent ev); - } - - public interface HapticFeedbackCallback { - void virtualKeyFeedback(KeyEvent event); - } - - static class QueuedEvent { - InputDevice inputDevice; - long whenNano; - int flags; // From the raw event - int classType; // One of the class constants in InputEvent - Object event; - boolean inQueue; - - void copyFrom(QueuedEvent that) { - this.inputDevice = that.inputDevice; - this.whenNano = that.whenNano; - this.flags = that.flags; - this.classType = that.classType; - this.event = that.event; - } - - @Override - public String toString() { - return "QueuedEvent{" - + Integer.toHexString(System.identityHashCode(this)) - + " " + event + "}"; - } - - // not copied - QueuedEvent prev; - 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) Slog.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); - } - } - - private void readVirtualKeys(String deviceName) { - try { - FileInputStream fis = new FileInputStream( - "/sys/board_properties/virtualkeys." + deviceName); - InputStreamReader isr = new InputStreamReader(fis); - BufferedReader br = new BufferedReader(isr, 2048); - String str = br.readLine(); - if (str != null) { - String[] it = str.split(":"); - if (DEBUG_VIRTUAL_KEYS) Slog.v(TAG, "***** VIRTUAL KEYS: " + it); - final int N = it.length-6; - for (int i=0; i<=N; i+=6) { - if (!"0x01".equals(it[i])) { - Slog.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) Slog.v(TAG, "Virtual key " - + sb.scancode + ": center=" + sb.centerx + "," - + sb.centery + " size=" + sb.width + "x" - + sb.height); - mVirtualKeys.add(sb); - } catch (NumberFormatException e) { - Slog.w(TAG, "Bad number at region " + i + " in: " - + str, e); - } - } - } - br.close(); - } catch (FileNotFoundException e) { - Slog.i(TAG, "No virtual keys found"); - } catch (IOException e) { - Slog.w(TAG, "Error reading virtual keys", e); - } - } - - private void readExcludedDevices() { - // Read partner-provided list of excluded input devices - XmlPullParser parser = null; - // Environment.getRootDirectory() is a fancy way of saying ANDROID_ROOT or "/system". - File confFile = new File(Environment.getRootDirectory(), EXCLUDED_DEVICES_PATH); - FileReader confreader = null; - try { - confreader = new FileReader(confFile); - parser = Xml.newPullParser(); - parser.setInput(confreader); - XmlUtils.beginDocument(parser, "devices"); - - while (true) { - XmlUtils.nextElement(parser); - if (!"device".equals(parser.getName())) { - break; - } - String name = parser.getAttributeValue(null, "name"); - if (name != null) { - if (DEBUG) Slog.v(TAG, "addExcludedDevice " + name); - addExcludedDevice(name); - } - } - } catch (FileNotFoundException e) { - // It's ok if the file does not exist. - } catch (Exception e) { - Slog.e(TAG, "Exception while parsing '" + confFile.getAbsolutePath() + "'", e); - } finally { - try { if (confreader != null) confreader.close(); } catch (IOException e) { } - } - } - - KeyInputQueue(Context context, HapticFeedbackCallback hapticFeedbackCallback) { - if (MEASURE_LATENCY) { - lt = new LatencyTimer(100, 1000); - } - - Resources r = context.getResources(); - BAD_TOUCH_HACK = r.getBoolean(com.android.internal.R.bool.config_filterTouchEvents); - - JUMPY_TOUCH_HACK = r.getBoolean(com.android.internal.R.bool.config_filterJumpyTouchEvents); - - mHapticFeedbackCallback = hapticFeedbackCallback; - - if (! WindowManagerService.ENABLE_NATIVE_INPUT_DISPATCH) { - readExcludedDevices(); - } - - 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; - - if (! WindowManagerService.ENABLE_NATIVE_INPUT_DISPATCH) { - mThread.start(); - } - } - - 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) { - 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; - //Slog.i("foo", "***** HAVE TOUCHSCREEN!"); - } - if ((d.classes&RawInputEvent.CLASS_ALPHAKEY) != 0) { - config.keyboard - = Configuration.KEYBOARD_QWERTY; - //Slog.i("foo", "***** HAVE QWERTY!"); - } - if ((d.classes&RawInputEvent.CLASS_TRACKBALL) != 0) { - config.navigation - = Configuration.NAVIGATION_TRACKBALL; - //Slog.i("foo", "***** HAVE TRACKBALL!"); - } else if ((d.classes&RawInputEvent.CLASS_DPAD) != 0) { - config.navigation - = Configuration.NAVIGATION_DPAD; - //Slog.i("foo", "***** HAVE DPAD!"); - } - } - } - } - } - - public int getScancodeState(int code) { - synchronized (mFirst) { - VirtualKey vk = mPressedVirtualKey; - if (vk != null) { - if (vk.scancode == code) { - return 2; - } - } - return nativeGetScancodeState(code); - } - } - - public int getScancodeState(int deviceId, int code) { - synchronized (mFirst) { - VirtualKey vk = mPressedVirtualKey; - if (vk != null) { - if (vk.scancode == code) { - return 2; - } - } - return nativeGetScancodeState(deviceId, code); - } - } - - public int getTrackballScancodeState(int code) { - synchronized (mFirst) { - final int N = mDevices.size(); - for (int i=0; i<N; i++) { - InputDevice dev = mDevices.valueAt(i); - if ((dev.classes&RawInputEvent.CLASS_TRACKBALL) != 0) { - int res = nativeGetScancodeState(dev.id, code); - if (res > 0) { - return res; - } - } - } - } - - return 0; - } - - public int getDPadScancodeState(int code) { - synchronized (mFirst) { - final int N = mDevices.size(); - for (int i=0; i<N; i++) { - InputDevice dev = mDevices.valueAt(i); - if ((dev.classes&RawInputEvent.CLASS_DPAD) != 0) { - int res = nativeGetScancodeState(dev.id, code); - if (res > 0) { - return res; - } - } - } - } - - return 0; - } - - public int getKeycodeState(int code) { - synchronized (mFirst) { - VirtualKey vk = mPressedVirtualKey; - if (vk != null) { - if (vk.lastKeycode == code) { - return 2; - } - } - return nativeGetKeycodeState(code); - } - } - - public int getKeycodeState(int deviceId, int code) { - synchronized (mFirst) { - VirtualKey vk = mPressedVirtualKey; - if (vk != null) { - if (vk.lastKeycode == code) { - return 2; - } - } - return nativeGetKeycodeState(deviceId, code); - } - } - - public int getTrackballKeycodeState(int code) { - synchronized (mFirst) { - final int N = mDevices.size(); - for (int i=0; i<N; i++) { - InputDevice dev = mDevices.valueAt(i); - if ((dev.classes&RawInputEvent.CLASS_TRACKBALL) != 0) { - int res = nativeGetKeycodeState(dev.id, code); - if (res > 0) { - return res; - } - } - } - } - - return 0; - } - - public int getDPadKeycodeState(int code) { - synchronized (mFirst) { - final int N = mDevices.size(); - for (int i=0; i<N; i++) { - InputDevice dev = mDevices.valueAt(i); - if ((dev.classes&RawInputEvent.CLASS_DPAD) != 0) { - int res = nativeGetKeycodeState(dev.id, code); - if (res > 0) { - return res; - } - } - } - } - - return 0; - } - - public static native String getDeviceName(int deviceId); - public static native int getDeviceClasses(int deviceId); - public static native void addExcludedDevice(String deviceName); - public static native boolean getAbsoluteInfo(int deviceId, int axis, - InputDevice.AbsoluteInfo outInfo); - public static native int getSwitchState(int sw); - public static native int getSwitchState(int deviceId, int sw); - public static native int nativeGetScancodeState(int code); - public static native int nativeGetScancodeState(int deviceId, int code); - public static native int nativeGetKeycodeState(int code); - public static native int nativeGetKeycodeState(int deviceId, int code); - 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, - 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); - } - - Thread mThread = new Thread("InputDeviceReader") { - public void run() { - if (DEBUG) Slog.v(TAG, "InputDeviceReader.run()"); - android.os.Process.setThreadPriority( - android.os.Process.THREAD_PRIORITY_URGENT_DISPLAY); - - RawInputEvent ev = new RawInputEvent(); - while (true) { - try { - InputDevice di; - - // block, doesn't release the monitor - readEvent(ev); - - boolean send = false; - boolean configChanged = false; - - if (false) { - Slog.i(TAG, "Input event: dev=0x" - + Integer.toHexString(ev.deviceId) - + " type=0x" + Integer.toHexString(ev.type) - + " scancode=" + ev.scancode - + " keycode=" + ev.keycode - + " value=" + ev.value); - } - - if (ev.type == RawInputEvent.EV_DEVICE_ADDED) { - synchronized (mFirst) { - di = newInputDevice(ev.deviceId); - if (di.classes != 0) { - // If this device is some kind of input class, - // we care about it. - mDevices.put(ev.deviceId, di); - if ((di.classes & RawInputEvent.CLASS_TOUCHSCREEN) != 0) { - readVirtualKeys(di.name); - } - // The configuration may have changed because - // of this device. - configChanged = true; - } else { - // We won't do anything with this device. - mIgnoredDevices.put(ev.deviceId, di); - Slog.i(TAG, "Ignoring non-input device: id=0x" - + Integer.toHexString(di.id) - + ", name=" + di.name); - } - } - } else if (ev.type == RawInputEvent.EV_DEVICE_REMOVED) { - synchronized (mFirst) { - if (false) { - Slog.i(TAG, "Device removed: id=0x" - + Integer.toHexString(ev.deviceId)); - } - di = mDevices.get(ev.deviceId); - if (di != null) { - mDevices.delete(ev.deviceId); - // The configuration may have changed because - // of this device. - configChanged = true; - } else if ((di=mIgnoredDevices.get(ev.deviceId)) != null) { - mIgnoredDevices.remove(ev.deviceId); - } else { - Slog.w(TAG, "Removing bad device id: " - + Integer.toHexString(ev.deviceId)); - continue; - } - } - } else { - di = getInputDevice(ev.deviceId); - if (di == null) { - // This may be some junk from an ignored device. - continue; - } - - // first crack at it - send = preprocessEvent(di, ev); - - if (ev.type == RawInputEvent.EV_KEY) { - di.mMetaKeysState = makeMetaState(ev.keycode, - ev.value != 0, di.mMetaKeysState); - mHaveGlobalMetaState = false; - } - } - - if (configChanged) { - synchronized (mFirst) { - addLocked(di, System.nanoTime(), 0, - RawInputEvent.CLASS_CONFIGURATION_CHANGED, - null); - } - } - - if (!send) { - continue; - } - - synchronized (mFirst) { - // NOTE: The event timebase absolutely must be the same - // timebase as SystemClock.uptimeMillis(). - //curTime = gotOne ? ev.when : SystemClock.uptimeMillis(); - final long curTime = SystemClock.uptimeMillis(); - final long curTimeNano = System.nanoTime(); - //Slog.i(TAG, "curTime=" + curTime + ", systemClock=" + SystemClock.uptimeMillis()); - - final int classes = di.classes; - final int type = ev.type; - final int scancode = ev.scancode; - send = false; - - // Is it a key event? - if (type == RawInputEvent.EV_KEY && - (classes&RawInputEvent.CLASS_KEYBOARD) != 0 && - (scancode < RawInputEvent.BTN_FIRST || - scancode > RawInputEvent.BTN_LAST)) { - boolean down; - if (ev.value != 0) { - down = true; - di.mKeyDownTime = curTime; - } else { - down = false; - } - int keycode = rotateKeyCodeLocked(ev.keycode); - addLocked(di, curTimeNano, ev.flags, - RawInputEvent.CLASS_KEYBOARD, - newKeyEvent(di, di.mKeyDownTime, curTime, down, - keycode, 0, scancode, - ((ev.flags & WindowManagerPolicy.FLAG_WOKE_HERE) != 0) - ? KeyEvent.FLAG_WOKE_HERE : 0)); - - } else if (ev.type == RawInputEvent.EV_KEY) { - // Single touch protocol: touch going down or up. - if (ev.scancode == RawInputEvent.BTN_TOUCH && - (classes&(RawInputEvent.CLASS_TOUCHSCREEN - |RawInputEvent.CLASS_TOUCHSCREEN_MT)) - == RawInputEvent.CLASS_TOUCHSCREEN) { - di.mAbs.changed = true; - di.mAbs.mDown[0] = ev.value != 0; - - // Trackball (mouse) protocol: press down or up. - } else if (ev.scancode == RawInputEvent.BTN_MOUSE && - (classes&RawInputEvent.CLASS_TRACKBALL) != 0) { - di.mRel.changed = true; - di.mRel.mNextNumPointers = ev.value != 0 ? 1 : 0; - send = true; - } - - // Process position events from multitouch protocol. - } else if (ev.type == RawInputEvent.EV_ABS && - (classes&RawInputEvent.CLASS_TOUCHSCREEN_MT) != 0) { - if (ev.scancode == RawInputEvent.ABS_MT_TOUCH_MAJOR) { - di.mAbs.changed = true; - di.mAbs.mNextData[di.mAbs.mAddingPointerOffset - + MotionEvent.SAMPLE_PRESSURE] = ev.value; - } else if (ev.scancode == RawInputEvent.ABS_MT_POSITION_X) { - di.mAbs.changed = true; - di.mAbs.mNextData[di.mAbs.mAddingPointerOffset - + MotionEvent.SAMPLE_X] = ev.value; - if (DEBUG_POINTERS) Slog.v(TAG, "MT @" - + di.mAbs.mAddingPointerOffset - + " X:" + ev.value); - } else if (ev.scancode == RawInputEvent.ABS_MT_POSITION_Y) { - di.mAbs.changed = true; - di.mAbs.mNextData[di.mAbs.mAddingPointerOffset - + MotionEvent.SAMPLE_Y] = ev.value; - if (DEBUG_POINTERS) Slog.v(TAG, "MT @" - + di.mAbs.mAddingPointerOffset - + " Y:" + ev.value); - } else if (ev.scancode == RawInputEvent.ABS_MT_WIDTH_MAJOR) { - di.mAbs.changed = true; - di.mAbs.mNextData[di.mAbs.mAddingPointerOffset - + MotionEvent.SAMPLE_SIZE] = ev.value; - } - - // Process position events from single touch protocol. - } else if (ev.type == RawInputEvent.EV_ABS && - (classes&RawInputEvent.CLASS_TOUCHSCREEN) != 0) { - if (ev.scancode == RawInputEvent.ABS_X) { - di.mAbs.changed = true; - di.curTouchVals[MotionEvent.SAMPLE_X] = ev.value; - } else if (ev.scancode == RawInputEvent.ABS_Y) { - di.mAbs.changed = true; - di.curTouchVals[MotionEvent.SAMPLE_Y] = ev.value; - } else if (ev.scancode == RawInputEvent.ABS_PRESSURE) { - di.mAbs.changed = true; - di.curTouchVals[MotionEvent.SAMPLE_PRESSURE] = ev.value; - di.curTouchVals[MotionEvent.NUM_SAMPLE_DATA - + MotionEvent.SAMPLE_PRESSURE] = ev.value; - } else if (ev.scancode == RawInputEvent.ABS_TOOL_WIDTH) { - di.mAbs.changed = true; - di.curTouchVals[MotionEvent.SAMPLE_SIZE] = ev.value; - di.curTouchVals[MotionEvent.NUM_SAMPLE_DATA - + MotionEvent.SAMPLE_SIZE] = ev.value; - } - - // Process movement events from trackball (mouse) protocol. - } else if (ev.type == RawInputEvent.EV_REL && - (classes&RawInputEvent.CLASS_TRACKBALL) != 0) { - // Add this relative movement into our totals. - if (ev.scancode == RawInputEvent.REL_X) { - di.mRel.changed = true; - di.mRel.mNextData[MotionEvent.SAMPLE_X] += ev.value; - } else if (ev.scancode == RawInputEvent.REL_Y) { - di.mRel.changed = true; - di.mRel.mNextData[MotionEvent.SAMPLE_Y] += ev.value; - } - } - - // Handle multitouch protocol sync: tells us that the - // driver has returned all data for -one- of the pointers - // that is currently down. - if (ev.type == RawInputEvent.EV_SYN - && ev.scancode == RawInputEvent.SYN_MT_REPORT - && di.mAbs != null) { - di.mAbs.changed = true; - if (di.mAbs.mNextData[MotionEvent.SAMPLE_PRESSURE] > 0) { - // If the value is <= 0, the pointer is not - // down, so keep it in the count. - - if (di.mAbs.mNextData[di.mAbs.mAddingPointerOffset - + MotionEvent.SAMPLE_PRESSURE] != 0) { - final int num = di.mAbs.mNextNumPointers+1; - di.mAbs.mNextNumPointers = num; - if (DEBUG_POINTERS) Slog.v(TAG, - "MT_REPORT: now have " + num + " pointers"); - final int newOffset = (num <= InputDevice.MAX_POINTERS) - ? (num * MotionEvent.NUM_SAMPLE_DATA) - : (InputDevice.MAX_POINTERS * - MotionEvent.NUM_SAMPLE_DATA); - di.mAbs.mAddingPointerOffset = newOffset; - di.mAbs.mNextData[newOffset - + MotionEvent.SAMPLE_PRESSURE] = 0; - } else { - if (DEBUG_POINTERS) Slog.v(TAG, "MT_REPORT: no pointer"); - } - } - - // Handle general event sync: all data for the current - // event update has been delivered. - } else if (send || (ev.type == RawInputEvent.EV_SYN - && ev.scancode == RawInputEvent.SYN_REPORT)) { - if (mDisplay != null) { - if (!mHaveGlobalMetaState) { - computeGlobalMetaStateLocked(); - } - - MotionEvent me; - - InputDevice.MotionState ms = di.mAbs; - if (ms.changed) { - ms.everChanged = true; - ms.changed = false; - - if ((classes&(RawInputEvent.CLASS_TOUCHSCREEN - |RawInputEvent.CLASS_TOUCHSCREEN_MT)) - == RawInputEvent.CLASS_TOUCHSCREEN) { - ms.mNextNumPointers = 0; - if (ms.mDown[0]) { - System.arraycopy(di.curTouchVals, 0, - ms.mNextData, 0, - MotionEvent.NUM_SAMPLE_DATA); - ms.mNextNumPointers++; - } - } - - if (BAD_TOUCH_HACK) { - ms.dropBadPoint(di); - } - if (JUMPY_TOUCH_HACK) { - ms.dropJumpyPoint(di); - } - - boolean doMotion = !monitorVirtualKey(di, - ev, curTime, curTimeNano); - - if (doMotion && ms.mNextNumPointers > 0 - && (ms.mLastNumPointers == 0 - || ms.mSkipLastPointers)) { - doMotion = !generateVirtualKeyDown(di, - ev, curTime, curTimeNano); - } - - if (doMotion) { - // XXX Need to be able to generate - // multiple events here, for example - // if two fingers change up/down state - // at the same time. - do { - me = ms.generateAbsMotion(di, curTime, - curTimeNano, mDisplay, - mOrientation, mGlobalMetaState); - if (DEBUG_POINTERS) Slog.v(TAG, "Absolute: x=" - + di.mAbs.mNextData[MotionEvent.SAMPLE_X] - + " y=" - + di.mAbs.mNextData[MotionEvent.SAMPLE_Y] - + " ev=" + me); - if (me != null) { - if (WindowManagerPolicy.WATCH_POINTER) { - Slog.i(TAG, "Enqueueing: " + me); - } - addLocked(di, curTimeNano, ev.flags, - RawInputEvent.CLASS_TOUCHSCREEN, me); - } - } while (ms.hasMore()); - } else { - // We are consuming movement in the - // virtual key area... but still - // propagate this to the previous - // data for comparisons. - int num = ms.mNextNumPointers; - if (num > InputDevice.MAX_POINTERS) { - num = InputDevice.MAX_POINTERS; - } - System.arraycopy(ms.mNextData, 0, - ms.mLastData, 0, - num * MotionEvent.NUM_SAMPLE_DATA); - ms.mLastNumPointers = num; - ms.mSkipLastPointers = true; - } - - ms.finish(); - } - - ms = di.mRel; - if (ms.changed) { - ms.everChanged = true; - ms.changed = false; - - me = ms.generateRelMotion(di, curTime, - curTimeNano, - mOrientation, mGlobalMetaState); - if (false) Slog.v(TAG, "Relative: x=" - + di.mRel.mNextData[MotionEvent.SAMPLE_X] - + " y=" - + di.mRel.mNextData[MotionEvent.SAMPLE_Y] - + " ev=" + me); - if (me != null) { - addLocked(di, curTimeNano, ev.flags, - RawInputEvent.CLASS_TRACKBALL, me); - } - } - } - } - } - - } catch (RuntimeException exc) { - Slog.e(TAG, "InputReaderThread uncaught exception", exc); - } - } - } - }; - - private boolean isInsideDisplay(InputDevice dev) { - 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 true; - } - - if (absm.mNextData[MotionEvent.SAMPLE_X] >= absx.minValue - && absm.mNextData[MotionEvent.SAMPLE_X] <= absx.maxValue - && absm.mNextData[MotionEvent.SAMPLE_Y] >= absy.minValue - && absm.mNextData[MotionEvent.SAMPLE_Y] <= absy.maxValue) { - if (DEBUG_VIRTUAL_KEYS) Slog.v(TAG, "Input (" - + absm.mNextData[MotionEvent.SAMPLE_X] - + "," + absm.mNextData[MotionEvent.SAMPLE_Y] - + ") inside of display"); - return true; - } - - return false; - } - - private VirtualKey findVirtualKey(InputDevice dev) { - final int N = mVirtualKeys.size(); - if (N <= 0) { - return null; - } - - final InputDevice.MotionState absm = dev.mAbs; - for (int i=0; i<N; i++) { - VirtualKey sb = mVirtualKeys.get(i); - sb.computeHitRect(dev, mDisplayWidth, mDisplayHeight); - if (DEBUG_VIRTUAL_KEYS) Slog.v(TAG, "Hit test (" - + absm.mNextData[MotionEvent.SAMPLE_X] + "," - + absm.mNextData[MotionEvent.SAMPLE_Y] + ") in code " - + sb.scancode + " - (" + sb.hitLeft - + "," + sb.hitTop + ")-(" + sb.hitRight + "," - + sb.hitBottom + ")"); - if (sb.checkHit(absm.mNextData[MotionEvent.SAMPLE_X], - absm.mNextData[MotionEvent.SAMPLE_Y])) { - if (DEBUG_VIRTUAL_KEYS) Slog.v(TAG, "Hit!"); - return sb; - } - } - - return null; - } - - private boolean generateVirtualKeyDown(InputDevice di, RawInputEvent ev, - long curTime, long curTimeNano) { - if (isInsideDisplay(di)) { - // Didn't consume event. - return false; - } - - - VirtualKey vk = findVirtualKey(di); - if (vk != null) { - final InputDevice.MotionState ms = di.mAbs; - mPressedVirtualKey = vk; - vk.lastKeycode = scancodeToKeycode(di.id, vk.scancode); - ms.mLastNumPointers = ms.mNextNumPointers; - di.mKeyDownTime = curTime; - if (DEBUG_VIRTUAL_KEYS) Slog.v(TAG, - "Generate key down for: " + vk.scancode - + " (keycode=" + vk.lastKeycode + ")"); - KeyEvent event = newKeyEvent(di, di.mKeyDownTime, curTime, true, - vk.lastKeycode, 0, vk.scancode, - KeyEvent.FLAG_VIRTUAL_HARD_KEY); - mHapticFeedbackCallback.virtualKeyFeedback(event); - addLocked(di, curTimeNano, ev.flags, RawInputEvent.CLASS_KEYBOARD, - event); - } - - // We always consume the event, even if we didn't - // generate a key event. 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. - // Note that for all of this we are only looking at the - // first pointer, since what we are handling here is the - // first pointer going down, and this is the coordinate - // that will be used to dispatch the event. - if (false) { - final InputDevice.AbsoluteInfo absx = di.absX; - final InputDevice.AbsoluteInfo absy = di.absY; - final InputDevice.MotionState absm = di.mAbs; - Slog.v(TAG, "Rejecting (" - + absm.mNextData[MotionEvent.SAMPLE_X] + "," - + absm.mNextData[MotionEvent.SAMPLE_Y] + "): outside of (" - + absx.minValue + "," + absy.minValue - + ")-(" + absx.maxValue + "," - + absx.maxValue + ")"); - } - return true; - } - - private boolean monitorVirtualKey(InputDevice di, RawInputEvent ev, - long curTime, long curTimeNano) { - VirtualKey vk = mPressedVirtualKey; - if (vk == null) { - return false; - } - - final InputDevice.MotionState ms = di.mAbs; - if (ms.mNextNumPointers <= 0) { - mPressedVirtualKey = null; - ms.mLastNumPointers = 0; - if (DEBUG_VIRTUAL_KEYS) Slog.v(TAG, "Generate key up for: " + vk.scancode); - KeyEvent event = newKeyEvent(di, di.mKeyDownTime, curTime, false, - vk.lastKeycode, 0, vk.scancode, - KeyEvent.FLAG_VIRTUAL_HARD_KEY); - mHapticFeedbackCallback.virtualKeyFeedback(event); - addLocked(di, curTimeNano, ev.flags, RawInputEvent.CLASS_KEYBOARD, - event); - return true; - - } else if (isInsideDisplay(di)) { - // Whoops the pointer has moved into - // the display area! Cancel the - // virtual key and start a pointer - // motion. - mPressedVirtualKey = null; - if (DEBUG_VIRTUAL_KEYS) Slog.v(TAG, "Cancel key up for: " + vk.scancode); - KeyEvent event = newKeyEvent(di, di.mKeyDownTime, curTime, false, - vk.lastKeycode, 0, vk.scancode, - KeyEvent.FLAG_CANCELED | KeyEvent.FLAG_VIRTUAL_HARD_KEY); - mHapticFeedbackCallback.virtualKeyFeedback(event); - addLocked(di, curTimeNano, ev.flags, RawInputEvent.CLASS_KEYBOARD, - event); - ms.mLastNumPointers = 0; - return false; - } - - return true; - } - - /** - * Returns a new meta state for the given keys and old state. - */ - private static final int makeMetaState(int keycode, boolean down, int old) { - 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 void computeGlobalMetaStateLocked() { - int i = mDevices.size(); - mGlobalMetaState = 0; - while ((--i) >= 0) { - mGlobalMetaState |= mDevices.valueAt(i).mMetaKeysState; - } - mHaveGlobalMetaState = true; - } - - /* - * Return true if you want the event to get passed on to the - * rest of the system, and false if you've handled it and want - * it dropped. - */ - abstract boolean preprocessEvent(InputDevice device, RawInputEvent event); - - InputDevice getInputDevice(int deviceId) { - synchronized (mFirst) { - return getInputDeviceLocked(deviceId); - } - } - - private InputDevice getInputDeviceLocked(int deviceId) { - return mDevices.get(deviceId); - } - - public void setOrientation(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; - } - } - } - - public int rotateKeyCode(int keyCode) { - synchronized(mFirst) { - return rotateKeyCodeLocked(keyCode); - } - } - - private int rotateKeyCodeLocked(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; - } - - boolean hasEvents() { - synchronized (mFirst) { - return mFirst.next != mLast; - } - } - - /* - * returns true if we returned an event, and false if we timed out - */ - QueuedEvent getEvent(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; - } - } - - /** - * Return true if the queue has an up event pending that corresponds - * to the same key as the given key event. - */ - boolean hasKeyUpEvent(KeyEvent origEvent) { - synchronized (mFirst) { - final int keyCode = origEvent.getKeyCode(); - QueuedEvent cur = mLast.prev; - while (cur.prev != null) { - if (cur.classType == RawInputEvent.CLASS_KEYBOARD) { - KeyEvent ke = (KeyEvent)cur.event; - if (ke.getAction() == KeyEvent.ACTION_UP - && ke.getKeyCode() == keyCode) { - return true; - } - } - cur = cur.prev; - } - } - - return false; - } - - void recycleEvent(QueuedEvent ev) { - synchronized (mFirst) { - //Slog.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) Slog.i(TAG, "Detach rel " + ev.event); - ev.inputDevice.mRel.currentMove = null; - ev.inputDevice.mRel.mNextData[MotionEvent.SAMPLE_X] = 0; - ev.inputDevice.mRel.mNextData[MotionEvent.SAMPLE_Y] = 0; - } - recycleLocked(ev); - } - } - - void filterQueue(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; - } - } - } - - private QueuedEvent obtainLocked(InputDevice device, long whenNano, - int flags, int classType, Object event) { - QueuedEvent ev; - if (mCacheCount == 0) { - ev = new QueuedEvent(); - } else { - ev = mCache; - ev.inQueue = false; - mCache = ev.next; - mCacheCount--; - } - ev.inputDevice = device; - ev.whenNano = whenNano; - ev.flags = flags; - ev.classType = classType; - ev.event = event; - return ev; - } - - private void recycleLocked(QueuedEvent ev) { - if (ev.inQueue) { - throw new RuntimeException("Event already in queue!"); - } - if (mCacheCount < 10) { - mCacheCount++; - ev.next = mCache; - mCache = ev; - ev.inQueue = true; - } - } - - private void addLocked(InputDevice device, long whenNano, int flags, - int classType, Object event) { - boolean poke = mFirst.next == mLast; - - QueuedEvent ev = obtainLocked(device, whenNano, flags, classType, event); - QueuedEvent p = mLast.prev; - while (p != mFirst && ev.whenNano < p.whenNano) { - p = p.prev; - } - - ev.next = p.next; - ev.prev = p; - p.next = ev; - ev.next.prev = ev; - ev.inQueue = true; - - if (poke) { - long time; - if (MEASURE_LATENCY) { - time = System.nanoTime(); - } - mFirst.notify(); - mWakeLock.acquire(); - if (MEASURE_LATENCY) { - lt.sample("1 addLocked-queued event ", System.nanoTime() - time); - } - } - } - - private InputDevice newInputDevice(int deviceId) { - int classes = getDeviceClasses(deviceId); - String name = getDeviceName(deviceId); - InputDevice.AbsoluteInfo absX = null; - InputDevice.AbsoluteInfo absY = null; - InputDevice.AbsoluteInfo absPressure = null; - InputDevice.AbsoluteInfo absSize = null; - if (classes != 0) { - Slog.i(TAG, "Device added: id=0x" + Integer.toHexString(deviceId) - + ", name=" + name - + ", classes=" + Integer.toHexString(classes)); - if ((classes&RawInputEvent.CLASS_TOUCHSCREEN_MT) != 0) { - absX = loadAbsoluteInfo(deviceId, - RawInputEvent.ABS_MT_POSITION_X, "X"); - absY = loadAbsoluteInfo(deviceId, - RawInputEvent.ABS_MT_POSITION_Y, "Y"); - absPressure = loadAbsoluteInfo(deviceId, - RawInputEvent.ABS_MT_TOUCH_MAJOR, "Pressure"); - absSize = loadAbsoluteInfo(deviceId, - RawInputEvent.ABS_MT_WIDTH_MAJOR, "Size"); - } else 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"); - } - } - - return new InputDevice(deviceId, classes, name, absX, absY, absPressure, absSize); - } - - private InputDevice.AbsoluteInfo loadAbsoluteInfo(int id, int channel, - String name) { - InputDevice.AbsoluteInfo info = new InputDevice.AbsoluteInfo(); - if (getAbsoluteInfo(id, channel, info) - && info.minValue != info.maxValue) { - Slog.i(TAG, " " + name + ": min=" + info.minValue - + " max=" + info.maxValue - + " flat=" + info.flat - + " fuzz=" + info.fuzz); - info.range = info.maxValue-info.minValue; - return info; - } - Slog.i(TAG, " " + name + ": unknown values"); - return null; - } - private static native boolean readEvent(RawInputEvent outEvent); - - void dump(PrintWriter pw, String prefix) { - synchronized (mFirst) { - for (int i=0; i<mDevices.size(); i++) { - InputDevice dev = mDevices.valueAt(i); - pw.print(prefix); pw.print("Device #"); - pw.print(mDevices.keyAt(i)); pw.print(" "); - pw.print(dev.name); pw.print(" (classes=0x"); - pw.print(Integer.toHexString(dev.classes)); - pw.println("):"); - pw.print(prefix); pw.print(" mKeyDownTime="); - pw.print(dev.mKeyDownTime); pw.print(" mMetaKeysState="); - pw.println(dev.mMetaKeysState); - if (dev.absX != null) { - pw.print(prefix); pw.print(" absX: "); dev.absX.dump(pw); - pw.println(""); - } - if (dev.absY != null) { - pw.print(prefix); pw.print(" absY: "); dev.absY.dump(pw); - pw.println(""); - } - if (dev.absPressure != null) { - pw.print(prefix); pw.print(" absPressure: "); - dev.absPressure.dump(pw); pw.println(""); - } - if (dev.absSize != null) { - pw.print(prefix); pw.print(" absSize: "); - dev.absSize.dump(pw); pw.println(""); - } - if (dev.mAbs.everChanged) { - pw.print(prefix); pw.println(" mAbs:"); - dev.mAbs.dump(pw, prefix + " "); - } - if (dev.mRel.everChanged) { - pw.print(prefix); pw.println(" mRel:"); - dev.mRel.dump(pw, prefix + " "); - } - } - pw.println(" "); - for (int i=0; i<mIgnoredDevices.size(); i++) { - InputDevice dev = mIgnoredDevices.valueAt(i); - pw.print(prefix); pw.print("Ignored Device #"); - pw.print(mIgnoredDevices.keyAt(i)); pw.print(" "); - pw.print(dev.name); pw.print(" (classes=0x"); - pw.print(Integer.toHexString(dev.classes)); - pw.println(")"); - } - pw.println(" "); - for (int i=0; i<mVirtualKeys.size(); i++) { - VirtualKey vk = mVirtualKeys.get(i); - pw.print(prefix); pw.print("Virtual Key #"); - pw.print(i); pw.println(":"); - pw.print(prefix); pw.print(" scancode="); pw.println(vk.scancode); - pw.print(prefix); pw.print(" centerx="); pw.print(vk.centerx); - pw.print(" centery="); pw.print(vk.centery); - pw.print(" width="); pw.print(vk.width); - pw.print(" height="); pw.println(vk.height); - pw.print(prefix); pw.print(" hitLeft="); pw.print(vk.hitLeft); - pw.print(" hitTop="); pw.print(vk.hitTop); - pw.print(" hitRight="); pw.print(vk.hitRight); - pw.print(" hitBottom="); pw.println(vk.hitBottom); - if (vk.lastDevice != null) { - pw.print(prefix); pw.print(" lastDevice=#"); - pw.println(vk.lastDevice.id); - } - if (vk.lastKeycode != 0) { - pw.print(prefix); pw.print(" lastKeycode="); - pw.println(vk.lastKeycode); - } - } - pw.println(" "); - pw.print(prefix); pw.print(" Default keyboard: "); - pw.println(SystemProperties.get("hw.keyboards.0.devname")); - pw.print(prefix); pw.print(" mGlobalMetaState="); - pw.print(mGlobalMetaState); pw.print(" mHaveGlobalMetaState="); - pw.println(mHaveGlobalMetaState); - pw.print(prefix); pw.print(" mDisplayWidth="); - pw.print(mDisplayWidth); pw.print(" mDisplayHeight="); - pw.println(mDisplayHeight); - pw.print(prefix); pw.print(" mOrientation="); - pw.println(mOrientation); - if (mPressedVirtualKey != null) { - pw.print(prefix); pw.print(" mPressedVirtualKey.scancode="); - pw.println(mPressedVirtualKey.scancode); - } - } - } -} diff --git a/services/java/com/android/server/PowerManagerService.java b/services/java/com/android/server/PowerManagerService.java index 493a348..e9d5efc 100644 --- a/services/java/com/android/server/PowerManagerService.java +++ b/services/java/com/android/server/PowerManagerService.java @@ -247,6 +247,9 @@ class PowerManagerService extends IPowerManager.Stub private static final boolean mSpew = false; private static final boolean mDebugProximitySensor = (true || mSpew); private static final boolean mDebugLightSensor = (false || mSpew); + + private native void nativeInit(); + private native void nativeSetPowerState(boolean screenOn, boolean screenBright); /* static PrintStream mLog; @@ -481,6 +484,11 @@ class PowerManagerService extends IPowerManager.Stub } } } + + nativeInit(); + synchronized (mLocks) { + updateNativePowerStateLocked(); + } } void initInThread() { @@ -1557,8 +1565,16 @@ class PowerManagerService extends IPowerManager.Stub } } } + + updateNativePowerStateLocked(); } } + + private void updateNativePowerStateLocked() { + nativeSetPowerState( + (mPowerState & SCREEN_ON_BIT) != 0, + (mPowerState & SCREEN_BRIGHT) == SCREEN_BRIGHT); + } private int screenOffFinishedAnimatingLocked(int reason) { // I don't think we need to check the current state here because all of these diff --git a/services/java/com/android/server/WindowManagerService.java b/services/java/com/android/server/WindowManagerService.java index 483f9eb..38f1e1f 100644 --- a/services/java/com/android/server/WindowManagerService.java +++ b/services/java/com/android/server/WindowManagerService.java @@ -48,7 +48,6 @@ import com.android.internal.view.IInputContext; import com.android.internal.view.IInputMethodClient; import com.android.internal.view.IInputMethodManager; import com.android.internal.view.WindowManagerPolicyThread; -import com.android.server.KeyInputQueue.QueuedEvent; import com.android.server.am.BatteryStatsService; import android.Manifest; @@ -95,6 +94,7 @@ import android.util.Slog; import android.util.SparseIntArray; import android.view.Display; import android.view.Gravity; +import android.view.HapticFeedbackConstants; import android.view.IApplicationToken; import android.view.IOnKeyguardExitResult; import android.view.IRotationWatcher; @@ -105,7 +105,6 @@ import android.view.InputChannel; import android.view.InputQueue; import android.view.KeyEvent; import android.view.MotionEvent; -import android.view.RawInputEvent; import android.view.Surface; import android.view.SurfaceSession; import android.view.View; @@ -137,7 +136,7 @@ import java.util.List; /** {@hide} */ public class WindowManagerService extends IWindowManager.Stub - implements Watchdog.Monitor, KeyInputQueue.HapticFeedbackCallback { + implements Watchdog.Monitor { static final String TAG = "WindowManager"; static final boolean DEBUG = false; static final boolean DEBUG_FOCUS = false; @@ -159,17 +158,12 @@ public class WindowManagerService extends IWindowManager.Stub static final boolean SHOW_TRANSACTIONS = false; static final boolean HIDE_STACK_CRAWLS = true; static final boolean MEASURE_LATENCY = false; - static final boolean ENABLE_NATIVE_INPUT_DISPATCH = - WindowManagerPolicy.ENABLE_NATIVE_INPUT_DISPATCH; static private LatencyTimer lt; static final boolean PROFILE_ORIENTATION = false; static final boolean BLUR = true; static final boolean localLOGV = DEBUG; - /** How long to wait for subsequent key repeats, in milliseconds */ - static final int KEY_REPEAT_DELAY = 50; - /** How much to multiply the policy's type layer, to reserve room * for multiple windows of the same type and Z-ordering adjustment * with TYPE_LAYER_OFFSET. */ @@ -210,34 +204,11 @@ public class WindowManagerService extends IWindowManager.Stub // Default input dispatching timeout in nanoseconds. private static final long DEFAULT_INPUT_DISPATCHING_TIMEOUT_NANOS = 5000 * 1000000L; - static final int INJECT_FAILED = 0; - static final int INJECT_SUCCEEDED = 1; - static final int INJECT_NO_PERMISSION = -1; - static final int UPDATE_FOCUS_NORMAL = 0; static final int UPDATE_FOCUS_WILL_ASSIGN_LAYERS = 1; static final int UPDATE_FOCUS_PLACING_SURFACES = 2; static final int UPDATE_FOCUS_WILL_PLACE_SURFACES = 3; - /** The minimum time between dispatching touch events. */ - int mMinWaitTimeBetweenTouchEvents = 1000 / 35; - - // Last touch event time - long mLastTouchEventTime = 0; - - // Last touch event type - int mLastTouchEventType = OTHER_EVENT; - - // Time to wait before calling useractivity again. This saves CPU usage - // when we get a flood of touch events. - static final int MIN_TIME_BETWEEN_USERACTIVITIES = 1000; - - // Last time we call user activity - long mLastUserActivityCallTime = 0; - - // Last time we updated battery stats - long mLastBatteryStatsCallTime = 0; - private static final String SYSTEM_SECURE = "ro.secure"; private static final String SYSTEM_DEBUGGABLE = "ro.debuggable"; @@ -486,7 +457,6 @@ public class WindowManagerService extends IWindowManager.Stub float mLastWallpaperY = -1; float mLastWallpaperXStep = -1; float mLastWallpaperYStep = -1; - boolean mSendingPointersToWallpaper = false; // This is set when we are waiting for a wallpaper to tell us it is done // changing its scroll position. WindowState mWaitingOnWallpaper; @@ -504,10 +474,7 @@ public class WindowManagerService extends IWindowManager.Stub float mWindowAnimationScale = 1.0f; float mTransitionAnimationScale = 1.0f; - final KeyWaiter mKeyWaiter = new KeyWaiter(); - final KeyQ mQueue; final InputManager mInputManager; - final InputDispatcherThread mInputThread; // Who is holding the screen on. Session mHoldingScreenOn; @@ -523,8 +490,6 @@ public class WindowManagerService extends IWindowManager.Stub private ViewServer mViewServer; - final Rect mTempRect = new Rect(); - final Configuration mTempConfiguration = new Configuration(); int mScreenLayout = Configuration.SCREENLAYOUT_SIZE_UNDEFINED; @@ -652,28 +617,11 @@ public class WindowManagerService extends IWindowManager.Stub filter.addAction(DevicePolicyManager.ACTION_DEVICE_POLICY_MANAGER_STATE_CHANGED); mContext.registerReceiver(mBroadcastReceiver, filter); - int max_events_per_sec = 35; - try { - max_events_per_sec = Integer.parseInt(SystemProperties - .get("windowsmgr.max_events_per_sec")); - if (max_events_per_sec < 1) { - max_events_per_sec = 35; - } - } catch (NumberFormatException e) { - } - mMinWaitTimeBetweenTouchEvents = 1000 / max_events_per_sec; - mHoldingScreenWakeLock = pmc.newWakeLock(PowerManager.SCREEN_BRIGHT_WAKE_LOCK, "KEEP_SCREEN_ON_FLAG"); mHoldingScreenWakeLock.setReferenceCounted(false); - if (ENABLE_NATIVE_INPUT_DISPATCH) { - mInputManager = new InputManager(context, this, mPolicy, pmc, mPowerManager); - } else { - mInputManager = null; - } - mQueue = new KeyQ(); - mInputThread = new InputDispatcherThread(); + mInputManager = new InputManager(context, this, pmc, mPowerManager); PolicyThread thr = new PolicyThread(mPolicy, this, context, pm); thr.start(); @@ -687,11 +635,7 @@ public class WindowManagerService extends IWindowManager.Stub } } - if (ENABLE_NATIVE_INPUT_DISPATCH) { - mInputManager.start(); - } else { - mInputThread.start(); - } + mInputManager.start(); // Add ourself to the Watchdog monitors. Watchdog.getInstance().addMonitor(this); @@ -1817,70 +1761,6 @@ public class WindowManagerService extends IWindowManager.Stub } } } - - void sendPointerToWallpaperLocked(WindowState srcWin, - MotionEvent pointer, long eventTime) { - int curTokenIndex = mWallpaperTokens.size(); - while (curTokenIndex > 0) { - curTokenIndex--; - WindowToken token = mWallpaperTokens.get(curTokenIndex); - int curWallpaperIndex = token.windows.size(); - while (curWallpaperIndex > 0) { - curWallpaperIndex--; - WindowState wallpaper = token.windows.get(curWallpaperIndex); - if ((wallpaper.mAttrs.flags & - WindowManager.LayoutParams.FLAG_NOT_TOUCHABLE) != 0) { - continue; - } - try { - MotionEvent ev = MotionEvent.obtainNoHistory(pointer); - if (srcWin != null) { - ev.offsetLocation(srcWin.mFrame.left-wallpaper.mFrame.left, - srcWin.mFrame.top-wallpaper.mFrame.top); - } else { - ev.offsetLocation(-wallpaper.mFrame.left, -wallpaper.mFrame.top); - } - switch (pointer.getAction()) { - case MotionEvent.ACTION_DOWN: - mSendingPointersToWallpaper = true; - break; - case MotionEvent.ACTION_UP: - mSendingPointersToWallpaper = false; - break; - } - wallpaper.mClient.dispatchPointer(ev, eventTime, false); - } catch (RemoteException e) { - Slog.w(TAG, "Failure sending pointer to wallpaper", e); - } - } - } - } - - void dispatchPointerElsewhereLocked(WindowState srcWin, WindowState relWin, - MotionEvent pointer, long eventTime, boolean skipped) { - if (relWin != null) { - mPolicy.dispatchedPointerEventLw(pointer, relWin.mFrame.left, relWin.mFrame.top); - } else { - mPolicy.dispatchedPointerEventLw(pointer, 0, 0); - } - - // If we sent an initial down to the wallpaper, then continue - // sending events until the final up. - if (mSendingPointersToWallpaper) { - if (skipped) { - Slog.i(TAG, "Sending skipped pointer to wallpaper!"); - } - sendPointerToWallpaperLocked(relWin, pointer, eventTime); - - // If we are on top of the wallpaper, then the wallpaper also - // gets to see this movement. - } else if (srcWin != null - && pointer.getAction() == MotionEvent.ACTION_DOWN - && mWallpaperTarget == srcWin - && srcWin.mAttrs.type != WindowManager.LayoutParams.TYPE_KEYGUARD) { - sendPointerToWallpaperLocked(relWin, pointer, eventTime); - } - } public int addWindow(Session session, IWindow client, WindowManager.LayoutParams attrs, int viewVisibility, @@ -1903,12 +1783,7 @@ public class WindowManagerService extends IWindowManager.Stub mDisplay = wm.getDefaultDisplay(); mInitialDisplayWidth = mDisplay.getWidth(); mInitialDisplayHeight = mDisplay.getHeight(); - if (ENABLE_NATIVE_INPUT_DISPATCH) { - mInputManager.setDisplaySize(0, - mInitialDisplayWidth, mInitialDisplayHeight); - } else { - mQueue.setDisplay(mDisplay); - } + mInputManager.setDisplaySize(0, mInitialDisplayWidth, mInitialDisplayHeight); reportNewConfig = true; } @@ -2002,15 +1877,13 @@ public class WindowManagerService extends IWindowManager.Stub return res; } - if (ENABLE_NATIVE_INPUT_DISPATCH) { - if (outInputChannel != null) { - String name = win.makeInputChannelName(); - InputChannel[] inputChannels = InputChannel.openInputChannelPair(name); - win.mInputChannel = inputChannels[0]; - inputChannels[1].transferToBinderOutParameter(outInputChannel); - - mInputManager.registerInputChannel(win.mInputChannel); - } + if (outInputChannel != null) { + String name = win.makeInputChannelName(); + InputChannel[] inputChannels = InputChannel.openInputChannelPair(name); + win.mInputChannel = inputChannels[0]; + inputChannels[1].transferToBinderOutParameter(outInputChannel); + + mInputManager.registerInputChannel(win.mInputChannel); } // From now on, no exceptions or errors allowed! @@ -2186,14 +2059,7 @@ public class WindowManagerService extends IWindowManager.Stub } private void removeWindowInnerLocked(Session session, WindowState win) { - if (ENABLE_NATIVE_INPUT_DISPATCH) { - mInputMonitor.windowIsBeingRemovedLw(win); - } else { - mKeyWaiter.finishedKey(session, win.mClient, true, - KeyWaiter.RETURN_NOTHING); - mKeyWaiter.releasePendingPointerLocked(win.mSession); - mKeyWaiter.releasePendingTrackballLocked(win.mSession); - } + mInputMonitor.windowIsBeingRemovedLw(win); win.mRemoved = true; @@ -2561,12 +2427,7 @@ public class WindowManagerService extends IWindowManager.Stub applyAnimationLocked(win, transit, false)) { focusMayChange = true; win.mExiting = true; - if (ENABLE_NATIVE_INPUT_DISPATCH) { - mInputMonitor.windowIsBecomingInvisibleLw(win); - } else { - mKeyWaiter.finishedKey(session, client, true, - KeyWaiter.RETURN_NOTHING); - } + mInputMonitor.windowIsBecomingInvisibleLw(win); } else if (win.isAnimating()) { // Currently in a hide animation... turn this into // an exit. @@ -3027,12 +2888,7 @@ public class WindowManagerService extends IWindowManager.Stub if (win.isVisibleNow()) { applyAnimationLocked(win, WindowManagerPolicy.TRANSIT_EXIT, false); - if (ENABLE_NATIVE_INPUT_DISPATCH) { - mInputMonitor.windowIsBeingRemovedLw(win); - } else { - mKeyWaiter.finishedKey(win.mSession, win.mClient, true, - KeyWaiter.RETURN_NOTHING); - } + mInputMonitor.windowIsBeingRemovedLw(win); changed = true; } } @@ -3349,12 +3205,8 @@ public class WindowManagerService extends IWindowManager.Stub if (DEBUG_FOCUS) Slog.v(TAG, "Clearing focused app, was " + mFocusedApp); changed = mFocusedApp != null; mFocusedApp = null; - if (ENABLE_NATIVE_INPUT_DISPATCH) { - if (changed) { - mInputMonitor.setFocusedAppLw(null); - } - } else { - mKeyWaiter.tickle(); + if (changed) { + mInputMonitor.setFocusedAppLw(null); } } else { AppWindowToken newFocus = findAppWindowToken(token); @@ -3365,12 +3217,8 @@ public class WindowManagerService extends IWindowManager.Stub changed = mFocusedApp != newFocus; mFocusedApp = newFocus; if (DEBUG_FOCUS) Slog.v(TAG, "Set focused app to: " + mFocusedApp); - if (ENABLE_NATIVE_INPUT_DISPATCH) { - if (changed) { - mInputMonitor.setFocusedAppLw(newFocus); - } - } else { - mKeyWaiter.tickle(); + if (changed) { + mInputMonitor.setFocusedAppLw(newFocus); } } @@ -3682,12 +3530,7 @@ public class WindowManagerService extends IWindowManager.Stub applyAnimationLocked(win, WindowManagerPolicy.TRANSIT_EXIT, false); } - if (ENABLE_NATIVE_INPUT_DISPATCH) { - mInputMonitor.windowIsBecomingInvisibleLw(win); - } else { - mKeyWaiter.finishedKey(win.mSession, win.mClient, true, - KeyWaiter.RETURN_NOTHING); - } + mInputMonitor.windowIsBecomingInvisibleLw(win); changed = true; } } @@ -3972,11 +3815,7 @@ public class WindowManagerService extends IWindowManager.Stub if (DEBUG_FOCUS) Slog.v(TAG, "Removing focused app token:" + wtoken); mFocusedApp = null; updateFocusedWindowLocked(UPDATE_FOCUS_NORMAL); - if (ENABLE_NATIVE_INPUT_DISPATCH) { - mInputMonitor.setFocusedAppLw(null); - } else { - mKeyWaiter.tickle(); - } + mInputMonitor.setFocusedAppLw(null); } } else { Slog.w(TAG, "Attempted to remove non-existing app token: " + token); @@ -4441,11 +4280,7 @@ public class WindowManagerService extends IWindowManager.Stub "getSwitchState()")) { throw new SecurityException("Requires READ_INPUT_STATE permission"); } - if (ENABLE_NATIVE_INPUT_DISPATCH) { - return mInputManager.getSwitchState(sw); - } else { - return KeyInputQueue.getSwitchState(sw); - } + return mInputManager.getSwitchState(sw); } public int getSwitchStateForDevice(int devid, int sw) { @@ -4453,11 +4288,7 @@ public class WindowManagerService extends IWindowManager.Stub "getSwitchStateForDevice()")) { throw new SecurityException("Requires READ_INPUT_STATE permission"); } - if (ENABLE_NATIVE_INPUT_DISPATCH) { - return mInputManager.getSwitchState(devid, sw); - } else { - return KeyInputQueue.getSwitchState(devid, sw); - } + return mInputManager.getSwitchState(devid, sw); } public int getScancodeState(int sw) { @@ -4465,11 +4296,7 @@ public class WindowManagerService extends IWindowManager.Stub "getScancodeState()")) { throw new SecurityException("Requires READ_INPUT_STATE permission"); } - if (ENABLE_NATIVE_INPUT_DISPATCH) { - return mInputManager.getScancodeState(sw); - } else { - return mQueue.getScancodeState(sw); - } + return mInputManager.getScancodeState(sw); } public int getScancodeStateForDevice(int devid, int sw) { @@ -4477,11 +4304,7 @@ public class WindowManagerService extends IWindowManager.Stub "getScancodeStateForDevice()")) { throw new SecurityException("Requires READ_INPUT_STATE permission"); } - if (ENABLE_NATIVE_INPUT_DISPATCH) { - return mInputManager.getScancodeState(devid, sw); - } else { - return mQueue.getScancodeState(devid, sw); - } + return mInputManager.getScancodeState(devid, sw); } public int getTrackballScancodeState(int sw) { @@ -4489,11 +4312,7 @@ public class WindowManagerService extends IWindowManager.Stub "getTrackballScancodeState()")) { throw new SecurityException("Requires READ_INPUT_STATE permission"); } - if (ENABLE_NATIVE_INPUT_DISPATCH) { - return mInputManager.getTrackballScancodeState(sw); - } else { - return mQueue.getTrackballScancodeState(sw); - } + return mInputManager.getTrackballScancodeState(sw); } public int getDPadScancodeState(int sw) { @@ -4501,11 +4320,7 @@ public class WindowManagerService extends IWindowManager.Stub "getDPadScancodeState()")) { throw new SecurityException("Requires READ_INPUT_STATE permission"); } - if (ENABLE_NATIVE_INPUT_DISPATCH) { - return mInputManager.getDPadScancodeState(sw); - } else { - return mQueue.getDPadScancodeState(sw); - } + return mInputManager.getDPadScancodeState(sw); } public int getKeycodeState(int sw) { @@ -4513,11 +4328,7 @@ public class WindowManagerService extends IWindowManager.Stub "getKeycodeState()")) { throw new SecurityException("Requires READ_INPUT_STATE permission"); } - if (ENABLE_NATIVE_INPUT_DISPATCH) { - return mInputManager.getKeycodeState(sw); - } else { - return mQueue.getKeycodeState(sw); - } + return mInputManager.getKeycodeState(sw); } public int getKeycodeStateForDevice(int devid, int sw) { @@ -4525,11 +4336,7 @@ public class WindowManagerService extends IWindowManager.Stub "getKeycodeStateForDevice()")) { throw new SecurityException("Requires READ_INPUT_STATE permission"); } - if (ENABLE_NATIVE_INPUT_DISPATCH) { - return mInputManager.getKeycodeState(devid, sw); - } else { - return mQueue.getKeycodeState(devid, sw); - } + return mInputManager.getKeycodeState(devid, sw); } public int getTrackballKeycodeState(int sw) { @@ -4537,11 +4344,7 @@ public class WindowManagerService extends IWindowManager.Stub "getTrackballKeycodeState()")) { throw new SecurityException("Requires READ_INPUT_STATE permission"); } - if (ENABLE_NATIVE_INPUT_DISPATCH) { - return mInputManager.getTrackballKeycodeState(sw); - } else { - return mQueue.getTrackballKeycodeState(sw); - } + return mInputManager.getTrackballKeycodeState(sw); } public int getDPadKeycodeState(int sw) { @@ -4549,19 +4352,11 @@ public class WindowManagerService extends IWindowManager.Stub "getDPadKeycodeState()")) { throw new SecurityException("Requires READ_INPUT_STATE permission"); } - if (ENABLE_NATIVE_INPUT_DISPATCH) { - return mInputManager.getDPadKeycodeState(sw); - } else { - return mQueue.getDPadKeycodeState(sw); - } + return mInputManager.getDPadKeycodeState(sw); } public boolean hasKeys(int[] keycodes, boolean[] keyExists) { - if (ENABLE_NATIVE_INPUT_DISPATCH) { - return mInputManager.hasKeys(keycodes, keyExists); - } else { - return KeyInputQueue.hasKeys(keycodes, keyExists); - } + return mInputManager.hasKeys(keycodes, keyExists); } public void enableScreenAfterBoot() { @@ -4706,11 +4501,7 @@ public class WindowManagerService extends IWindowManager.Stub mLayoutNeeded = true; startFreezingDisplayLocked(); Slog.i(TAG, "Setting rotation to " + rotation + ", animFlags=" + animFlags); - if (ENABLE_NATIVE_INPUT_DISPATCH) { - mInputManager.setDisplayOrientation(0, rotation); - } else { - mQueue.setOrientation(rotation); - } + mInputManager.setDisplayOrientation(0, rotation); if (mDisplayEnabled) { Surface.setOrientation(0, rotation, animFlags); } @@ -5041,11 +4832,8 @@ public class WindowManagerService extends IWindowManager.Stub if (mDisplay == null) { return false; } - if (ENABLE_NATIVE_INPUT_DISPATCH) { - mInputManager.getInputConfiguration(config); - } else { - mQueue.getInputConfiguration(config); - } + + mInputManager.getInputConfiguration(config); // Use the effective "visual" dimensions based on current rotation final boolean rotated = (mRotation == Surface.ROTATION_90 @@ -5326,6 +5114,13 @@ public class WindowManagerService extends IWindowManager.Stub mTempInputWindows.clear(); } + /* Provides feedback for a virtual key down. */ + public void virtualKeyDownFeedback() { + synchronized (mWindowMap) { + mPolicy.performHapticFeedbackLw(null, HapticFeedbackConstants.VIRTUAL_KEY, false); + } + } + /* Notifies that an app switch key (BACK / HOME) has just been pressed. * This essentially starts a .5 second timeout for the application to process * subsequent input events while waiting for the app switch to occur. If it takes longer @@ -5334,30 +5129,28 @@ public class WindowManagerService extends IWindowManager.Stub public void notifyAppSwitchComing() { // TODO Not implemented yet. Should go in the native side. } - + + /* Notifies that the lid switch changed state. */ + public void notifyLidSwitchChanged(long whenNanos, boolean lidOpen) { + mPolicy.notifyLidSwitchChanged(whenNanos, lidOpen); + } + /* Provides an opportunity for the window manager policy to intercept early key * processing as soon as the key has been read from the device. */ - public int interceptKeyBeforeQueueing(int deviceId, int type, int scanCode, - int keyCode, int policyFlags, int value, long whenNanos, boolean isScreenOn) { - RawInputEvent event = new RawInputEvent(); - event.deviceId = deviceId; - event.type = type; - event.scancode = scanCode; - event.keycode = keyCode; - event.flags = policyFlags; - event.value = value; - event.when = whenNanos / 1000000; - - return mPolicy.interceptKeyTq(event, isScreenOn); + public int interceptKeyBeforeQueueing(long whenNanos, int keyCode, boolean down, + int policyFlags, boolean isScreenOn) { + return mPolicy.interceptKeyBeforeQueueing(whenNanos, + keyCode, down, policyFlags, isScreenOn); } /* Provides an opportunity for the window manager policy to process a key before * ordinary dispatch. */ - public boolean interceptKeyBeforeDispatching(InputChannel focus, int keyCode, - int metaState, boolean down, int repeatCount, int policyFlags) { + public boolean interceptKeyBeforeDispatching(InputChannel focus, + int action, int flags, int keyCode, int metaState, int repeatCount, + int policyFlags) { WindowState windowState = getWindowStateForInputChannel(focus); - return mPolicy.interceptKeyTi(windowState, keyCode, metaState, down, repeatCount, - policyFlags); + return mPolicy.interceptKeyBeforeDispatching(windowState, action, flags, + keyCode, metaState, repeatCount, policyFlags); } /* Called when the current input focus changes. @@ -5496,450 +5289,6 @@ public class WindowManagerService extends IWindowManager.Stub } } - private final void wakeupIfNeeded(WindowState targetWin, int eventType) { - long curTime = SystemClock.uptimeMillis(); - - if (eventType == TOUCH_EVENT || eventType == LONG_TOUCH_EVENT || eventType == CHEEK_EVENT) { - if (mLastTouchEventType == eventType && - (curTime - mLastUserActivityCallTime) < MIN_TIME_BETWEEN_USERACTIVITIES) { - return; - } - mLastUserActivityCallTime = curTime; - mLastTouchEventType = eventType; - } - - if (targetWin == null - || targetWin.mAttrs.type != WindowManager.LayoutParams.TYPE_KEYGUARD) { - mPowerManager.userActivity(curTime, false, eventType, false); - } - } - - // tells if it's a cheek event or not -- this function is stateful - private static final int EVENT_NONE = 0; - private static final int EVENT_UNKNOWN = 0; - private static final int EVENT_CHEEK = 0; - private static final int EVENT_IGNORE_DURATION = 300; // ms - private static final float CHEEK_THRESHOLD = 0.6f; - private int mEventState = EVENT_NONE; - private float mEventSize; - - private int eventType(MotionEvent ev) { - float size = ev.getSize(); - switch (ev.getAction()) { - case MotionEvent.ACTION_DOWN: - mEventSize = size; - return (mEventSize > CHEEK_THRESHOLD) ? CHEEK_EVENT : TOUCH_EVENT; - case MotionEvent.ACTION_UP: - if (size > mEventSize) mEventSize = size; - return (mEventSize > CHEEK_THRESHOLD) ? CHEEK_EVENT : TOUCH_UP_EVENT; - case MotionEvent.ACTION_MOVE: - final int N = ev.getHistorySize(); - if (size > mEventSize) mEventSize = size; - if (mEventSize > CHEEK_THRESHOLD) return CHEEK_EVENT; - for (int i=0; i<N; i++) { - size = ev.getHistoricalSize(i); - if (size > mEventSize) mEventSize = size; - if (mEventSize > CHEEK_THRESHOLD) return CHEEK_EVENT; - } - if (ev.getEventTime() < ev.getDownTime() + EVENT_IGNORE_DURATION) { - return TOUCH_EVENT; - } else { - return LONG_TOUCH_EVENT; - } - default: - // not good - return OTHER_EVENT; - } - } - - private boolean mFatTouch; // remove me together with dispatchPointer - - /** - * @return Returns true if event was dispatched, false if it was dropped for any reason - */ - private int dispatchPointer(QueuedEvent qev, MotionEvent ev, int pid, int uid) { - if (DEBUG_INPUT || WindowManagerPolicy.WATCH_POINTER) Slog.v(TAG, - "dispatchPointer " + ev); - - if (MEASURE_LATENCY) { - lt.sample("3 Wait for last dispatch ", System.nanoTime() - qev.whenNano); - } - - Object targetObj = mKeyWaiter.waitForNextEventTarget(null, qev, - ev, true, false, pid, uid); - - if (MEASURE_LATENCY) { - lt.sample("3 Last dispatch finished ", System.nanoTime() - qev.whenNano); - } - - int action = ev.getAction(); - - if (action == MotionEvent.ACTION_UP) { - // let go of our target - mKeyWaiter.mMotionTarget = null; - mPowerManager.logPointerUpEvent(); - } else if (action == MotionEvent.ACTION_DOWN) { - mPowerManager.logPointerDownEvent(); - } - - if (targetObj == null) { - // In this case we are either dropping the event, or have received - // a move or up without a down. It is common to receive move - // events in such a way, since this means the user is moving the - // pointer without actually pressing down. All other cases should - // be atypical, so let's log them. - if (action != MotionEvent.ACTION_MOVE) { - Slog.w(TAG, "No window to dispatch pointer action " + ev.getAction()); - } - synchronized (mWindowMap) { - dispatchPointerElsewhereLocked(null, null, ev, ev.getEventTime(), true); - } - if (qev != null) { - mQueue.recycleEvent(qev); - } - ev.recycle(); - return INJECT_FAILED; - } - if (targetObj == mKeyWaiter.CONSUMED_EVENT_TOKEN) { - synchronized (mWindowMap) { - dispatchPointerElsewhereLocked(null, null, ev, ev.getEventTime(), true); - } - if (qev != null) { - mQueue.recycleEvent(qev); - } - ev.recycle(); - return INJECT_SUCCEEDED; - } - - WindowState target = (WindowState)targetObj; - - final long eventTime = ev.getEventTime(); - final long eventTimeNano = ev.getEventTimeNano(); - - //Slog.i(TAG, "Sending " + ev + " to " + target); - - if (uid != 0 && uid != target.mSession.mUid) { - if (mContext.checkPermission( - android.Manifest.permission.INJECT_EVENTS, pid, uid) - != PackageManager.PERMISSION_GRANTED) { - Slog.w(TAG, "Permission denied: injecting pointer event from pid " - + pid + " uid " + uid + " to window " + target - + " owned by uid " + target.mSession.mUid); - if (qev != null) { - mQueue.recycleEvent(qev); - } - ev.recycle(); - return INJECT_NO_PERMISSION; - } - } - - if (MEASURE_LATENCY) { - lt.sample("4 in dispatchPointer ", System.nanoTime() - eventTimeNano); - } - - if ((target.mAttrs.flags & - WindowManager.LayoutParams.FLAG_IGNORE_CHEEK_PRESSES) != 0) { - //target wants to ignore fat touch events - boolean cheekPress = mPolicy.isCheekPressedAgainstScreen(ev); - //explicit flag to return without processing event further - boolean returnFlag = false; - if((action == MotionEvent.ACTION_DOWN)) { - mFatTouch = false; - if(cheekPress) { - mFatTouch = true; - returnFlag = true; - } - } else { - if(action == MotionEvent.ACTION_UP) { - if(mFatTouch) { - //earlier even was invalid doesnt matter if current up is cheekpress or not - mFatTouch = false; - returnFlag = true; - } else if(cheekPress) { - //cancel the earlier event - ev.setAction(MotionEvent.ACTION_CANCEL); - action = MotionEvent.ACTION_CANCEL; - } - } else if(action == MotionEvent.ACTION_MOVE) { - if(mFatTouch) { - //two cases here - //an invalid down followed by 0 or moves(valid or invalid) - //a valid down, invalid move, more moves. want to ignore till up - returnFlag = true; - } else if(cheekPress) { - //valid down followed by invalid moves - //an invalid move have to cancel earlier action - ev.setAction(MotionEvent.ACTION_CANCEL); - action = MotionEvent.ACTION_CANCEL; - if (DEBUG_INPUT) Slog.v(TAG, "Sending cancel for invalid ACTION_MOVE"); - //note that the subsequent invalid moves will not get here - mFatTouch = true; - } - } - } //else if action - if(returnFlag) { - //recycle que, ev - if (qev != null) { - mQueue.recycleEvent(qev); - } - ev.recycle(); - return INJECT_FAILED; - } - } //end if target - - // Enable this for testing the "right" value - if (false && action == MotionEvent.ACTION_DOWN) { - int max_events_per_sec = 35; - try { - max_events_per_sec = Integer.parseInt(SystemProperties - .get("windowsmgr.max_events_per_sec")); - if (max_events_per_sec < 1) { - max_events_per_sec = 35; - } - } catch (NumberFormatException e) { - } - mMinWaitTimeBetweenTouchEvents = 1000 / max_events_per_sec; - } - - /* - * Throttle events to minimize CPU usage when there's a flood of events - * e.g. constant contact with the screen - */ - if (action == MotionEvent.ACTION_MOVE) { - long nextEventTime = mLastTouchEventTime + mMinWaitTimeBetweenTouchEvents; - long now = SystemClock.uptimeMillis(); - if (now < nextEventTime) { - try { - Thread.sleep(nextEventTime - now); - } catch (InterruptedException e) { - } - mLastTouchEventTime = nextEventTime; - } else { - mLastTouchEventTime = now; - } - } - - if (MEASURE_LATENCY) { - lt.sample("5 in dispatchPointer ", System.nanoTime() - eventTimeNano); - } - - synchronized(mWindowMap) { - if (!target.isVisibleLw()) { - // During this motion dispatch, the target window has become - // invisible. - dispatchPointerElsewhereLocked(null, null, ev, ev.getEventTime(), false); - if (qev != null) { - mQueue.recycleEvent(qev); - } - ev.recycle(); - return INJECT_SUCCEEDED; - } - - if (qev != null && action == MotionEvent.ACTION_MOVE) { - mKeyWaiter.bindTargetWindowLocked(target, - KeyWaiter.RETURN_PENDING_POINTER, qev); - ev = null; - } else { - if (action == MotionEvent.ACTION_DOWN) { - WindowState out = mKeyWaiter.mOutsideTouchTargets; - if (out != null) { - MotionEvent oev = MotionEvent.obtain(ev); - oev.setAction(MotionEvent.ACTION_OUTSIDE); - do { - final Rect frame = out.mFrame; - oev.offsetLocation(-(float)frame.left, -(float)frame.top); - try { - out.mClient.dispatchPointer(oev, eventTime, false); - } catch (android.os.RemoteException e) { - Slog.i(TAG, "WINDOW DIED during outside motion dispatch: " + out); - } - oev.offsetLocation((float)frame.left, (float)frame.top); - out = out.mNextOutsideTouch; - } while (out != null); - mKeyWaiter.mOutsideTouchTargets = null; - } - } - - dispatchPointerElsewhereLocked(target, null, ev, ev.getEventTime(), false); - - final Rect frame = target.mFrame; - ev.offsetLocation(-(float)frame.left, -(float)frame.top); - mKeyWaiter.bindTargetWindowLocked(target); - } - } - - // finally offset the event to the target's coordinate system and - // dispatch the event. - try { - if (DEBUG_INPUT || DEBUG_FOCUS || WindowManagerPolicy.WATCH_POINTER) { - Slog.v(TAG, "Delivering pointer " + qev + " to " + target); - } - - if (MEASURE_LATENCY) { - lt.sample("6 before svr->client ipc ", System.nanoTime() - eventTimeNano); - } - - target.mClient.dispatchPointer(ev, eventTime, true); - - if (MEASURE_LATENCY) { - lt.sample("7 after svr->client ipc ", System.nanoTime() - eventTimeNano); - } - return INJECT_SUCCEEDED; - } catch (android.os.RemoteException e) { - Slog.i(TAG, "WINDOW DIED during motion dispatch: " + target); - mKeyWaiter.mMotionTarget = null; - try { - removeWindow(target.mSession, target.mClient); - } catch (java.util.NoSuchElementException ex) { - // This will happen if the window has already been - // removed. - } - } - return INJECT_FAILED; - } - - /** - * @return Returns true if event was dispatched, false if it was dropped for any reason - */ - private int dispatchTrackball(QueuedEvent qev, MotionEvent ev, int pid, int uid) { - if (DEBUG_INPUT) Slog.v( - TAG, "dispatchTrackball [" + ev.getAction() +"] <" + ev.getX() + ", " + ev.getY() + ">"); - - Object focusObj = mKeyWaiter.waitForNextEventTarget(null, qev, - ev, false, false, pid, uid); - if (focusObj == null) { - Slog.w(TAG, "No focus window, dropping trackball: " + ev); - if (qev != null) { - mQueue.recycleEvent(qev); - } - ev.recycle(); - return INJECT_FAILED; - } - if (focusObj == mKeyWaiter.CONSUMED_EVENT_TOKEN) { - if (qev != null) { - mQueue.recycleEvent(qev); - } - ev.recycle(); - return INJECT_SUCCEEDED; - } - - WindowState focus = (WindowState)focusObj; - - if (uid != 0 && uid != focus.mSession.mUid) { - if (mContext.checkPermission( - android.Manifest.permission.INJECT_EVENTS, pid, uid) - != PackageManager.PERMISSION_GRANTED) { - Slog.w(TAG, "Permission denied: injecting key event from pid " - + pid + " uid " + uid + " to window " + focus - + " owned by uid " + focus.mSession.mUid); - if (qev != null) { - mQueue.recycleEvent(qev); - } - ev.recycle(); - return INJECT_NO_PERMISSION; - } - } - - final long eventTime = ev.getEventTime(); - - synchronized(mWindowMap) { - if (qev != null && ev.getAction() == MotionEvent.ACTION_MOVE) { - mKeyWaiter.bindTargetWindowLocked(focus, - KeyWaiter.RETURN_PENDING_TRACKBALL, qev); - // We don't deliver movement events to the client, we hold - // them and wait for them to call back. - ev = null; - } else { - mKeyWaiter.bindTargetWindowLocked(focus); - } - } - - try { - focus.mClient.dispatchTrackball(ev, eventTime, true); - return INJECT_SUCCEEDED; - } catch (android.os.RemoteException e) { - Slog.i(TAG, "WINDOW DIED during key dispatch: " + focus); - try { - removeWindow(focus.mSession, focus.mClient); - } catch (java.util.NoSuchElementException ex) { - // This will happen if the window has already been - // removed. - } - } - - return INJECT_FAILED; - } - - /** - * @return Returns true if event was dispatched, false if it was dropped for any reason - */ - private int dispatchKey(KeyEvent event, int pid, int uid) { - if (DEBUG_INPUT) Slog.v(TAG, "Dispatch key: " + event); - - Object focusObj = mKeyWaiter.waitForNextEventTarget(event, null, - null, false, false, pid, uid); - if (focusObj == null) { - Slog.w(TAG, "No focus window, dropping: " + event); - return INJECT_FAILED; - } - if (focusObj == mKeyWaiter.CONSUMED_EVENT_TOKEN) { - return INJECT_SUCCEEDED; - } - - // Okay we have finished waiting for the last event to be processed. - // First off, if this is a repeat event, check to see if there is - // a corresponding up event in the queue. If there is, we will - // just drop the repeat, because it makes no sense to repeat after - // the user has released a key. (This is especially important for - // long presses.) - if (event.getRepeatCount() > 0 && mQueue.hasKeyUpEvent(event)) { - return INJECT_SUCCEEDED; - } - - WindowState focus = (WindowState)focusObj; - - if (DEBUG_INPUT) Slog.v( - TAG, "Dispatching to " + focus + ": " + event); - - if (uid != 0 && uid != focus.mSession.mUid) { - if (mContext.checkPermission( - android.Manifest.permission.INJECT_EVENTS, pid, uid) - != PackageManager.PERMISSION_GRANTED) { - Slog.w(TAG, "Permission denied: injecting key event from pid " - + pid + " uid " + uid + " to window " + focus - + " owned by uid " + focus.mSession.mUid); - return INJECT_NO_PERMISSION; - } - } - - synchronized(mWindowMap) { - mKeyWaiter.bindTargetWindowLocked(focus); - } - - // NOSHIP extra state logging - mKeyWaiter.recordDispatchState(event, focus); - // END NOSHIP - - try { - if (DEBUG_INPUT || DEBUG_FOCUS) { - Slog.v(TAG, "Delivering key " + event.getKeyCode() - + " to " + focus); - } - focus.mClient.dispatchKey(event); - return INJECT_SUCCEEDED; - } catch (android.os.RemoteException e) { - Slog.i(TAG, "WINDOW DIED during key dispatch: " + focus); - try { - removeWindow(focus.mSession, focus.mClient); - } catch (java.util.NoSuchElementException ex) { - // This will happen if the window has already been - // removed. - } - } - - return INJECT_FAILED; - } - public void pauseKeyDispatching(IBinder _token) { if (!checkCallingPermission(android.Manifest.permission.MANAGE_APP_TOKENS, "pauseKeyDispatching()")) { @@ -5949,11 +5298,7 @@ public class WindowManagerService extends IWindowManager.Stub synchronized (mWindowMap) { WindowToken token = mTokenMap.get(_token); if (token != null) { - if (ENABLE_NATIVE_INPUT_DISPATCH) { - mInputMonitor.pauseDispatchingLw(token); - } else { - mKeyWaiter.pauseDispatchingLocked(token); - } + mInputMonitor.pauseDispatchingLw(token); } } } @@ -5967,11 +5312,7 @@ public class WindowManagerService extends IWindowManager.Stub synchronized (mWindowMap) { WindowToken token = mTokenMap.get(_token); if (token != null) { - if (ENABLE_NATIVE_INPUT_DISPATCH) { - mInputMonitor.resumeDispatchingLw(token); - } else { - mKeyWaiter.resumeDispatchingLocked(token); - } + mInputMonitor.resumeDispatchingLw(token); } } } @@ -5983,11 +5324,7 @@ public class WindowManagerService extends IWindowManager.Stub } synchronized (mWindowMap) { - if (ENABLE_NATIVE_INPUT_DISPATCH) { - mInputMonitor.setEventDispatchingLw(enabled); - } else { - mKeyWaiter.setEventDispatchingLocked(enabled); - } + mInputMonitor.setEventDispatchingLw(enabled); } } @@ -6020,16 +5357,8 @@ public class WindowManagerService extends IWindowManager.Stub final int uid = Binder.getCallingUid(); final long ident = Binder.clearCallingIdentity(); - final int result; - if (ENABLE_NATIVE_INPUT_DISPATCH) { - result = mInputManager.injectKeyEvent(newEvent, InputQueue.INPUT_EVENT_NATURE_KEY, - pid, uid, sync, INJECTION_TIMEOUT_MILLIS); - } else { - result = dispatchKey(newEvent, pid, uid); - if (sync) { - mKeyWaiter.waitForNextEventTarget(null, null, null, false, true, pid, uid); - } - } + final int result = mInputManager.injectKeyEvent(newEvent, + InputQueue.INPUT_EVENT_NATURE_KEY, pid, uid, sync, INJECTION_TIMEOUT_MILLIS); Binder.restoreCallingIdentity(ident); return reportInjectionResult(result); @@ -6049,16 +5378,8 @@ public class WindowManagerService extends IWindowManager.Stub final int uid = Binder.getCallingUid(); final long ident = Binder.clearCallingIdentity(); - final int result; - if (ENABLE_NATIVE_INPUT_DISPATCH) { - result = mInputManager.injectMotionEvent(ev, InputQueue.INPUT_EVENT_NATURE_TOUCH, - pid, uid, sync, INJECTION_TIMEOUT_MILLIS); - } else { - result = dispatchPointer(null, ev, pid, uid); - if (sync) { - mKeyWaiter.waitForNextEventTarget(null, null, null, false, true, pid, uid); - } - } + final int result = mInputManager.injectMotionEvent(ev, + InputQueue.INPUT_EVENT_NATURE_TOUCH, pid, uid, sync, INJECTION_TIMEOUT_MILLIS); Binder.restoreCallingIdentity(ident); return reportInjectionResult(result); @@ -6078,48 +5399,29 @@ public class WindowManagerService extends IWindowManager.Stub final int uid = Binder.getCallingUid(); final long ident = Binder.clearCallingIdentity(); - final int result; - if (ENABLE_NATIVE_INPUT_DISPATCH) { - result = mInputManager.injectMotionEvent(ev, InputQueue.INPUT_EVENT_NATURE_TRACKBALL, - pid, uid, sync, INJECTION_TIMEOUT_MILLIS); - } else { - result = dispatchTrackball(null, ev, pid, uid); - if (sync) { - mKeyWaiter.waitForNextEventTarget(null, null, null, false, true, pid, uid); - } - } + final int result = mInputManager.injectMotionEvent(ev, + InputQueue.INPUT_EVENT_NATURE_TRACKBALL, pid, uid, sync, INJECTION_TIMEOUT_MILLIS); Binder.restoreCallingIdentity(ident); return reportInjectionResult(result); } private boolean reportInjectionResult(int result) { - if (ENABLE_NATIVE_INPUT_DISPATCH) { - switch (result) { - case InputManager.INPUT_EVENT_INJECTION_PERMISSION_DENIED: - Slog.w(TAG, "Input event injection permission denied."); - throw new SecurityException( - "Injecting to another application requires INJECT_EVENTS permission"); - case InputManager.INPUT_EVENT_INJECTION_SUCCEEDED: - Slog.v(TAG, "Input event injection succeeded."); - return true; - case InputManager.INPUT_EVENT_INJECTION_TIMED_OUT: - Slog.w(TAG, "Input event injection timed out."); - return false; - case InputManager.INPUT_EVENT_INJECTION_FAILED: - default: - Slog.w(TAG, "Input event injection failed."); - return false; - } - } else { - switch (result) { - case INJECT_NO_PERMISSION: - throw new SecurityException( - "Injecting to another application requires INJECT_EVENTS permission"); - case INJECT_SUCCEEDED: - return true; - } - return false; + switch (result) { + case InputManager.INPUT_EVENT_INJECTION_PERMISSION_DENIED: + Slog.w(TAG, "Input event injection permission denied."); + throw new SecurityException( + "Injecting to another application requires INJECT_EVENTS permission"); + case InputManager.INPUT_EVENT_INJECTION_SUCCEEDED: + Slog.v(TAG, "Input event injection succeeded."); + return true; + case InputManager.INPUT_EVENT_INJECTION_TIMED_OUT: + Slog.w(TAG, "Input event injection timed out."); + return false; + case InputManager.INPUT_EVENT_INJECTION_FAILED: + default: + Slog.w(TAG, "Input event injection failed."); + return false; } } @@ -6133,867 +5435,6 @@ public class WindowManagerService extends IWindowManager.Stub return mCurrentFocus; } - /** - * This class holds the state for dispatching key events. This state - * is protected by the KeyWaiter instance, NOT by the window lock. You - * can be holding the main window lock while acquire the KeyWaiter lock, - * but not the other way around. - */ - final class KeyWaiter { - // NOSHIP debugging - public class DispatchState { - private KeyEvent event; - private WindowState focus; - private long time; - private WindowState lastWin; - private IBinder lastBinder; - private boolean finished; - private boolean gotFirstWindow; - private boolean eventDispatching; - private long timeToSwitch; - private boolean wasFrozen; - private boolean focusPaused; - private WindowState curFocus; - - DispatchState(KeyEvent theEvent, WindowState theFocus) { - focus = theFocus; - event = theEvent; - time = System.currentTimeMillis(); - // snapshot KeyWaiter state - lastWin = mLastWin; - lastBinder = mLastBinder; - finished = mFinished; - gotFirstWindow = mGotFirstWindow; - eventDispatching = mEventDispatching; - timeToSwitch = mTimeToSwitch; - wasFrozen = mWasFrozen; - curFocus = mCurrentFocus; - // cache the paused state at ctor time as well - if (theFocus == null || theFocus.mToken == null) { - focusPaused = false; - } else { - focusPaused = theFocus.mToken.paused; - } - } - - public String toString() { - return "{{" + event + " to " + focus + " @ " + time - + " lw=" + lastWin + " lb=" + lastBinder - + " fin=" + finished + " gfw=" + gotFirstWindow - + " ed=" + eventDispatching + " tts=" + timeToSwitch - + " wf=" + wasFrozen + " fp=" + focusPaused - + " mcf=" + curFocus + "}}"; - } - }; - private DispatchState mDispatchState = null; - public void recordDispatchState(KeyEvent theEvent, WindowState theFocus) { - mDispatchState = new DispatchState(theEvent, theFocus); - } - // END NOSHIP - - public static final int RETURN_NOTHING = 0; - public static final int RETURN_PENDING_POINTER = 1; - public static final int RETURN_PENDING_TRACKBALL = 2; - - final Object SKIP_TARGET_TOKEN = new Object(); - final Object CONSUMED_EVENT_TOKEN = new Object(); - - private WindowState mLastWin = null; - private IBinder mLastBinder = null; - private boolean mFinished = true; - private boolean mGotFirstWindow = false; - private boolean mEventDispatching = true; - private long mTimeToSwitch = 0; - /* package */ boolean mWasFrozen = false; - - // Target of Motion events - WindowState mMotionTarget; - - // Windows above the target who would like to receive an "outside" - // touch event for any down events outside of them. - WindowState mOutsideTouchTargets; - - /** - * Wait for the last event dispatch to complete, then find the next - * target that should receive the given event and wait for that one - * to be ready to receive it. - */ - Object waitForNextEventTarget(KeyEvent nextKey, QueuedEvent qev, - MotionEvent nextMotion, boolean isPointerEvent, - boolean failIfTimeout, int callingPid, int callingUid) { - long startTime = SystemClock.uptimeMillis(); - long keyDispatchingTimeout = 5 * 1000; - long waitedFor = 0; - - while (true) { - // Figure out which window we care about. It is either the - // last window we are waiting to have process the event or, - // if none, then the next window we think the event should go - // to. Note: we retrieve mLastWin outside of the lock, so - // it may change before we lock. Thus we must check it again. - WindowState targetWin = mLastWin; - boolean targetIsNew = targetWin == null; - if (DEBUG_INPUT) Slog.v( - TAG, "waitForLastKey: mFinished=" + mFinished + - ", mLastWin=" + mLastWin); - if (targetIsNew) { - Object target = findTargetWindow(nextKey, qev, nextMotion, - isPointerEvent, callingPid, callingUid); - if (target == SKIP_TARGET_TOKEN) { - // The user has pressed a special key, and we are - // dropping all pending events before it. - if (DEBUG_INPUT) Slog.v(TAG, "Skipping: " + nextKey - + " " + nextMotion); - return null; - } - if (target == CONSUMED_EVENT_TOKEN) { - if (DEBUG_INPUT) Slog.v(TAG, "Consumed: " + nextKey - + " " + nextMotion); - return target; - } - targetWin = (WindowState)target; - } - - AppWindowToken targetApp = null; - - // Now: is it okay to send the next event to this window? - synchronized (this) { - // First: did we come here based on the last window not - // being null, but it changed by the time we got here? - // If so, try again. - if (!targetIsNew && mLastWin == null) { - continue; - } - - // We never dispatch events if not finished with the - // last one, or the display is frozen. - if (mFinished && !mDisplayFrozen) { - // If event dispatching is disabled, then we - // just consume the events. - if (!mEventDispatching) { - if (DEBUG_INPUT) Slog.v(TAG, - "Skipping event; dispatching disabled: " - + nextKey + " " + nextMotion); - return null; - } - if (targetWin != null) { - // If this is a new target, and that target is not - // paused or unresponsive, then all looks good to - // handle the event. - if (targetIsNew && !targetWin.mToken.paused) { - return targetWin; - } - - // If we didn't find a target window, and there is no - // focused app window, then just eat the events. - } else if (mFocusedApp == null) { - if (DEBUG_INPUT) Slog.v(TAG, - "Skipping event; no focused app: " - + nextKey + " " + nextMotion); - return null; - } - } - - if (DEBUG_INPUT) Slog.v( - TAG, "Waiting for last key in " + mLastBinder - + " target=" + targetWin - + " mFinished=" + mFinished - + " mDisplayFrozen=" + mDisplayFrozen - + " targetIsNew=" + targetIsNew - + " paused=" - + (targetWin != null ? targetWin.mToken.paused : false) - + " mFocusedApp=" + mFocusedApp - + " mCurrentFocus=" + mCurrentFocus); - - targetApp = targetWin != null - ? targetWin.mAppToken : mFocusedApp; - - long curTimeout = keyDispatchingTimeout; - if (mTimeToSwitch != 0) { - long now = SystemClock.uptimeMillis(); - if (mTimeToSwitch <= now) { - // If an app switch key has been pressed, and we have - // waited too long for the current app to finish - // processing keys, then wait no more! - doFinishedKeyLocked(false); - continue; - } - long switchTimeout = mTimeToSwitch - now; - if (curTimeout > switchTimeout) { - curTimeout = switchTimeout; - } - } - - try { - // after that continue - // processing keys, so we don't get stuck. - if (DEBUG_INPUT) Slog.v( - TAG, "Waiting for key dispatch: " + curTimeout); - wait(curTimeout); - if (DEBUG_INPUT) Slog.v(TAG, "Finished waiting @" - + SystemClock.uptimeMillis() + " startTime=" - + startTime + " switchTime=" + mTimeToSwitch - + " target=" + targetWin + " mLW=" + mLastWin - + " mLB=" + mLastBinder + " fin=" + mFinished - + " mCurrentFocus=" + mCurrentFocus); - } catch (InterruptedException e) { - } - } - - // If we were frozen during configuration change, restart the - // timeout checks from now; otherwise look at whether we timed - // out before awakening. - if (mWasFrozen) { - waitedFor = 0; - mWasFrozen = false; - } else { - waitedFor = SystemClock.uptimeMillis() - startTime; - } - - if (waitedFor >= keyDispatchingTimeout && mTimeToSwitch == 0) { - IApplicationToken at = null; - synchronized (this) { - Slog.w(TAG, "Key dispatching timed out sending to " + - (targetWin != null ? targetWin.mAttrs.getTitle() - : "<null>: no window ready for key dispatch")); - // NOSHIP debugging - Slog.w(TAG, "Previous dispatch state: " + mDispatchState); - Slog.w(TAG, "Current dispatch state: " + - new DispatchState(nextKey, targetWin)); - // END NOSHIP - //dump(); - if (targetWin != null) { - at = targetWin.getAppToken(); - } else if (targetApp != null) { - at = targetApp.appToken; - } - } - - boolean abort = true; - if (at != null) { - try { - long timeout = at.getKeyDispatchingTimeout(); - if (timeout > waitedFor) { - // we did not wait the proper amount of time for this application. - // set the timeout to be the real timeout and wait again. - keyDispatchingTimeout = timeout - waitedFor; - continue; - } else { - abort = at.keyDispatchingTimedOut(); - } - } catch (RemoteException ex) { - } - } - - synchronized (this) { - if (abort && (mLastWin == targetWin || targetWin == null)) { - mFinished = true; - if (mLastWin != null) { - if (DEBUG_INPUT) Slog.v(TAG, - "Window " + mLastWin + - " timed out on key input"); - if (mLastWin.mToken.paused) { - Slog.w(TAG, "Un-pausing dispatching to this window"); - mLastWin.mToken.paused = false; - } - } - if (mMotionTarget == targetWin) { - mMotionTarget = null; - } - mLastWin = null; - mLastBinder = null; - if (failIfTimeout || targetWin == null) { - return null; - } - } else { - Slog.w(TAG, "Continuing to wait for key to be dispatched"); - startTime = SystemClock.uptimeMillis(); - } - } - } - } - } - - Object findTargetWindow(KeyEvent nextKey, QueuedEvent qev, - MotionEvent nextMotion, boolean isPointerEvent, - int callingPid, int callingUid) { - mOutsideTouchTargets = null; - - if (nextKey != null) { - // Find the target window for a normal key event. - final int keycode = nextKey.getKeyCode(); - final int repeatCount = nextKey.getRepeatCount(); - final boolean down = nextKey.getAction() != KeyEvent.ACTION_UP; - boolean dispatch = mKeyWaiter.checkShouldDispatchKey(keycode); - - if (!dispatch) { - if (callingUid == 0 || - mContext.checkPermission( - android.Manifest.permission.INJECT_EVENTS, - callingPid, callingUid) - == PackageManager.PERMISSION_GRANTED) { - mPolicy.interceptKeyTi(null, keycode, - nextKey.getMetaState(), down, repeatCount, - nextKey.getFlags()); - } - Slog.w(TAG, "Event timeout during app switch: dropping " - + nextKey); - return SKIP_TARGET_TOKEN; - } - - // System.out.println("##### [" + SystemClock.uptimeMillis() + "] WindowManagerService.dispatchKey(" + keycode + ", " + down + ", " + repeatCount + ")"); - - WindowState focus = null; - synchronized(mWindowMap) { - focus = getFocusedWindowLocked(); - } - - wakeupIfNeeded(focus, LocalPowerManager.BUTTON_EVENT); - - if (callingUid == 0 || - (focus != null && callingUid == focus.mSession.mUid) || - mContext.checkPermission( - android.Manifest.permission.INJECT_EVENTS, - callingPid, callingUid) - == PackageManager.PERMISSION_GRANTED) { - if (mPolicy.interceptKeyTi(focus, - keycode, nextKey.getMetaState(), down, repeatCount, - nextKey.getFlags())) { - return CONSUMED_EVENT_TOKEN; - } - } - - return focus; - - } else if (!isPointerEvent) { - boolean dispatch = mKeyWaiter.checkShouldDispatchKey(-1); - if (!dispatch) { - Slog.w(TAG, "Event timeout during app switch: dropping trackball " - + nextMotion); - return SKIP_TARGET_TOKEN; - } - - WindowState focus = null; - synchronized(mWindowMap) { - focus = getFocusedWindowLocked(); - } - - wakeupIfNeeded(focus, LocalPowerManager.BUTTON_EVENT); - return focus; - } - - if (nextMotion == null) { - return SKIP_TARGET_TOKEN; - } - - boolean dispatch = mKeyWaiter.checkShouldDispatchKey( - KeyEvent.KEYCODE_UNKNOWN); - if (!dispatch) { - Slog.w(TAG, "Event timeout during app switch: dropping pointer " - + nextMotion); - return SKIP_TARGET_TOKEN; - } - - // Find the target window for a pointer event. - int action = nextMotion.getAction(); - final float xf = nextMotion.getX(); - final float yf = nextMotion.getY(); - final long eventTime = nextMotion.getEventTime(); - - final boolean screenWasOff = qev != null - && (qev.flags&WindowManagerPolicy.FLAG_BRIGHT_HERE) != 0; - - WindowState target = null; - - synchronized(mWindowMap) { - synchronized (this) { - if (action == MotionEvent.ACTION_DOWN) { - if (mMotionTarget != null) { - // this is weird, we got a pen down, but we thought it was - // already down! - // XXX: We should probably send an ACTION_UP to the current - // target. - Slog.w(TAG, "Pointer down received while already down in: " - + mMotionTarget); - mMotionTarget = null; - } - - // ACTION_DOWN is special, because we need to lock next events to - // the window we'll land onto. - final int x = (int)xf; - final int y = (int)yf; - - final ArrayList windows = mWindows; - final int N = windows.size(); - WindowState topErrWindow = null; - final Rect tmpRect = mTempRect; - for (int i=N-1; i>=0; i--) { - WindowState child = (WindowState)windows.get(i); - //Slog.i(TAG, "Checking dispatch to: " + child); - final int flags = child.mAttrs.flags; - if ((flags & WindowManager.LayoutParams.FLAG_SYSTEM_ERROR) != 0) { - if (topErrWindow == null) { - topErrWindow = child; - } - } - if (!child.isVisibleLw()) { - //Slog.i(TAG, "Not visible!"); - continue; - } - if ((flags & WindowManager.LayoutParams.FLAG_NOT_TOUCHABLE) != 0) { - //Slog.i(TAG, "Not touchable!"); - if ((flags & WindowManager.LayoutParams - .FLAG_WATCH_OUTSIDE_TOUCH) != 0) { - child.mNextOutsideTouch = mOutsideTouchTargets; - mOutsideTouchTargets = child; - } - continue; - } - tmpRect.set(child.mFrame); - if (child.mTouchableInsets == ViewTreeObserver - .InternalInsetsInfo.TOUCHABLE_INSETS_CONTENT) { - // The touch is inside of the window if it is - // inside the frame, AND the content part of that - // frame that was given by the application. - tmpRect.left += child.mGivenContentInsets.left; - tmpRect.top += child.mGivenContentInsets.top; - tmpRect.right -= child.mGivenContentInsets.right; - tmpRect.bottom -= child.mGivenContentInsets.bottom; - } else if (child.mTouchableInsets == ViewTreeObserver - .InternalInsetsInfo.TOUCHABLE_INSETS_VISIBLE) { - // The touch is inside of the window if it is - // inside the frame, AND the visible part of that - // frame that was given by the application. - tmpRect.left += child.mGivenVisibleInsets.left; - tmpRect.top += child.mGivenVisibleInsets.top; - tmpRect.right -= child.mGivenVisibleInsets.right; - tmpRect.bottom -= child.mGivenVisibleInsets.bottom; - } - final int touchFlags = flags & - (WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE - |WindowManager.LayoutParams.FLAG_NOT_TOUCH_MODAL); - if (tmpRect.contains(x, y) || touchFlags == 0) { - //Slog.i(TAG, "Using this target!"); - if (!screenWasOff || (flags & - WindowManager.LayoutParams.FLAG_TOUCHABLE_WHEN_WAKING) != 0) { - mMotionTarget = child; - } else { - //Slog.i(TAG, "Waking, skip!"); - mMotionTarget = null; - } - break; - } - - if ((flags & WindowManager.LayoutParams - .FLAG_WATCH_OUTSIDE_TOUCH) != 0) { - child.mNextOutsideTouch = mOutsideTouchTargets; - mOutsideTouchTargets = child; - //Slog.i(TAG, "Adding to outside target list: " + child); - } - } - - // if there's an error window but it's not accepting - // focus (typically because it is not yet visible) just - // wait for it -- any other focused window may in fact - // be in ANR state. - if (topErrWindow != null && mMotionTarget != topErrWindow) { - mMotionTarget = null; - } - } - - target = mMotionTarget; - } - } - - wakeupIfNeeded(target, eventType(nextMotion)); - - // Pointer events are a little different -- if there isn't a - // target found for any event, then just drop it. - return target != null ? target : SKIP_TARGET_TOKEN; - } - - boolean checkShouldDispatchKey(int keycode) { - synchronized (this) { - if (mPolicy.isAppSwitchKeyTqTiLwLi(keycode)) { - mTimeToSwitch = 0; - return true; - } - if (mTimeToSwitch != 0 - && mTimeToSwitch < SystemClock.uptimeMillis()) { - return false; - } - return true; - } - } - - void bindTargetWindowLocked(WindowState win, - int pendingWhat, QueuedEvent pendingMotion) { - synchronized (this) { - bindTargetWindowLockedLocked(win, pendingWhat, pendingMotion); - } - } - - void bindTargetWindowLocked(WindowState win) { - synchronized (this) { - bindTargetWindowLockedLocked(win, RETURN_NOTHING, null); - } - } - - void bindTargetWindowLockedLocked(WindowState win, - int pendingWhat, QueuedEvent pendingMotion) { - mLastWin = win; - mLastBinder = win.mClient.asBinder(); - mFinished = false; - if (pendingMotion != null) { - final Session s = win.mSession; - if (pendingWhat == RETURN_PENDING_POINTER) { - releasePendingPointerLocked(s); - s.mPendingPointerMove = pendingMotion; - s.mPendingPointerWindow = win; - if (DEBUG_INPUT) Slog.v(TAG, - "bindTargetToWindow " + s.mPendingPointerMove); - } else if (pendingWhat == RETURN_PENDING_TRACKBALL) { - releasePendingTrackballLocked(s); - s.mPendingTrackballMove = pendingMotion; - s.mPendingTrackballWindow = win; - } - } - } - - void releasePendingPointerLocked(Session s) { - if (DEBUG_INPUT) Slog.v(TAG, - "releasePendingPointer " + s.mPendingPointerMove); - if (s.mPendingPointerMove != null) { - mQueue.recycleEvent(s.mPendingPointerMove); - s.mPendingPointerMove = null; - } - } - - void releasePendingTrackballLocked(Session s) { - if (s.mPendingTrackballMove != null) { - mQueue.recycleEvent(s.mPendingTrackballMove); - s.mPendingTrackballMove = null; - } - } - - MotionEvent finishedKey(Session session, IWindow client, boolean force, - int returnWhat) { - if (DEBUG_INPUT) Slog.v( - TAG, "finishedKey: client=" + client + ", force=" + force); - - if (client == null) { - return null; - } - - MotionEvent res = null; - QueuedEvent qev = null; - WindowState win = null; - - synchronized (this) { - if (DEBUG_INPUT) Slog.v( - TAG, "finishedKey: client=" + client.asBinder() - + ", force=" + force + ", last=" + mLastBinder - + " (token=" + (mLastWin != null ? mLastWin.mToken : null) + ")"); - - if (returnWhat == RETURN_PENDING_POINTER) { - qev = session.mPendingPointerMove; - win = session.mPendingPointerWindow; - session.mPendingPointerMove = null; - session.mPendingPointerWindow = null; - } else if (returnWhat == RETURN_PENDING_TRACKBALL) { - qev = session.mPendingTrackballMove; - win = session.mPendingTrackballWindow; - session.mPendingTrackballMove = null; - session.mPendingTrackballWindow = null; - } - - if (mLastBinder == client.asBinder()) { - if (DEBUG_INPUT) Slog.v( - TAG, "finishedKey: last paused=" - + ((mLastWin != null) ? mLastWin.mToken.paused : "null")); - if (mLastWin != null && (!mLastWin.mToken.paused || force - || !mEventDispatching)) { - doFinishedKeyLocked(true); - } else { - // Make sure to wake up anyone currently waiting to - // dispatch a key, so they can re-evaluate their - // current situation. - mFinished = true; - notifyAll(); - } - } - - if (qev != null) { - res = (MotionEvent)qev.event; - if (DEBUG_INPUT) Slog.v(TAG, - "Returning pending motion: " + res); - mQueue.recycleEvent(qev); - if (win != null && returnWhat == RETURN_PENDING_POINTER) { - res.offsetLocation(-win.mFrame.left, -win.mFrame.top); - } - } - } - - if (res != null && returnWhat == RETURN_PENDING_POINTER) { - synchronized (mWindowMap) { - dispatchPointerElsewhereLocked(win, win, res, res.getEventTime(), false); - } - } - - return res; - } - - void tickle() { - synchronized (this) { - notifyAll(); - } - } - - void handleNewWindowLocked(WindowState newWindow) { - if (!newWindow.canReceiveKeys()) { - return; - } - synchronized (this) { - if (DEBUG_INPUT) Slog.v( - TAG, "New key dispatch window: win=" - + newWindow.mClient.asBinder() - + ", last=" + mLastBinder - + " (token=" + (mLastWin != null ? mLastWin.mToken : null) - + "), finished=" + mFinished + ", paused=" - + newWindow.mToken.paused); - - // Displaying a window implicitly causes dispatching to - // be unpaused. (This is to protect against bugs if someone - // pauses dispatching but forgets to resume.) - newWindow.mToken.paused = false; - - mGotFirstWindow = true; - - if ((newWindow.mAttrs.flags & FLAG_SYSTEM_ERROR) != 0) { - if (DEBUG_INPUT) Slog.v(TAG, - "New SYSTEM_ERROR window; resetting state"); - mLastWin = null; - mLastBinder = null; - mMotionTarget = null; - mFinished = true; - } else if (mLastWin != null) { - // If the new window is above the window we are - // waiting on, then stop waiting and let key dispatching - // start on the new guy. - if (DEBUG_INPUT) Slog.v( - TAG, "Last win layer=" + mLastWin.mLayer - + ", new win layer=" + newWindow.mLayer); - if (newWindow.mLayer >= mLastWin.mLayer) { - // The new window is above the old; finish pending input to the last - // window and start directing it to the new one. - mLastWin.mToken.paused = false; - doFinishedKeyLocked(false); // does a notifyAll() - return; - } - } - - // Now that we've put a new window state in place, make the event waiter - // take notice and retarget its attentions. - notifyAll(); - } - } - - void pauseDispatchingLocked(WindowToken token) { - synchronized (this) - { - if (DEBUG_INPUT) Slog.v(TAG, "Pausing WindowToken " + token); - token.paused = true; - - /* - if (mLastWin != null && !mFinished && mLastWin.mBaseLayer <= layer) { - mPaused = true; - } else { - if (mLastWin == null) { - Slog.i(TAG, "Key dispatching not paused: no last window."); - } else if (mFinished) { - Slog.i(TAG, "Key dispatching not paused: finished last key."); - } else { - Slog.i(TAG, "Key dispatching not paused: window in higher layer."); - } - } - */ - } - } - - void resumeDispatchingLocked(WindowToken token) { - synchronized (this) { - if (token.paused) { - if (DEBUG_INPUT) Slog.v( - TAG, "Resuming WindowToken " + token - + ", last=" + mLastBinder - + " (token=" + (mLastWin != null ? mLastWin.mToken : null) - + "), finished=" + mFinished + ", paused=" - + token.paused); - token.paused = false; - if (mLastWin != null && mLastWin.mToken == token && mFinished) { - doFinishedKeyLocked(false); - } else { - notifyAll(); - } - } - } - } - - void setEventDispatchingLocked(boolean enabled) { - synchronized (this) { - mEventDispatching = enabled; - notifyAll(); - } - } - - void appSwitchComing() { - synchronized (this) { - // Don't wait for more than .5 seconds for app to finish - // processing the pending events. - long now = SystemClock.uptimeMillis() + 500; - if (DEBUG_INPUT) Slog.v(TAG, "appSwitchComing: " + now); - if (mTimeToSwitch == 0 || now < mTimeToSwitch) { - mTimeToSwitch = now; - } - notifyAll(); - } - } - - private final void doFinishedKeyLocked(boolean force) { - if (mLastWin != null) { - releasePendingPointerLocked(mLastWin.mSession); - releasePendingTrackballLocked(mLastWin.mSession); - } - - if (force || mLastWin == null || !mLastWin.mToken.paused - || !mLastWin.isVisibleLw()) { - // If the current window has been paused, we aren't -really- - // finished... so let the waiters still wait. - mLastWin = null; - mLastBinder = null; - } - mFinished = true; - notifyAll(); - } - } - - private class KeyQ extends KeyInputQueue - implements KeyInputQueue.FilterCallback { - KeyQ() { - super(mContext, WindowManagerService.this); - } - - @Override - boolean preprocessEvent(InputDevice device, RawInputEvent event) { - if (mPolicy.preprocessInputEventTq(event)) { - return true; - } - - switch (event.type) { - case RawInputEvent.EV_KEY: { - // XXX begin hack - if (DEBUG) { - if (event.keycode == KeyEvent.KEYCODE_G) { - if (event.value != 0) { - // G down - mPolicy.screenTurnedOff(WindowManagerPolicy.OFF_BECAUSE_OF_USER); - } - return false; - } - if (event.keycode == KeyEvent.KEYCODE_D) { - if (event.value != 0) { - //dump(); - } - return false; - } - } - // XXX end hack - - boolean screenIsOff = !mPowerManager.isScreenOn(); - boolean screenIsDim = !mPowerManager.isScreenBright(); - int actions = mPolicy.interceptKeyTq(event, !screenIsOff); - - if ((actions & WindowManagerPolicy.ACTION_GO_TO_SLEEP) != 0) { - mPowerManager.goToSleep(event.when); - } - - if (screenIsOff) { - event.flags |= WindowManagerPolicy.FLAG_WOKE_HERE; - } - if (screenIsDim) { - event.flags |= WindowManagerPolicy.FLAG_BRIGHT_HERE; - } - if ((actions & WindowManagerPolicy.ACTION_POKE_USER_ACTIVITY) != 0) { - mPowerManager.userActivity(event.when, false, - LocalPowerManager.BUTTON_EVENT, false); - } - - if ((actions & WindowManagerPolicy.ACTION_PASS_TO_USER) != 0) { - if (event.value != 0 && mPolicy.isAppSwitchKeyTqTiLwLi(event.keycode)) { - filterQueue(this); - mKeyWaiter.appSwitchComing(); - } - return true; - } else { - return false; - } - } - - case RawInputEvent.EV_REL: { - boolean screenIsOff = !mPowerManager.isScreenOn(); - boolean screenIsDim = !mPowerManager.isScreenBright(); - if (screenIsOff) { - if (!mPolicy.isWakeRelMovementTq(event.deviceId, - device.classes, event)) { - //Slog.i(TAG, "dropping because screenIsOff and !isWakeKey"); - return false; - } - event.flags |= WindowManagerPolicy.FLAG_WOKE_HERE; - } - if (screenIsDim) { - event.flags |= WindowManagerPolicy.FLAG_BRIGHT_HERE; - } - return true; - } - - case RawInputEvent.EV_ABS: { - boolean screenIsOff = !mPowerManager.isScreenOn(); - boolean screenIsDim = !mPowerManager.isScreenBright(); - if (screenIsOff) { - if (!mPolicy.isWakeAbsMovementTq(event.deviceId, - device.classes, event)) { - //Slog.i(TAG, "dropping because screenIsOff and !isWakeKey"); - return false; - } - event.flags |= WindowManagerPolicy.FLAG_WOKE_HERE; - } - if (screenIsDim) { - event.flags |= WindowManagerPolicy.FLAG_BRIGHT_HERE; - } - return true; - } - - default: - return true; - } - } - - public int filterEvent(QueuedEvent ev) { - switch (ev.classType) { - case RawInputEvent.CLASS_KEYBOARD: - KeyEvent ke = (KeyEvent)ev.event; - if (mPolicy.isMovementKeyTi(ke.getKeyCode())) { - Slog.w(TAG, "Dropping movement key during app switch: " - + ke.getKeyCode() + ", action=" + ke.getAction()); - return FILTER_REMOVE; - } - return FILTER_ABORT; - default: - return FILTER_KEEP; - } - } - } - public boolean detectSafeMode() { mSafeMode = mPolicy.detectSafeMode(); return mSafeMode; @@ -7003,219 +5444,6 @@ public class WindowManagerService extends IWindowManager.Stub mPolicy.systemReady(); } - private final class InputDispatcherThread extends Thread { - // Time to wait when there is nothing to do: 9999 seconds. - static final int LONG_WAIT=9999*1000; - - public InputDispatcherThread() { - super("InputDispatcher"); - } - - @Override - public void run() { - while (true) { - try { - process(); - } catch (Exception e) { - Slog.e(TAG, "Exception in input dispatcher", e); - } - } - } - - private void process() { - android.os.Process.setThreadPriority( - android.os.Process.THREAD_PRIORITY_URGENT_DISPLAY); - - // The last key event we saw - KeyEvent lastKey = null; - - // Last keydown time for auto-repeating keys - long lastKeyTime = SystemClock.uptimeMillis(); - long nextKeyTime = lastKeyTime+LONG_WAIT; - long downTime = 0; - - // How many successive repeats we generated - int keyRepeatCount = 0; - - // Need to report that configuration has changed? - boolean configChanged = false; - - while (true) { - long curTime = SystemClock.uptimeMillis(); - - if (DEBUG_INPUT) Slog.v( - TAG, "Waiting for next key: now=" + curTime - + ", repeat @ " + nextKeyTime); - - // Retrieve next event, waiting only as long as the next - // repeat timeout. If the configuration has changed, then - // don't wait at all -- we'll report the change as soon as - // we have processed all events. - QueuedEvent ev = mQueue.getEvent( - (int)((!configChanged && curTime < nextKeyTime) - ? (nextKeyTime-curTime) : 0)); - - if (DEBUG_INPUT && ev != null) Slog.v( - TAG, "Event: type=" + ev.classType + " data=" + ev.event); - - if (MEASURE_LATENCY) { - lt.sample("2 got event ", System.nanoTime() - ev.whenNano); - } - - if (lastKey != null && !mPolicy.allowKeyRepeat()) { - // cancel key repeat at the request of the policy. - lastKey = null; - downTime = 0; - lastKeyTime = curTime; - nextKeyTime = curTime + LONG_WAIT; - } - try { - if (ev != null) { - curTime = SystemClock.uptimeMillis(); - int eventType; - if (ev.classType == RawInputEvent.CLASS_TOUCHSCREEN) { - eventType = eventType((MotionEvent)ev.event); - } else if (ev.classType == RawInputEvent.CLASS_KEYBOARD || - ev.classType == RawInputEvent.CLASS_TRACKBALL) { - eventType = LocalPowerManager.BUTTON_EVENT; - } else { - eventType = LocalPowerManager.OTHER_EVENT; - } - try { - if ((curTime - mLastBatteryStatsCallTime) - >= MIN_TIME_BETWEEN_USERACTIVITIES) { - mLastBatteryStatsCallTime = curTime; - mBatteryStats.noteInputEvent(); - } - } catch (RemoteException e) { - // Ignore - } - - if (ev.classType == RawInputEvent.CLASS_CONFIGURATION_CHANGED) { - // do not wake screen in this case - } else if (eventType != TOUCH_EVENT - && eventType != LONG_TOUCH_EVENT - && eventType != CHEEK_EVENT) { - mPowerManager.userActivity(curTime, false, - eventType, false); - } else if (mLastTouchEventType != eventType - || (curTime - mLastUserActivityCallTime) - >= MIN_TIME_BETWEEN_USERACTIVITIES) { - mLastUserActivityCallTime = curTime; - mLastTouchEventType = eventType; - mPowerManager.userActivity(curTime, false, - eventType, false); - } - - switch (ev.classType) { - case RawInputEvent.CLASS_KEYBOARD: - KeyEvent ke = (KeyEvent)ev.event; - if (ke.isDown()) { - lastKeyTime = curTime; - if (lastKey != null && - ke.getKeyCode() == lastKey.getKeyCode()) { - keyRepeatCount++; - // Arbitrary long timeout to block - // repeating here since we know that - // the device driver takes care of it. - nextKeyTime = lastKeyTime + LONG_WAIT; - if (DEBUG_INPUT) Slog.v( - TAG, "Received repeated key down"); - } else { - downTime = curTime; - keyRepeatCount = 0; - nextKeyTime = lastKeyTime - + ViewConfiguration.getLongPressTimeout(); - if (DEBUG_INPUT) Slog.v( - TAG, "Received key down: first repeat @ " - + nextKeyTime); - } - lastKey = ke; - } else { - lastKey = null; - downTime = 0; - keyRepeatCount = 0; - // Arbitrary long timeout. - lastKeyTime = curTime; - nextKeyTime = curTime + LONG_WAIT; - if (DEBUG_INPUT) Slog.v( - TAG, "Received key up: ignore repeat @ " - + nextKeyTime); - } - if (keyRepeatCount > 0) { - dispatchKey(KeyEvent.changeTimeRepeat(ke, - ke.getEventTime(), keyRepeatCount), 0, 0); - } else { - dispatchKey(ke, 0, 0); - } - mQueue.recycleEvent(ev); - break; - case RawInputEvent.CLASS_TOUCHSCREEN: - //Slog.i(TAG, "Read next event " + ev); - dispatchPointer(ev, (MotionEvent)ev.event, 0, 0); - break; - case RawInputEvent.CLASS_TRACKBALL: - dispatchTrackball(ev, (MotionEvent)ev.event, 0, 0); - break; - case RawInputEvent.CLASS_CONFIGURATION_CHANGED: - configChanged = true; - break; - default: - mQueue.recycleEvent(ev); - break; - } - - } else if (configChanged) { - configChanged = false; - sendNewConfiguration(); - - } else if (lastKey != null) { - curTime = SystemClock.uptimeMillis(); - - // Timeout occurred while key was down. If it is at or - // past the key repeat time, dispatch the repeat. - if (DEBUG_INPUT) Slog.v( - TAG, "Key timeout: repeat=" + nextKeyTime - + ", now=" + curTime); - if (curTime < nextKeyTime) { - continue; - } - - lastKeyTime = nextKeyTime; - nextKeyTime = nextKeyTime + KEY_REPEAT_DELAY; - keyRepeatCount++; - if (DEBUG_INPUT) Slog.v( - TAG, "Key repeat: count=" + keyRepeatCount - + ", next @ " + nextKeyTime); - KeyEvent newEvent; - if (downTime != 0 && (downTime - + ViewConfiguration.getLongPressTimeout()) - <= curTime) { - newEvent = KeyEvent.changeTimeRepeat(lastKey, - curTime, keyRepeatCount, - lastKey.getFlags() | KeyEvent.FLAG_LONG_PRESS); - downTime = 0; - } else { - newEvent = KeyEvent.changeTimeRepeat(lastKey, - curTime, keyRepeatCount); - } - dispatchKey(newEvent, 0, 0); - - } else { - curTime = SystemClock.uptimeMillis(); - - lastKeyTime = curTime; - nextKeyTime = curTime + LONG_WAIT; - } - - } catch (Exception e) { - Slog.e(TAG, - "Input thread received uncaught exception: " + e, e); - } - } - } - } - // ------------------------------------------------------------- // Client Session State // ------------------------------------------------------------- @@ -7231,20 +5459,6 @@ public class WindowManagerService extends IWindowManager.Stub int mNumWindow = 0; boolean mClientDead = false; - /** - * Current pointer move event being dispatched to client window... must - * hold key lock to access. - */ - QueuedEvent mPendingPointerMove; - WindowState mPendingPointerWindow; - - /** - * Current trackball move event being dispatched to client window... must - * hold key lock to access. - */ - QueuedEvent mPendingTrackballMove; - WindowState mPendingTrackballWindow; - public Session(IInputMethodClient client, IInputContext inputContext) { mClient = client; mInputContext = inputContext; @@ -7363,36 +5577,6 @@ public class WindowManagerService extends IWindowManager.Stub finishDrawingWindow(this, window); } - public void finishKey(IWindow window) { - if (localLOGV) Slog.v( - TAG, "IWindow finishKey called for " + window); - if (ENABLE_NATIVE_INPUT_DISPATCH) { - throw new IllegalStateException("Should not be called anymore."); - } - mKeyWaiter.finishedKey(this, window, false, - KeyWaiter.RETURN_NOTHING); - } - - public MotionEvent getPendingPointerMove(IWindow window) { - if (localLOGV) Slog.v( - TAG, "IWindow getPendingMotionEvent called for " + window); - if (ENABLE_NATIVE_INPUT_DISPATCH) { - throw new IllegalStateException("Should not be called anymore."); - } - return mKeyWaiter.finishedKey(this, window, false, - KeyWaiter.RETURN_PENDING_POINTER); - } - - public MotionEvent getPendingTrackballMove(IWindow window) { - if (localLOGV) Slog.v( - TAG, "IWindow getPendingMotionEvent called for " + window); - if (ENABLE_NATIVE_INPUT_DISPATCH) { - throw new IllegalStateException("Should not be called anymore."); - } - return mKeyWaiter.finishedKey(this, window, false, - KeyWaiter.RETURN_PENDING_TRACKBALL); - } - public void setInTouchMode(boolean mode) { synchronized(mWindowMap) { mInTouchMode = mode; @@ -7496,16 +5680,6 @@ public class WindowManagerService extends IWindowManager.Stub pw.print(prefix); pw.print("mNumWindow="); pw.print(mNumWindow); pw.print(" mClientDead="); pw.print(mClientDead); pw.print(" mSurfaceSession="); pw.println(mSurfaceSession); - if (mPendingPointerWindow != null || mPendingPointerMove != null) { - pw.print(prefix); - pw.print("mPendingPointerWindow="); pw.print(mPendingPointerWindow); - pw.print(" mPendingPointerMove="); pw.println(mPendingPointerMove); - } - if (mPendingTrackballWindow != null || mPendingTrackballMove != null) { - pw.print(prefix); - pw.print("mPendingTrackballWindow="); pw.print(mPendingTrackballWindow); - pw.print(" mPendingTrackballMove="); pw.println(mPendingTrackballMove); - } } @Override @@ -7556,8 +5730,6 @@ public class WindowManagerService extends IWindowManager.Stub boolean mObscured; boolean mTurnOnScreen; - WindowState mNextOutsideTouch; - int mLayoutSeq = -1; Configuration mConfiguration = null; @@ -8074,16 +6246,6 @@ public class WindowManagerService extends IWindowManager.Stub } void destroySurfaceLocked() { - // Window is no longer on-screen, so can no longer receive - // key events... if we were waiting for it to finish - // handling a key event, the wait is over! - if (! ENABLE_NATIVE_INPUT_DISPATCH) { - mKeyWaiter.finishedKey(mSession, mClient, true, - KeyWaiter.RETURN_NOTHING); - mKeyWaiter.releasePendingPointerLocked(mSession); - mKeyWaiter.releasePendingTrackballLocked(mSession); - } - if (mAppToken != null && this == mAppToken.startingWindow) { mAppToken.startingDisplayed = false; } @@ -8099,9 +6261,7 @@ public class WindowManagerService extends IWindowManager.Stub WindowState c = (WindowState)mChildWindows.get(i); c.mAttachedHidden = true; - if (ENABLE_NATIVE_INPUT_DISPATCH) { - mInputMonitor.windowIsBecomingInvisibleLw(c); - } + mInputMonitor.windowIsBecomingInvisibleLw(c); } if (mReportDestroySurface) { @@ -8410,12 +6570,8 @@ public class WindowManagerService extends IWindowManager.Stub } mLastHidden = true; - if (ENABLE_NATIVE_INPUT_DISPATCH) { - for (int i=0; i<N; i++) { - mInputMonitor.windowIsBecomingInvisibleLw((WindowState)mChildWindows.get(i)); - } - } else { - mKeyWaiter.releasePendingPointerLocked(mSession); + for (int i=0; i<N; i++) { + mInputMonitor.windowIsBecomingInvisibleLw((WindowState)mChildWindows.get(i)); } } mExiting = false; @@ -8752,13 +6908,11 @@ public class WindowManagerService extends IWindowManager.Stub // we are doing this as part of processing a death note.) } - if (ENABLE_NATIVE_INPUT_DISPATCH) { - if (mInputChannel != null) { - mInputManager.unregisterInputChannel(mInputChannel); - - mInputChannel.dispose(); - mInputChannel = null; - } + if (mInputChannel != null) { + mInputManager.unregisterInputChannel(mInputChannel); + + mInputChannel.dispose(); + mInputChannel = null; } } @@ -10174,9 +8328,7 @@ public class WindowManagerService extends IWindowManager.Stub } // Window frames may have changed. Tell the input dispatcher about it. - if (ENABLE_NATIVE_INPUT_DISPATCH) { - mInputMonitor.updateInputWindowsLw(); - } + mInputMonitor.updateInputWindowsLw(); return mPolicy.finishLayoutLw(); } @@ -10977,11 +9129,7 @@ public class WindowManagerService extends IWindowManager.Stub Slog.w(TAG, "Exception hiding surface in " + w); } } - if (ENABLE_NATIVE_INPUT_DISPATCH) { - mInputMonitor.windowIsBecomingInvisibleLw(w); - } else { - mKeyWaiter.releasePendingPointerLocked(w.mSession); - } + mInputMonitor.windowIsBecomingInvisibleLw(w); } // If we are waiting for this window to handle an // orientation change, well, it is hidden, so @@ -11583,13 +9731,7 @@ public class WindowManagerService extends IWindowManager.Stub } private void finishUpdateFocusedWindowAfterAssignLayersLocked() { - if (ENABLE_NATIVE_INPUT_DISPATCH) { - mInputMonitor.setInputFocusLw(mCurrentFocus); - } else { - if (mCurrentFocus != null) { - mKeyWaiter.handleNewWindowLocked(mCurrentFocus); - } - } + mInputMonitor.setInputFocusLw(mCurrentFocus); } private WindowState computeFocusedWindowLocked() { @@ -11663,17 +9805,6 @@ public class WindowManagerService extends IWindowManager.Stub private void startFreezingDisplayLocked() { if (mDisplayFrozen) { - // Freezing the display also suspends key event delivery, to - // keep events from going astray while the display is reconfigured. - // If someone has changed orientation again while the screen is - // still frozen, the events will continue to be blocked while the - // successive orientation change is processed. To prevent spurious - // ANRs, we reset the event dispatch timeout in this case. - if (! ENABLE_NATIVE_INPUT_DISPATCH) { - synchronized (mKeyWaiter) { - mKeyWaiter.mWasFrozen = true; - } - } return; } @@ -11696,9 +9827,7 @@ public class WindowManagerService extends IWindowManager.Stub mDisplayFrozen = true; - if (ENABLE_NATIVE_INPUT_DISPATCH) { - mInputMonitor.freezeInputDispatchingLw(); - } + mInputMonitor.freezeInputDispatchingLw(); if (mNextAppTransition != WindowManagerPolicy.TRANSIT_UNSET) { mNextAppTransition = WindowManagerPolicy.TRANSIT_UNSET; @@ -11731,16 +9860,7 @@ public class WindowManagerService extends IWindowManager.Stub } Surface.unfreezeDisplay(0); - // Reset the key delivery timeout on unfreeze, too. We force a wakeup here - // too because regular key delivery processing should resume immediately. - if (ENABLE_NATIVE_INPUT_DISPATCH) { - mInputMonitor.thawInputDispatchingLw(); - } else { - synchronized (mKeyWaiter) { - mKeyWaiter.mWasFrozen = true; - mKeyWaiter.notifyAll(); - } - } + mInputMonitor.thawInputDispatchingLw(); // While the display is frozen we don't re-compute the orientation // to avoid inconsistent states. However, something interesting @@ -11772,13 +9892,8 @@ public class WindowManagerService extends IWindowManager.Stub return; } - if (ENABLE_NATIVE_INPUT_DISPATCH) { - pw.println("Input Dispatcher State:"); - mInputManager.dump(pw); - } else { - pw.println("Input State:"); - mQueue.dump(pw, " "); - } + pw.println("Input Dispatcher State:"); + mInputManager.dump(pw); pw.println(" "); synchronized(mWindowMap) { @@ -11995,16 +10110,6 @@ public class WindowManagerService extends IWindowManager.Stub } pw.print(" DisplayWidth="); pw.print(mDisplay.getWidth()); pw.print(" DisplayHeight="); pw.println(mDisplay.getHeight()); - - if (! ENABLE_NATIVE_INPUT_DISPATCH) { - pw.println(" KeyWaiter state:"); - pw.print(" mLastWin="); pw.print(mKeyWaiter.mLastWin); - pw.print(" mLastBinder="); pw.println(mKeyWaiter.mLastBinder); - pw.print(" mFinished="); pw.print(mKeyWaiter.mFinished); - pw.print(" mGotFirstWindow="); pw.print(mKeyWaiter.mGotFirstWindow); - pw.print(" mEventDispatching="); pw.print(mKeyWaiter.mEventDispatching); - pw.print(" mTimeToSwitch="); pw.println(mKeyWaiter.mTimeToSwitch); - } } } @@ -12012,12 +10117,6 @@ public class WindowManagerService extends IWindowManager.Stub public void monitor() { synchronized (mWindowMap) { } synchronized (mKeyguardTokenWatcher) { } - synchronized (mKeyWaiter) { } - synchronized (mInputMonitor) { } - } - - public void virtualKeyFeedback(KeyEvent event) { - mPolicy.keyFeedbackFromInput(event); } /** diff --git a/services/jni/Android.mk b/services/jni/Android.mk index 499ca86..0cf36b3 100644 --- a/services/jni/Android.mk +++ b/services/jni/Android.mk @@ -4,9 +4,9 @@ include $(CLEAR_VARS) LOCAL_SRC_FILES:= \ com_android_server_AlarmManagerService.cpp \ com_android_server_BatteryService.cpp \ - com_android_server_KeyInputQueue.cpp \ com_android_server_InputManager.cpp \ com_android_server_LightsService.cpp \ + com_android_server_PowerManagerService.cpp \ com_android_server_SensorService.cpp \ com_android_server_SystemServer.cpp \ com_android_server_VibratorService.cpp \ diff --git a/services/jni/com_android_server_InputManager.cpp b/services/jni/com_android_server_InputManager.cpp index d0f856b..fc901f4 100644 --- a/services/jni/com_android_server_InputManager.cpp +++ b/services/jni/com_android_server_InputManager.cpp @@ -40,6 +40,7 @@ #include "../../core/jni/android_view_KeyEvent.h" #include "../../core/jni/android_view_MotionEvent.h" #include "../../core/jni/android_view_InputChannel.h" +#include "com_android_server_PowerManagerService.h" namespace android { @@ -107,16 +108,6 @@ enum { LAST_SYSTEM_WINDOW = 2999, }; -enum { - POWER_MANAGER_OTHER_EVENT = 0, - POWER_MANAGER_CHEEK_EVENT = 1, - POWER_MANAGER_TOUCH_EVENT = 2, // touch events are TOUCH for 300ms, and then either - // up events or LONG_TOUCH events. - POWER_MANAGER_LONG_TOUCH_EVENT = 3, - POWER_MANAGER_TOUCH_UP_EVENT = 4, - POWER_MANAGER_BUTTON_EVENT = 5, // Button and trackball events. -}; - // Delay between reporting long touch events to the power manager. const nsecs_t EVENT_IGNORE_DURATION = 300 * 1000000LL; // 300 ms @@ -133,20 +124,16 @@ const nsecs_t MIN_INPUT_DISPATCHING_TIMEOUT = 1000 * 1000000LL; // 1 sec static struct { jclass clazz; - jmethodID isScreenOn; - jmethodID isScreenBright; jmethodID notifyConfigurationChanged; jmethodID notifyLidSwitchChanged; jmethodID notifyInputChannelBroken; jmethodID notifyInputChannelANR; jmethodID notifyInputChannelRecoveredFromANR; jmethodID notifyANR; - jmethodID virtualKeyFeedback; + jmethodID virtualKeyDownFeedback; jmethodID interceptKeyBeforeQueueing; jmethodID interceptKeyBeforeDispatching; jmethodID checkInjectEventsPermission; - jmethodID goToSleep; - jmethodID pokeUserActivity; jmethodID notifyAppSwitchComing; jmethodID filterTouchEvents; jmethodID filterJumpyTouchEvents; @@ -228,9 +215,7 @@ public: virtual bool getDisplayInfo(int32_t displayId, int32_t* width, int32_t* height, int32_t* orientation); - virtual void virtualKeyFeedback(nsecs_t when, int32_t deviceId, - int32_t action, int32_t flags, int32_t keyCode, - int32_t scanCode, int32_t metaState, nsecs_t downTime); + virtual void virtualKeyDownFeedback(); virtual int32_t interceptKey(nsecs_t when, int32_t deviceId, bool down, int32_t keyCode, int32_t scanCode, uint32_t policyFlags); virtual int32_t interceptTrackball(nsecs_t when, bool buttonChanged, bool buttonDown, @@ -321,7 +306,7 @@ private: int32_t mDisplayWidth, mDisplayHeight; int32_t mDisplayOrientation; - // Callbacks. + // Power manager interactions. bool isScreenOn(); bool isScreenBright(); @@ -369,9 +354,9 @@ private: void releaseTouchedWindowLd(); - int32_t identifyTrackballEventTargets(MotionEvent* motionEvent, uint32_t policyFlags, + int32_t waitForTrackballEventTargets(MotionEvent* motionEvent, uint32_t policyFlags, int32_t injectorPid, int32_t injectorUid, Vector<InputTarget>& outTargets); - int32_t identifyTouchEventTargets(MotionEvent* motionEvent, uint32_t policyFlags, + int32_t waitForTouchEventTargets(MotionEvent* motionEvent, uint32_t policyFlags, int32_t injectorPid, int32_t injectorUid, Vector<InputTarget>& outTargets); bool interceptKeyBeforeDispatching(const InputTarget& target, @@ -391,6 +376,7 @@ private: } static bool isAppSwitchKey(int32_t keyCode); + static bool isPolicyKey(int32_t keyCode, bool isScreenOn); static bool checkAndClearExceptionFromCallback(JNIEnv* env, const char* methodName); }; @@ -422,6 +408,36 @@ bool NativeInputManager::isAppSwitchKey(int32_t keyCode) { return keyCode == KEYCODE_HOME || keyCode == KEYCODE_ENDCALL; } +bool NativeInputManager::isPolicyKey(int32_t keyCode, bool isScreenOn) { + // Special keys that the WindowManagerPolicy might care about. + switch (keyCode) { + case KEYCODE_VOLUME_UP: + case KEYCODE_VOLUME_DOWN: + case KEYCODE_ENDCALL: + case KEYCODE_POWER: + case KEYCODE_CALL: + case KEYCODE_HOME: + case KEYCODE_MENU: + case KEYCODE_SEARCH: + // media keys + case KEYCODE_HEADSETHOOK: + case KEYCODE_MEDIA_PLAY_PAUSE: + case KEYCODE_MEDIA_STOP: + case KEYCODE_MEDIA_NEXT: + case KEYCODE_MEDIA_PREVIOUS: + case KEYCODE_MEDIA_REWIND: + case KEYCODE_MEDIA_FAST_FORWARD: + return true; + default: + // We need to pass all keys to the policy in the following cases: + // - screen is off + // - keyguard is visible + // - policy is performing key chording + //return ! isScreenOn || keyguardVisible || chording; + return true; // XXX stubbed out for now + } +} + bool NativeInputManager::checkAndClearExceptionFromCallback(JNIEnv* env, const char* methodName) { if (env->ExceptionCheck()) { LOGE("An exception was thrown by callback '%s'.", methodName); @@ -546,39 +562,22 @@ bool NativeInputManager::getDisplayInfo(int32_t displayId, } bool NativeInputManager::isScreenOn() { - JNIEnv* env = jniEnv(); - - jboolean result = env->CallBooleanMethod(mCallbacksObj, gCallbacksClassInfo.isScreenOn); - if (checkAndClearExceptionFromCallback(env, "isScreenOn")) { - return true; - } - return result; + return android_server_PowerManagerService_isScreenOn(); } bool NativeInputManager::isScreenBright() { - JNIEnv* env = jniEnv(); - - jboolean result = env->CallBooleanMethod(mCallbacksObj, gCallbacksClassInfo.isScreenBright); - if (checkAndClearExceptionFromCallback(env, "isScreenBright")) { - return true; - } - return result; + return android_server_PowerManagerService_isScreenBright(); } -void NativeInputManager::virtualKeyFeedback(nsecs_t when, int32_t deviceId, - int32_t action, int32_t flags, int32_t keyCode, - int32_t scanCode, int32_t metaState, nsecs_t downTime) { +void NativeInputManager::virtualKeyDownFeedback() { #if DEBUG_INPUT_READER_POLICY - LOGD("virtualKeyFeedback - when=%lld, deviceId=%d, action=%d, flags=%d, keyCode=%d, " - "scanCode=%d, metaState=%d, downTime=%lld", - when, deviceId, action, flags, keyCode, scanCode, metaState, downTime); + LOGD("virtualKeyDownFeedback"); #endif JNIEnv* env = jniEnv(); - env->CallVoidMethod(mCallbacksObj, gCallbacksClassInfo.virtualKeyFeedback, - when, deviceId, action, flags, keyCode, scanCode, metaState, downTime); - checkAndClearExceptionFromCallback(env, "virtualKeyFeedback"); + env->CallVoidMethod(mCallbacksObj, gCallbacksClassInfo.virtualKeyDownFeedback); + checkAndClearExceptionFromCallback(env, "virtualKeyDownFeedback"); } int32_t NativeInputManager::interceptKey(nsecs_t when, @@ -593,16 +592,21 @@ int32_t NativeInputManager::interceptKey(nsecs_t when, const int32_t WM_ACTION_POKE_USER_ACTIVITY = 2; const int32_t WM_ACTION_GO_TO_SLEEP = 4; - JNIEnv* env = jniEnv(); - bool isScreenOn = this->isScreenOn(); bool isScreenBright = this->isScreenBright(); - jint wmActions = env->CallIntMethod(mCallbacksObj, - gCallbacksClassInfo.interceptKeyBeforeQueueing, - deviceId, EV_KEY, scanCode, keyCode, policyFlags, down ? 1 : 0, when, isScreenOn); - if (checkAndClearExceptionFromCallback(env, "interceptKeyBeforeQueueing")) { - wmActions = 0; + jint wmActions = 0; + if (isPolicyKey(keyCode, isScreenOn)) { + JNIEnv* env = jniEnv(); + + wmActions = env->CallIntMethod(mCallbacksObj, + gCallbacksClassInfo.interceptKeyBeforeQueueing, + when, keyCode, down, policyFlags, isScreenOn); + if (checkAndClearExceptionFromCallback(env, "interceptKeyBeforeQueueing")) { + wmActions = 0; + } + } else { + wmActions = WM_ACTION_PASS_TO_USER; } int32_t actions = InputReaderPolicyInterface::ACTION_NONE; @@ -617,8 +621,7 @@ int32_t NativeInputManager::interceptKey(nsecs_t when, } if (wmActions & WM_ACTION_GO_TO_SLEEP) { - env->CallVoidMethod(mCallbacksObj, gCallbacksClassInfo.goToSleep, when); - checkAndClearExceptionFromCallback(env, "goToSleep"); + android_server_PowerManagerService_goToSleep(when); } if (wmActions & WM_ACTION_POKE_USER_ACTIVITY) { @@ -629,6 +632,8 @@ int32_t NativeInputManager::interceptKey(nsecs_t when, actions |= InputReaderPolicyInterface::ACTION_DISPATCH; if (down && isAppSwitchKey(keyCode)) { + JNIEnv* env = jniEnv(); + env->CallVoidMethod(mCallbacksObj, gCallbacksClassInfo.notifyAppSwitchComing); checkAndClearExceptionFromCallback(env, "notifyAppSwitchComing"); @@ -1531,11 +1536,13 @@ int32_t NativeInputManager::waitForKeyEventTargets(KeyEvent* keyEvent, uint32_t windowType = focusedWindow->layoutParamsType; } // release lock - const InputTarget& target = outTargets.top(); - bool consumed = interceptKeyBeforeDispatching(target, keyEvent, policyFlags); - if (consumed) { - outTargets.clear(); - return INPUT_EVENT_INJECTION_SUCCEEDED; + if (isPolicyKey(keyEvent->getKeyCode(), isScreenOn())) { + const InputTarget& target = outTargets.top(); + bool consumed = interceptKeyBeforeDispatching(target, keyEvent, policyFlags); + if (consumed) { + outTargets.clear(); + return INPUT_EVENT_INJECTION_SUCCEEDED; + } } pokeUserActivityIfNeeded(windowType, POWER_MANAGER_BUTTON_EVENT); @@ -1552,11 +1559,11 @@ int32_t NativeInputManager::waitForMotionEventTargets(MotionEvent* motionEvent, switch (motionEvent->getNature()) { case INPUT_EVENT_NATURE_TRACKBALL: - return identifyTrackballEventTargets(motionEvent, policyFlags, injectorPid, injectorUid, + return waitForTrackballEventTargets(motionEvent, policyFlags, injectorPid, injectorUid, outTargets); case INPUT_EVENT_NATURE_TOUCH: - return identifyTouchEventTargets(motionEvent, policyFlags, injectorPid, injectorUid, + return waitForTouchEventTargets(motionEvent, policyFlags, injectorPid, injectorUid, outTargets); default: @@ -1565,11 +1572,11 @@ int32_t NativeInputManager::waitForMotionEventTargets(MotionEvent* motionEvent, } } -int32_t NativeInputManager::identifyTrackballEventTargets(MotionEvent* motionEvent, +int32_t NativeInputManager::waitForTrackballEventTargets(MotionEvent* motionEvent, uint32_t policyFlags, int32_t injectorPid, int32_t injectorUid, Vector<InputTarget>& outTargets) { #if DEBUG_INPUT_DISPATCHER_POLICY - LOGD("identifyTrackballEventTargets - policyFlags=%d, injectorPid=%d, injectorUid=%d", + LOGD("waitForTrackballEventTargets - policyFlags=%d, injectorPid=%d, injectorUid=%d", policyFlags, injectorPid, injectorUid); #endif @@ -1591,11 +1598,11 @@ int32_t NativeInputManager::identifyTrackballEventTargets(MotionEvent* motionEve return INPUT_EVENT_INJECTION_SUCCEEDED; } -int32_t NativeInputManager::identifyTouchEventTargets(MotionEvent* motionEvent, +int32_t NativeInputManager::waitForTouchEventTargets(MotionEvent* motionEvent, uint32_t policyFlags, int32_t injectorPid, int32_t injectorUid, Vector<InputTarget>& outTargets) { #if DEBUG_INPUT_DISPATCHER_POLICY - LOGD("identifyTouchEventTargets - policyFlags=%d, injectorPid=%d, injectorUid=%d", + LOGD("waitForTouchEventTargets - policyFlags=%d, injectorPid=%d, injectorUid=%d", policyFlags, injectorPid, injectorUid); #endif @@ -1642,8 +1649,8 @@ bool NativeInputManager::interceptKeyBeforeDispatching(const InputTarget& target if (inputChannelObj) { jboolean consumed = env->CallBooleanMethod(mCallbacksObj, gCallbacksClassInfo.interceptKeyBeforeDispatching, - inputChannelObj, keyEvent->getKeyCode(), keyEvent->getMetaState(), - keyEvent->getAction() == KEY_EVENT_ACTION_DOWN, + inputChannelObj, keyEvent->getAction(), keyEvent->getFlags(), + keyEvent->getKeyCode(), keyEvent->getMetaState(), keyEvent->getRepeatCount(), policyFlags); bool error = checkAndClearExceptionFromCallback(env, "interceptKeyBeforeDispatching"); @@ -1665,10 +1672,7 @@ void NativeInputManager::pokeUserActivityIfNeeded(int32_t windowType, int32_t ev } void NativeInputManager::pokeUserActivity(nsecs_t eventTime, int32_t eventType) { - JNIEnv* env = jniEnv(); - env->CallVoidMethod(mCallbacksObj, gCallbacksClassInfo.pokeUserActivity, - eventTime, eventType); - checkAndClearExceptionFromCallback(env, "pokeUserActivity"); + android_server_PowerManagerService_userActivity(eventTime, eventType); } void NativeInputManager::dumpDispatchStateLd() { @@ -2082,12 +2086,6 @@ int register_android_server_InputManager(JNIEnv* env) { FIND_CLASS(gCallbacksClassInfo.clazz, "com/android/server/InputManager$Callbacks"); - GET_METHOD_ID(gCallbacksClassInfo.isScreenOn, gCallbacksClassInfo.clazz, - "isScreenOn", "()Z"); - - GET_METHOD_ID(gCallbacksClassInfo.isScreenBright, gCallbacksClassInfo.clazz, - "isScreenBright", "()Z"); - GET_METHOD_ID(gCallbacksClassInfo.notifyConfigurationChanged, gCallbacksClassInfo.clazz, "notifyConfigurationChanged", "(JIII)V"); @@ -2106,24 +2104,18 @@ int register_android_server_InputManager(JNIEnv* env) { GET_METHOD_ID(gCallbacksClassInfo.notifyANR, gCallbacksClassInfo.clazz, "notifyANR", "(Ljava/lang/Object;)J"); - GET_METHOD_ID(gCallbacksClassInfo.virtualKeyFeedback, gCallbacksClassInfo.clazz, - "virtualKeyFeedback", "(JIIIIIIJ)V"); + GET_METHOD_ID(gCallbacksClassInfo.virtualKeyDownFeedback, gCallbacksClassInfo.clazz, + "virtualKeyDownFeedback", "()V"); GET_METHOD_ID(gCallbacksClassInfo.interceptKeyBeforeQueueing, gCallbacksClassInfo.clazz, - "interceptKeyBeforeQueueing", "(IIIIIIJZ)I"); + "interceptKeyBeforeQueueing", "(JIZIZ)I"); GET_METHOD_ID(gCallbacksClassInfo.interceptKeyBeforeDispatching, gCallbacksClassInfo.clazz, - "interceptKeyBeforeDispatching", "(Landroid/view/InputChannel;IIZII)Z"); + "interceptKeyBeforeDispatching", "(Landroid/view/InputChannel;IIIIII)Z"); GET_METHOD_ID(gCallbacksClassInfo.checkInjectEventsPermission, gCallbacksClassInfo.clazz, "checkInjectEventsPermission", "(II)Z"); - GET_METHOD_ID(gCallbacksClassInfo.goToSleep, gCallbacksClassInfo.clazz, - "goToSleep", "(J)V"); - - GET_METHOD_ID(gCallbacksClassInfo.pokeUserActivity, gCallbacksClassInfo.clazz, - "pokeUserActivity", "(JI)V"); - GET_METHOD_ID(gCallbacksClassInfo.notifyAppSwitchComing, gCallbacksClassInfo.clazz, "notifyAppSwitchComing", "()V"); diff --git a/services/jni/com_android_server_KeyInputQueue.cpp b/services/jni/com_android_server_KeyInputQueue.cpp deleted file mode 100644 index f9e3585..0000000 --- a/services/jni/com_android_server_KeyInputQueue.cpp +++ /dev/null @@ -1,358 +0,0 @@ -/* - * Copyright (C) 2007 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 "Input" - -#include "jni.h" -#include "JNIHelp.h" -#include <utils/misc.h> -#include <utils/Log.h> - -#include <ui/EventHub.h> -#include <utils/threads.h> - -#include <stdio.h> - -namespace android { - -// ---------------------------------------------------------------------------- - -static struct input_offsets_t -{ - jfieldID mMinValue; - jfieldID mMaxValue; - jfieldID mFlat; - jfieldID mFuzz; - - jfieldID mDeviceId; - jfieldID mType; - jfieldID mScancode; - jfieldID mKeycode; - jfieldID mFlags; - jfieldID mValue; - jfieldID mWhen; -} gInputOffsets; - -// ---------------------------------------------------------------------------- - -static Mutex gLock; -static sp<EventHub> gHub; - -static jboolean -android_server_KeyInputQueue_readEvent(JNIEnv* env, jobject clazz, - jobject event) -{ - gLock.lock(); - sp<EventHub> hub = gHub; - if (hub == NULL) { - hub = new EventHub; - gHub = hub; - } - gLock.unlock(); - - int32_t deviceId; - int32_t type; - int32_t scancode, keycode; - uint32_t flags; - int32_t value; - nsecs_t when; - bool res = hub->getEvent(&deviceId, &type, &scancode, &keycode, - &flags, &value, &when); - - env->SetIntField(event, gInputOffsets.mDeviceId, (jint)deviceId); - env->SetIntField(event, gInputOffsets.mType, (jint)type); - env->SetIntField(event, gInputOffsets.mScancode, (jint)scancode); - env->SetIntField(event, gInputOffsets.mKeycode, (jint)keycode); - env->SetIntField(event, gInputOffsets.mFlags, (jint)flags); - env->SetIntField(event, gInputOffsets.mValue, value); - env->SetLongField(event, gInputOffsets.mWhen, - (jlong)(nanoseconds_to_milliseconds(when))); - - return res; -} - -static jint -android_server_KeyInputQueue_getDeviceClasses(JNIEnv* env, jobject clazz, - jint deviceId) -{ - jint classes = 0; - gLock.lock(); - if (gHub != NULL) classes = gHub->getDeviceClasses(deviceId); - gLock.unlock(); - return classes; -} - -static jstring -android_server_KeyInputQueue_getDeviceName(JNIEnv* env, jobject clazz, - jint deviceId) -{ - String8 name; - gLock.lock(); - if (gHub != NULL) name = gHub->getDeviceName(deviceId); - gLock.unlock(); - - if (name.size() > 0) { - return env->NewStringUTF(name.string()); - } - return NULL; -} - -static void -android_server_KeyInputQueue_addExcludedDevice(JNIEnv* env, jobject clazz, - jstring deviceName) -{ - gLock.lock(); - sp<EventHub> hub = gHub; - if (hub == NULL) { - hub = new EventHub; - gHub = hub; - } - gLock.unlock(); - - const char* nameStr = env->GetStringUTFChars(deviceName, NULL); - gHub->addExcludedDevice(nameStr); - env->ReleaseStringUTFChars(deviceName, nameStr); -} - -static jboolean -android_server_KeyInputQueue_getAbsoluteInfo(JNIEnv* env, jobject clazz, - jint deviceId, jint axis, - jobject info) -{ - int32_t minValue, maxValue, flat, fuzz; - int res = -1; - gLock.lock(); - if (gHub != NULL) { - res = gHub->getAbsoluteInfo(deviceId, axis, - &minValue, &maxValue, &flat, &fuzz); - } - gLock.unlock(); - - if (res < 0) return JNI_FALSE; - - env->SetIntField(info, gInputOffsets.mMinValue, (jint)minValue); - env->SetIntField(info, gInputOffsets.mMaxValue, (jint)maxValue); - env->SetIntField(info, gInputOffsets.mFlat, (jint)flat); - env->SetIntField(info, gInputOffsets.mFuzz, (jint)fuzz); - return JNI_TRUE; -} - -static jint -android_server_KeyInputQueue_getSwitchState(JNIEnv* env, jobject clazz, - jint sw) -{ - jint st = -1; - gLock.lock(); - if (gHub != NULL) st = gHub->getSwitchState(-1, -1, sw); - gLock.unlock(); - - return st; -} - -static jint -android_server_KeyInputQueue_getSwitchStateDevice(JNIEnv* env, jobject clazz, - jint deviceId, jint sw) -{ - jint st = -1; - gLock.lock(); - if (gHub != NULL) st = gHub->getSwitchState(deviceId, -1, sw); - gLock.unlock(); - - return st; -} - -static jint -android_server_KeyInputQueue_getScancodeState(JNIEnv* env, jobject clazz, - jint sw) -{ - jint st = -1; - gLock.lock(); - if (gHub != NULL) st = gHub->getScanCodeState(0, -1, sw); - gLock.unlock(); - - return st; -} - -static jint -android_server_KeyInputQueue_getScancodeStateDevice(JNIEnv* env, jobject clazz, - jint deviceId, jint sw) -{ - jint st = -1; - gLock.lock(); - if (gHub != NULL) st = gHub->getScanCodeState(deviceId, -1, sw); - gLock.unlock(); - - return st; -} - -static jint -android_server_KeyInputQueue_getKeycodeState(JNIEnv* env, jobject clazz, - jint sw) -{ - jint st = -1; - gLock.lock(); - if (gHub != NULL) st = gHub->getKeyCodeState(0, -1, sw); - gLock.unlock(); - - return st; -} - -static jint -android_server_KeyInputQueue_getKeycodeStateDevice(JNIEnv* env, jobject clazz, - jint deviceId, jint sw) -{ - jint st = -1; - gLock.lock(); - if (gHub != NULL) st = gHub->getKeyCodeState(deviceId,-1, sw); - gLock.unlock(); - - 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) -{ - jboolean ret = JNI_FALSE; - - int32_t* codes = env->GetIntArrayElements(keyCodes, NULL); - uint8_t* flags = env->GetBooleanArrayElements(outFlags, NULL); - jsize numCodes = env->GetArrayLength(keyCodes); - if (numCodes == env->GetArrayLength(outFlags)) { - gLock.lock(); - if (gHub != NULL) ret = gHub->hasKeys(numCodes, codes, flags); - gLock.unlock(); - } - - env->ReleaseBooleanArrayElements(outFlags, flags, 0); - env->ReleaseIntArrayElements(keyCodes, codes, 0); - return ret; -} - -// ---------------------------------------------------------------------------- - -/* - * JNI registration. - */ -static JNINativeMethod gInputMethods[] = { - /* name, signature, funcPtr */ - { "readEvent", "(Landroid/view/RawInputEvent;)Z", - (void*) android_server_KeyInputQueue_readEvent }, - { "getDeviceClasses", "(I)I", - (void*) android_server_KeyInputQueue_getDeviceClasses }, - { "getDeviceName", "(I)Ljava/lang/String;", - (void*) android_server_KeyInputQueue_getDeviceName }, - { "addExcludedDevice", "(Ljava/lang/String;)V", - (void*) android_server_KeyInputQueue_addExcludedDevice }, - { "getAbsoluteInfo", "(IILcom/android/server/InputDevice$AbsoluteInfo;)Z", - (void*) android_server_KeyInputQueue_getAbsoluteInfo }, - { "getSwitchState", "(I)I", - (void*) android_server_KeyInputQueue_getSwitchState }, - { "getSwitchState", "(II)I", - (void*) android_server_KeyInputQueue_getSwitchStateDevice }, - { "nativeGetScancodeState", "(I)I", - (void*) android_server_KeyInputQueue_getScancodeState }, - { "nativeGetScancodeState", "(II)I", - (void*) android_server_KeyInputQueue_getScancodeStateDevice }, - { "nativeGetKeycodeState", "(I)I", - (void*) android_server_KeyInputQueue_getKeycodeState }, - { "nativeGetKeycodeState", "(II)I", - (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) -{ - jclass input = env->FindClass("com/android/server/KeyInputQueue"); - LOG_FATAL_IF(input == NULL, "Unable to find class com/android/server/KeyInputQueue"); - int res = jniRegisterNativeMethods(env, "com/android/server/KeyInputQueue", - gInputMethods, NELEM(gInputMethods)); - - jclass absoluteInfo = env->FindClass("com/android/server/InputDevice$AbsoluteInfo"); - LOG_FATAL_IF(absoluteInfo == NULL, "Unable to find class com/android/server/InputDevice$AbsoluteInfo"); - - gInputOffsets.mMinValue - = env->GetFieldID(absoluteInfo, "minValue", "I"); - LOG_FATAL_IF(gInputOffsets.mMinValue == NULL, "Unable to find InputDevice.AbsoluteInfo.minValue"); - - gInputOffsets.mMaxValue - = env->GetFieldID(absoluteInfo, "maxValue", "I"); - LOG_FATAL_IF(gInputOffsets.mMaxValue == NULL, "Unable to find InputDevice.AbsoluteInfo.maxValue"); - - gInputOffsets.mFlat - = env->GetFieldID(absoluteInfo, "flat", "I"); - LOG_FATAL_IF(gInputOffsets.mFlat == NULL, "Unable to find InputDevice.AbsoluteInfo.flat"); - - gInputOffsets.mFuzz - = env->GetFieldID(absoluteInfo, "fuzz", "I"); - LOG_FATAL_IF(gInputOffsets.mFuzz == NULL, "Unable to find InputDevice.AbsoluteInfo.fuzz"); - - jclass inputEvent = env->FindClass("android/view/RawInputEvent"); - LOG_FATAL_IF(inputEvent == NULL, "Unable to find class android/view/RawInputEvent"); - - gInputOffsets.mDeviceId - = env->GetFieldID(inputEvent, "deviceId", "I"); - LOG_FATAL_IF(gInputOffsets.mDeviceId == NULL, "Unable to find RawInputEvent.deviceId"); - - gInputOffsets.mType - = env->GetFieldID(inputEvent, "type", "I"); - LOG_FATAL_IF(gInputOffsets.mType == NULL, "Unable to find RawInputEvent.type"); - - gInputOffsets.mScancode - = env->GetFieldID(inputEvent, "scancode", "I"); - LOG_FATAL_IF(gInputOffsets.mScancode == NULL, "Unable to find RawInputEvent.scancode"); - - gInputOffsets.mKeycode - = env->GetFieldID(inputEvent, "keycode", "I"); - LOG_FATAL_IF(gInputOffsets.mKeycode == NULL, "Unable to find RawInputEvent.keycode"); - - gInputOffsets.mFlags - = env->GetFieldID(inputEvent, "flags", "I"); - LOG_FATAL_IF(gInputOffsets.mFlags == NULL, "Unable to find RawInputEvent.flags"); - - gInputOffsets.mValue - = env->GetFieldID(inputEvent, "value", "I"); - LOG_FATAL_IF(gInputOffsets.mValue == NULL, "Unable to find RawInputEvent.value"); - - gInputOffsets.mWhen - = env->GetFieldID(inputEvent, "when", "J"); - LOG_FATAL_IF(gInputOffsets.mWhen == NULL, "Unable to find RawInputEvent.when"); - - return res; -} - -}; // namespace android - diff --git a/services/jni/com_android_server_PowerManagerService.cpp b/services/jni/com_android_server_PowerManagerService.cpp new file mode 100644 index 0000000..b80dbc5 --- /dev/null +++ b/services/jni/com_android_server_PowerManagerService.cpp @@ -0,0 +1,142 @@ +/* + * 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 "PowerManagerService-JNI" + +//#define LOG_NDEBUG 0 + +#include "JNIHelp.h" +#include "jni.h" +#include <limits.h> +#include <android_runtime/AndroidRuntime.h> +#include "com_android_server_PowerManagerService.h" + +namespace android { + +// ---------------------------------------------------------------------------- + +static struct { + jclass clazz; + + jmethodID goToSleep; + jmethodID userActivity; +} gPowerManagerServiceClassInfo; + +// ---------------------------------------------------------------------------- + +static jobject gPowerManagerServiceObj; + +static Mutex gPowerManagerLock; +static bool gScreenOn; +static bool gScreenBright; + +// ---------------------------------------------------------------------------- + +static bool checkAndClearExceptionFromCallback(JNIEnv* env, const char* methodName) { + if (env->ExceptionCheck()) { + LOGE("An exception was thrown by callback '%s'.", methodName); + LOGE_EX(env); + env->ExceptionClear(); + return true; + } + return false; +} + +bool android_server_PowerManagerService_isScreenOn() { + AutoMutex _l(gPowerManagerLock); + return gScreenOn; +} + +bool android_server_PowerManagerService_isScreenBright() { + AutoMutex _l(gPowerManagerLock); + return gScreenBright; +} + +void android_server_PowerManagerService_userActivity(nsecs_t eventTime, int32_t eventType) { + if (gPowerManagerServiceObj) { + JNIEnv* env = AndroidRuntime::getJNIEnv(); + + env->CallVoidMethod(gPowerManagerServiceObj, gPowerManagerServiceClassInfo.userActivity, + nanoseconds_to_milliseconds(eventTime), false, eventType, false); + checkAndClearExceptionFromCallback(env, "userActivity"); + } +} + +void android_server_PowerManagerService_goToSleep(nsecs_t eventTime) { + if (gPowerManagerServiceObj) { + JNIEnv* env = AndroidRuntime::getJNIEnv(); + + env->CallVoidMethod(gPowerManagerServiceObj, gPowerManagerServiceClassInfo.goToSleep, + nanoseconds_to_milliseconds(eventTime)); + checkAndClearExceptionFromCallback(env, "goToSleep"); + } +} + +// ---------------------------------------------------------------------------- + +static void android_server_PowerManagerService_nativeInit(JNIEnv* env, jobject obj) { + gPowerManagerServiceObj = env->NewGlobalRef(obj); +} + +static void android_server_PowerManagerService_nativeSetPowerState(JNIEnv* env, + jobject serviceObj, jboolean screenOn, jboolean screenBright) { + AutoMutex _l(gPowerManagerLock); + gScreenOn = screenOn; + gScreenBright = screenBright; +} + +// ---------------------------------------------------------------------------- + +static JNINativeMethod gPowerManagerServiceMethods[] = { + /* name, signature, funcPtr */ + { "nativeInit", "()V", + (void*) android_server_PowerManagerService_nativeInit }, + { "nativeSetPowerState", "(ZZ)V", + (void*) android_server_PowerManagerService_nativeSetPowerState }, +}; + +#define FIND_CLASS(var, className) \ + var = env->FindClass(className); \ + LOG_FATAL_IF(! var, "Unable to find class " className); \ + var = jclass(env->NewGlobalRef(var)); + +#define GET_METHOD_ID(var, clazz, methodName, methodDescriptor) \ + var = env->GetMethodID(clazz, methodName, methodDescriptor); \ + LOG_FATAL_IF(! var, "Unable to find method " methodName); + +#define GET_FIELD_ID(var, clazz, fieldName, fieldDescriptor) \ + var = env->GetFieldID(clazz, fieldName, fieldDescriptor); \ + LOG_FATAL_IF(! var, "Unable to find field " fieldName); + +int register_android_server_PowerManagerService(JNIEnv* env) { + int res = jniRegisterNativeMethods(env, "com/android/server/PowerManagerService", + gPowerManagerServiceMethods, NELEM(gPowerManagerServiceMethods)); + LOG_FATAL_IF(res < 0, "Unable to register native methods."); + + // Callbacks + + FIND_CLASS(gPowerManagerServiceClassInfo.clazz, "com/android/server/PowerManagerService"); + + GET_METHOD_ID(gPowerManagerServiceClassInfo.goToSleep, gPowerManagerServiceClassInfo.clazz, + "goToSleep", "(J)V"); + + GET_METHOD_ID(gPowerManagerServiceClassInfo.userActivity, gPowerManagerServiceClassInfo.clazz, + "userActivity", "(JZIZ)V"); + + return 0; +} + +} /* namespace android */ diff --git a/services/jni/com_android_server_PowerManagerService.h b/services/jni/com_android_server_PowerManagerService.h new file mode 100644 index 0000000..9b05f38 --- /dev/null +++ b/services/jni/com_android_server_PowerManagerService.h @@ -0,0 +1,42 @@ +/* + * 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. + */ + +#ifndef _ANDROID_SERVER_POWER_MANAGER_SERVICE_H +#define _ANDROID_SERVER_POWER_MANAGER_SERVICE_H + +#include "JNIHelp.h" +#include "jni.h" + +namespace android { + +enum { + POWER_MANAGER_OTHER_EVENT = 0, + POWER_MANAGER_CHEEK_EVENT = 1, + POWER_MANAGER_TOUCH_EVENT = 2, // touch events are TOUCH for 300ms, and then either + // up events or LONG_TOUCH events. + POWER_MANAGER_LONG_TOUCH_EVENT = 3, + POWER_MANAGER_TOUCH_UP_EVENT = 4, + POWER_MANAGER_BUTTON_EVENT = 5, // Button and trackball events. +}; + +extern bool android_server_PowerManagerService_isScreenOn(); +extern bool android_server_PowerManagerService_isScreenBright(); +extern void android_server_PowerManagerService_userActivity(nsecs_t eventTime, int32_t eventType); +extern void android_server_PowerManagerService_goToSleep(nsecs_t eventTime); + +} // namespace android + +#endif // _ANDROID_SERVER_POWER_MANAGER_SERVICE_H diff --git a/services/jni/onload.cpp b/services/jni/onload.cpp index a1a6838..1a2d8b6 100644 --- a/services/jni/onload.cpp +++ b/services/jni/onload.cpp @@ -6,9 +6,9 @@ namespace android { int register_android_server_AlarmManagerService(JNIEnv* env); int register_android_server_BatteryService(JNIEnv* env); -int register_android_server_KeyInputQueue(JNIEnv* env); int register_android_server_InputManager(JNIEnv* env); int register_android_server_LightsService(JNIEnv* env); +int register_android_server_PowerManagerService(JNIEnv* env); int register_android_server_SensorService(JNIEnv* env); int register_android_server_VibratorService(JNIEnv* env); int register_android_server_SystemServer(JNIEnv* env); @@ -28,7 +28,7 @@ extern "C" jint JNI_OnLoad(JavaVM* vm, void* reserved) } LOG_ASSERT(env, "Could not retrieve the env!"); - register_android_server_KeyInputQueue(env); + register_android_server_PowerManagerService(env); register_android_server_InputManager(env); register_android_server_LightsService(env); register_android_server_AlarmManagerService(env); |