Add test for InputReader location calibration

This patch adds a test for the new native location calibration
code. The Java interface is not tested.

Change-Id: Id7496486f6b6e2ade12ada607b62d1594af488e8
diff --git a/services/inputflinger/InputReader.h b/services/inputflinger/InputReader.h
index 0e57bcd..43d4869 100644
--- a/services/inputflinger/InputReader.h
+++ b/services/inputflinger/InputReader.h
@@ -268,6 +268,12 @@
         y_xmix(0.0f), y_scale(1.0f), y_offset(0.0f) {
     }
 
+    TouchAffineTransformation(float xscale, float xymix, float xoffset,
+            float yxmix, float yscale, float yoffset) :
+        x_scale(xscale), x_ymix(xymix), x_offset(xoffset),
+        y_xmix(yxmix), y_scale(yscale), y_offset(yoffset) {
+    }
+
     void applyTo(float& x, float& y) const;
 };
 
diff --git a/services/inputflinger/tests/InputReader_test.cpp b/services/inputflinger/tests/InputReader_test.cpp
index 140d169..34d70ae 100644
--- a/services/inputflinger/tests/InputReader_test.cpp
+++ b/services/inputflinger/tests/InputReader_test.cpp
@@ -128,6 +128,7 @@
     InputReaderConfiguration mConfig;
     KeyedVector<int32_t, sp<FakePointerController> > mPointerControllers;
     Vector<InputDeviceInfo> mInputDevices;
+    TouchAffineTransformation transform;
 
 protected:
     virtual ~FakeInputReaderPolicy() { }
@@ -174,7 +175,11 @@
     }
 
     TouchAffineTransformation getTouchAffineTransformation(const String8& inputDeviceDescriptor) {
-        return TouchAffineTransformation();
+        return transform;
+    }
+
+    void setTouchAffineTransformation(const TouchAffineTransformation t) {
+        transform = t;
     }
 
 private:
@@ -2467,6 +2472,7 @@
     static const float Y_PRECISION;
 
     static const float GEOMETRIC_SCALE;
+    static const TouchAffineTransformation AFFINE_TRANSFORM;
 
     static const VirtualKeyDefinition VIRTUAL_KEYS[2];
 
@@ -2486,8 +2492,11 @@
 
     void prepareDisplay(int32_t orientation);
     void prepareVirtualKeys();
+    void prepareLocationCalibration();
     int32_t toRawX(float displayX);
     int32_t toRawY(float displayY);
+    float toCookedX(float rawX, float rawY);
+    float toCookedY(float rawX, float rawY);
     float toDisplayX(int32_t rawX);
     float toDisplayY(int32_t rawY);
 };
@@ -2514,6 +2523,8 @@
 const int32_t TouchInputMapperTest::RAW_SLOT_MAX = 9;
 const float TouchInputMapperTest::X_PRECISION = float(RAW_X_MAX - RAW_X_MIN + 1) / DISPLAY_WIDTH;
 const float TouchInputMapperTest::Y_PRECISION = float(RAW_Y_MAX - RAW_Y_MIN + 1) / DISPLAY_HEIGHT;
+const TouchAffineTransformation TouchInputMapperTest::AFFINE_TRANSFORM =
+        TouchAffineTransformation(1, -2, 3, -4, 5, -6);
 
 const float TouchInputMapperTest::GEOMETRIC_SCALE =
         avg(float(DISPLAY_WIDTH) / (RAW_X_MAX - RAW_X_MIN + 1),
@@ -2535,6 +2546,10 @@
     mFakeEventHub->addKey(DEVICE_ID, KEY_MENU, 0, AKEYCODE_MENU, POLICY_FLAG_WAKE);
 }
 
+void TouchInputMapperTest::prepareLocationCalibration() {
+    mFakePolicy->setTouchAffineTransformation(AFFINE_TRANSFORM);
+}
+
 int32_t TouchInputMapperTest::toRawX(float displayX) {
     return int32_t(displayX * (RAW_X_MAX - RAW_X_MIN + 1) / DISPLAY_WIDTH + RAW_X_MIN);
 }
@@ -2543,6 +2558,16 @@
     return int32_t(displayY * (RAW_Y_MAX - RAW_Y_MIN + 1) / DISPLAY_HEIGHT + RAW_Y_MIN);
 }
 
+float TouchInputMapperTest::toCookedX(float rawX, float rawY) {
+    AFFINE_TRANSFORM.applyTo(rawX, rawY);
+    return rawX;
+}
+
+float TouchInputMapperTest::toCookedY(float rawX, float rawY) {
+    AFFINE_TRANSFORM.applyTo(rawX, rawY);
+    return rawY;
+}
+
 float TouchInputMapperTest::toDisplayX(int32_t rawX) {
     return float(rawX - RAW_X_MIN) * DISPLAY_WIDTH / (RAW_X_MAX - RAW_X_MIN + 1);
 }
@@ -3230,6 +3255,30 @@
     ASSERT_EQ(tilt, args.pointerCoords[0].getAxisValue(AMOTION_EVENT_AXIS_TILT));
 }
 
+TEST_F(SingleTouchInputMapperTest, Process_XYAxes_AffineCalibration) {
+    SingleTouchInputMapper* mapper = new SingleTouchInputMapper(mDevice);
+    addConfigurationProperty("touch.deviceType", "touchScreen");
+    prepareDisplay(DISPLAY_ORIENTATION_0);
+    prepareLocationCalibration();
+    prepareButtons();
+    prepareAxes(POSITION);
+    addMapperAndConfigure(mapper);
+
+    int32_t rawX = 100;
+    int32_t rawY = 200;
+
+    float x = toDisplayX(toCookedX(rawX, rawY));
+    float y = toDisplayY(toCookedY(rawX, rawY));
+
+    processDown(mapper, rawX, rawY);
+    processSync(mapper);
+
+    NotifyMotionArgs args;
+    ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&args));
+    ASSERT_NO_FATAL_FAILURE(assertPointerCoords(args.pointerCoords[0],
+            x, y, 1, 0, 0, 0, 0, 0, 0, 0));
+}
+
 TEST_F(SingleTouchInputMapperTest, Process_ShouldHandleAllButtons) {
     SingleTouchInputMapper* mapper = new SingleTouchInputMapper(mDevice);
     addConfigurationProperty("touch.deviceType", "touchScreen");