summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--core/java/android/hardware/input/IInputManager.aidl6
-rw-r--r--core/java/android/hardware/input/InputManager.java38
-rw-r--r--core/java/android/hardware/input/TouchCalibration.aidl19
-rw-r--r--core/java/android/hardware/input/TouchCalibration.java126
-rw-r--r--core/res/AndroidManifest.xml8
-rw-r--r--core/res/res/values/strings.xml4
-rw-r--r--services/core/java/com/android/server/input/InputManagerService.java35
-rw-r--r--services/core/java/com/android/server/input/PersistentDataStore.java73
8 files changed, 308 insertions, 1 deletions
diff --git a/core/java/android/hardware/input/IInputManager.aidl b/core/java/android/hardware/input/IInputManager.aidl
index f1e7e98..4214115 100644
--- a/core/java/android/hardware/input/IInputManager.aidl
+++ b/core/java/android/hardware/input/IInputManager.aidl
@@ -19,6 +19,7 @@ package android.hardware.input;
import android.hardware.input.InputDeviceIdentifier;
import android.hardware.input.KeyboardLayout;
import android.hardware.input.IInputDevicesChangedListener;
+import android.hardware.input.TouchCalibration;
import android.os.IBinder;
import android.view.InputDevice;
import android.view.InputEvent;
@@ -39,6 +40,11 @@ interface IInputManager {
// applications, the caller must have the INJECT_EVENTS permission.
boolean injectInputEvent(in InputEvent ev, int mode);
+ // Calibrate input device position
+ TouchCalibration getTouchCalibrationForInputDevice(String inputDeviceDescriptor);
+ void setTouchCalibrationForInputDevice(String inputDeviceDescriptor,
+ in TouchCalibration calibration);
+
// Keyboard layouts configuration.
KeyboardLayout[] getKeyboardLayouts();
KeyboardLayout getKeyboardLayout(String keyboardLayoutDescriptor);
diff --git a/core/java/android/hardware/input/InputManager.java b/core/java/android/hardware/input/InputManager.java
index a2aeafb..ece5d82 100644
--- a/core/java/android/hardware/input/InputManager.java
+++ b/core/java/android/hardware/input/InputManager.java
@@ -500,6 +500,44 @@ public final class InputManager {
}
/**
+ * Gets the TouchCalibration applied to the specified input device's coordinates.
+ *
+ * @param inputDeviceDescriptor The input device descriptor.
+ * @return The TouchCalibration currently assigned for use with the given
+ * input device. If none is set, an identity TouchCalibration is returned.
+ *
+ * @hide
+ */
+ public TouchCalibration getTouchCalibration(String inputDeviceDescriptor) {
+ try {
+ return mIm.getTouchCalibrationForInputDevice(inputDeviceDescriptor);
+ } catch (RemoteException ex) {
+ Log.w(TAG, "Could not get calibration matrix for input device.", ex);
+ return TouchCalibration.IDENTITY;
+ }
+ }
+
+ /**
+ * Sets the TouchCalibration to apply to the specified input device's coordinates.
+ * <p>
+ * This method may have the side-effect of causing the input device in question
+ * to be reconfigured. Requires {@link android.Manifest.permissions.SET_INPUT_CALIBRATION}.
+ * </p>
+ *
+ * @param inputDeviceDescriptor The input device descriptor.
+ * @param calibration The calibration to be applied
+ *
+ * @hide
+ */
+ public void setTouchCalibration(String inputDeviceDescriptor, TouchCalibration calibration) {
+ try {
+ mIm.setTouchCalibrationForInputDevice(inputDeviceDescriptor, calibration);
+ } catch (RemoteException ex) {
+ Log.w(TAG, "Could not set calibration matrix for input device.", ex);
+ }
+ }
+
+ /**
* Gets the mouse pointer speed.
* <p>
* Only returns the permanent mouse pointer speed. Ignores any temporary pointer
diff --git a/core/java/android/hardware/input/TouchCalibration.aidl b/core/java/android/hardware/input/TouchCalibration.aidl
new file mode 100644
index 0000000..2c28774
--- /dev/null
+++ b/core/java/android/hardware/input/TouchCalibration.aidl
@@ -0,0 +1,19 @@
+/*
+ * Copyright (C) 2014 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.hardware.input;
+
+parcelable TouchCalibration;
diff --git a/core/java/android/hardware/input/TouchCalibration.java b/core/java/android/hardware/input/TouchCalibration.java
new file mode 100644
index 0000000..025fad0
--- /dev/null
+++ b/core/java/android/hardware/input/TouchCalibration.java
@@ -0,0 +1,126 @@
+/*
+ * Copyright (C) 2014 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.hardware.input;
+
+import android.os.Parcel;
+import android.os.Parcelable;
+
+/**
+ * Encapsulates calibration data for input devices.
+ *
+ * @hide
+ */
+public class TouchCalibration implements Parcelable {
+
+ public static final TouchCalibration IDENTITY = new TouchCalibration();
+
+ public static final Parcelable.Creator<TouchCalibration> CREATOR
+ = new Parcelable.Creator<TouchCalibration>() {
+ public TouchCalibration createFromParcel(Parcel in) {
+ return new TouchCalibration(in);
+ }
+
+ public TouchCalibration[] newArray(int size) {
+ return new TouchCalibration[size];
+ }
+ };
+
+ private final float mXScale, mXYMix, mXOffset;
+ private final float mYXMix, mYScale, mYOffset;
+
+ /**
+ * Create a new TouchCalibration initialized to the identity transformation.
+ */
+ public TouchCalibration() {
+ this(1,0,0,0,1,0);
+ }
+
+ /**
+ * Create a new TouchCalibration from affine transformation paramters.
+ * @param xScale Influence of input x-axis value on output x-axis value.
+ * @param xyMix Influence of input y-axis value on output x-axis value.
+ * @param xOffset Constant offset to be applied to output x-axis value.
+ * @param yXMix Influence of input x-axis value on output y-axis value.
+ * @param yScale Influence of input y-axis value on output y-axis value.
+ * @param yOffset Constant offset to be applied to output y-axis value.
+ */
+ public TouchCalibration(float xScale, float xyMix, float xOffset,
+ float yxMix, float yScale, float yOffset) {
+ mXScale = xScale;
+ mXYMix = xyMix;
+ mXOffset = xOffset;
+ mYXMix = yxMix;
+ mYScale = yScale;
+ mYOffset = yOffset;
+ }
+
+ public TouchCalibration(Parcel in) {
+ mXScale = in.readFloat();
+ mXYMix = in.readFloat();
+ mXOffset = in.readFloat();
+ mYXMix = in.readFloat();
+ mYScale = in.readFloat();
+ mYOffset = in.readFloat();
+ }
+
+ @Override
+ public void writeToParcel(Parcel dest, int flags) {
+ dest.writeFloat(mXScale);
+ dest.writeFloat(mXYMix);
+ dest.writeFloat(mXOffset);
+ dest.writeFloat(mYXMix);
+ dest.writeFloat(mYScale);
+ dest.writeFloat(mYOffset);
+ }
+
+ @Override
+ public int describeContents() {
+ return 0;
+ }
+
+ public float[] getAffineTransform() {
+ return new float[] { mXScale, mXYMix, mXOffset, mYXMix, mYScale, mYOffset };
+ }
+
+ @Override
+ public boolean equals(Object obj) {
+ if (obj == this) {
+ return true;
+ } else if (obj instanceof TouchCalibration) {
+ TouchCalibration cal = (TouchCalibration)obj;
+
+ return (cal.mXScale == mXScale) &&
+ (cal.mXYMix == mXYMix) &&
+ (cal.mXOffset == mXOffset) &&
+ (cal.mYXMix == mYXMix) &&
+ (cal.mYScale == mYScale) &&
+ (cal.mYOffset == mYOffset);
+ } else {
+ return false;
+ }
+ }
+
+ @Override
+ public int hashCode() {
+ return Float.floatToIntBits(mXScale) ^
+ Float.floatToIntBits(mXYMix) ^
+ Float.floatToIntBits(mXOffset) ^
+ Float.floatToIntBits(mYXMix) ^
+ Float.floatToIntBits(mYScale) ^
+ Float.floatToIntBits(mYOffset);
+ }
+}
diff --git a/core/res/AndroidManifest.xml b/core/res/AndroidManifest.xml
index 4c0ddeb..b99cb90 100644
--- a/core/res/AndroidManifest.xml
+++ b/core/res/AndroidManifest.xml
@@ -2069,6 +2069,14 @@
android:description="@string/permdesc_setPointerSpeed"
android:protectionLevel="signature" />
+ <!-- Allows low-level access to setting input device calibration.
+ <p>Not for use by normal applications.
+ @hide -->
+ <permission android:name="android.permission.SET_INPUT_CALIBRATION"
+ android:label="@string/permlab_setInputCalibration"
+ android:description="@string/permdesc_setInputCalibration"
+ android:protectionLevel="signature" />
+
<!-- Allows low-level access to setting the keyboard layout.
<p>Not for use by third-party applications.
@hide -->
diff --git a/core/res/res/values/strings.xml b/core/res/res/values/strings.xml
index afb7085..f1bcf65 100644
--- a/core/res/res/values/strings.xml
+++ b/core/res/res/values/strings.xml
@@ -2012,6 +2012,10 @@
<!-- Description of an application permission, listed so the user can choose whether they want to allow the application to do this. -->
<string name="permdesc_accessNetworkConditions">Allows an application to listen for observations on network conditions. Should never be needed for normal apps.</string>
+ <string name="permlab_setInputCalibration">change input device calibration</string>
+ <!-- Description of an application permission, listed so the user can choose whether they want to allow the application to do this. -->
+ <string name="permdesc_setInputCalibration">Allows the app to modify the calibration parameters of the touch screen. Should never be needed for normal apps.</string>
+
<!-- Policy administration -->
<!-- Title of policy access to limiting the user's password choices -->
diff --git a/services/core/java/com/android/server/input/InputManagerService.java b/services/core/java/com/android/server/input/InputManagerService.java
index e49382e..16972f6 100644
--- a/services/core/java/com/android/server/input/InputManagerService.java
+++ b/services/core/java/com/android/server/input/InputManagerService.java
@@ -52,6 +52,7 @@ import android.hardware.input.InputDeviceIdentifier;
import android.hardware.input.InputManager;
import android.hardware.input.InputManagerInternal;
import android.hardware.input.KeyboardLayout;
+import android.hardware.input.TouchCalibration;
import android.os.Binder;
import android.os.Bundle;
import android.os.Environment;
@@ -700,6 +701,40 @@ public class InputManagerService extends IInputManager.Stub
mTempFullKeyboards.clear();
}
+ @Override // Binder call
+ public TouchCalibration getTouchCalibrationForInputDevice(String inputDeviceDescriptor) {
+ if (inputDeviceDescriptor == null) {
+ throw new IllegalArgumentException("inputDeviceDescriptor must not be null");
+ }
+
+ synchronized (mDataStore) {
+ return mDataStore.getTouchCalibration(inputDeviceDescriptor);
+ }
+ }
+
+ @Override // Binder call
+ public void setTouchCalibrationForInputDevice(String inputDeviceDescriptor,
+ TouchCalibration calibration) {
+ if (!checkCallingPermission(android.Manifest.permission.SET_INPUT_CALIBRATION,
+ "setTouchCalibrationForInputDevice()")) {
+ throw new SecurityException("Requires SET_INPUT_CALIBRATION permission");
+ }
+ if (inputDeviceDescriptor == null) {
+ throw new IllegalArgumentException("inputDeviceDescriptor must not be null");
+ }
+ if (calibration == null) {
+ throw new IllegalArgumentException("calibration must not be null");
+ }
+
+ synchronized (mDataStore) {
+ try {
+ mDataStore.setTouchCalibration(inputDeviceDescriptor, calibration);
+ } finally {
+ mDataStore.saveIfNeeded();
+ }
+ }
+ }
+
// Must be called on handler.
private void showMissingKeyboardLayoutNotification() {
if (!mKeyboardLayoutNotificationShown) {
diff --git a/services/core/java/com/android/server/input/PersistentDataStore.java b/services/core/java/com/android/server/input/PersistentDataStore.java
index 71de776..9ea369d 100644
--- a/services/core/java/com/android/server/input/PersistentDataStore.java
+++ b/services/core/java/com/android/server/input/PersistentDataStore.java
@@ -24,6 +24,7 @@ import org.xmlpull.v1.XmlPullParser;
import org.xmlpull.v1.XmlPullParserException;
import org.xmlpull.v1.XmlSerializer;
+import android.hardware.input.TouchCalibration;
import android.util.AtomicFile;
import android.util.Slog;
import android.util.Xml;
@@ -82,6 +83,25 @@ final class PersistentDataStore {
}
}
+ public TouchCalibration getTouchCalibration(String inputDeviceDescriptor) {
+ InputDeviceState state = getInputDeviceState(inputDeviceDescriptor, false);
+ if (state == null) {
+ return TouchCalibration.IDENTITY;
+ }
+ else {
+ return state.getTouchCalibration();
+ }
+ }
+
+ public boolean setTouchCalibration(String inputDeviceDescriptor, TouchCalibration calibration) {
+ InputDeviceState state = getInputDeviceState(inputDeviceDescriptor, true);
+ if (state.setTouchCalibration(calibration)) {
+ setDirty();
+ return true;
+ }
+ return false;
+ }
+
public String getCurrentKeyboardLayout(String inputDeviceDescriptor) {
InputDeviceState state = getInputDeviceState(inputDeviceDescriptor, false);
return state != null ? state.getCurrentKeyboardLayout() : null;
@@ -275,9 +295,25 @@ final class PersistentDataStore {
}
private static final class InputDeviceState {
+ private static final String[] CALIBRATION_NAME = { "x_scale",
+ "x_ymix", "x_offset", "y_xmix", "y_scale", "y_offset" };
+
+ private TouchCalibration mTouchCalibration = TouchCalibration.IDENTITY;
private String mCurrentKeyboardLayout;
private ArrayList<String> mKeyboardLayouts = new ArrayList<String>();
+ public TouchCalibration getTouchCalibration() {
+ return mTouchCalibration;
+ }
+
+ public boolean setTouchCalibration(TouchCalibration calibration) {
+ if (calibration.equals(mTouchCalibration)) {
+ return false;
+ }
+ mTouchCalibration = calibration;
+ return true;
+ }
+
public String getCurrentKeyboardLayout() {
return mCurrentKeyboardLayout;
}
@@ -389,6 +425,31 @@ final class PersistentDataStore {
}
mCurrentKeyboardLayout = descriptor;
}
+ } else if (parser.getName().equals("calibration")) {
+ String format = parser.getAttributeValue(null, "format");
+ 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();
+
+ 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]);
+ } else {
+ throw new XmlPullParserException("Unsupported format for calibration.");
+ }
}
}
@@ -411,6 +472,16 @@ 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]);
+ }
+ serializer.endTag(null, "calibration");
}
}
-} \ No newline at end of file
+}