am 8d60866e: Input device calibration and capabilities.

Merge commit '8d60866e2100db70ecf0502c14768a384514d7e9' into gingerbread-plus-aosp

* commit '8d60866e2100db70ecf0502c14768a384514d7e9':
  Input device calibration and capabilities.
This commit is contained in:
Jeff Brown
2010-08-30 18:22:32 -07:00
committed by Android Git Automerger
15 changed files with 1775 additions and 431 deletions

View File

@@ -177208,14 +177208,19 @@
deprecated="not deprecated"
visibility="public"
>
<constructor name="InputDevice"
type="android.view.InputDevice"
<implements name="android.os.Parcelable">
</implements>
<method name="describeContents"
return="int"
abstract="false"
native="false"
synchronized="false"
static="false"
final="false"
deprecated="not deprecated"
visibility="public"
>
</constructor>
</method>
<method name="getDevice"
return="android.view.InputDevice"
abstract="false"
@@ -177229,6 +177234,28 @@
<parameter name="id" type="int">
</parameter>
</method>
<method name="getDeviceIds"
return="int[]"
abstract="false"
native="false"
synchronized="false"
static="true"
final="false"
deprecated="not deprecated"
visibility="public"
>
</method>
<method name="getId"
return="int"
abstract="false"
native="false"
synchronized="false"
static="false"
final="false"
deprecated="not deprecated"
visibility="public"
>
</method>
<method name="getKeyCharacterMap"
return="android.view.KeyCharacterMap"
abstract="false"
@@ -177261,7 +177288,7 @@
deprecated="not deprecated"
visibility="public"
>
<parameter name="range" type="int">
<parameter name="rangeType" type="int">
</parameter>
</method>
<method name="getName"
@@ -177286,8 +177313,8 @@
visibility="public"
>
</method>
<method name="hasKey"
return="boolean"
<method name="writeToParcel"
return="void"
abstract="false"
native="false"
synchronized="false"
@@ -177296,9 +177323,21 @@
deprecated="not deprecated"
visibility="public"
>
<parameter name="keyCode" type="int">
<parameter name="out" type="android.os.Parcel">
</parameter>
<parameter name="flags" type="int">
</parameter>
</method>
<field name="CREATOR"
type="android.os.Parcelable.Creator"
transient="false"
volatile="false"
static="true"
final="true"
deprecated="not deprecated"
visibility="public"
>
</field>
<field name="KEYBOARD_TYPE_ALPHABETIC"
type="int"
transient="false"
@@ -177627,14 +177666,6 @@
deprecated="not deprecated"
visibility="public"
>
<constructor name="InputDevice.MotionRange"
type="android.view.InputDevice.MotionRange"
static="false"
final="false"
deprecated="not deprecated"
visibility="public"
>
</constructor>
<method name="getFlat"
return="float"
abstract="false"

View File

