Merge "Pipe through bounding box information (DO NOT MERGE)" into jb-mr2-dev
diff --git a/core/java/com/android/internal/widget/PointerLocationView.java b/core/java/com/android/internal/widget/PointerLocationView.java
index 34cdd93..f10a2e8 100644
--- a/core/java/com/android/internal/widget/PointerLocationView.java
+++ b/core/java/com/android/internal/widget/PointerLocationView.java
@@ -61,6 +61,13 @@
         private float mAltXVelocity;
         private float mAltYVelocity;
 
+        // Current bounding box, if any
+        private boolean mHasBoundingBox;
+        private float mBoundingLeft;
+        private float mBoundingTop;
+        private float mBoundingRight;
+        private float mBoundingBottom;
+
         // Position estimator.
         private VelocityTracker.Estimator mEstimator = new VelocityTracker.Estimator();
         private VelocityTracker.Estimator mAltEstimator = new VelocityTracker.Estimator();
@@ -388,6 +395,12 @@
                         ps.mCoords.x + orientationVectorX * tiltScale,
                         ps.mCoords.y + orientationVectorY * tiltScale,
                         3.0f, mPaint);
+
+                // Draw the current bounding box
+                if (ps.mHasBoundingBox) {
+                    canvas.drawRect(ps.mBoundingLeft, ps.mBoundingTop,
+                            ps.mBoundingRight, ps.mBoundingBottom, mPaint);
+                }
             }
         }
     }
@@ -400,20 +413,20 @@
             for (int i = 0; i < NI; i++) {
                 final int id = event.getPointerId(i);
                 event.getHistoricalPointerCoords(i, historyPos, mTempCoords);
-                logCoords(type, action, i, mTempCoords, id,
-                        event.getToolType(i), event.getButtonState());
+                logCoords(type, action, i, mTempCoords, id, event);
             }
         }
         for (int i = 0; i < NI; i++) {
             final int id = event.getPointerId(i);
             event.getPointerCoords(i, mTempCoords);
-            logCoords(type, action, i, mTempCoords, id,
-                    event.getToolType(i), event.getButtonState());
+            logCoords(type, action, i, mTempCoords, id, event);
         }
     }
 
     private void logCoords(String type, int action, int index,
-            MotionEvent.PointerCoords coords, int id, int toolType, int buttonState) {
+            MotionEvent.PointerCoords coords, int id, MotionEvent event) {
+        final int toolType = event.getToolType(index);
+        final int buttonState = event.getButtonState();
         final String prefix;
         switch (action & MotionEvent.ACTION_MASK) {
             case MotionEvent.ACTION_DOWN:
@@ -483,6 +496,12 @@
                 .append(" Distance=").append(coords.getAxisValue(MotionEvent.AXIS_DISTANCE), 1)
                 .append(" VScroll=").append(coords.getAxisValue(MotionEvent.AXIS_VSCROLL), 1)
                 .append(" HScroll=").append(coords.getAxisValue(MotionEvent.AXIS_HSCROLL), 1)
+                .append(" BoundingBox=[(")
+                .append(event.getAxisValue(MotionEvent.AXIS_GENERIC_1), 3)
+                .append(", ").append(event.getAxisValue(MotionEvent.AXIS_GENERIC_2), 3).append(")")
+                .append(", (").append(event.getAxisValue(MotionEvent.AXIS_GENERIC_3), 3)
+                .append(", ").append(event.getAxisValue(MotionEvent.AXIS_GENERIC_4), 3)
+                .append(")]")
                 .append(" ToolType=").append(MotionEvent.toolTypeToString(toolType))
                 .append(" ButtonState=").append(MotionEvent.buttonStateToString(buttonState))
                 .toString());
@@ -530,6 +549,8 @@
 
             final PointerState ps = mPointers.get(id);
             ps.mCurDown = true;
+            ps.mHasBoundingBox = (InputDevice.getDevice(event.getDeviceId()).
+                    getMotionRange(MotionEvent.AXIS_GENERIC_1) != null);
         }
 
         final int NI = event.getPointerCount();
