Merge "Introduce mAffineCalibration for location calibration"
diff --git a/services/inputflinger/InputReader.cpp b/services/inputflinger/InputReader.cpp
index 5eaf00b..9a4f848 100644
--- a/services/inputflinger/InputReader.cpp
+++ b/services/inputflinger/InputReader.cpp
@@ -218,6 +218,17 @@
 }
 
 
+// -- TouchAffineTransformation --
+void TouchAffineTransformation::applyTo(float& x, float& y) const {
+    float newX, newY;
+    newX = x * x_scale + y * x_ymix + x_offset;
+    newY = x * y_xmix + y * y_scale + y_offset;
+
+    x = newX;
+    y = newY;
+}
+
+
 // --- InputReader ---
 
 InputReader::InputReader(const sp<EventHubInterface>& eventHub,
@@ -2642,6 +2653,7 @@
     dumpVirtualKeys(dump);
     dumpRawPointerAxes(dump);
     dumpCalibration(dump);
+    dumpAffineTransformation(dump);
     dumpSurface(dump);
 
     dump.appendFormat(INDENT3 "Translation and Scaling Factors:\n");
@@ -3631,6 +3643,17 @@
     }
 }
 
+void TouchInputMapper::dumpAffineTransformation(String8& dump) {
+    dump.append(INDENT3 "Affine Transformation:\n");
+
+    dump.appendFormat(INDENT4 "X scale: %0.3f\n", mAffineTransform.x_scale);
+    dump.appendFormat(INDENT4 "X ymix: %0.3f\n", mAffineTransform.x_ymix);
+    dump.appendFormat(INDENT4 "X offset: %0.3f\n", mAffineTransform.x_offset);
+    dump.appendFormat(INDENT4 "Y xmix: %0.3f\n", mAffineTransform.y_xmix);
+    dump.appendFormat(INDENT4 "Y scale: %0.3f\n", mAffineTransform.y_scale);
+    dump.appendFormat(INDENT4 "Y offset: %0.3f\n", mAffineTransform.y_offset);
+}
+
 void TouchInputMapper::reset(nsecs_t when) {
     mCursorButtonAccumulator.reset(getDevice());
     mCursorScrollAccumulator.reset(getDevice());
@@ -4246,13 +4269,19 @@
             break;
         }
 
-        // X, Y, and the bounding box for coverage information
-        // Adjust coords for surface orientation.
-        float x, y, left, top, right, bottom;
+        // Adjust X,Y coords for device calibration
+        // TODO: Adjust coverage coords?
+        float xTransformed = in.x, yTransformed = in.y;
+        mAffineTransform.applyTo(xTransformed, yTransformed);
+
+        // Adjust X, Y, and coverage coords for surface orientation.
+        float x, y;
+        float left, top, right, bottom;
+
         switch (mSurfaceOrientation) {
         case DISPLAY_ORIENTATION_90:
-            x = float(in.y - mRawPointerAxes.y.minValue) * mYScale + mYTranslate;
-            y = float(mRawPointerAxes.x.maxValue - in.x) * mXScale + mXTranslate;
+            x = float(yTransformed - mRawPointerAxes.y.minValue) * mYScale + mYTranslate;
+            y = float(mRawPointerAxes.x.maxValue - xTransformed) * mXScale + mXTranslate;
             left = float(rawTop - mRawPointerAxes.y.minValue) * mYScale + mYTranslate;
             right = float(rawBottom- mRawPointerAxes.y.minValue) * mYScale + mYTranslate;
             bottom = float(mRawPointerAxes.x.maxValue - rawLeft) * mXScale + mXTranslate;
@@ -4263,8 +4292,8 @@
             }
             break;
         case DISPLAY_ORIENTATION_180:
-            x = float(mRawPointerAxes.x.maxValue - in.x) * mXScale + mXTranslate;
-            y = float(mRawPointerAxes.y.maxValue - in.y) * mYScale + mYTranslate;
+            x = float(mRawPointerAxes.x.maxValue - xTransformed) * mXScale + mXTranslate;
+            y = float(mRawPointerAxes.y.maxValue - yTransformed) * mYScale + mYTranslate;
             left = float(mRawPointerAxes.x.maxValue - rawRight) * mXScale + mXTranslate;
             right = float(mRawPointerAxes.x.maxValue - rawLeft) * mXScale + mXTranslate;
             bottom = float(mRawPointerAxes.y.maxValue - rawTop) * mYScale + mYTranslate;
@@ -4275,8 +4304,8 @@
             }
             break;
         case DISPLAY_ORIENTATION_270:
-            x = float(mRawPointerAxes.y.maxValue - in.y) * mYScale + mYTranslate;
-            y = float(in.x - mRawPointerAxes.x.minValue) * mXScale + mXTranslate;
+            x = float(mRawPointerAxes.y.maxValue - yTransformed) * mYScale + mYTranslate;
+            y = float(xTransformed - mRawPointerAxes.x.minValue) * mXScale + mXTranslate;
             left = float(mRawPointerAxes.y.maxValue - rawBottom) * mYScale + mYTranslate;
             right = float(mRawPointerAxes.y.maxValue - rawTop) * mYScale + mYTranslate;
             bottom = float(rawRight - mRawPointerAxes.x.minValue) * mXScale + mXTranslate;
@@ -4287,8 +4316,8 @@
             }
             break;
         default:
-            x = float(in.x - mRawPointerAxes.x.minValue) * mXScale + mXTranslate;
-            y = float(in.y - mRawPointerAxes.y.minValue) * mYScale + mYTranslate;
+            x = float(xTransformed - mRawPointerAxes.x.minValue) * mXScale + mXTranslate;
+            y = float(yTransformed - mRawPointerAxes.y.minValue) * mYScale + mYTranslate;
             left = float(rawLeft - mRawPointerAxes.x.minValue) * mXScale + mXTranslate;
             right = float(rawRight - mRawPointerAxes.x.minValue) * mXScale + mXTranslate;
             bottom = float(rawBottom - mRawPointerAxes.y.minValue) * mYScale + mYTranslate;
diff --git a/services/inputflinger/InputReader.h b/services/inputflinger/InputReader.h
index 36b206a..5c72c71 100644
--- a/services/inputflinger/InputReader.h
+++ b/services/inputflinger/InputReader.h
@@ -252,6 +252,23 @@
 };
 
 
+struct TouchAffineTransformation {
+    float x_scale;
+    float x_ymix;
+    float x_offset;
+    float y_xmix;
+    float y_scale;
+    float y_offset;
+
+    TouchAffineTransformation() :
+        x_scale(1.0f), x_ymix(0.0f), x_offset(0.0f),
+        y_xmix(0.0f), y_scale(1.0f), y_offset(0.0f) {
+    }
+
+    void applyTo(float& x, float& y) const;
+};
+
+
 /*
  * Input reader policy interface.
  *
@@ -1295,6 +1312,9 @@
         }
     } mCalibration;
 
+    // Affine location transformation/calibration
+    struct TouchAffineTransformation mAffineTransform;
+
     // Raw pointer axis information from the driver.
     RawPointerAxes mRawPointerAxes;
 
@@ -1344,6 +1364,7 @@
     virtual void parseCalibration();
     virtual void resolveCalibration();
     virtual void dumpCalibration(String8& dump);
+    virtual void dumpAffineTransformation(String8& dump);
     virtual bool hasStylus() const = 0;
 
     virtual void syncTouch(nsecs_t when, bool* outHavePointerIds) = 0;