@@ -29,6 +29,7 @@ import android.view.KeyEvent;
import android.view.InputEvent;
import android.view.MotionEvent;
import android.view.InputChannel;
import android.view.InputDevice;
/**
* System private interface to the window manager.
@@ -125,6 +126,10 @@ interface IWindowManager
// Report whether the hardware supports the given keys; returns true if successful
boolean hasKeys(in int[] keycodes, inout boolean[] keyExists);
// Get input device information.
InputDevice getInputDevice(int deviceId);
int[] getInputDeviceIds();
// For testing
void setInTouchMode(boolean showFocus);

View File

@@ -0,0 +1,20 @@
/* //device/java/android/android.view.InputDevice.aidl
**
** Copyright 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 android.view;
parcelable InputDevice;

View File

@@ -16,6 +16,12 @@
package android.view;
import android.os.Parcel;
import android.os.Parcelable;
import android.os.RemoteException;
import android.os.ServiceManager;
import android.util.Log;
/**
* Describes the capabilities of a particular input device.
* <p>
@@ -32,12 +38,14 @@ package android.view;
* the appropriate interpretation.
* </p>
*/
public final class InputDevice {
public final class InputDevice implements Parcelable {
private int mId;
private String mName;
private int mSources;
private int mKeyboardType;
private MotionRange[] mMotionRanges;
/**
* A mask for input source classes.
*
@@ -246,6 +254,8 @@ public final class InputDevice {
*/
public static final int MOTION_RANGE_ORIENTATION = 8;
private static final int MOTION_RANGE_LAST = MOTION_RANGE_ORIENTATION;
/**
* There is no keyboard.
*/
@@ -261,6 +271,11 @@ public final class InputDevice {
* The keyboard supports a complement of alphabetic keys.
*/
public static final int KEYBOARD_TYPE_ALPHABETIC = 2;
// Called by native code.
private InputDevice() {
mMotionRanges = new MotionRange[MOTION_RANGE_LAST + 1];
}
/**
* Gets information about the input device with the specified id.
@@ -268,8 +283,35 @@ public final class InputDevice {
* @return The input device or null if not found.
*/
public static InputDevice getDevice(int id) {
// TODO
return null;
IWindowManager wm = IWindowManager.Stub.asInterface(ServiceManager.getService("window"));
try {
return wm.getInputDevice(id);
} catch (RemoteException ex) {
throw new RuntimeException(
"Could not get input device information from Window Manager.", ex);
}
}
/**
* Gets the ids of all input devices in the system.
* @return The input device ids.
*/
public static int[] getDeviceIds() {
IWindowManager wm = IWindowManager.Stub.asInterface(ServiceManager.getService("window"));
try {
return wm.getInputDeviceIds();
} catch (RemoteException ex) {
throw new RuntimeException(
"Could not get input device ids from Window Manager.", ex);
}
}
/**
* Gets the input device id.
* @return The input device id.
*/
public int getId() {
return mId;
}
/**
@@ -307,23 +349,23 @@ public final class InputDevice {
/**
* Gets information about the range of values for a particular {@link MotionEvent}
* coordinate.
* @param range The motion range constant.
* @param rangeType The motion range constant.
* @return The range of values, or null if the requested coordinate is not
* supported by the device.
*/
public MotionRange getMotionRange(int range) {
// TODO
return null;
public MotionRange getMotionRange(int rangeType) {
if (rangeType < 0 || rangeType > MOTION_RANGE_LAST) {
throw new IllegalArgumentException("Requested range is out of bounds.");
}
return mMotionRanges[rangeType];
}
/**
* Returns true if the device supports a particular button or key.
* @param keyCode The key code.
* @return True if the device supports the key.
*/
public boolean hasKey(int keyCode) {
// TODO
return false;
private void addMotionRange(int rangeType, float min, float max, float flat, float fuzz) {
if (rangeType >= 0 && rangeType <= MOTION_RANGE_LAST) {
MotionRange range = new MotionRange(min, max, flat, fuzz);
mMotionRanges[rangeType] = range;
}
}
/**
@@ -331,13 +373,24 @@ public final class InputDevice {
* coordinate.
*/
public static final class MotionRange {
private float mMin;
private float mMax;
private float mFlat;
private float mFuzz;
private MotionRange(float min, float max, float flat, float fuzz) {
mMin = min;
mMax = max;
mFlat = flat;
mFuzz = fuzz;
}
/**
* Gets the minimum value for the coordinate.
* @return The minimum value.
*/
public float getMin() {
// TODO
return 0;
return mMin;
}
/**
@@ -345,8 +398,7 @@ public final class InputDevice {
* @return The minimum value.
*/
public float getMax() {
// TODO
return 0;
return mMax;
}
/**
@@ -354,8 +406,7 @@ public final class InputDevice {
* @return The range of values.
*/
public float getRange() {
// TODO
return 0;
return mMax - mMin;
}
/**
@@ -365,8 +416,7 @@ public final class InputDevice {
* @return The extent of the center flat position.
*/
public float getFlat() {
// TODO
return 0;
return mFlat;
}
/**
@@ -376,8 +426,127 @@ public final class InputDevice {
* @return The error tolerance.
*/
public float getFuzz() {
// TODO
return 0;
return mFuzz;
}
}
public static final Parcelable.Creator<InputDevice> CREATOR
= new Parcelable.Creator<InputDevice>() {
public InputDevice createFromParcel(Parcel in) {
InputDevice result = new InputDevice();
result.readFromParcel(in);
return result;
}
public InputDevice[] newArray(int size) {
return new InputDevice[size];
}
};
private void readFromParcel(Parcel in) {
mId = in.readInt();
mName = in.readString();
mSources = in.readInt();
mKeyboardType = in.readInt();
for (;;) {
int rangeType = in.readInt();
if (rangeType < 0) {
break;
}
addMotionRange(rangeType,
in.readFloat(), in.readFloat(), in.readFloat(), in.readFloat());
}
}
@Override
public void writeToParcel(Parcel out, int flags) {
out.writeInt(mId);
out.writeString(mName);
out.writeInt(mSources);
out.writeInt(mKeyboardType);
for (int i = 0; i <= MOTION_RANGE_LAST; i++) {
MotionRange range = mMotionRanges[i];
if (range != null) {
out.writeInt(i);
out.writeFloat(range.mMin);
out.writeFloat(range.mMax);
out.writeFloat(range.mFlat);
out.writeFloat(range.mFuzz);
}
}
out.writeInt(-1);
}
@Override
public int describeContents() {
return 0;
}
@Override
public String toString() {
StringBuilder description = new StringBuilder();
description.append("Input Device ").append(mId).append(": ").append(mName).append("\n");
description.append(" Keyboard Type: ");
switch (mKeyboardType) {
case KEYBOARD_TYPE_NONE:
description.append("none");
break;
case KEYBOARD_TYPE_NON_ALPHABETIC:
description.append("non-alphabetic");
break;
case KEYBOARD_TYPE_ALPHABETIC:
description.append("alphabetic");
break;
}
description.append("\n");
description.append(" Sources:");
appendSourceDescriptionIfApplicable(description, SOURCE_KEYBOARD, "keyboard");
appendSourceDescriptionIfApplicable(description, SOURCE_DPAD, "dpad");
appendSourceDescriptionIfApplicable(description, SOURCE_GAMEPAD, "gamepad");
appendSourceDescriptionIfApplicable(description, SOURCE_TOUCHSCREEN, "touchscreen");
appendSourceDescriptionIfApplicable(description, SOURCE_MOUSE, "mouse");
appendSourceDescriptionIfApplicable(description, SOURCE_TRACKBALL, "trackball");
appendSourceDescriptionIfApplicable(description, SOURCE_TOUCHPAD, "touchpad");
appendSourceDescriptionIfApplicable(description, SOURCE_JOYSTICK_LEFT, "joystick_left");
appendSourceDescriptionIfApplicable(description, SOURCE_JOYSTICK_RIGHT, "joystick_right");
description.append("\n");
appendRangeDescriptionIfApplicable(description, MOTION_RANGE_X, "x");
appendRangeDescriptionIfApplicable(description, MOTION_RANGE_Y, "y");
appendRangeDescriptionIfApplicable(description, MOTION_RANGE_PRESSURE, "pressure");
appendRangeDescriptionIfApplicable(description, MOTION_RANGE_SIZE, "size");
appendRangeDescriptionIfApplicable(description, MOTION_RANGE_TOUCH_MAJOR, "touchMajor");
appendRangeDescriptionIfApplicable(description, MOTION_RANGE_TOUCH_MINOR, "touchMinor");
appendRangeDescriptionIfApplicable(description, MOTION_RANGE_TOOL_MAJOR, "toolMajor");
appendRangeDescriptionIfApplicable(description, MOTION_RANGE_TOOL_MINOR, "toolMinor");
appendRangeDescriptionIfApplicable(description, MOTION_RANGE_ORIENTATION, "orientation");
return description.toString();
}
private void appendSourceDescriptionIfApplicable(StringBuilder description, int source,
String sourceName) {
if ((mSources & source) == source) {
description.append(" ");
description.append(sourceName);
}
}
private void appendRangeDescriptionIfApplicable(StringBuilder description,
int rangeType, String rangeName) {
MotionRange range = mMotionRanges[rangeType];
if (range != null) {
description.append(" Range[").append(rangeName);
description.append("]: min=").append(range.mMin);
description.append(" max=").append(range.mMax);
description.append(" flat=").append(range.mFlat);
description.append(" fuzz=").append(range.mFuzz);
description.append("\n");
}
}
}

View File

@@ -19,8 +19,10 @@ package com.android.internal.widget;
import android.content.Context;
import android.graphics.Canvas;
import android.graphics.Paint;
import android.graphics.RectF;
import android.graphics.Paint.FontMetricsInt;
import android.util.Log;
import android.view.InputDevice;
import android.view.MotionEvent;
import android.view.VelocityTracker;
import android.view.View;
@@ -29,17 +31,45 @@ import android.view.ViewConfiguration;
import java.util.ArrayList;
public class PointerLocationView extends View {
private static final String TAG = "Pointer";
public static class PointerState {
private final ArrayList<Float> mXs = new ArrayList<Float>();
private final ArrayList<Float> mYs = new ArrayList<Float>();
// Trace of previous points.
private float[] mTraceX = new float[32];
private float[] mTraceY = new float[32];
private int mTraceCount;
// True if the pointer is down.
private boolean mCurDown;
private int mCurX;
private int mCurY;
private float mCurPressure;
private float mCurSize;
private int mCurWidth;
// Most recent coordinates.
private MotionEvent.PointerCoords mCoords = new MotionEvent.PointerCoords();
// Most recent velocity.
private float mXVelocity;
private float mYVelocity;
public void clearTrace() {
mTraceCount = 0;
}
public void addTrace(float x, float y) {
int traceCapacity = mTraceX.length;
if (mTraceCount == traceCapacity) {
traceCapacity *= 2;
float[] newTraceX = new float[traceCapacity];
System.arraycopy(mTraceX, 0, newTraceX, 0, mTraceCount);
mTraceX = newTraceX;
float[] newTraceY = new float[traceCapacity];
System.arraycopy(mTraceY, 0, newTraceY, 0, mTraceCount);
mTraceY = newTraceY;
}
mTraceX[mTraceCount] = x;
mTraceY[mTraceCount] = y;
mTraceCount += 1;
}
}
private final ViewConfiguration mVC;
@@ -54,11 +84,12 @@ public class PointerLocationView extends View {
private boolean mCurDown;
private int mCurNumPointers;
private int mMaxNumPointers;
private final ArrayList<PointerState> mPointers
= new ArrayList<PointerState>();
private final ArrayList<PointerState> mPointers = new ArrayList<PointerState>();
private final VelocityTracker mVelocity;
private final FasterStringBuilder mText = new FasterStringBuilder();
private boolean mPrintCoords = true;
public PointerLocationView(Context c) {
@@ -94,6 +125,18 @@ public class PointerLocationView extends View {
mPointers.add(ps);
mVelocity = VelocityTracker.obtain();
logInputDeviceCapabilities();
}
private void logInputDeviceCapabilities() {
int[] deviceIds = InputDevice.getDeviceIds();
for (int i = 0; i < deviceIds.length; i++) {
InputDevice device = InputDevice.getDevice(deviceIds[i]);
if (device != null) {
Log.i(TAG, device.toString());
}
}
}
public void setPrintCoords(boolean state) {
@@ -113,6 +156,21 @@ public class PointerLocationView extends View {
+ " bottom=" + mTextMetrics.bottom);
}
}
// Draw an oval. When angle is 0 radians, orients the major axis vertically,
// angles less than or greater than 0 radians rotate the major axis left or right.
private RectF mReusableOvalRect = new RectF();
private void drawOval(Canvas canvas, float x, float y, float major, float minor,
float angle, Paint paint) {
canvas.save(Canvas.MATRIX_SAVE_FLAG);
canvas.rotate((float) (angle * 180 / Math.PI), x, y);
mReusableOvalRect.left = x - minor / 2;
mReusableOvalRect.right = x + minor / 2;
mReusableOvalRect.top = y - major / 2;
mReusableOvalRect.bottom = y + major / 2;
canvas.drawOval(mReusableOvalRect, paint);
canvas.restore();
}
@Override
protected void onDraw(Canvas canvas) {
@@ -124,76 +182,80 @@ public class PointerLocationView extends View {
final int NP = mPointers.size();
// Labels
if (NP > 0) {
final PointerState ps = mPointers.get(0);
canvas.drawRect(0, 0, itemW-1, bottom,mTextBackgroundPaint);
canvas.drawText("P: " + mCurNumPointers + " / " + mMaxNumPointers,
1, base, mTextPaint);
canvas.drawText(mText.clear()
.append("P: ").append(mCurNumPointers)
.append(" / ").append(mMaxNumPointers)
.toString(), 1, base, mTextPaint);
final int N = ps.mXs.size();
final int N = ps.mTraceCount;
if ((mCurDown && ps.mCurDown) || N == 0) {
canvas.drawRect(itemW, 0, (itemW * 2) - 1, bottom, mTextBackgroundPaint);
canvas.drawText("X: " + ps.mCurX, 1 + itemW, base, mTextPaint);
canvas.drawText(mText.clear()
.append("X: ").append(ps.mCoords.x, 1)
.toString(), 1 + itemW, base, mTextPaint);
canvas.drawRect(itemW * 2, 0, (itemW * 3) - 1, bottom, mTextBackgroundPaint);
canvas.drawText("Y: " + ps.mCurY, 1 + itemW * 2, base, mTextPaint);
canvas.drawText(mText.clear()
.append("Y: ").append(ps.mCoords.y, 1)
.toString(), 1 + itemW * 2, base, mTextPaint);
} else {
float dx = ps.mXs.get(N-1) - ps.mXs.get(0);
float dy = ps.mYs.get(N-1) - ps.mYs.get(0);
float dx = ps.mTraceX[N - 1] - ps.mTraceX[0];
float dy = ps.mTraceY[N - 1] - ps.mTraceY[0];
canvas.drawRect(itemW, 0, (itemW * 2) - 1, bottom,
Math.abs(dx) < mVC.getScaledTouchSlop()
? mTextBackgroundPaint : mTextLevelPaint);
canvas.drawText("dX: " + String.format("%.1f", dx), 1 + itemW, base, mTextPaint);
canvas.drawText(mText.clear()
.append("dX: ").append(dx, 1)
.toString(), 1 + itemW, base, mTextPaint);
canvas.drawRect(itemW * 2, 0, (itemW * 3) - 1, bottom,
Math.abs(dy) < mVC.getScaledTouchSlop()
? mTextBackgroundPaint : mTextLevelPaint);
canvas.drawText("dY: " + String.format("%.1f", dy), 1 + itemW * 2, base, mTextPaint);
canvas.drawText(mText.clear()
.append("dY: ").append(dy, 1)
.toString(), 1 + itemW * 2, base, mTextPaint);
}
canvas.drawRect(itemW * 3, 0, (itemW * 4) - 1, bottom, mTextBackgroundPaint);
int velocity = (int) (ps.mXVelocity * 1000);
canvas.drawText("Xv: " + velocity, 1 + itemW * 3, base, mTextPaint);
canvas.drawText(mText.clear()
.append("Xv: ").append(ps.mXVelocity, 3)
.toString(), 1 + itemW * 3, base, mTextPaint);
canvas.drawRect(itemW * 4, 0, (itemW * 5) - 1, bottom, mTextBackgroundPaint);
velocity = (int) (ps.mYVelocity * 1000);
canvas.drawText("Yv: " + velocity, 1 + itemW * 4, base, mTextPaint);
canvas.drawText(mText.clear()
.append("Yv: ").append(ps.mYVelocity, 3)
.toString(), 1 + itemW * 4, base, mTextPaint);
canvas.drawRect(itemW * 5, 0, (itemW * 6) - 1, bottom, mTextBackgroundPaint);
canvas.drawRect(itemW * 5, 0, (itemW * 5) + (ps.mCurPressure * itemW) - 1,
canvas.drawRect(itemW * 5, 0, (itemW * 5) + (ps.mCoords.pressure * itemW) - 1,
bottom, mTextLevelPaint);
canvas.drawText("Prs: " + String.format("%.2f", ps.mCurPressure), 1 + itemW * 5,
base, mTextPaint);
canvas.drawText(mText.clear()
.append("Prs: ").append(ps.mCoords.pressure, 2)
.toString(), 1 + itemW * 5, base, mTextPaint);
canvas.drawRect(itemW * 6, 0, w, bottom, mTextBackgroundPaint);
canvas.drawRect(itemW * 6, 0, (itemW * 6) + (ps.mCurSize * itemW) - 1,
canvas.drawRect(itemW * 6, 0, (itemW * 6) + (ps.mCoords.size * itemW) - 1,
bottom, mTextLevelPaint);
canvas.drawText("Size: " + String.format("%.2f", ps.mCurSize), 1 + itemW * 6,
base, mTextPaint);
canvas.drawText(mText.clear()
.append("Size: ").append(ps.mCoords.size, 2)
.toString(), 1 + itemW * 6, base, mTextPaint);
}
for (int p=0; p<NP; p++) {
// Pointer trace.
for (int p = 0; p < NP; p++) {
final PointerState ps = mPointers.get(p);
if (mCurDown && ps.mCurDown) {
canvas.drawLine(0, (int)ps.mCurY, getWidth(), (int)ps.mCurY, mTargetPaint);
canvas.drawLine((int)ps.mCurX, 0, (int)ps.mCurX, getHeight(), mTargetPaint);
int pressureLevel = (int)(ps.mCurPressure*255);
mPaint.setARGB(255, pressureLevel, 128, 255-pressureLevel);
canvas.drawPoint(ps.mCurX, ps.mCurY, mPaint);
canvas.drawCircle(ps.mCurX, ps.mCurY, ps.mCurWidth, mPaint);
}
}
for (int p=0; p<NP; p++) {
final PointerState ps = mPointers.get(p);
final int N = ps.mXs.size();
float lastX=0, lastY=0;
// Draw path.
final int N = ps.mTraceCount;
float lastX = 0, lastY = 0;
boolean haveLast = false;
boolean drawn = false;
mPaint.setARGB(255, 128, 255, 255);
for (int i=0; i<N; i++) {
float x = ps.mXs.get(i);
float y = ps.mYs.get(i);
for (int i=0; i < N; i++) {
float x = ps.mTraceX[i];
float y = ps.mTraceY[i];
if (Float.isNaN(x)) {
haveLast = false;
continue;
@@ -208,21 +270,57 @@ public class PointerLocationView extends View {
haveLast = true;
}
// Draw velocity vector.
if (drawn) {
mPaint.setARGB(255, 255, 64, 128);
float xVel = ps.mXVelocity * (1000/60);
float yVel = ps.mYVelocity * (1000/60);
canvas.drawLine(lastX, lastY, lastX+xVel, lastY+yVel, mPaint);
float xVel = ps.mXVelocity * (1000 / 60);
float yVel = ps.mYVelocity * (1000 / 60);
canvas.drawLine(lastX, lastY, lastX + xVel, lastY + yVel, mPaint);
}
if (mCurDown && ps.mCurDown) {
// Draw crosshairs.
canvas.drawLine(0, ps.mCoords.y, getWidth(), ps.mCoords.y, mTargetPaint);
canvas.drawLine(ps.mCoords.x, 0, ps.mCoords.x, getHeight(), mTargetPaint);
// Draw current point.
int pressureLevel = (int)(ps.mCoords.pressure * 255);
mPaint.setARGB(255, pressureLevel, 255, 255 - pressureLevel);
canvas.drawPoint(ps.mCoords.x, ps.mCoords.y, mPaint);
// Draw current touch ellipse.
mPaint.setARGB(255, pressureLevel, 255 - pressureLevel, 128);
drawOval(canvas, ps.mCoords.x, ps.mCoords.y, ps.mCoords.touchMajor,
ps.mCoords.touchMinor, ps.mCoords.orientation, mPaint);
// Draw current tool ellipse.
mPaint.setARGB(255, pressureLevel, 128, 255 - pressureLevel);
drawOval(canvas, ps.mCoords.x, ps.mCoords.y, ps.mCoords.toolMajor,
ps.mCoords.toolMinor, ps.mCoords.orientation, mPaint);
}
}
}
}
private void logPointerCoords(MotionEvent.PointerCoords coords, int id) {
Log.i(TAG, mText.clear()
.append("Pointer ").append(id + 1)
.append(": (").append(coords.x, 3).append(", ").append(coords.y, 3)
.append(") Pressure=").append(coords.pressure, 3)
.append(" Size=").append(coords.size, 3)
.append(" TouchMajor=").append(coords.touchMajor, 3)
.append(" TouchMinor=").append(coords.touchMinor, 3)
.append(" ToolMajor=").append(coords.toolMajor, 3)
.append(" ToolMinor=").append(coords.toolMinor, 3)
.append(" Orientation=").append((float)(coords.orientation * 180 / Math.PI), 1)
.append("deg").toString());
}
public void addTouchEvent(MotionEvent event) {
synchronized (mPointers) {
int action = event.getAction();
//Log.i("Pointer", "Motion: action=0x" + Integer.toHexString(action)
//Log.i(TAG, "Motion: action=0x" + Integer.toHexString(action)
// + " pointers=" + event.getPointerCount());
int NP = mPointers.size();
@@ -235,35 +333,33 @@ public class PointerLocationView extends View {
//} else {
// mRect.setEmpty();
//}
if (action == MotionEvent.ACTION_DOWN) {
mVelocity.clear();
if (action == MotionEvent.ACTION_DOWN
|| (action & MotionEvent.ACTION_MASK) == MotionEvent.ACTION_POINTER_DOWN) {
final int index = (action & MotionEvent.ACTION_POINTER_INDEX_MASK)
>> MotionEvent.ACTION_POINTER_INDEX_SHIFT; // will be 0 for down
if (action == MotionEvent.ACTION_DOWN) {
for (int p=0; p<NP; p++) {
final PointerState ps = mPointers.get(p);
ps.clearTrace();
ps.mCurDown = false;
}
mCurDown = true;
mMaxNumPointers = 0;
mVelocity.clear();
}
for (int p=0; p<NP; p++) {
final PointerState ps = mPointers.get(p);
ps.mXs.clear();
ps.mYs.clear();
ps.mCurDown = false;
}
mPointers.get(0).mCurDown = true;
mMaxNumPointers = 0;
if (mPrintCoords) {
Log.i("Pointer", "Pointer 1: DOWN");
}
}
if ((action&MotionEvent.ACTION_MASK) == MotionEvent.ACTION_POINTER_DOWN) {
final int index = (action&MotionEvent.ACTION_POINTER_INDEX_MASK)
>> MotionEvent.ACTION_POINTER_INDEX_SHIFT;
final int id = event.getPointerId(index);
while (NP <= id) {
PointerState ps = new PointerState();
mPointers.add(ps);
NP++;
}
final PointerState ps = mPointers.get(id);
ps.mCurDown = true;
if (mPrintCoords) {
Log.i("Pointer", "Pointer " + (id+1) + ": DOWN");
Log.i(TAG, mText.clear().append("Pointer ")
.append(id + 1).append(": DOWN").toString());
}
}
@@ -284,58 +380,38 @@ public class PointerLocationView extends View {
final PointerState ps = mPointers.get(id);
final int N = event.getHistorySize();
for (int j=0; j<N; j++) {
event.getHistoricalPointerCoords(i, j, ps.mCoords);
if (mPrintCoords) {
Log.i("Pointer", "Pointer " + (id+1) + ": ("
+ event.getHistoricalX(i, j)
+ ", " + event.getHistoricalY(i, j) + ")"
+ " Prs=" + event.getHistoricalPressure(i, j)
+ " Size=" + event.getHistoricalSize(i, j));
logPointerCoords(ps.mCoords, id);
}
ps.mXs.add(event.getHistoricalX(i, j));
ps.mYs.add(event.getHistoricalY(i, j));
ps.addTrace(event.getHistoricalX(i, j), event.getHistoricalY(i, j));
}
event.getPointerCoords(i, ps.mCoords);
if (mPrintCoords) {
Log.i("Pointer", "Pointer " + (id+1) + ": ("
+ event.getX(i) + ", " + event.getY(i) + ")"
+ " Prs=" + event.getPressure(i)
+ " Size=" + event.getSize(i));
logPointerCoords(ps.mCoords, id);
}
ps.mXs.add(event.getX(i));
ps.mYs.add(event.getY(i));
ps.mCurX = (int)event.getX(i);
ps.mCurY = (int)event.getY(i);
//Log.i("Pointer", "Pointer #" + p + ": (" + ps.mCurX
// + "," + ps.mCurY + ")");
ps.mCurPressure = event.getPressure(i);
ps.mCurSize = event.getSize(i);
ps.mCurWidth = (int)(ps.mCurSize*(getWidth()/3));
ps.addTrace(ps.mCoords.x, ps.mCoords.y);
ps.mXVelocity = mVelocity.getXVelocity(id);
ps.mYVelocity = mVelocity.getYVelocity(id);
}
if ((action&MotionEvent.ACTION_MASK) == MotionEvent.ACTION_POINTER_UP) {
final int index = (action&MotionEvent.ACTION_POINTER_INDEX_MASK)
>> MotionEvent.ACTION_POINTER_INDEX_SHIFT;
if (action == MotionEvent.ACTION_UP
|| (action & MotionEvent.ACTION_MASK) == MotionEvent.ACTION_POINTER_UP) {
final int index = (action & MotionEvent.ACTION_POINTER_INDEX_MASK)
>> MotionEvent.ACTION_POINTER_INDEX_SHIFT; // will be 0 for UP
final int id = event.getPointerId(index);
final PointerState ps = mPointers.get(id);
ps.mXs.add(Float.NaN);
ps.mYs.add(Float.NaN);
ps.mCurDown = false;
if (mPrintCoords) {
Log.i("Pointer", "Pointer " + (id+1) + ": UP");
Log.i(TAG, mText.clear().append("Pointer ")
.append(id + 1).append(": UP").toString());
}
}
if (action == MotionEvent.ACTION_UP) {
for (int i=0; i<NI; i++) {
final int id = event.getPointerId(i);
final PointerState ps = mPointers.get(id);
if (ps.mCurDown) {
ps.mCurDown = false;
if (mPrintCoords) {
Log.i("Pointer", "Pointer " + (id+1) + ": UP");
}
}
if (action == MotionEvent.ACTION_UP) {
mCurDown = false;
} else {
ps.addTrace(Float.NaN, Float.NaN);
}
}
@@ -356,8 +432,120 @@ public class PointerLocationView extends View {
@Override
public boolean onTrackballEvent(MotionEvent event) {
Log.i("Pointer", "Trackball: " + event);
Log.i(TAG, "Trackball: " + event);
return super.onTrackballEvent(event);
}
// HACK
// A quick and dirty string builder implementation optimized for GC.
// Using the basic StringBuilder implementation causes the application grind to a halt when
// more than a couple of pointers are down due to the number of temporary objects allocated
// while formatting strings for drawing or logging.
private static final class FasterStringBuilder {
private char[] mChars;
private int mLength;
public FasterStringBuilder() {
mChars = new char[64];
}
public FasterStringBuilder clear() {
mLength = 0;
return this;
}
public FasterStringBuilder append(String value) {
final int valueLength = value.length();
final int index = reserve(valueLength);
value.getChars(0, valueLength, mChars, index);
mLength += valueLength;
return this;
}
public FasterStringBuilder append(int value) {
return append(value, 0);
}
public FasterStringBuilder append(int value, int zeroPadWidth) {
final boolean negative = value < 0;
if (negative) {
value = - value;
if (value < 0) {
append("-2147483648");
return this;
}
}
int index = reserve(11);
final char[] chars = mChars;
if (value == 0) {
chars[index++] = '0';
mLength += 1;
return this;
}
if (negative) {
chars[index++] = '-';
}
int divisor = 1000000000;
int numberWidth = 10;
while (value < divisor) {
divisor /= 10;
numberWidth -= 1;
if (numberWidth < zeroPadWidth) {
chars[index++] = '0';
}
}
do {
int digit = value / divisor;
value -= digit * divisor;
divisor /= 10;
chars[index++] = (char) (digit + '0');
} while (divisor != 0);
mLength = index;
return this;
}
public FasterStringBuilder append(float value, int precision) {
int scale = 1;
for (int i = 0; i < precision; i++) {
scale *= 10;
}
value = (float) (Math.rint(value * scale) / scale);
append((int) value);
if (precision != 0) {
append(".");
value = Math.abs(value);
value -= Math.floor(value);
append((int) (value * scale), precision);
}
return this;
}
@Override
public String toString() {
return new String(mChars, 0, mLength);
}
private int reserve(int length) {
final int oldLength = mLength;
final int newLength = mLength + length;
final char[] oldChars = mChars;
final int oldCapacity = oldChars.length;
if (newLength > oldCapacity) {
final int newCapacity = oldCapacity * 2;
final char[] newChars = new char[newCapacity];
System.arraycopy(oldChars, 0, newChars, 0, oldLength);
mChars = newChars;
}
return oldLength;
}
}
}

View File

@@ -82,6 +82,14 @@ struct RawAbsoluteAxisInfo {
int32_t fuzz; // error tolerance, eg. fuzz == 4 means value is +/- 4 due to noise
inline int32_t getRange() { return maxValue - minValue; }
inline void clear() {
valid = false;
minValue = 0;
maxValue = 0;
flat = 0;
fuzz = 0;
}
};
/*

View File

@@ -453,6 +453,10 @@ public:
inline void setKeyboardType(int32_t keyboardType) { mKeyboardType = keyboardType; }
inline int32_t getKeyboardType() const { return mKeyboardType; }
inline const KeyedVector<int32_t, MotionRange> getMotionRanges() const {
return mMotionRanges;
}
private:
int32_t mId;
String8 mName;

View File

@@ -35,6 +35,34 @@ namespace android {
class InputDevice;
class InputMapper;
/* Describes a virtual key. */
struct VirtualKeyDefinition {
int32_t scanCode;
// configured position data, specified in display coords
int32_t centerX;
int32_t centerY;
int32_t width;
int32_t height;
};
/* Specifies input device calibration settings. */
class InputDeviceCalibration {
public:
InputDeviceCalibration();
void clear();
void addProperty(const String8& key, const String8& value);
bool tryGetProperty(const String8& key, String8& outValue) const;
bool tryGetProperty(const String8& key, int32_t& outValue) const;
bool tryGetProperty(const String8& key, float& outValue) const;
private:
KeyedVector<String8, String8> mProperties;
};
/*
* Input reader policy interface.
@@ -73,17 +101,6 @@ public:
ACTION_APP_SWITCH_COMING = 0x00000002,
};
/* Describes a virtual key. */
struct VirtualKeyDefinition {
int32_t scanCode;
// configured position data, specified in display coords
int32_t centerX;
int32_t centerY;
int32_t width;
int32_t height;
};
/* Gets information about the display with the specified id.
* Returns true if the display info is available, false otherwise.
*/
@@ -135,6 +152,10 @@ public:
virtual void getVirtualKeyDefinitions(const String8& deviceName,
Vector<VirtualKeyDefinition>& outVirtualKeyDefinitions) = 0;
/* Gets the calibration for an input device. */
virtual void getInputDeviceCalibration(const String8& deviceName,
InputDeviceCalibration& outCalibration) = 0;
/* Gets the excluded device names for the platform. */
virtual void getExcludedDeviceNames(Vector<String8>& outExcludedDeviceNames) = 0;
};
@@ -327,6 +348,10 @@ public:
int32_t getMetaState();
inline const InputDeviceCalibration& getCalibration() {
return mCalibration;
}
private:
InputReaderContext* mContext;
int32_t mId;
@@ -338,6 +363,8 @@ private:
typedef int32_t (InputMapper::*GetStateFunc)(uint32_t sourceMask, int32_t code);
int32_t getState(uint32_t sourceMask, int32_t code, GetStateFunc getStateFunc);
InputDeviceCalibration mCalibration;
};
@@ -538,12 +565,12 @@ protected:
}
};
// Raw data for a single pointer.
struct PointerData {
uint32_t id;
int32_t x;
int32_t y;
int32_t pressure;
int32_t size;
int32_t touchMajor;
int32_t touchMinor;
int32_t toolMajor;
@@ -551,6 +578,7 @@ protected:
int32_t orientation;
};
// Raw data for a collection of pointers including a pointer id mapping table.
struct TouchData {
uint32_t pointerCount;
PointerData pointers[MAX_POINTERS];
@@ -584,18 +612,82 @@ protected:
bool useAveragingTouchFilter;
} mParameters;
// Raw axis information.
struct Axes {
// Immutable calibration parameters in parsed form.
struct Calibration {
// Touch Area
enum TouchAreaCalibration {
TOUCH_AREA_CALIBRATION_DEFAULT,
TOUCH_AREA_CALIBRATION_NONE,
TOUCH_AREA_CALIBRATION_GEOMETRIC,
TOUCH_AREA_CALIBRATION_PRESSURE,
};
TouchAreaCalibration touchAreaCalibration;
// Tool Area
enum ToolAreaCalibration {
TOOL_AREA_CALIBRATION_DEFAULT,
TOOL_AREA_CALIBRATION_NONE,
TOOL_AREA_CALIBRATION_GEOMETRIC,
TOOL_AREA_CALIBRATION_LINEAR,
};
ToolAreaCalibration toolAreaCalibration;
bool haveToolAreaLinearScale;
float toolAreaLinearScale;
bool haveToolAreaLinearBias;
float toolAreaLinearBias;
bool haveToolAreaIsSummed;
int32_t toolAreaIsSummed;
// Pressure
enum PressureCalibration {
PRESSURE_CALIBRATION_DEFAULT,
PRESSURE_CALIBRATION_NONE,
PRESSURE_CALIBRATION_PHYSICAL,
PRESSURE_CALIBRATION_AMPLITUDE,
};
enum PressureSource {
PRESSURE_SOURCE_DEFAULT,
PRESSURE_SOURCE_PRESSURE,
PRESSURE_SOURCE_TOUCH,
};
PressureCalibration pressureCalibration;
PressureSource pressureSource;
bool havePressureScale;
float pressureScale;
// Size
enum SizeCalibration {
SIZE_CALIBRATION_DEFAULT,
SIZE_CALIBRATION_NONE,
SIZE_CALIBRATION_NORMALIZED,
};
SizeCalibration sizeCalibration;
// Orientation
enum OrientationCalibration {
ORIENTATION_CALIBRATION_DEFAULT,
ORIENTATION_CALIBRATION_NONE,
ORIENTATION_CALIBRATION_INTERPOLATED,
};
OrientationCalibration orientationCalibration;
} mCalibration;
// Raw axis information from the driver.
struct RawAxes {
RawAbsoluteAxisInfo x;
RawAbsoluteAxisInfo y;
RawAbsoluteAxisInfo pressure;
RawAbsoluteAxisInfo size;
RawAbsoluteAxisInfo touchMajor;
RawAbsoluteAxisInfo touchMinor;
RawAbsoluteAxisInfo toolMajor;
RawAbsoluteAxisInfo toolMinor;
RawAbsoluteAxisInfo orientation;
} mAxes;
} mRawAxes;
// Current and previous touch sample data.
TouchData mCurrentTouch;
@@ -620,10 +712,13 @@ protected:
float yScale;
float yPrecision;
int32_t pressureOrigin;
float geometricScale;
float toolAreaLinearScale;
float toolAreaLinearBias;
float pressureScale;
int32_t sizeOrigin;
float sizeScale;
float orientationScale;
@@ -632,12 +727,22 @@ protected:
struct OrientedRanges {
InputDeviceInfo::MotionRange x;
InputDeviceInfo::MotionRange y;
bool havePressure;
InputDeviceInfo::MotionRange pressure;
bool haveSize;
InputDeviceInfo::MotionRange size;
bool haveTouchArea;
InputDeviceInfo::MotionRange touchMajor;
InputDeviceInfo::MotionRange touchMinor;
bool haveToolArea;
InputDeviceInfo::MotionRange toolMajor;
InputDeviceInfo::MotionRange toolMinor;
bool haveOrientation;
InputDeviceInfo::MotionRange orientation;
} orientedRanges;
@@ -653,9 +758,14 @@ protected:
} currentVirtualKey;
} mLocked;
virtual void configureAxes();
virtual void configureParameters();
virtual void configureRawAxes();
virtual void logRawAxes();
virtual bool configureSurfaceLocked();
virtual void configureVirtualKeysLocked();
virtual void parseCalibration();
virtual void resolveCalibration();
virtual void logCalibration();
enum TouchResult {
// Dispatch the touch normally.
@@ -713,7 +823,8 @@ private:
TouchResult consumeOffScreenTouches(nsecs_t when, uint32_t policyFlags);
void dispatchTouches(nsecs_t when, uint32_t policyFlags);
void dispatchTouch(nsecs_t when, uint32_t policyFlags, TouchData* touch,
BitSet32 idBits, uint32_t changedId, int32_t motionEventAction);
BitSet32 idBits, uint32_t changedId, uint32_t pointerCount,
int32_t motionEventAction);
void applyPolicyAndDispatchVirtualKey(nsecs_t when, uint32_t policyFlags,
int32_t keyEventAction, int32_t keyEventFlags,
@@ -738,7 +849,7 @@ public:
virtual void process(const RawEvent* rawEvent);
protected:
virtual void configureAxes();
virtual void configureRawAxes();
private:
struct Accumulator {
@@ -767,7 +878,7 @@ private:
int32_t mX;
int32_t mY;
int32_t mPressure;
int32_t mSize;
int32_t mToolWidth;
void initialize();
@@ -784,7 +895,7 @@ public:
virtual void process(const RawEvent* rawEvent);
protected:
virtual void configureAxes();
virtual void configureRawAxes();
private:
struct Accumulator {

View File

@@ -139,11 +139,7 @@ uint32_t EventHub::getDeviceClasses(int32_t deviceId) const
status_t EventHub::getAbsoluteAxisInfo(int32_t deviceId, int axis,
RawAbsoluteAxisInfo* outAxisInfo) const {
outAxisInfo->valid = false;
outAxisInfo->minValue = 0;
outAxisInfo->maxValue = 0;
outAxisInfo->flat = 0;
outAxisInfo->fuzz = 0;
outAxisInfo->clear();
AutoMutex _l(mLock);
device_t* device = getDevice(deviceId);
@@ -709,8 +705,7 @@ int EventHub::open_device(const char *deviceName)
LOGV("Getting absolute controllers...");
if (ioctl(fd, EVIOCGBIT(EV_ABS, sizeof(abs_bitmask)), abs_bitmask) >= 0) {
// Is this a new modern multi-touch driver?
if (test_bit(ABS_MT_TOUCH_MAJOR, abs_bitmask)
&& test_bit(ABS_MT_POSITION_X, abs_bitmask)
if (test_bit(ABS_MT_POSITION_X, abs_bitmask)
&& test_bit(ABS_MT_POSITION_Y, abs_bitmask)) {
device->classes |= INPUT_DEVICE_CLASS_TOUCHSCREEN | INPUT_DEVICE_CLASS_TOUCHSCREEN_MT;

View File

@@ -405,12 +405,15 @@ void InputDispatcher::processMotionLockedInterruptible(
sampleCount += 1;
}
for (uint32_t i = 0; i < entry->pointerCount; i++) {
LOGD(" Pointer %d: id=%d, x=%f, y=%f, pressure=%f, size=%f",
LOGD(" Pointer %d: id=%d, x=%f, y=%f, pressure=%f, size=%f, "
"touchMajor=%f, touchMinor=%d, toolMajor=%f, toolMinor=%f, "
"orientation=%f",
i, entry->pointerIds[i],
sample->pointerCoords[i].x,
sample->pointerCoords[i].y,
sample->pointerCoords[i].pressure,
sample->pointerCoords[i].size);
sample->pointerCoords[i].x, sample->pointerCoords[i].y,
sample->pointerCoords[i].pressure, sample->pointerCoords[i].size,
sample->pointerCoords[i].touchMajor, sample->pointerCoords[i].touchMinor,
sample->pointerCoords[i].toolMajor, sample->pointerCoords[i].toolMinor,
sample->pointerCoords[i].orientation);
}
// Keep in mind that due to batching, it is possible for the number of samples actually
@@ -1080,9 +1083,14 @@ void InputDispatcher::notifyMotion(nsecs_t eventTime, int32_t deviceId, int32_t
eventTime, deviceId, source, policyFlags, action, metaState, edgeFlags,
xPrecision, yPrecision, downTime);
for (uint32_t i = 0; i < pointerCount; i++) {
LOGD(" Pointer %d: id=%d, x=%f, y=%f, pressure=%f, size=%f",
LOGD(" Pointer %d: id=%d, x=%f, y=%f, pressure=%f, size=%f, "
"touchMajor=%f, touchMinor=%d, toolMajor=%f, toolMinor=%f, "
"orientation=%f",
i, pointerIds[i], pointerCoords[i].x, pointerCoords[i].y,
pointerCoords[i].pressure, pointerCoords[i].size);
pointerCoords[i].pressure, pointerCoords[i].size,
pointerCoords[i].touchMajor, pointerCoords[i].touchMinor,
pointerCoords[i].toolMajor, pointerCoords[i].toolMinor,
pointerCoords[i].orientation);
}
#endif

File diff suppressed because it is too large Load Diff

View File

@@ -718,8 +718,6 @@ int32_t AInputDevice_getKeyboardType(AInputDevice* device);
int32_t AInputDevice_getMotionRange(AInputDevice* device, int32_t rangeType,
float* outMin, float* outMax, float* outFlat, float* outFuzz);
//TODO hasKey, keymap stuff, etc...
#ifdef __cplusplus
}
#endif

View File

@@ -30,6 +30,7 @@ import android.os.SystemProperties;
import android.util.Slog;
import android.util.Xml;
import android.view.InputChannel;
import android.view.InputDevice;
import android.view.InputEvent;
import android.view.KeyEvent;
import android.view.MotionEvent;
@@ -45,6 +46,7 @@ import java.io.IOException;
import java.io.InputStreamReader;
import java.io.PrintWriter;
import java.util.ArrayList;
import java.util.Properties;
/*
* Wraps the C++ InputManager and provides its callbacks.
@@ -82,6 +84,8 @@ public class InputManager {
private static native void nativeSetInputDispatchMode(boolean enabled, boolean frozen);
private static native void nativeSetFocusedApplication(InputApplication application);
private static native void nativePreemptInputDispatch();
private static native InputDevice nativeGetInputDevice(int deviceId);
private static native int[] nativeGetInputDeviceIds();
private static native String nativeDump();
// Input event injection constants defined in InputDispatcher.h.
@@ -302,6 +306,23 @@ public class InputManager {
return nativeInjectInputEvent(event, injectorPid, injectorUid, syncMode, timeoutMillis);
}
/**
* Gets information about the input device with the specified id.
* @param id The device id.
* @return The input device or null if not found.
*/
public InputDevice getInputDevice(int deviceId) {
return nativeGetInputDevice(deviceId);
}
/**
* Gets the ids of all input devices in the system.
* @return The input device ids.
*/
public int[] getInputDeviceIds() {
return nativeGetInputDeviceIds();
}
public void setInputWindows(InputWindow[] windows) {
nativeSetInputWindows(windows);
}
@@ -335,6 +356,11 @@ public class InputManager {
public int height;
}
private static final class InputDeviceCalibration {
public String[] keys;
public String[] values;
}
/*
* Callbacks from native.
*/
@@ -343,6 +369,7 @@ public class InputManager {
private static final boolean DEBUG_VIRTUAL_KEYS = false;
private static final String EXCLUDED_DEVICES_PATH = "etc/excluded-input-devices.xml";
private static final String CALIBRATION_DIR_PATH = "usr/idc/";
@SuppressWarnings("unused")
public void virtualKeyDownFeedback() {
@@ -438,8 +465,8 @@ public class InputManager {
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]);
Slog.w(TAG, "Unknown virtual key type at elem #"
+ i + ": " + it[i] + " for device " + deviceName);
continue;
}
try {
@@ -455,21 +482,46 @@ public class InputManager {
+ key.height);
keys.add(key);
} catch (NumberFormatException e) {
Slog.w(TAG, "Bad number at region " + i + " in: "
+ str, e);
Slog.w(TAG, "Bad number in virtual key definition at region "
+ i + " in: " + str + " for device " + deviceName, e);
}
}
}
br.close();
} catch (FileNotFoundException e) {
Slog.i(TAG, "No virtual keys found");
Slog.i(TAG, "No virtual keys found for device " + deviceName + ".");
} catch (IOException e) {
Slog.w(TAG, "Error reading virtual keys", e);
Slog.w(TAG, "Error reading virtual keys for device " + deviceName + ".", e);
}
return keys.toArray(new VirtualKeyDefinition[keys.size()]);
}
@SuppressWarnings("unused")
public InputDeviceCalibration getInputDeviceCalibration(String deviceName) {
// Calibration is specified as a sequence of colon-delimited key value pairs.
Properties properties = new Properties();
File calibrationFile = new File(Environment.getRootDirectory(),
CALIBRATION_DIR_PATH + deviceName + ".idc");
if (calibrationFile.exists()) {
try {
properties.load(new FileInputStream(calibrationFile));
} catch (IOException ex) {
Slog.w(TAG, "Error reading input device calibration properties for device "
+ deviceName + " from " + calibrationFile + ".", ex);
}
} else {
Slog.i(TAG, "No input device calibration properties found for device "
+ deviceName + ".");
return null;
}
InputDeviceCalibration calibration = new InputDeviceCalibration();
calibration.keys = properties.keySet().toArray(new String[properties.size()]);
calibration.values = properties.values().toArray(new String[properties.size()]);
return calibration;
}
@SuppressWarnings("unused")
public String[] getExcludedDeviceNames() {
ArrayList<String> names = new ArrayList<String>();

View File

@@ -4392,6 +4392,14 @@ public class WindowManagerService extends IWindowManager.Stub
return mInputManager.monitorInput(inputChannelName);
}
public InputDevice getInputDevice(int deviceId) {
return mInputManager.getInputDevice(deviceId);
}
public int[] getInputDeviceIds() {
return mInputManager.getInputDeviceIds();
}
public void enableScreenAfterBoot() {
synchronized(mWindowMap) {
if (mSystemBooted) {

View File

@@ -138,6 +138,7 @@ static struct {
jmethodID filterTouchEvents;
jmethodID filterJumpyTouchEvents;
jmethodID getVirtualKeyDefinitions;
jmethodID getInputDeviceCalibration;
jmethodID getExcludedDeviceNames;
jmethodID getMaxEventsPerSecond;
} gCallbacksClassInfo;
@@ -152,6 +153,13 @@ static struct {
jfieldID height;
} gVirtualKeyDefinitionClassInfo;
static struct {
jclass clazz;
jfieldID keys;
jfieldID values;
} gInputDeviceCalibrationClassInfo;
static struct {
jclass clazz;
@@ -189,6 +197,19 @@ static struct {
jclass clazz;
} gMotionEventClassInfo;
static struct {
jclass clazz;
jmethodID ctor;
jmethodID addMotionRange;
jfieldID mId;
jfieldID mName;
jfieldID mSources;
jfieldID mKeyboardType;
jfieldID mMotionRanges;
} gInputDeviceClassInfo;
// ----------------------------------------------------------------------------
static inline nsecs_t now() {
@@ -235,7 +256,9 @@ public:
virtual bool filterTouchEvents();
virtual bool filterJumpyTouchEvents();
virtual void getVirtualKeyDefinitions(const String8& deviceName,
Vector<InputReaderPolicyInterface::VirtualKeyDefinition>& outVirtualKeyDefinitions);
Vector<VirtualKeyDefinition>& outVirtualKeyDefinitions);
virtual void getInputDeviceCalibration(const String8& deviceName,
InputDeviceCalibration& outCalibration);
virtual void getExcludedDeviceNames(Vector<String8>& outExcludedDeviceNames);
/* --- InputDispatcherPolicyInterface implementation --- */
@@ -761,7 +784,9 @@ bool NativeInputManager::filterJumpyTouchEvents() {
}
void NativeInputManager::getVirtualKeyDefinitions(const String8& deviceName,
Vector<InputReaderPolicyInterface::VirtualKeyDefinition>& outVirtualKeyDefinitions) {
Vector<VirtualKeyDefinition>& outVirtualKeyDefinitions) {
outVirtualKeyDefinitions.clear();
JNIEnv* env = jniEnv();
jstring deviceNameStr = env->NewStringUTF(deviceName.string());
@@ -793,7 +818,51 @@ void NativeInputManager::getVirtualKeyDefinitions(const String8& deviceName,
}
}
void NativeInputManager::getInputDeviceCalibration(const String8& deviceName,
InputDeviceCalibration& outCalibration) {
outCalibration.clear();
JNIEnv* env = jniEnv();
jstring deviceNameStr = env->NewStringUTF(deviceName.string());
if (! checkAndClearExceptionFromCallback(env, "getInputDeviceCalibration")) {
jobject result = env->CallObjectMethod(mCallbacksObj,
gCallbacksClassInfo.getInputDeviceCalibration, deviceNameStr);
if (! checkAndClearExceptionFromCallback(env, "getInputDeviceCalibration") && result) {
jobjectArray keys = jobjectArray(env->GetObjectField(result,
gInputDeviceCalibrationClassInfo.keys));
jobjectArray values = jobjectArray(env->GetObjectField(result,
gInputDeviceCalibrationClassInfo.values));
jsize length = env->GetArrayLength(keys);
for (jsize i = 0; i < length; i++) {
jstring keyStr = jstring(env->GetObjectArrayElement(keys, i));
jstring valueStr = jstring(env->GetObjectArrayElement(values, i));
const char* keyChars = env->GetStringUTFChars(keyStr, NULL);
String8 key(keyChars);
env->ReleaseStringUTFChars(keyStr, keyChars);
const char* valueChars = env->GetStringUTFChars(valueStr, NULL);
String8 value(valueChars);
env->ReleaseStringUTFChars(valueStr, valueChars);
outCalibration.addProperty(key, value);
env->DeleteLocalRef(keyStr);
env->DeleteLocalRef(valueStr);
}
env->DeleteLocalRef(keys);
env->DeleteLocalRef(values);
env->DeleteLocalRef(result);
}
env->DeleteLocalRef(deviceNameStr);
}
}
void NativeInputManager::getExcludedDeviceNames(Vector<String8>& outExcludedDeviceNames) {
outExcludedDeviceNames.clear();
JNIEnv* env = jniEnv();
jobjectArray result = jobjectArray(env->CallObjectMethod(mCallbacksObj,
@@ -2199,6 +2268,66 @@ static void android_server_InputManager_nativePreemptInputDispatch(JNIEnv* env,
gNativeInputManager->preemptInputDispatch();
}
static jobject android_server_InputManager_nativeGetInputDevice(JNIEnv* env,
jclass clazz, jint deviceId) {
if (checkInputManagerUnitialized(env)) {
return NULL;
}
InputDeviceInfo deviceInfo;
status_t status = gNativeInputManager->getInputManager()->getInputDeviceInfo(
deviceId, & deviceInfo);
if (status) {
return NULL;
}
jobject deviceObj = env->NewObject(gInputDeviceClassInfo.clazz, gInputDeviceClassInfo.ctor);
if (! deviceObj) {
return NULL;
}
jstring deviceNameObj = env->NewStringUTF(deviceInfo.getName().string());
if (! deviceNameObj) {
return NULL;
}
env->SetIntField(deviceObj, gInputDeviceClassInfo.mId, deviceInfo.getId());
env->SetObjectField(deviceObj, gInputDeviceClassInfo.mName, deviceNameObj);
env->SetIntField(deviceObj, gInputDeviceClassInfo.mSources, deviceInfo.getSources());
env->SetIntField(deviceObj, gInputDeviceClassInfo.mKeyboardType, deviceInfo.getKeyboardType());
const KeyedVector<int, InputDeviceInfo::MotionRange>& ranges = deviceInfo.getMotionRanges();
for (size_t i = 0; i < ranges.size(); i++) {
int rangeType = ranges.keyAt(i);
const InputDeviceInfo::MotionRange& range = ranges.valueAt(i);
env->CallVoidMethod(deviceObj, gInputDeviceClassInfo.addMotionRange,
rangeType, range.min, range.max, range.flat, range.fuzz);
if (env->ExceptionCheck()) {
return NULL;
}
}
return deviceObj;
}
static jintArray android_server_InputManager_nativeGetInputDeviceIds(JNIEnv* env,
jclass clazz) {
if (checkInputManagerUnitialized(env)) {
return NULL;
}
Vector<int> deviceIds;
gNativeInputManager->getInputManager()->getInputDeviceIds(deviceIds);
jintArray deviceIdsObj = env->NewIntArray(deviceIds.size());
if (! deviceIdsObj) {
return NULL;
}
env->SetIntArrayRegion(deviceIdsObj, 0, deviceIds.size(), deviceIds.array());
return deviceIdsObj;
}
static jstring android_server_InputManager_nativeDump(JNIEnv* env, jclass clazz) {
if (checkInputManagerUnitialized(env)) {
return NULL;
@@ -2242,6 +2371,10 @@ static JNINativeMethod gInputManagerMethods[] = {
(void*) android_server_InputManager_nativeSetInputDispatchMode },
{ "nativePreemptInputDispatch", "()V",
(void*) android_server_InputManager_nativePreemptInputDispatch },
{ "nativeGetInputDevice", "(I)Landroid/view/InputDevice;",
(void*) android_server_InputManager_nativeGetInputDevice },
{ "nativeGetInputDeviceIds", "()[I",
(void*) android_server_InputManager_nativeGetInputDeviceIds },
{ "nativeDump", "()Ljava/lang/String;",
(void*) android_server_InputManager_nativeDump },
};
@@ -2311,6 +2444,10 @@ int register_android_server_InputManager(JNIEnv* env) {
"getVirtualKeyDefinitions",
"(Ljava/lang/String;)[Lcom/android/server/InputManager$VirtualKeyDefinition;");
GET_METHOD_ID(gCallbacksClassInfo.getInputDeviceCalibration, gCallbacksClassInfo.clazz,
"getInputDeviceCalibration",
"(Ljava/lang/String;)Lcom/android/server/InputManager$InputDeviceCalibration;");
GET_METHOD_ID(gCallbacksClassInfo.getExcludedDeviceNames, gCallbacksClassInfo.clazz,
"getExcludedDeviceNames", "()[Ljava/lang/String;");
@@ -2337,6 +2474,17 @@ int register_android_server_InputManager(JNIEnv* env) {
GET_FIELD_ID(gVirtualKeyDefinitionClassInfo.height, gVirtualKeyDefinitionClassInfo.clazz,
"height", "I");
// InputDeviceCalibration
FIND_CLASS(gInputDeviceCalibrationClassInfo.clazz,
"com/android/server/InputManager$InputDeviceCalibration");
GET_FIELD_ID(gInputDeviceCalibrationClassInfo.keys, gInputDeviceCalibrationClassInfo.clazz,
"keys", "[Ljava/lang/String;");
GET_FIELD_ID(gInputDeviceCalibrationClassInfo.values, gInputDeviceCalibrationClassInfo.clazz,
"values", "[Ljava/lang/String;");
// InputWindow
FIND_CLASS(gInputWindowClassInfo.clazz, "com/android/server/InputWindow");
@@ -2407,10 +2555,35 @@ int register_android_server_InputManager(JNIEnv* env) {
FIND_CLASS(gKeyEventClassInfo.clazz, "android/view/KeyEvent");
// MotionEVent
// MotionEvent
FIND_CLASS(gMotionEventClassInfo.clazz, "android/view/MotionEvent");
// InputDevice
FIND_CLASS(gInputDeviceClassInfo.clazz, "android/view/InputDevice");
GET_METHOD_ID(gInputDeviceClassInfo.ctor, gInputDeviceClassInfo.clazz,
"<init>", "()V");
GET_METHOD_ID(gInputDeviceClassInfo.addMotionRange, gInputDeviceClassInfo.clazz,
"addMotionRange", "(IFFFF)V");
GET_FIELD_ID(gInputDeviceClassInfo.mId, gInputDeviceClassInfo.clazz,
"mId", "I");
GET_FIELD_ID(gInputDeviceClassInfo.mName, gInputDeviceClassInfo.clazz,
"mName", "Ljava/lang/String;");
GET_FIELD_ID(gInputDeviceClassInfo.mSources, gInputDeviceClassInfo.clazz,
"mSources", "I");
GET_FIELD_ID(gInputDeviceClassInfo.mKeyboardType, gInputDeviceClassInfo.clazz,
"mKeyboardType", "I");
GET_FIELD_ID(gInputDeviceClassInfo.mMotionRanges, gInputDeviceClassInfo.clazz,
"mMotionRanges", "[Landroid/view/InputDevice$MotionRange;");
return 0;
}