@@ -549,8 +570,7 @@
                 final PointerCoords coords = ps != null ? ps.mCoords : mTempCoords;
                 event.getHistoricalPointerCoords(i, historyPos, coords);
                 if (mPrintCoords) {
-                    logCoords("Pointer", action, i, coords, id,
-                            event.getToolType(i), event.getButtonState());
+                    logCoords("Pointer", action, i, coords, id, event);
                 }
                 if (ps != null) {
                     ps.addTrace(coords.x, coords.y);
@@ -563,8 +583,7 @@
             final PointerCoords coords = ps != null ? ps.mCoords : mTempCoords;
             event.getPointerCoords(i, coords);
             if (mPrintCoords) {
-                logCoords("Pointer", action, i, coords, id,
-                        event.getToolType(i), event.getButtonState());
+                logCoords("Pointer", action, i, coords, id, event);
             }
             if (ps != null) {
                 ps.addTrace(coords.x, coords.y);
@@ -577,6 +596,13 @@
                     mAltVelocity.getEstimator(id, ps.mAltEstimator);
                 }
                 ps.mToolType = event.getToolType(i);
+
+                if (ps.mHasBoundingBox) {
+                    ps.mBoundingLeft = event.getAxisValue(MotionEvent.AXIS_GENERIC_1, i);
+                    ps.mBoundingTop = event.getAxisValue(MotionEvent.AXIS_GENERIC_2, i);
+                    ps.mBoundingRight = event.getAxisValue(MotionEvent.AXIS_GENERIC_3, i);
+                    ps.mBoundingBottom = event.getAxisValue(MotionEvent.AXIS_GENERIC_4, i);
+                }
             }
         }
 
diff --git a/services/input/InputReader.cpp b/services/input/InputReader.cpp
index 10d7591..c774763 100644
--- a/services/input/InputReader.cpp
+++ b/services/input/InputReader.cpp
@@ -2619,6 +2619,18 @@
             info->addMotionRange(AMOTION_EVENT_AXIS_HSCROLL, mSource, -1.0f, 1.0f, 0.0f, 0.0f,
                     0.0f);
         }
+        if (mCalibration.coverageCalibration == Calibration::COVERAGE_CALIBRATION_BOX) {
+            const InputDeviceInfo::MotionRange& x = mOrientedRanges.x;
+            const InputDeviceInfo::MotionRange& y = mOrientedRanges.y;
+            info->addMotionRange(AMOTION_EVENT_AXIS_GENERIC_1, mSource, x.min, x.max, x.flat,
+                    x.fuzz, x.resolution);
+            info->addMotionRange(AMOTION_EVENT_AXIS_GENERIC_2, mSource, y.min, y.max, y.flat,
+                    y.fuzz, y.resolution);
+            info->addMotionRange(AMOTION_EVENT_AXIS_GENERIC_3, mSource, x.min, x.max, x.flat,
+                    x.fuzz, x.resolution);
+            info->addMotionRange(AMOTION_EVENT_AXIS_GENERIC_4, mSource, y.min, y.max, y.flat,
+                    y.fuzz, y.resolution);
+        }
     }
 }
 
@@ -3448,6 +3460,19 @@
 
     out.haveDistanceScale = in.tryGetProperty(String8("touch.distance.scale"),
             out.distanceScale);
+
+    out.coverageCalibration = Calibration::COVERAGE_CALIBRATION_DEFAULT;
+    String8 coverageCalibrationString;
+    if (in.tryGetProperty(String8("touch.coverage.calibration"), coverageCalibrationString)) {
+        if (coverageCalibrationString == "none") {
+            out.coverageCalibration = Calibration::COVERAGE_CALIBRATION_NONE;
+        } else if (coverageCalibrationString == "box") {
+            out.coverageCalibration = Calibration::COVERAGE_CALIBRATION_BOX;
+        } else if (coverageCalibrationString != "default") {
+            ALOGW("Invalid value for touch.coverage.calibration: '%s'",
+                    coverageCalibrationString.string());
+        }
+    }
 }
 
 void TouchInputMapper::resolveCalibration() {
@@ -3486,6 +3511,11 @@
     } else {
         mCalibration.distanceCalibration = Calibration::DISTANCE_CALIBRATION_NONE;
     }
+
+    // Coverage
+    if (mCalibration.coverageCalibration == Calibration::COVERAGE_CALIBRATION_DEFAULT) {
+        mCalibration.coverageCalibration = Calibration::COVERAGE_CALIBRATION_NONE;
+    }
 }
 
 void TouchInputMapper::dumpCalibration(String8& dump) {
@@ -3578,6 +3608,17 @@
         dump.appendFormat(INDENT4 "touch.distance.scale: %0.3f\n",
                 mCalibration.distanceScale);
     }
+
+    switch (mCalibration.coverageCalibration) {
+    case Calibration::COVERAGE_CALIBRATION_NONE:
+        dump.append(INDENT4 "touch.coverage.calibration: none\n");
+        break;
+    case Calibration::COVERAGE_CALIBRATION_BOX:
+        dump.append(INDENT4 "touch.coverage.calibration: box\n");
+        break;
+    default:
+        ALOG_ASSERT(false);
+    }
 }
 
 void TouchInputMapper::reset(nsecs_t when) {
@@ -4185,13 +4226,31 @@
             distance = 0;
         }
 
