Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit d5220742 authored by Jason Gerecke's avatar Jason Gerecke Committed by Michael Wright
Browse files

Support unique calibration per orientation

Updates the format of the calibration XML to store the Surface rotation
that a specific calibration applies to. Also updates the API to require
a rotation value for get/set, and has the native framework supply this
according to the current rotation whenever it changes.

Change-Id: I72b6703f646dd18db537365c5c9843f720a5f41e
parent 857aa7be
Loading
Loading
Loading
Loading
+2 −2
Original line number Diff line number Diff line
@@ -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.
+5 −4
Original line number Diff line number Diff line
@@ -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);
        }
+10 −4
Original line number Diff line number Diff line
@@ -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 {
+105 −35
Original line number Diff line number Diff line
@@ -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,11 +443,26 @@ 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")) {
                    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.");
                        }
                    }

                    float[] matrix = TouchCalibration.IDENTITY.getAffineTransform();
                    int depth = parser.getDepth();
                    while (XmlUtils.nextElementWithin(parser, depth)) {
@@ -445,10 +476,16 @@ final class PersistentDataStore {
                            }
                        }
                    }
                        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");
            }

            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");
            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.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");
                }
            }
        }

        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 + "'");
        }
    }
}
+8 −5
Original line number Diff line number Diff line
@@ -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