Merge "fix live wallpapers on Droid" into gingerbread
diff --git a/include/ui/Input.h b/include/ui/Input.h
index 57b292b..a2e0ba0 100644
--- a/include/ui/Input.h
+++ b/include/ui/Input.h
@@ -43,7 +43,7 @@
 /*
  * Declare a concrete type for the NDK's input event forward declaration.
  */
-struct input_event_t { };
+struct AInputEvent { };
 
 namespace android {
 
@@ -87,9 +87,6 @@
     // Indicates that the screen was dim when the event was received and the event
     // should brighten the device.
     POLICY_FLAG_BRIGHT_HERE = 0x20000000,
-
-    // Indicates that the dispatcher should call back into the policy before dispatching. */
-    POLICY_FLAG_INTERCEPT_DISPATCH = 0x40000000,
 };
 
 /*
@@ -136,7 +133,7 @@
 /*
  * Input events.
  */
-class InputEvent : public input_event_t {
+class InputEvent : public AInputEvent {
 public:
     virtual ~InputEvent() { }
 
@@ -145,7 +142,7 @@
     inline int32_t getDeviceId() const { return mDeviceId; }
 
     inline int32_t getNature() const { return mNature; }
-
+    
 protected:
     void initialize(int32_t deviceId, int32_t nature);
 
@@ -179,6 +176,14 @@
 
     inline nsecs_t getEventTime() const { return mEventTime; }
 
+    // Return true if this event may have a default action implementation.
+    static bool hasDefaultAction(int32_t keyCode);
+    bool hasDefaultAction() const;
+
+    // Return true if this event represents a system key.
+    static bool isSystemKey(int32_t keyCode);
+    bool isSystemKey() const;
+    
     void initialize(
             int32_t deviceId,
             int32_t nature,
diff --git a/include/ui/InputReader.h b/include/ui/InputReader.h
index 2093560..781da35 100644
--- a/include/ui/InputReader.h
+++ b/include/ui/InputReader.h
@@ -53,6 +53,8 @@
  */
 struct InputDevice {
     struct AbsoluteAxisInfo {
+        bool valid;        // set to true if axis parameters are known, false otherwise
+
         int32_t minValue;  // minimum value
         int32_t maxValue;  // maximum value
         int32_t range;     // range of values, equal to maxValue - minValue
@@ -272,9 +274,16 @@
         } jumpyTouchFilter;
 
         struct Precalculated {
+            int32_t xOrigin;
             float xScale;
+
+            int32_t yOrigin;
             float yScale;
+
+            int32_t pressureOrigin;
             float pressureScale;
+
+            int32_t sizeOrigin;
             float sizeScale;
         } precalculated;
 
@@ -362,10 +371,6 @@
         // The input dispatcher should add POLICY_FLAG_BRIGHT_HERE to the policy flags it
         // passes through the dispatch pipeline.
         ACTION_BRIGHT_HERE = 0x00000008,
-
-        // The input dispatcher should add POLICY_FLAG_INTERCEPT_DISPATCH to the policy flags
-        // it passed through the dispatch pipeline.
-        ACTION_INTERCEPT_DISPATCH = 0x00000010
     };
 
     /* Describes a virtual key. */
diff --git a/include/ui/InputTransport.h b/include/ui/InputTransport.h
index d6bded6..2dfe2a8 100644
--- a/include/ui/InputTransport.h
+++ b/include/ui/InputTransport.h
@@ -333,18 +333,20 @@
 /*
  * NDK input queue API.
  */
-struct input_queue_t {
+struct AInputQueue {
 public:
     /* Creates a consumer associated with an input channel. */
-    explicit input_queue_t(const android::sp<android::InputChannel>& channel);
+    explicit AInputQueue(const android::sp<android::InputChannel>& channel);
 
     /* Destroys the consumer and releases its input channel. */
-    ~input_queue_t();
+    virtual ~AInputQueue();
 
     inline android::InputConsumer& getConsumer() { return mConsumer; }
     
     android::status_t consume(android::InputEvent** event);
     
+    virtual void doDefaultKey(android::KeyEvent* keyEvent) = 0;
+    
 private:
     android::InputConsumer mConsumer;
     android::PreallocatedInputEventFactory mInputEventFactory;
diff --git a/libs/ui/Input.cpp b/libs/ui/Input.cpp
index 4121b5a..a64251f 100644
--- a/libs/ui/Input.cpp
+++ b/libs/ui/Input.cpp
@@ -20,6 +20,70 @@
 
 // class KeyEvent
 
+bool KeyEvent::hasDefaultAction(int32_t keyCode) {
+    switch (keyCode) {
+        case KEYCODE_HOME:
+        case KEYCODE_BACK:
+        case KEYCODE_CALL:
+        case KEYCODE_ENDCALL:
+        case KEYCODE_VOLUME_UP:
+        case KEYCODE_VOLUME_DOWN:
+        case KEYCODE_POWER:
+        case KEYCODE_CAMERA:
+        case KEYCODE_HEADSETHOOK:
+        case KEYCODE_MENU:
+        case KEYCODE_NOTIFICATION:
+        case KEYCODE_FOCUS:
+        case KEYCODE_SEARCH:
+        case KEYCODE_MEDIA_PLAY_PAUSE:
+        case KEYCODE_MEDIA_STOP:
+        case KEYCODE_MEDIA_NEXT:
+        case KEYCODE_MEDIA_PREVIOUS:
+        case KEYCODE_MEDIA_REWIND:
+        case KEYCODE_MEDIA_FAST_FORWARD:
+        case KEYCODE_MUTE:
+            return true;
+    }
+    
+    return false;
+}
+
+bool KeyEvent::hasDefaultAction() const {
+    return hasDefaultAction(getKeyCode());
+}
+
+bool KeyEvent::isSystemKey(int32_t keyCode) {
+    switch (keyCode) {
+        case KEYCODE_MENU:
+        case KEYCODE_SOFT_RIGHT:
+        case KEYCODE_HOME:
+        case KEYCODE_BACK:
+        case KEYCODE_CALL:
+        case KEYCODE_ENDCALL:
+        case KEYCODE_VOLUME_UP:
+        case KEYCODE_VOLUME_DOWN:
+        case KEYCODE_MUTE:
+        case KEYCODE_POWER:
+        case KEYCODE_HEADSETHOOK:
+        case KEYCODE_MEDIA_PLAY_PAUSE:
+        case KEYCODE_MEDIA_STOP:
+        case KEYCODE_MEDIA_NEXT:
+        case KEYCODE_MEDIA_PREVIOUS:
+        case KEYCODE_MEDIA_REWIND:
+        case KEYCODE_MEDIA_FAST_FORWARD:
+        case KEYCODE_CAMERA:
+        case KEYCODE_FOCUS:
+        case KEYCODE_SEARCH:
+            return true;
+    }
+    
+    return false;
+}
+
+bool KeyEvent::isSystemKey() const {
+    return isSystemKey(getKeyCode());
+}
+
 void KeyEvent::initialize(
         int32_t deviceId,
         int32_t nature,
diff --git a/libs/ui/InputDispatcher.cpp b/libs/ui/InputDispatcher.cpp
index 0fc29b2..8f6d1fe 100644
--- a/libs/ui/InputDispatcher.cpp
+++ b/libs/ui/InputDispatcher.cpp
@@ -232,6 +232,9 @@
     LOGD("processConfigurationChanged - eventTime=%lld", entry->eventTime);
 #endif
 
+    // Reset key repeating in case a keyboard device was added or removed or something.
+    resetKeyRepeatLocked();
+
     mLock.unlock();
 
     mPolicy->notifyConfigurationChanged(entry->eventTime);
diff --git a/libs/ui/InputReader.cpp b/libs/ui/InputReader.cpp
index 8087f84..899027c 100644
--- a/libs/ui/InputReader.cpp
+++ b/libs/ui/InputReader.cpp
@@ -387,6 +387,11 @@
  * points has moved more than a screen height from the last position,
  * then drop it. */
 bool InputDevice::TouchScreenState::applyBadTouchFilter() {
+    // This hack requires valid axis parameters.
+    if (! parameters.yAxis.valid) {
+        return false;
+    }
+
     uint32_t pointerCount = currentTouch.pointerCount;
 
     // Nothing to do if there are no points.
@@ -466,6 +471,11 @@
  * the coordinate value for one axis has jumped to the other pointer's location.
  */
 bool InputDevice::TouchScreenState::applyJumpyTouchFilter() {
+    // This hack requires valid axis parameters.
+    if (! parameters.yAxis.valid) {
+        return false;
+    }
+
     uint32_t pointerCount = currentTouch.pointerCount;
     if (lastTouch.pointerCount != pointerCount) {
 #if DEBUG_HACKS
@@ -724,6 +734,12 @@
 }
 
 bool InputDevice::TouchScreenState::isPointInsideDisplay(int32_t x, int32_t y) const {
+    if (! parameters.xAxis.valid || ! parameters.yAxis.valid) {
+        // Assume all points on a touch screen without valid axis parameters are
+        // inside the display.
+        return true;
+    }
+
     return x >= parameters.xAxis.minValue
         && x <= parameters.xAxis.maxValue
         && y >= parameters.yAxis.minValue
@@ -1435,6 +1451,9 @@
     int32_t pointerIds[MAX_POINTERS];
     PointerCoords pointerCoords[MAX_POINTERS];
 
+    const InputDevice::TouchScreenState::Precalculated& precalculated =
+            device->touchScreen.precalculated;
+
     // Walk through the the active pointers and map touch screen coordinates (TouchData) into
     // display coordinates (PointerCoords) and adjust for display orientation.
     while (! idBits.isEmpty()) {
@@ -1442,18 +1461,14 @@
         idBits.clearBit(id);
         uint32_t index = touch->idToIndex[id];
 
-        float x = (float(touch->pointers[index].x)
-                        - device->touchScreen.parameters.xAxis.minValue)
-                * device->touchScreen.precalculated.xScale;
-        float y = (float(touch->pointers[index].y)
-                        - device->touchScreen.parameters.yAxis.minValue)
-                * device->touchScreen.precalculated.yScale;
-        float pressure = (float(touch->pointers[index].pressure)
-                        - device->touchScreen.parameters.pressureAxis.minValue)
-                * device->touchScreen.precalculated.pressureScale;
-        float size = (float(touch->pointers[index].size)
-                        - device->touchScreen.parameters.sizeAxis.minValue)
-                * device->touchScreen.precalculated.sizeScale;
+        float x = float(touch->pointers[index].x
+                - precalculated.xOrigin) * precalculated.xScale;
+        float y = float(touch->pointers[index].y
+                - precalculated.yOrigin) * precalculated.yScale;
+        float pressure = float(touch->pointers[index].pressure
+                - precalculated.pressureOrigin) * precalculated.pressureScale;
+        float size = float(touch->pointers[index].size
+                - precalculated.sizeOrigin) * precalculated.sizeScale;
 
         switch (mDisplayOrientation) {
         case InputReaderPolicyInterface::ROTATION_90: {
@@ -1624,10 +1639,6 @@
         *policyFlags |= POLICY_FLAG_BRIGHT_HERE;
     }
 
-    if (policyActions & InputReaderPolicyInterface::ACTION_INTERCEPT_DISPATCH) {
-        *policyFlags |= POLICY_FLAG_INTERCEPT_DISPATCH;
-    }
-
     return policyActions & InputReaderPolicyInterface::ACTION_DISPATCH;
 }
 
@@ -1651,7 +1662,11 @@
             }
         }
 
-        mDisplayOrientation = newOrientation;
+        if (newOrientation != mDisplayOrientation) {
+            LOGD("Display orientation changed to %d", mDisplayOrientation);
+
+            mDisplayOrientation = newOrientation;
+        }
         return true;
     } else {
         resetDisplayProperties();
@@ -1740,10 +1755,25 @@
         device->touchScreen.parameters.useJumpyTouchFilter =
                 mPolicy->filterJumpyTouchEvents();
 
-        device->touchScreen.precalculated.pressureScale =
-                1.0f / device->touchScreen.parameters.pressureAxis.range;
-        device->touchScreen.precalculated.sizeScale =
-                1.0f / device->touchScreen.parameters.sizeAxis.range;
+        if (device->touchScreen.parameters.pressureAxis.valid) {
+            device->touchScreen.precalculated.pressureOrigin =
+                    device->touchScreen.parameters.pressureAxis.minValue;
+            device->touchScreen.precalculated.pressureScale =
+                    1.0f / device->touchScreen.parameters.pressureAxis.range;
+        } else {
+            device->touchScreen.precalculated.pressureOrigin = 0;
+            device->touchScreen.precalculated.pressureScale = 1.0f;
+        }
+
+        if (device->touchScreen.parameters.sizeAxis.valid) {
+            device->touchScreen.precalculated.sizeOrigin =
+                    device->touchScreen.parameters.sizeAxis.minValue;
+            device->touchScreen.precalculated.sizeScale =
+                    1.0f / device->touchScreen.parameters.sizeAxis.range;
+        } else {
+            device->touchScreen.precalculated.sizeOrigin = 0;
+            device->touchScreen.precalculated.sizeScale = 1.0f;
+        }
     }
 
     if (device->isTrackball()) {
@@ -1758,22 +1788,42 @@
 
 void InputReader::configureDeviceForCurrentDisplaySize(InputDevice* device) {
     if (device->isTouchScreen()) {
-        if (mDisplayWidth < 0) {
-            LOGD("Skipping part of touch screen configuration since display size is unknown.");
-        } else {
-            LOGI("Device configured: id=0x%x, name=%s (display size was changed)", device->id,
-                    device->name.string());
-            configureVirtualKeys(device);
+        if (device->touchScreen.parameters.xAxis.valid
+                && device->touchScreen.parameters.yAxis.valid) {
+            device->touchScreen.precalculated.xOrigin =
+                    device->touchScreen.parameters.xAxis.minValue;
+            device->touchScreen.precalculated.yOrigin =
+                    device->touchScreen.parameters.yAxis.minValue;
 
-            device->touchScreen.precalculated.xScale =
-                    float(mDisplayWidth) / device->touchScreen.parameters.xAxis.range;
-            device->touchScreen.precalculated.yScale =
-                    float(mDisplayHeight) / device->touchScreen.parameters.yAxis.range;
+            if (mDisplayWidth < 0) {
+                LOGD("Skipping part of touch screen configuration since display size is unknown.");
+
+                device->touchScreen.precalculated.xScale = 1.0f;
+                device->touchScreen.precalculated.yScale = 1.0f;
+            } else {
+                LOGI("Device configured: id=0x%x, name=%s (display size was changed)", device->id,
+                        device->name.string());
+
+                device->touchScreen.precalculated.xScale =
+                        float(mDisplayWidth) / device->touchScreen.parameters.xAxis.range;
+                device->touchScreen.precalculated.yScale =
+                        float(mDisplayHeight) / device->touchScreen.parameters.yAxis.range;
+
+                configureVirtualKeys(device);
+            }
+        } else {
+            device->touchScreen.precalculated.xOrigin = 0;
+            device->touchScreen.precalculated.xScale = 1.0f;
+            device->touchScreen.precalculated.yOrigin = 0;
+            device->touchScreen.precalculated.yScale = 1.0f;
         }
     }
 }
 
 void InputReader::configureVirtualKeys(InputDevice* device) {
+    assert(device->touchScreen.parameters.xAxis.valid
+            && device->touchScreen.parameters.yAxis.valid);
+
     device->touchScreen.virtualKeys.clear();
 
     Vector<InputReaderPolicyInterface::VirtualKeyDefinition> virtualKeyDefinitions;
@@ -1837,16 +1887,18 @@
         if (out->range != 0) {
             LOGI("  %s: min=%d max=%d flat=%d fuzz=%d",
                     name, out->minValue, out->maxValue, out->flat, out->fuzz);
+            out->valid = true;
             return;
         }
     }
 
+    out->valid = false;
     out->minValue = 0;
     out->maxValue = 0;
     out->flat = 0;
     out->fuzz = 0;
     out->range = 0;
-    LOGI("  %s: unknown axis values, setting to zero", name);
+    LOGI("  %s: unknown axis values, marking as invalid", name);
 }
 
 void InputReader::configureExcludedDevices() {
diff --git a/libs/ui/InputTransport.cpp b/libs/ui/InputTransport.cpp
index f56537a..25def3c 100644
--- a/libs/ui/InputTransport.cpp
+++ b/libs/ui/InputTransport.cpp
@@ -691,7 +691,7 @@
 
 } // namespace android
 
-// --- input_queue_t ---
+// --- AInputQueue ---
 
 using android::InputEvent;
 using android::InputChannel;
@@ -699,13 +699,13 @@
 using android::sp;
 using android::status_t;
 
-input_queue_t::input_queue_t(const sp<InputChannel>& channel) :
+AInputQueue::AInputQueue(const sp<InputChannel>& channel) :
         mConsumer(channel) {
 }
 
-input_queue_t::~input_queue_t() {
+AInputQueue::~AInputQueue() {
 }
 
-status_t input_queue_t::consume(InputEvent** event) {
+status_t AInputQueue::consume(InputEvent** event) {
     return mConsumer.consume(&mInputEventFactory, event);
 }