Merge "Support unique calibration per orientation"

This commit is contained in:
Michael Wright
2014-03-10 23:40:51 +00:00
committed by Android (Google) Code Review
5 changed files with 129 additions and 49 deletions

View File

@@ -41,8 +41,8 @@ interface IInputManager {
boolean injectInputEvent(in InputEvent ev, int mode); boolean injectInputEvent(in InputEvent ev, int mode);
// Calibrate input device position // Calibrate input device position
TouchCalibration getTouchCalibrationForInputDevice(String inputDeviceDescriptor); TouchCalibration getTouchCalibrationForInputDevice(String inputDeviceDescriptor, int rotation);
void setTouchCalibrationForInputDevice(String inputDeviceDescriptor, void setTouchCalibrationForInputDevice(String inputDeviceDescriptor, int rotation,
in TouchCalibration calibration); in TouchCalibration calibration);
// Keyboard layouts configuration. // Keyboard layouts configuration.

View File

@@ -508,9 +508,9 @@ public final class InputManager {
* *
* @hide * @hide
*/ */
public TouchCalibration getTouchCalibration(String inputDeviceDescriptor) { public TouchCalibration getTouchCalibration(String inputDeviceDescriptor, int surfaceRotation) {
try { try {
return mIm.getTouchCalibrationForInputDevice(inputDeviceDescriptor); return mIm.getTouchCalibrationForInputDevice(inputDeviceDescriptor, surfaceRotation);
} catch (RemoteException ex) { } catch (RemoteException ex) {
Log.w(TAG, "Could not get calibration matrix for input device.", ex); Log.w(TAG, "Could not get calibration matrix for input device.", ex);
return TouchCalibration.IDENTITY; return TouchCalibration.IDENTITY;
@@ -529,9 +529,10 @@ public final class InputManager {
* *
* @hide * @hide
*/ */
public void setTouchCalibration(String inputDeviceDescriptor, TouchCalibration calibration) { public void setTouchCalibration(String inputDeviceDescriptor, int surfaceRotation,
TouchCalibration calibration) {
try { try {
mIm.setTouchCalibrationForInputDevice(inputDeviceDescriptor, calibration); mIm.setTouchCalibrationForInputDevice(inputDeviceDescriptor, surfaceRotation, calibration);
} catch (RemoteException ex) { } catch (RemoteException ex) {
Log.w(TAG, "Could not set calibration matrix for input device.", ex); Log.w(TAG, "Could not set calibration matrix for input device.", ex);
} }

View File

@@ -77,6 +77,7 @@ import android.view.InputDevice;
import android.view.InputEvent; import android.view.InputEvent;
import android.view.KeyEvent; import android.view.KeyEvent;
import android.view.PointerIcon; import android.view.PointerIcon;
import android.view.Surface;
import android.view.ViewConfiguration; import android.view.ViewConfiguration;
import android.view.WindowManagerPolicy; import android.view.WindowManagerPolicy;
import android.widget.Toast; import android.widget.Toast;
@@ -703,18 +704,19 @@ public class InputManagerService extends IInputManager.Stub
} }
@Override // Binder call & native callback @Override // Binder call & native callback
public TouchCalibration getTouchCalibrationForInputDevice(String inputDeviceDescriptor) { public TouchCalibration getTouchCalibrationForInputDevice(String inputDeviceDescriptor,
int surfaceRotation) {
if (inputDeviceDescriptor == null) { if (inputDeviceDescriptor == null) {
throw new IllegalArgumentException("inputDeviceDescriptor must not be null"); throw new IllegalArgumentException("inputDeviceDescriptor must not be null");
} }
synchronized (mDataStore) { synchronized (mDataStore) {
return mDataStore.getTouchCalibration(inputDeviceDescriptor); return mDataStore.getTouchCalibration(inputDeviceDescriptor, surfaceRotation);
} }
} }
@Override // Binder call @Override // Binder call
public void setTouchCalibrationForInputDevice(String inputDeviceDescriptor, public void setTouchCalibrationForInputDevice(String inputDeviceDescriptor, int surfaceRotation,
TouchCalibration calibration) { TouchCalibration calibration) {
if (!checkCallingPermission(android.Manifest.permission.SET_INPUT_CALIBRATION, if (!checkCallingPermission(android.Manifest.permission.SET_INPUT_CALIBRATION,
"setTouchCalibrationForInputDevice()")) { "setTouchCalibrationForInputDevice()")) {
@@ -726,10 +728,14 @@ public class InputManagerService extends IInputManager.Stub
if (calibration == null) { if (calibration == null) {
throw new IllegalArgumentException("calibration must not be null"); throw new IllegalArgumentException("calibration must not be null");
} }
if (surfaceRotation < Surface.ROTATION_0 || surfaceRotation > Surface.ROTATION_270) {
throw new IllegalArgumentException("surfaceRotation value out of bounds");
}
synchronized (mDataStore) { synchronized (mDataStore) {
try { try {
if (mDataStore.setTouchCalibration(inputDeviceDescriptor, calibration)) { if (mDataStore.setTouchCalibration(inputDeviceDescriptor, surfaceRotation,
calibration)) {
nativeReloadCalibration(mPtr); nativeReloadCalibration(mPtr);
} }
} finally { } finally {

View File

@@ -24,6 +24,7 @@ import org.xmlpull.v1.XmlPullParser;
import org.xmlpull.v1.XmlPullParserException; import org.xmlpull.v1.XmlPullParserException;
import org.xmlpull.v1.XmlSerializer; import org.xmlpull.v1.XmlSerializer;
import android.view.Surface;
import android.hardware.input.TouchCalibration; import android.hardware.input.TouchCalibration;
import android.util.AtomicFile; import android.util.AtomicFile;
import android.util.Slog; import android.util.Slog;
@@ -83,22 +84,27 @@ final class PersistentDataStore {
} }
} }
public TouchCalibration getTouchCalibration(String inputDeviceDescriptor) { public TouchCalibration getTouchCalibration(String inputDeviceDescriptor, int surfaceRotation) {
InputDeviceState state = getInputDeviceState(inputDeviceDescriptor, false); InputDeviceState state = getInputDeviceState(inputDeviceDescriptor, false);
if (state == null) { if (state == null) {
return TouchCalibration.IDENTITY; return TouchCalibration.IDENTITY;
} }
else {
return state.getTouchCalibration(); TouchCalibration cal = state.getTouchCalibration(surfaceRotation);
if (cal == null) {
return TouchCalibration.IDENTITY;
} }
return cal;
} }
public boolean setTouchCalibration(String inputDeviceDescriptor, TouchCalibration calibration) { public boolean setTouchCalibration(String inputDeviceDescriptor, int surfaceRotation, TouchCalibration calibration) {
InputDeviceState state = getInputDeviceState(inputDeviceDescriptor, true); InputDeviceState state = getInputDeviceState(inputDeviceDescriptor, true);
if (state.setTouchCalibration(calibration)) {
if (state.setTouchCalibration(surfaceRotation, calibration)) {
setDirty(); setDirty();
return true; return true;
} }
return false; return false;
} }
@@ -298,20 +304,30 @@ final class PersistentDataStore {
private static final String[] CALIBRATION_NAME = { "x_scale", private static final String[] CALIBRATION_NAME = { "x_scale",
"x_ymix", "x_offset", "y_xmix", "y_scale", "y_offset" }; "x_ymix", "x_offset", "y_xmix", "y_scale", "y_offset" };
private TouchCalibration mTouchCalibration = TouchCalibration.IDENTITY; private TouchCalibration[] mTouchCalibration = new TouchCalibration[4];
private String mCurrentKeyboardLayout; private String mCurrentKeyboardLayout;
private ArrayList<String> mKeyboardLayouts = new ArrayList<String>(); private ArrayList<String> mKeyboardLayouts = new ArrayList<String>();
public TouchCalibration getTouchCalibration() { public TouchCalibration getTouchCalibration(int surfaceRotation) {
return mTouchCalibration; try {
return mTouchCalibration[surfaceRotation];
} catch (ArrayIndexOutOfBoundsException ex) {
Slog.w(InputManagerService.TAG, "Cannot get touch calibration.", ex);
return null;
}
} }
public boolean setTouchCalibration(TouchCalibration calibration) { public boolean setTouchCalibration(int surfaceRotation, TouchCalibration calibration) {
if (calibration.equals(mTouchCalibration)) { try {
if (!calibration.equals(mTouchCalibration[surfaceRotation])) {
mTouchCalibration[surfaceRotation] = calibration;
return true;
}
return false;
} catch (ArrayIndexOutOfBoundsException ex) {
Slog.w(InputManagerService.TAG, "Cannot set touch calibration.", ex);
return false; return false;
} }
mTouchCalibration = calibration;
return true;
} }
public String getCurrentKeyboardLayout() { public String getCurrentKeyboardLayout() {
@@ -427,28 +443,49 @@ final class PersistentDataStore {
} }
} else if (parser.getName().equals("calibration")) { } else if (parser.getName().equals("calibration")) {
String format = parser.getAttributeValue(null, "format"); String format = parser.getAttributeValue(null, "format");
String rotation = parser.getAttributeValue(null, "rotation");
int r = -1;
if (format == null) { if (format == null) {
throw new XmlPullParserException( throw new XmlPullParserException(
"Missing format attribute on calibration."); "Missing format attribute on calibration.");
} }
if (format.equals("affine")) { if (!format.equals("affine")) {
float[] matrix = TouchCalibration.IDENTITY.getAffineTransform(); throw new XmlPullParserException(
int depth = parser.getDepth(); "Unsupported format for calibration.");
while (XmlUtils.nextElementWithin(parser, depth)) { }
String tag = parser.getName().toLowerCase(); if (rotation != null) {
String value = parser.nextText(); try {
r = stringToSurfaceRotation(rotation);
} catch (IllegalArgumentException e) {
throw new XmlPullParserException(
"Unsupported rotation for calibration.");
}
}
for (int i = 0; i < matrix.length && i < CALIBRATION_NAME.length; i++) { float[] matrix = TouchCalibration.IDENTITY.getAffineTransform();
if (tag.equals(CALIBRATION_NAME[i])) { int depth = parser.getDepth();
matrix[i] = Float.parseFloat(value); while (XmlUtils.nextElementWithin(parser, depth)) {
break; String tag = parser.getName().toLowerCase();
} String value = parser.nextText();
for (int i = 0; i < matrix.length && i < CALIBRATION_NAME.length; i++) {
if (tag.equals(CALIBRATION_NAME[i])) {
matrix[i] = Float.parseFloat(value);
break;
} }
} }
mTouchCalibration = new TouchCalibration(matrix[0], matrix[1], matrix[2], }
matrix[3], matrix[4], matrix[5]);
if (r == -1) {
// Assume calibration applies to all rotations
for (r = 0; r < mTouchCalibration.length; r++) {
mTouchCalibration[r] = new TouchCalibration(matrix[0],
matrix[1], matrix[2], matrix[3], matrix[4], matrix[5]);
}
} else { } else {
throw new XmlPullParserException("Unsupported format for calibration."); mTouchCalibration[r] = new TouchCalibration(matrix[0],
matrix[1], matrix[2], matrix[3], matrix[4], matrix[5]);
} }
} }
} }
@@ -473,15 +510,48 @@ final class PersistentDataStore {
serializer.endTag(null, "keyboard-layout"); serializer.endTag(null, "keyboard-layout");
} }
serializer.startTag(null, "calibration"); for (int i = 0; i < mTouchCalibration.length; i++) {
serializer.attribute(null, "format", "affine"); if (mTouchCalibration[i] != null) {
float[] transform = mTouchCalibration.getAffineTransform(); String rotation = surfaceRotationToString(i);
for (int i = 0; i < transform.length && i < CALIBRATION_NAME.length; i++) { float[] transform = mTouchCalibration[i].getAffineTransform();
serializer.startTag(null, CALIBRATION_NAME[i]);
serializer.text(Float.toString(transform[i])); serializer.startTag(null, "calibration");
serializer.endTag(null, CALIBRATION_NAME[i]); serializer.attribute(null, "format", "affine");
serializer.attribute(null, "rotation", rotation);
for (int j = 0; j < transform.length && j < CALIBRATION_NAME.length; j++) {
serializer.startTag(null, CALIBRATION_NAME[j]);
serializer.text(Float.toString(transform[j]));
serializer.endTag(null, CALIBRATION_NAME[j]);
}
serializer.endTag(null, "calibration");
}
} }
serializer.endTag(null, "calibration"); }
private static String surfaceRotationToString(int surfaceRotation) {
switch (surfaceRotation) {
case Surface.ROTATION_0: return "0";
case Surface.ROTATION_90: return "90";
case Surface.ROTATION_180: return "180";
case Surface.ROTATION_270: return "270";
}
throw new IllegalArgumentException("Unsupported surface rotation value" + surfaceRotation);
}
private static int stringToSurfaceRotation(String s) {
if ("0".equals(s)) {
return Surface.ROTATION_0;
}
if ("90".equals(s)) {
return Surface.ROTATION_90;
}
if ("180".equals(s)) {
return Surface.ROTATION_180;
}
if ("270".equals(s)) {
return Surface.ROTATION_270;
}
throw new IllegalArgumentException("Unsupported surface rotation string '" + s + "'");
} }
} }
} }

View File

@@ -198,8 +198,10 @@ public:
virtual void notifyInputDevicesChanged(const Vector<InputDeviceInfo>& inputDevices); virtual void notifyInputDevicesChanged(const Vector<InputDeviceInfo>& inputDevices);
virtual sp<KeyCharacterMap> getKeyboardLayoutOverlay(const InputDeviceIdentifier& identifier); virtual sp<KeyCharacterMap> getKeyboardLayoutOverlay(const InputDeviceIdentifier& identifier);
virtual String8 getDeviceAlias(const InputDeviceIdentifier& identifier); virtual String8 getDeviceAlias(const InputDeviceIdentifier& identifier);
TouchAffineTransformation getTouchAffineTransformation(JNIEnv *env, jfloatArray matrixArr); virtual TouchAffineTransformation getTouchAffineTransformation(JNIEnv *env,
TouchAffineTransformation getTouchAffineTransformation(const String8& inputDeviceDescriptor); jfloatArray matrixArr);
virtual TouchAffineTransformation getTouchAffineTransformation(
const String8& inputDeviceDescriptor, int32_t surfaceRotation);
/* --- InputDispatcherPolicyInterface implementation --- */ /* --- InputDispatcherPolicyInterface implementation --- */
@@ -781,13 +783,14 @@ TouchAffineTransformation NativeInputManager::getTouchAffineTransformation(
} }
TouchAffineTransformation NativeInputManager::getTouchAffineTransformation( TouchAffineTransformation NativeInputManager::getTouchAffineTransformation(
const String8& inputDeviceDescriptor) { const String8& inputDeviceDescriptor, int32_t surfaceRotation) {
JNIEnv* env = jniEnv(); JNIEnv* env = jniEnv();
ScopedLocalRef<jstring> descriptorObj(env, env->NewStringUTF(inputDeviceDescriptor.string())); ScopedLocalRef<jstring> descriptorObj(env, env->NewStringUTF(inputDeviceDescriptor.string()));
jobject cal = env->CallObjectMethod(mServiceObj, jobject cal = env->CallObjectMethod(mServiceObj,
gServiceClassInfo.getTouchCalibrationForInputDevice, descriptorObj.get()); gServiceClassInfo.getTouchCalibrationForInputDevice, descriptorObj.get(),
surfaceRotation);
jfloatArray matrixArr = jfloatArray(env->CallObjectMethod(cal, jfloatArray matrixArr = jfloatArray(env->CallObjectMethod(cal,
gTouchCalibrationClassInfo.getAffineTransform)); gTouchCalibrationClassInfo.getAffineTransform));
@@ -1506,7 +1509,7 @@ int register_android_server_InputManager(JNIEnv* env) {
GET_METHOD_ID(gServiceClassInfo.getTouchCalibrationForInputDevice, clazz, GET_METHOD_ID(gServiceClassInfo.getTouchCalibrationForInputDevice, clazz,
"getTouchCalibrationForInputDevice", "getTouchCalibrationForInputDevice",
"(Ljava/lang/String;)Landroid/hardware/input/TouchCalibration;"); "(Ljava/lang/String;I)Landroid/hardware/input/TouchCalibration;");
// InputDevice // InputDevice