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);
// Calibrate input device position
TouchCalibration getTouchCalibrationForInputDevice(String inputDeviceDescriptor);
void setTouchCalibrationForInputDevice(String inputDeviceDescriptor,
TouchCalibration getTouchCalibrationForInputDevice(String inputDeviceDescriptor, int rotation);
void setTouchCalibrationForInputDevice(String inputDeviceDescriptor, int rotation,
in TouchCalibration calibration);
// Keyboard layouts configuration.

View File

@@ -508,9 +508,9 @@ public final class InputManager {
*
* @hide
*/
public TouchCalibration getTouchCalibration(String inputDeviceDescriptor) {
public TouchCalibration getTouchCalibration(String inputDeviceDescriptor, int surfaceRotation) {
try {
return mIm.getTouchCalibrationForInputDevice(inputDeviceDescriptor);
return mIm.getTouchCalibrationForInputDevice(inputDeviceDescriptor, surfaceRotation);
} catch (RemoteException ex) {
Log.w(TAG, "Could not get calibration matrix for input device.", ex);
return TouchCalibration.IDENTITY;
@@ -529,9 +529,10 @@ public final class InputManager {
*
* @hide
*/
public void setTouchCalibration(String inputDeviceDescriptor, TouchCalibration calibration) {
public void setTouchCalibration(String inputDeviceDescriptor, int surfaceRotation,
TouchCalibration calibration) {
try {
mIm.setTouchCalibrationForInputDevice(inputDeviceDescriptor, calibration);
mIm.setTouchCalibrationForInputDevice(inputDeviceDescriptor, surfaceRotation, calibration);
} catch (RemoteException 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.KeyEvent;
import android.view.PointerIcon;
import android.view.Surface;
import android.view.ViewConfiguration;
import android.view.WindowManagerPolicy;
import android.widget.Toast;
@@ -703,18 +704,19 @@ public class InputManagerService extends IInputManager.Stub
}
@Override // Binder call & native callback
public TouchCalibration getTouchCalibrationForInputDevice(String inputDeviceDescriptor) {
public TouchCalibration getTouchCalibrationForInputDevice(String inputDeviceDescriptor,
int surfaceRotation) {
if (inputDeviceDescriptor == null) {
throw new IllegalArgumentException("inputDeviceDescriptor must not be null");
}
synchronized (mDataStore) {
return mDataStore.getTouchCalibration(inputDeviceDescriptor);
return mDataStore.getTouchCalibration(inputDeviceDescriptor, surfaceRotation);
}
}
@Override // Binder call
public void setTouchCalibrationForInputDevice(String inputDeviceDescriptor,
public void setTouchCalibrationForInputDevice(String inputDeviceDescriptor, int surfaceRotation,
TouchCalibration calibration) {
if (!checkCallingPermission(android.Manifest.permission.SET_INPUT_CALIBRATION,
"setTouchCalibrationForInputDevice()")) {
@@ -726,10 +728,14 @@ public class InputManagerService extends IInputManager.Stub
if (calibration == 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) {
try {
if (mDataStore.setTouchCalibration(inputDeviceDescriptor, calibration)) {
if (mDataStore.setTouchCalibration(inputDeviceDescriptor, surfaceRotation,
calibration)) {
nativeReloadCalibration(mPtr);
}
} finally {

View File

@@ -24,6 +24,7 @@ import org.xmlpull.v1.XmlPullParser;
import org.xmlpull.v1.XmlPullParserException;
import org.xmlpull.v1.XmlSerializer;
import android.view.Surface;
import android.hardware.input.TouchCalibration;
import android.util.AtomicFile;
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);
if (state == null) {
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);
if (state.setTouchCalibration(calibration)) {
if (state.setTouchCalibration(surfaceRotation, calibration)) {
setDirty();
return true;
}
return false;
}
@@ -298,20 +304,30 @@ final class PersistentDataStore {
private static final String[] CALIBRATION_NAME = { "x_scale",
"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 ArrayList<String> mKeyboardLayouts = new ArrayList<String>();
public TouchCalibration getTouchCalibration() {
return mTouchCalibration;
public TouchCalibration getTouchCalibration(int surfaceRotation) {
try {
return mTouchCalibration[surfaceRotation];
} catch (ArrayIndexOutOfBoundsException ex) {
Slog.w(InputManagerService.TAG, "Cannot get touch calibration.", ex);
return null;
}
}
public boolean setTouchCalibration(TouchCalibration calibration) {
if (calibration.equals(mTouchCalibration)) {
public boolean setTouchCalibration(int surfaceRotation, TouchCalibration calibration) {
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;
}
mTouchCalibration = calibration;
return true;
}
public String getCurrentKeyboardLayout() {
@@ -427,28 +443,49 @@ final class PersistentDataStore {
}
} else if (parser.getName().equals("calibration")) {
String format = parser.getAttributeValue(null, "format");
String rotation = parser.getAttributeValue(null, "rotation");
int r = -1;
if (format == null) {
throw new XmlPullParserException(
"Missing format attribute on calibration.");
}
if (format.equals("affine")) {
float[] matrix = TouchCalibration.IDENTITY.getAffineTransform();
int depth = parser.getDepth();
while (XmlUtils.nextElementWithin(parser, depth)) {
String tag = parser.getName().toLowerCase();
String value = parser.nextText();
if (!format.equals("affine")) {
throw new XmlPullParserException(
"Unsupported format for calibration.");
}
if (rotation != null) {
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++) {
if (tag.equals(CALIBRATION_NAME[i])) {
matrix[i] = Float.parseFloat(value);
break;
}
float[] matrix = TouchCalibration.IDENTITY.getAffineTransform();
int depth = parser.getDepth();
while (XmlUtils.nextElementWithin(parser, depth)) {
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 {
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.startTag(null, "calibration");
serializer.attribute(null, "format", "affine");
float[] transform = mTouchCalibration.getAffineTransform();
for (int i = 0; i < transform.length && i < CALIBRATION_NAME.length; i++) {
serializer.startTag(null, CALIBRATION_NAME[i]);
serializer.text(Float.toString(transform[i]));
serializer.endTag(null, CALIBRATION_NAME[i]);
for (int i = 0; i < mTouchCalibration.length; i++) {
if (mTouchCalibration[i] != null) {
String rotation = surfaceRotationToString(i);
float[] transform = mTouchCalibration[i].getAffineTransform();
serializer.startTag(null, "calibration");
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 sp<KeyCharacterMap> getKeyboardLayoutOverlay(const InputDeviceIdentifier& identifier);
virtual String8 getDeviceAlias(const InputDeviceIdentifier& identifier);
TouchAffineTransformation getTouchAffineTransformation(JNIEnv *env, jfloatArray matrixArr);
TouchAffineTransformation getTouchAffineTransformation(const String8& inputDeviceDescriptor);
virtual TouchAffineTransformation getTouchAffineTransformation(JNIEnv *env,
jfloatArray matrixArr);
virtual TouchAffineTransformation getTouchAffineTransformation(
const String8& inputDeviceDescriptor, int32_t surfaceRotation);
/* --- InputDispatcherPolicyInterface implementation --- */
@@ -781,13 +783,14 @@ TouchAffineTransformation NativeInputManager::getTouchAffineTransformation(
}
TouchAffineTransformation NativeInputManager::getTouchAffineTransformation(
const String8& inputDeviceDescriptor) {
const String8& inputDeviceDescriptor, int32_t surfaceRotation) {
JNIEnv* env = jniEnv();
ScopedLocalRef<jstring> descriptorObj(env, env->NewStringUTF(inputDeviceDescriptor.string()));
jobject cal = env->CallObjectMethod(mServiceObj,
gServiceClassInfo.getTouchCalibrationForInputDevice, descriptorObj.get());
gServiceClassInfo.getTouchCalibrationForInputDevice, descriptorObj.get(),
surfaceRotation);
jfloatArray matrixArr = jfloatArray(env->CallObjectMethod(cal,
gTouchCalibrationClassInfo.getAffineTransform));
@@ -1506,7 +1509,7 @@ int register_android_server_InputManager(JNIEnv* env) {
GET_METHOD_ID(gServiceClassInfo.getTouchCalibrationForInputDevice, clazz,
"getTouchCalibrationForInputDevice",
"(Ljava/lang/String;)Landroid/hardware/input/TouchCalibration;");
"(Ljava/lang/String;I)Landroid/hardware/input/TouchCalibration;");
// InputDevice