-        // X and Y
+        // Coverage
+        int32_t rawLeft, rawTop, rawRight, rawBottom;
+        switch (mCalibration.coverageCalibration) {
+        case Calibration::COVERAGE_CALIBRATION_BOX:
+            rawLeft = (in.toolMinor & 0xffff0000) >> 16;
+            rawRight = in.toolMinor & 0x0000ffff;
+            rawBottom = in.toolMajor & 0x0000ffff;
+            rawTop = (in.toolMajor & 0xffff0000) >> 16;
+            break;
+        default:
+            rawLeft = rawTop = rawRight = rawBottom = 0;
+            break;
+        }
+
+        // X, Y, and the bounding box for coverage information
         // Adjust coords for surface orientation.
-        float x, y;
+        float x, y, 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;
+            left = float(rawTop - mRawPointerAxes.y.minValue) * mYScale + mYTranslate;
+            right = float(rawBottom- mRawPointerAxes.y.minValue) * mYScale + mYTranslate;
+            bottom = float(mRawPointerAxes.x.maxValue - rawLeft) * mXScale + mXTranslate;
+            top = float(mRawPointerAxes.x.maxValue - rawRight) * mXScale + mXTranslate;
             orientation -= M_PI_2;
             if (orientation < - M_PI_2) {
                 orientation += M_PI;
@@ -4200,10 +4259,18 @@
         case DISPLAY_ORIENTATION_180:
             x = float(mRawPointerAxes.x.maxValue - in.x) * mXScale + mXTranslate;
             y = float(mRawPointerAxes.y.maxValue - in.y) * 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;
+            top = float(mRawPointerAxes.y.maxValue - rawBottom) * mYScale + mYTranslate;
             break;
         case DISPLAY_ORIENTATION_270:
             x = float(mRawPointerAxes.y.maxValue - in.y) * mYScale + mYTranslate;
             y = float(in.x - 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;
+            top = float(rawLeft - mRawPointerAxes.x.minValue) * mXScale + mXTranslate;
             orientation += M_PI_2;
             if (orientation > M_PI_2) {
                 orientation -= M_PI;
@@ -4212,6 +4279,10 @@
         default:
             x = float(in.x - mRawPointerAxes.x.minValue) * mXScale + mXTranslate;
             y = float(in.y - 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;
+            top = float(rawTop - mRawPointerAxes.y.minValue) * mYScale + mYTranslate;
             break;
         }
 
@@ -4224,11 +4295,18 @@
         out.setAxisValue(AMOTION_EVENT_AXIS_SIZE, size);
         out.setAxisValue(AMOTION_EVENT_AXIS_TOUCH_MAJOR, touchMajor);
         out.setAxisValue(AMOTION_EVENT_AXIS_TOUCH_MINOR, touchMinor);
-        out.setAxisValue(AMOTION_EVENT_AXIS_TOOL_MAJOR, toolMajor);
-        out.setAxisValue(AMOTION_EVENT_AXIS_TOOL_MINOR, toolMinor);
         out.setAxisValue(AMOTION_EVENT_AXIS_ORIENTATION, orientation);
         out.setAxisValue(AMOTION_EVENT_AXIS_TILT, tilt);
         out.setAxisValue(AMOTION_EVENT_AXIS_DISTANCE, distance);
+        if (mCalibration.coverageCalibration == Calibration::COVERAGE_CALIBRATION_BOX) {
+            out.setAxisValue(AMOTION_EVENT_AXIS_GENERIC_1, left);
+            out.setAxisValue(AMOTION_EVENT_AXIS_GENERIC_2, top);
+            out.setAxisValue(AMOTION_EVENT_AXIS_GENERIC_3, right);
+            out.setAxisValue(AMOTION_EVENT_AXIS_GENERIC_4, bottom);
+        } else {
+            out.setAxisValue(AMOTION_EVENT_AXIS_TOOL_MAJOR, toolMajor);
+            out.setAxisValue(AMOTION_EVENT_AXIS_TOOL_MINOR, toolMinor);
+        }
 
         // Write output properties.
         PointerProperties& properties = mCurrentCookedPointerData.pointerProperties[i];
diff --git a/services/input/InputReader.h b/services/input/InputReader.h
index f87f98e..0189ba7 100644
--- a/services/input/InputReader.h
+++ b/services/input/InputReader.h
@@ -1267,6 +1267,14 @@
         bool haveDistanceScale;
         float distanceScale;
 
+        enum CoverageCalibration {
+            COVERAGE_CALIBRATION_DEFAULT,
+            COVERAGE_CALIBRATION_NONE,
+            COVERAGE_CALIBRATION_BOX,
+        };
+
+        CoverageCalibration coverageCalibration;
+
         inline void applySizeScaleAndBias(float* outSize) const {
             if (haveSizeScale) {
                 *outSize *= sizeScale;