Merge "Fix the ISurfaceComposer onTransact switch."
diff --git a/NOTICE b/NOTICE
index 8d6f583..9324631 100644
--- a/NOTICE
+++ b/NOTICE
@@ -72,6 +72,15 @@
 OF ANY KIND, either express or implied; not even the implied warranty
 of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
 
+   =========================================================================
+   ==  NOTICE file corresponding to the section 4 d of                    ==
+   ==  the Apache License, Version 2.0,                                   ==
+   ==  in this case for Additional Codecs code.                           ==
+   =========================================================================
+
+Additional Codecs
+These files are Copyright 2003-2010 VisualOn, but released under
+the Apache2 License.
 
                                Apache License
                            Version 2.0, January 2004
diff --git a/include/binder/CursorWindow.h b/include/binder/CursorWindow.h
index 4fbff2a..f0b2909 100644
--- a/include/binder/CursorWindow.h
+++ b/include/binder/CursorWindow.h
@@ -25,7 +25,6 @@
 #include <utils/RefBase.h>
 
 #define DEFAULT_WINDOW_SIZE 4096
-#define MAX_WINDOW_SIZE (1024 * 1024)
 #define WINDOW_ALLOCATION_SIZE 4096
 
 #define ROW_SLOT_CHUNK_NUM_ROWS 16
diff --git a/include/gui/ISurfaceTexture.h b/include/gui/ISurfaceTexture.h
new file mode 100644
index 0000000..77d37f1
--- /dev/null
+++ b/include/gui/ISurfaceTexture.h
@@ -0,0 +1,91 @@
+/*
+ * Copyright (C) 2010 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef ANDROID_GUI_ISURFACETEXTURE_H
+#define ANDROID_GUI_ISURFACETEXTURE_H
+
+#include <stdint.h>
+#include <sys/types.h>
+
+#include <utils/Errors.h>
+#include <utils/RefBase.h>
+
+#include <binder/IInterface.h>
+
+#include <ui/GraphicBuffer.h>
+#include <ui/Rect.h>
+
+namespace android {
+// ----------------------------------------------------------------------------
+
+class ISurfaceTexture : public IInterface
+{
+public:
+    DECLARE_META_INTERFACE(SurfaceTexture);
+
+    // requestBuffer requests a new buffer for the given index. The server (i.e.
+    // the ISurfaceTexture implementation) assigns the newly created buffer to
+    // the given slot index, and the client is expected to mirror the
+    // slot->buffer mapping so that it's not necessary to transfer a
+    // GraphicBuffer for every dequeue operation.
+    virtual sp<GraphicBuffer> requestBuffer(int slot, uint32_t w, uint32_t h,
+            uint32_t format, uint32_t usage) = 0;
+
+    // setBufferCount sets the number of buffer slots available. Calling this
+    // will also cause all buffer slots to be emptied. The caller should empty
+    // its mirrored copy of the buffer slots when calling this method.
+    virtual status_t setBufferCount(int bufferCount) = 0;
+
+    // dequeueBuffer requests a new buffer slot for the client to use. Ownership
+    // of the slot is transfered to the client, meaning that the server will not
+    // use the contents of the buffer associated with that slot. The slot index
+    // returned may or may not contain a buffer. If the slot is empty the client
+    // should call requestBuffer to assign a new buffer to that slot. The client
+    // is expected to either call cancelBuffer on the dequeued slot or to fill
+    // in the contents of its associated buffer contents and call queueBuffer.
+    virtual status_t dequeueBuffer(int *slot) = 0;
+
+    // queueBuffer indicates that the client has finished filling in the
+    // contents of the buffer associated with slot and transfers ownership of
+    // that slot back to the server. It is not valid to call queueBuffer on a
+    // slot that is not owned by the client or one for which a buffer associated
+    // via requestBuffer.
+    virtual status_t queueBuffer(int slot) = 0;
+
+    // cancelBuffer indicates that the client does not wish to fill in the
+    // buffer associated with slot and transfers ownership of the slot back to
+    // the server.
+    virtual void cancelBuffer(int slot) = 0;
+
+    virtual status_t setCrop(const Rect& reg) = 0;
+    virtual status_t setTransform(uint32_t transform) = 0;
+};
+
+// ----------------------------------------------------------------------------
+
+class BnSurfaceTexture : public BnInterface<ISurfaceTexture>
+{
+public:
+    virtual status_t    onTransact( uint32_t code,
+                                    const Parcel& data,
+                                    Parcel* reply,
+                                    uint32_t flags = 0);
+};
+
+// ----------------------------------------------------------------------------
+}; // namespace android
+
+#endif // ANDROID_GUI_ISURFACETEXTURE_H
diff --git a/include/gui/SurfaceTexture.h b/include/gui/SurfaceTexture.h
new file mode 100644
index 0000000..002e48b
--- /dev/null
+++ b/include/gui/SurfaceTexture.h
@@ -0,0 +1,207 @@
+/*
+ * Copyright (C) 2010 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef ANDROID_GUI_SURFACETEXTURE_H
+#define ANDROID_GUI_SURFACETEXTURE_H
+
+#include <EGL/egl.h>
+#include <EGL/eglext.h>
+#include <GLES2/gl2.h>
+
+#include <gui/ISurfaceTexture.h>
+
+#include <ui/GraphicBuffer.h>
+
+#include <utils/threads.h>
+#include <utils/Vector.h>
+
+#define ANDROID_GRAPHICS_SURFACETEXTURE_JNI_ID "mSurfaceTexture"
+
+namespace android {
+// ----------------------------------------------------------------------------
+
+class IGraphicBufferAlloc;
+
+class SurfaceTexture : public BnSurfaceTexture {
+public:
+    enum { MIN_BUFFER_SLOTS = 3 };
+    enum { NUM_BUFFER_SLOTS = 32 };
+
+    // tex indicates the name OpenGL texture to which images are to be streamed.
+    // This texture name cannot be changed once the SurfaceTexture is created.
+    SurfaceTexture(GLuint tex);
+
+    virtual ~SurfaceTexture();
+
+    // setBufferCount updates the number of available buffer slots.  After
+    // calling this all buffer slots are both unallocated and owned by the
+    // SurfaceTexture object (i.e. they are not owned by the client).
+    virtual status_t setBufferCount(int bufferCount);
+
+    virtual sp<GraphicBuffer> requestBuffer(int buf, uint32_t w, uint32_t h,
+            uint32_t format, uint32_t usage);
+
+    // dequeueBuffer gets the next buffer slot index for the client to use. If a
+    // buffer slot is available then that slot index is written to the location
+    // pointed to by the buf argument and a status of OK is returned.  If no
+    // slot is available then a status of -EBUSY is returned and buf is
+    // unmodified.
+    virtual status_t dequeueBuffer(int *buf);
+
+    virtual status_t queueBuffer(int buf);
+    virtual void cancelBuffer(int buf);
+    virtual status_t setCrop(const Rect& reg);
+    virtual status_t setTransform(uint32_t transform);
+
+    // updateTexImage sets the image contents of the target texture to that of
+    // the most recently queued buffer.
+    //
+    // This call may only be made while the OpenGL ES context to which the
+    // target texture belongs is bound to the calling thread.
+    status_t updateTexImage();
+
+    // getTransformMatrix retrieves the 4x4 texture coordinate transform matrix
+    // associated with the texture image set by the most recent call to
+    // updateTexImage.
+    //
+    // This transform matrix maps 2D homogeneous texture coordinates of the form
+    // (s, t, 0, 1) with s and t in the inclusive range [0, 1] to the texture
+    // coordinate that should be used to sample that location from the texture.
+    // Sampling the texture outside of the range of this transform is undefined.
+    //
+    // This transform is necessary to compensate for transforms that the stream
+    // content producer may implicitly apply to the content. By forcing users of
+    // a SurfaceTexture to apply this transform we avoid performing an extra
+    // copy of the data that would be needed to hide the transform from the
+    // user.
+    //
+    // The matrix is stored in column-major order so that it may be passed
+    // directly to OpenGL ES via the glLoadMatrixf or glUniformMatrix4fv
+    // functions.
+    void getTransformMatrix(float mtx[16]);
+
+private:
+
+    // freeAllBuffers frees the resources (both GraphicBuffer and EGLImage) for
+    // all slots.
+    void freeAllBuffers();
+
+    // createImage creates a new EGLImage from a GraphicBuffer.
+    EGLImageKHR createImage(EGLDisplay dpy,
+            const sp<GraphicBuffer>& graphicBuffer);
+
+    enum { INVALID_BUFFER_SLOT = -1 };
+
+    struct BufferSlot {
+        // mGraphicBuffer points to the buffer allocated for this slot or is NULL
+        // if no buffer has been allocated.
+        sp<GraphicBuffer> mGraphicBuffer;
+
+        // mEglImage is the EGLImage created from mGraphicBuffer.
+        EGLImageKHR mEglImage;
+
+        // mEglDisplay is the EGLDisplay used to create mEglImage.
+        EGLDisplay mEglDisplay;
+
+        // mOwnedByClient indicates whether the slot is currently accessible to a
+        // client and should not be used by the SurfaceTexture object. It gets
+        // set to true when dequeueBuffer returns the slot and is reset to false
+        // when the client calls either queueBuffer or cancelBuffer on the slot.
+        bool mOwnedByClient;
+    };
+
+    // mSlots is the array of buffer slots that must be mirrored on the client
+    // side. This allows buffer ownership to be transferred between the client
+    // and server without sending a GraphicBuffer over binder. The entire array
+    // is initialized to NULL at construction time, and buffers are allocated
+    // for a slot when requestBuffer is called with that slot's index.
+    BufferSlot mSlots[NUM_BUFFER_SLOTS];
+
+    // mBufferCount is the number of buffer slots that the client and server
+    // must maintain. It defaults to MIN_BUFFER_SLOTS and can be changed by
+    // calling setBufferCount.
+    int mBufferCount;
+
+    // mCurrentTexture is the buffer slot index of the buffer that is currently
+    // bound to the OpenGL texture. It is initialized to INVALID_BUFFER_SLOT,
+    // indicating that no buffer slot is currently bound to the texture. Note,
+    // however, that a value of INVALID_BUFFER_SLOT does not necessarily mean
+    // that no buffer is bound to the texture. A call to setBufferCount will
+    // reset mCurrentTexture to INVALID_BUFFER_SLOT.
+    int mCurrentTexture;
+
+    // mCurrentTextureBuf is the graphic buffer of the current texture. It's
+    // possible that this buffer is not associated with any buffer slot, so we
+    // must track it separately in order to properly use
+    // IGraphicBufferAlloc::freeAllGraphicBuffersExcept.
+    sp<GraphicBuffer> mCurrentTextureBuf;
+
+    // mCurrentCrop is the crop rectangle that applies to the current texture.
+    // It gets set to mLastQueuedCrop each time updateTexImage is called.
+    Rect mCurrentCrop;
+
+    // mCurrentTransform is the transform identifier for the current texture. It
+    // gets set to mLastQueuedTransform each time updateTexImage is called.
+    uint32_t mCurrentTransform;
+
+    // mLastQueued is the buffer slot index of the most recently enqueued buffer.
+    // At construction time it is initialized to INVALID_BUFFER_SLOT, and is
+    // updated each time queueBuffer is called.
+    int mLastQueued;
+
+    // mLastQueuedCrop is the crop rectangle for the buffer that was most
+    // recently queued. This gets set to mNextCrop each time queueBuffer gets
+    // called.
+    Rect mLastQueuedCrop;
+
+    // mLastQueuedTransform is the transform identifier for the buffer that was
+    // most recently queued. This gets set to mNextTransform each time
+    // queueBuffer gets called.
+    uint32_t mLastQueuedTransform;
+
+    // mNextCrop is the crop rectangle that will be used for the next buffer
+    // that gets queued. It is set by calling setCrop.
+    Rect mNextCrop;
+
+    // mNextTransform is the transform identifier that will be used for the next
+    // buffer that gets queued. It is set by calling setTransform.
+    uint32_t mNextTransform;
+
+    // mTexName is the name of the OpenGL texture to which streamed images will
+    // be bound when updateTexImage is called. It is set at construction time 
+    // changed with a call to setTexName.
+    const GLuint mTexName;
+
+    // mGraphicBufferAlloc is the connection to SurfaceFlinger that is used to
+    // allocate new GraphicBuffer objects.
+    sp<IGraphicBufferAlloc> mGraphicBufferAlloc;
+
+    // mAllocdBuffers is mirror of the list of buffers that SurfaceFlinger is
+    // referencing. This is kept so that gralloc implementations do not need to
+    // properly handle the case where SurfaceFlinger no longer holds a reference
+    // to a buffer, but other processes do.
+    Vector<sp<GraphicBuffer> > mAllocdBuffers;
+
+    // mMutex is the mutex used to prevent concurrent access to the member
+    // variables of SurfaceTexture objects. It must be locked whenever the
+    // member variables are accessed.
+    Mutex mMutex;
+};
+
+// ----------------------------------------------------------------------------
+}; // namespace android
+
+#endif // ANDROID_GUI_SURFACETEXTURE_H
diff --git a/include/gui/SurfaceTextureClient.h b/include/gui/SurfaceTextureClient.h
new file mode 100644
index 0000000..dd1d490
--- /dev/null
+++ b/include/gui/SurfaceTextureClient.h
@@ -0,0 +1,118 @@
+/*
+ * Copyright (C) 2010 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef ANDROID_GUI_SURFACETEXTURECLIENT_H
+#define ANDROID_GUI_SURFACETEXTURECLIENT_H
+
+#include <gui/ISurfaceTexture.h>
+#include <gui/SurfaceTexture.h>
+
+#include <ui/egl/android_natives.h>
+
+#include <utils/RefBase.h>
+#include <utils/threads.h>
+
+namespace android {
+
+class SurfaceTextureClient
+    : public EGLNativeBase<ANativeWindow, SurfaceTextureClient, RefBase>
+{
+public:
+    SurfaceTextureClient(const sp<ISurfaceTexture>& surfaceTexture);
+
+private:
+
+    // can't be copied
+    SurfaceTextureClient& operator = (const SurfaceTextureClient& rhs);
+    SurfaceTextureClient(const SurfaceTextureClient& rhs);
+
+    // ANativeWindow hooks
+    static int setSwapInterval(ANativeWindow* window, int interval);
+    static int dequeueBuffer(ANativeWindow* window, android_native_buffer_t** buffer);
+    static int cancelBuffer(ANativeWindow* window, android_native_buffer_t* buffer);
+    static int lockBuffer(ANativeWindow* window, android_native_buffer_t* buffer);
+    static int queueBuffer(ANativeWindow* window, android_native_buffer_t* buffer);
+    static int query(ANativeWindow* window, int what, int* value);
+    static int perform(ANativeWindow* window, int operation, ...);
+
+    int setSwapInterval(int interval);
+    int dequeueBuffer(android_native_buffer_t** buffer);
+    int lockBuffer(android_native_buffer_t* buffer);
+    int queueBuffer(android_native_buffer_t* buffer);
+    int cancelBuffer(android_native_buffer_t* buffer);
+    int query(int what, int* value);
+    int perform(int operation, va_list args);
+
+    int dispatchSetUsage(va_list args);
+    int dispatchConnect(va_list args);
+    int dispatchDisconnect(va_list args);
+    int dispatchSetCrop(va_list args);
+    int dispatchSetBufferCount(va_list args);
+    int dispatchSetBuffersGeometry(va_list args);
+    int dispatchSetBuffersTransform(va_list args);
+
+    int connect(int api);
+    int disconnect(int api);
+    int setUsage(uint32_t reqUsage);
+    int setCrop(Rect const* rect);
+    int setBufferCount(int bufferCount);
+    int setBuffersGeometry(int w, int h, int format);
+    int setBuffersTransform(int transform);
+
+    void freeAllBuffers();
+
+    enum { MIN_BUFFER_SLOTS = SurfaceTexture::MIN_BUFFER_SLOTS };
+    enum { NUM_BUFFER_SLOTS = SurfaceTexture::NUM_BUFFER_SLOTS };
+    enum { DEFAULT_FORMAT = PIXEL_FORMAT_RGBA_8888 };
+
+    // mSurfaceTexture is the interface to the surface texture server. All
+    // operations on the surface texture client ultimately translate into
+    // interactions with the server using this interface.
+    sp<ISurfaceTexture> mSurfaceTexture;
+
+    // mSlots stores the buffers that have been allocated for each buffer slot.
+    // It is initialized to null pointers, and gets filled in with the result of
+    // ISurfaceTexture::requestBuffer when the client dequeues a buffer from a
+    // slot that has not yet been used. The buffer allocated to a slot will also
+    // be replaced if the requested buffer usage or geometry differs from that
+    // of the buffer allocated to a slot.
+    sp<GraphicBuffer> mSlots[NUM_BUFFER_SLOTS];
+
+    // mReqWidth is the buffer width that will be requested at the next dequeue
+    // operation. It is initialized to 1.
+    uint32_t mReqWidth;
+
+    // mReqHeight is the buffer height that will be requested at the next deuque
+    // operation. It is initialized to 1.
+    uint32_t mReqHeight;
+
+    // mReqFormat is the buffer pixel format that will be requested at the next
+    // deuque operation. It is initialized to PIXEL_FORMAT_RGBA_8888.
+    uint32_t mReqFormat;
+
+    // mReqUsage is the set of buffer usage flags that will be requested
+    // at the next deuque operation. It is initialized to 0.
+    uint32_t mReqUsage;
+
+    // mMutex is the mutex used to prevent concurrent access to the member
+    // variables of SurfaceTexture objects. It must be locked whenever the
+    // member variables are accessed.
+    Mutex mMutex;
+};
+
+}; // namespace android
+
+#endif  // ANDROID_GUI_SURFACETEXTURECLIENT_H
diff --git a/include/surfaceflinger/IGraphicBufferAlloc.h b/include/surfaceflinger/IGraphicBufferAlloc.h
new file mode 100644
index 0000000..d996af7
--- /dev/null
+++ b/include/surfaceflinger/IGraphicBufferAlloc.h
@@ -0,0 +1,64 @@
+/*
+ * Copyright (C) 2011 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef ANDROID_SF_IGRAPHIC_BUFFER_ALLOC_H
+#define ANDROID_SF_IGRAPHIC_BUFFER_ALLOC_H
+
+#include <stdint.h>
+#include <sys/types.h>
+
+#include <utils/RefBase.h>
+
+#include <binder/IInterface.h>
+
+namespace android {
+// ----------------------------------------------------------------------------
+
+class IGraphicBufferAlloc : public IInterface
+{
+public:
+    DECLARE_META_INTERFACE(GraphicBufferAlloc);
+
+    /* Create a new GraphicBuffer for the client to use.  The server will
+     * maintain a reference to the newly created GraphicBuffer until
+     * freeAllGraphicBuffers is called.
+     */
+    virtual sp<GraphicBuffer> createGraphicBuffer(uint32_t w, uint32_t h,
+            PixelFormat format, uint32_t usage) = 0;
+
+    /* Free all but one of the GraphicBuffer objects that the server is
+     * currently referencing. If bufIndex is not a valid index of the buffers
+     * the server is referencing, then all buffers are freed.
+     */
+    virtual void freeAllGraphicBuffersExcept(int bufIndex) = 0;
+};
+
+// ----------------------------------------------------------------------------
+
+class BnGraphicBufferAlloc : public BnInterface<IGraphicBufferAlloc>
+{
+public:
+    virtual status_t    onTransact( uint32_t code,
+                                    const Parcel& data,
+                                    Parcel* reply,
+                                    uint32_t flags = 0);
+};
+
+// ----------------------------------------------------------------------------
+
+}; // namespace android
+
+#endif // ANDROID_SF_IGRAPHIC_BUFFER_ALLOC_H
diff --git a/include/surfaceflinger/ISurfaceComposer.h b/include/surfaceflinger/ISurfaceComposer.h
index 693fbfb..56ed3a4 100644
--- a/include/surfaceflinger/ISurfaceComposer.h
+++ b/include/surfaceflinger/ISurfaceComposer.h
@@ -28,6 +28,7 @@
 #include <ui/PixelFormat.h>
 
 #include <surfaceflinger/ISurfaceComposerClient.h>
+#include <surfaceflinger/IGraphicBufferAlloc.h>
 
 namespace android {
 // ----------------------------------------------------------------------------
@@ -96,6 +97,10 @@
      */
     virtual sp<ISurfaceComposerClient> createClientConnection() = 0;
 
+    /* create a graphic buffer allocator
+     */
+    virtual sp<IGraphicBufferAlloc> createGraphicBufferAlloc() = 0;
+
     /* retrieve the control block */
     virtual sp<IMemoryHeap> getCblk() const = 0;
 
@@ -144,6 +149,7 @@
         BOOT_FINISHED = IBinder::FIRST_CALL_TRANSACTION,
         CREATE_CONNECTION,
         CREATE_CLIENT_CONNECTION,
+        CREATE_GRAPHIC_BUFFER_ALLOC,
         GET_CBLK,
         OPEN_GLOBAL_TRANSACTION,
         CLOSE_GLOBAL_TRANSACTION,
diff --git a/include/surfaceflinger/Surface.h b/include/surfaceflinger/Surface.h
index 2df8ca3..5532052 100644
--- a/include/surfaceflinger/Surface.h
+++ b/include/surfaceflinger/Surface.h
@@ -233,7 +233,7 @@
      *  private stuff...
      */
     void init();
-    status_t validate() const;
+    status_t validate(bool inCancelBuffer = false) const;
     sp<ISurface> getISurface() const;
 
     inline const GraphicBufferMapper& getBufferMapper() const { return mBufferMapper; }
diff --git a/include/ui/DisplayInfo.h b/include/ui/DisplayInfo.h
index c419efe..edd28a6 100644
--- a/include/ui/DisplayInfo.h
+++ b/include/ui/DisplayInfo.h
@@ -37,6 +37,15 @@
     float               ydpi;
 };
 
+/* Display orientations as defined in Surface.java and ISurfaceComposer.h. */
+enum {
+    DISPLAY_ORIENTATION_0 = 0,
+    DISPLAY_ORIENTATION_90 = 1,
+    DISPLAY_ORIENTATION_180 = 2,
+    DISPLAY_ORIENTATION_270 = 3
+};
+
+
 }; // namespace android
 
 #endif // ANDROID_COMPOSER_DISPLAY_INFO_H
diff --git a/include/ui/EventHub.h b/include/ui/EventHub.h
deleted file mode 100644
index 6c6c297..0000000
--- a/include/ui/EventHub.h
+++ /dev/null
@@ -1,327 +0,0 @@
-/*
- * Copyright (C) 2005 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-//
-#ifndef _RUNTIME_EVENT_HUB_H
-#define _RUNTIME_EVENT_HUB_H
-
-#include <ui/Input.h>
-#include <ui/Keyboard.h>
-#include <ui/KeyLayoutMap.h>
-#include <ui/KeyCharacterMap.h>
-#include <ui/VirtualKeyMap.h>
-#include <utils/String8.h>
-#include <utils/threads.h>
-#include <utils/Log.h>
-#include <utils/threads.h>
-#include <utils/List.h>
-#include <utils/Errors.h>
-#include <utils/PropertyMap.h>
-#include <utils/Vector.h>
-
-#include <linux/input.h>
-
-/* These constants are not defined in linux/input.h but they are part of the multitouch
- * input protocol. */
-
-#define ABS_MT_TOUCH_MAJOR 0x30  /* Major axis of touching ellipse */
-#define ABS_MT_TOUCH_MINOR 0x31  /* Minor axis (omit if circular) */
-#define ABS_MT_WIDTH_MAJOR 0x32  /* Major axis of approaching ellipse */
-#define ABS_MT_WIDTH_MINOR 0x33  /* Minor axis (omit if circular) */
-#define ABS_MT_ORIENTATION 0x34  /* Ellipse orientation */
-#define ABS_MT_POSITION_X 0x35   /* Center X ellipse position */
-#define ABS_MT_POSITION_Y 0x36   /* Center Y ellipse position */
-#define ABS_MT_TOOL_TYPE 0x37    /* Type of touching device (finger, pen, ...) */
-#define ABS_MT_BLOB_ID 0x38      /* Group a set of packets as a blob */
-#define ABS_MT_TRACKING_ID 0x39  /* Unique ID of initiated contact */
-#define ABS_MT_PRESSURE 0x3a     /* Pressure on contact area */
-
-#define MT_TOOL_FINGER 0 /* Identifies a finger */
-#define MT_TOOL_PEN 1    /* Identifies a pen */
-
-#define SYN_MT_REPORT 2
-
-/* Convenience constants. */
-
-#define BTN_FIRST 0x100  // first button scancode
-#define BTN_LAST 0x15f   // last button scancode
-
-struct pollfd;
-
-namespace android {
-
-/*
- * A raw event as retrieved from the EventHub.
- */
-struct RawEvent {
-    nsecs_t when;
-    int32_t deviceId;
-    int32_t type;
-    int32_t scanCode;
-    int32_t keyCode;
-    int32_t value;
-    uint32_t flags;
-};
-
-/* Describes an absolute axis. */
-struct RawAbsoluteAxisInfo {
-    bool valid; // true if the information is valid, false otherwise
-
-    int32_t minValue;  // minimum value
-    int32_t maxValue;  // maximum value
-    int32_t flat;      // center flat position, eg. flat == 8 means center is between -8 and 8
-    int32_t fuzz;      // error tolerance, eg. fuzz == 4 means value is +/- 4 due to noise
-
-    inline int32_t getRange() { return maxValue - minValue; }
-
-    inline void clear() {
-        valid = false;
-        minValue = 0;
-        maxValue = 0;
-        flat = 0;
-        fuzz = 0;
-    }
-};
-
-/*
- * Input device classes.
- */
-enum {
-    /* The input device is a keyboard. */
-    INPUT_DEVICE_CLASS_KEYBOARD      = 0x00000001,
-
-    /* The input device is an alpha-numeric keyboard (not just a dial pad). */
-    INPUT_DEVICE_CLASS_ALPHAKEY      = 0x00000002,
-
-    /* The input device is a touchscreen (either single-touch or multi-touch). */
-    INPUT_DEVICE_CLASS_TOUCHSCREEN   = 0x00000004,
-
-    /* The input device is a trackball. */
-    INPUT_DEVICE_CLASS_TRACKBALL     = 0x00000008,
-
-    /* The input device is a multi-touch touchscreen. */
-    INPUT_DEVICE_CLASS_TOUCHSCREEN_MT= 0x00000010,
-
-    /* The input device is a directional pad (implies keyboard, has DPAD keys). */
-    INPUT_DEVICE_CLASS_DPAD          = 0x00000020,
-
-    /* The input device is a gamepad (implies keyboard, has BUTTON keys). */
-    INPUT_DEVICE_CLASS_GAMEPAD       = 0x00000040,
-
-    /* The input device has switches. */
-    INPUT_DEVICE_CLASS_SWITCH        = 0x00000080,
-};
-
-/*
- * Grand Central Station for events.
- *
- * The event hub aggregates input events received across all known input
- * devices on the system, including devices that may be emulated by the simulator
- * environment.  In addition, the event hub generates fake input events to indicate
- * when devices are added or removed.
- *
- * The event hub provies a stream of input events (via the getEvent function).
- * It also supports querying the current actual state of input devices such as identifying
- * which keys are currently down.  Finally, the event hub keeps track of the capabilities of
- * individual input devices, such as their class and the set of key codes that they support.
- */
-class EventHubInterface : public virtual RefBase {
-protected:
-    EventHubInterface() { }
-    virtual ~EventHubInterface() { }
-
-public:
-    // Synthetic raw event type codes produced when devices are added or removed.
-    enum {
-        // Sent when a device is added.
-        DEVICE_ADDED = 0x10000000,
-        // Sent when a device is removed.
-        DEVICE_REMOVED = 0x20000000,
-        // Sent when all added/removed devices from the most recent scan have been reported.
-        // This event is always sent at least once.
-        FINISHED_DEVICE_SCAN = 0x30000000,
-    };
-
-    virtual uint32_t getDeviceClasses(int32_t deviceId) const = 0;
-
-    virtual String8 getDeviceName(int32_t deviceId) const = 0;
-
-    virtual void getConfiguration(int32_t deviceId, PropertyMap* outConfiguration) const = 0;
-
-    virtual status_t getAbsoluteAxisInfo(int32_t deviceId, int axis,
-            RawAbsoluteAxisInfo* outAxisInfo) const = 0;
-
-    virtual status_t scancodeToKeycode(int32_t deviceId, int scancode,
-            int32_t* outKeycode, uint32_t* outFlags) const = 0;
-
-    // exclude a particular device from opening
-    // this can be used to ignore input devices for sensors
-    virtual void addExcludedDevice(const char* deviceName) = 0;
-
-    /*
-     * Wait for the next event to become available and return it.
-     * After returning, the EventHub holds onto a wake lock until the next call to getEvent.
-     * This ensures that the device will not go to sleep while the event is being processed.
-     * If the device needs to remain awake longer than that, then the caller is responsible
-     * for taking care of it (say, by poking the power manager user activity timer).
-     */
-    virtual bool getEvent(RawEvent* outEvent) = 0;
-
-    /*
-     * Query current input state.
-     */
-    virtual int32_t getScanCodeState(int32_t deviceId, int32_t scanCode) const = 0;
-    virtual int32_t getKeyCodeState(int32_t deviceId, int32_t keyCode) const = 0;
-    virtual int32_t getSwitchState(int32_t deviceId, int32_t sw) const = 0;
-
-    /*
-     * Examine key input devices for specific framework keycode support
-     */
-    virtual bool markSupportedKeyCodes(int32_t deviceId, size_t numCodes, const int32_t* keyCodes,
-            uint8_t* outFlags) const = 0;
-
-    virtual bool hasLed(int32_t deviceId, int32_t led) const = 0;
-    virtual void setLedState(int32_t deviceId, int32_t led, bool on) = 0;
-
-    virtual void getVirtualKeyDefinitions(int32_t deviceId,
-            Vector<VirtualKeyDefinition>& outVirtualKeys) const = 0;
-
-    virtual void dump(String8& dump) = 0;
-};
-
-class EventHub : public EventHubInterface
-{
-public:
-    EventHub();
-
-    status_t errorCheck() const;
-
-    virtual uint32_t getDeviceClasses(int32_t deviceId) const;
-
-    virtual String8 getDeviceName(int32_t deviceId) const;
-
-    virtual void getConfiguration(int32_t deviceId, PropertyMap* outConfiguration) const;
-
-    virtual status_t getAbsoluteAxisInfo(int32_t deviceId, int axis,
-            RawAbsoluteAxisInfo* outAxisInfo) const;
-
-    virtual status_t scancodeToKeycode(int32_t deviceId, int scancode,
-            int32_t* outKeycode, uint32_t* outFlags) const;
-
-    virtual void addExcludedDevice(const char* deviceName);
-
-    virtual int32_t getScanCodeState(int32_t deviceId, int32_t scanCode) const;
-    virtual int32_t getKeyCodeState(int32_t deviceId, int32_t keyCode) const;
-    virtual int32_t getSwitchState(int32_t deviceId, int32_t sw) const;
-
-    virtual bool markSupportedKeyCodes(int32_t deviceId, size_t numCodes,
-            const int32_t* keyCodes, uint8_t* outFlags) const;
-
-    virtual bool getEvent(RawEvent* outEvent);
-
-    virtual bool hasLed(int32_t deviceId, int32_t led) const;
-    virtual void setLedState(int32_t deviceId, int32_t led, bool on);
-
-    virtual void getVirtualKeyDefinitions(int32_t deviceId,
-            Vector<VirtualKeyDefinition>& outVirtualKeys) const;
-
-    virtual void dump(String8& dump);
-
-protected:
-    virtual ~EventHub();
-    
-private:
-    bool openPlatformInput(void);
-
-    int openDevice(const char *devicePath);
-    int closeDevice(const char *devicePath);
-    int scanDir(const char *dirname);
-    int readNotify(int nfd);
-
-    status_t mError;
-
-    struct Device {
-        Device* next;
-
-        int fd;
-        const int32_t id;
-        const String8 path;
-        const InputDeviceIdentifier identifier;
-
-        uint32_t classes;
-        uint8_t* keyBitmask;
-        String8 configurationFile;
-        PropertyMap* configuration;
-        VirtualKeyMap* virtualKeyMap;
-        KeyMap keyMap;
-
-        Device(int fd, int32_t id, const String8& path, const InputDeviceIdentifier& identifier);
-        ~Device();
-
-        void close();
-    };
-
-    Device* getDeviceLocked(int32_t deviceId) const;
-    bool hasKeycodeLocked(Device* device, int keycode) const;
-
-    int32_t getScanCodeStateLocked(Device* device, int32_t scanCode) const;
-    int32_t getKeyCodeStateLocked(Device* device, int32_t keyCode) const;
-    int32_t getSwitchStateLocked(Device* device, int32_t sw) const;
-    bool markSupportedKeyCodesLocked(Device* device, size_t numCodes,
-            const int32_t* keyCodes, uint8_t* outFlags) const;
-
-    void loadConfiguration(Device* device);
-    status_t loadVirtualKeyMap(Device* device);
-    status_t loadKeyMap(Device* device);
-    void setKeyboardProperties(Device* device, bool builtInKeyboard);
-    void clearKeyboardProperties(Device* device, bool builtInKeyboard);
-
-    // Protect all internal state.
-    mutable Mutex mLock;
-
-    // The actual id of the built-in keyboard, or -1 if none.
-    // EventHub remaps the built-in keyboard to id 0 externally as required by the API.
-    int32_t mBuiltInKeyboardId;
-
-    int32_t mNextDeviceId;
-
-    // Parallel arrays of fds and devices.
-    // First index is reserved for inotify.
-    Vector<struct pollfd> mFds;
-    Vector<Device*> mDevices;
-
-    Device *mOpeningDevices;
-    Device *mClosingDevices;
-
-    bool mOpened;
-    bool mNeedToSendFinishedDeviceScan;
-    List<String8> mExcludedDevices;
-
-    // device ids that report particular switches.
-#ifdef EV_SW
-    int32_t mSwitches[SW_MAX + 1];
-#endif
-
-    static const int INPUT_BUFFER_SIZE = 64;
-    struct input_event mInputBufferData[INPUT_BUFFER_SIZE];
-    size_t mInputBufferIndex;
-    size_t mInputBufferCount;
-    size_t mInputFdIndex;
-};
-
-}; // namespace android
-
-#endif // _RUNTIME_EVENT_HUB_H
diff --git a/include/ui/GraphicBuffer.h b/include/ui/GraphicBuffer.h
index aa65d93..8b256f4 100644
--- a/include/ui/GraphicBuffer.h
+++ b/include/ui/GraphicBuffer.h
@@ -121,6 +121,7 @@
     friend class Surface;
     friend class BpSurface;
     friend class BnSurface;
+    friend class SurfaceTextureClient;
     friend class LightRefBase<GraphicBuffer>;
     GraphicBuffer(const GraphicBuffer& rhs);
     GraphicBuffer& operator = (const GraphicBuffer& rhs);
diff --git a/include/ui/InputDispatcher.h b/include/ui/InputDispatcher.h
deleted file mode 100644
index 7305601..0000000
--- a/include/ui/InputDispatcher.h
+++ /dev/null
@@ -1,1110 +0,0 @@
-/*
- * Copyright (C) 2010 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-#ifndef _UI_INPUT_DISPATCHER_H
-#define _UI_INPUT_DISPATCHER_H
-
-#include <ui/Input.h>
-#include <ui/InputTransport.h>
-#include <utils/KeyedVector.h>
-#include <utils/Vector.h>
-#include <utils/threads.h>
-#include <utils/Timers.h>
-#include <utils/RefBase.h>
-#include <utils/String8.h>
-#include <utils/Looper.h>
-#include <utils/Pool.h>
-#include <utils/BitSet.h>
-
-#include <stddef.h>
-#include <unistd.h>
-#include <limits.h>
-
-
-namespace android {
-
-/*
- * Constants used to report the outcome of input event injection.
- */
-enum {
-    /* (INTERNAL USE ONLY) Specifies that injection is pending and its outcome is unknown. */
-    INPUT_EVENT_INJECTION_PENDING = -1,
-
-    /* Injection succeeded. */
-    INPUT_EVENT_INJECTION_SUCCEEDED = 0,
-
-    /* Injection failed because the injector did not have permission to inject
-     * into the application with input focus. */
-    INPUT_EVENT_INJECTION_PERMISSION_DENIED = 1,
-
-    /* Injection failed because there were no available input targets. */
-    INPUT_EVENT_INJECTION_FAILED = 2,
-
-    /* Injection failed due to a timeout. */
-    INPUT_EVENT_INJECTION_TIMED_OUT = 3
-};
-
-/*
- * Constants used to determine the input event injection synchronization mode.
- */
-enum {
-    /* Injection is asynchronous and is assumed always to be successful. */
-    INPUT_EVENT_INJECTION_SYNC_NONE = 0,
-
-    /* Waits for previous events to be dispatched so that the input dispatcher can determine
-     * whether input event injection willbe permitted based on the current input focus.
-     * Does not wait for the input event to finish processing. */
-    INPUT_EVENT_INJECTION_SYNC_WAIT_FOR_RESULT = 1,
-
-    /* Waits for the input event to be completely processed. */
-    INPUT_EVENT_INJECTION_SYNC_WAIT_FOR_FINISHED = 2,
-};
-
-
-/*
- * An input target specifies how an input event is to be dispatched to a particular window
- * including the window's input channel, control flags, a timeout, and an X / Y offset to
- * be added to input event coordinates to compensate for the absolute position of the
- * window area.
- */
-struct InputTarget {
-    enum {
-        /* This flag indicates that the event is being delivered to a foreground application. */
-        FLAG_FOREGROUND = 0x01,
-
-        /* This flag indicates that a MotionEvent with AMOTION_EVENT_ACTION_DOWN falls outside
-         * of the area of this target and so should instead be delivered as an
-         * AMOTION_EVENT_ACTION_OUTSIDE to this target. */
-        FLAG_OUTSIDE = 0x02,
-
-        /* This flag indicates that the target of a MotionEvent is partly or wholly
-         * obscured by another visible window above it.  The motion event should be
-         * delivered with flag AMOTION_EVENT_FLAG_WINDOW_IS_OBSCURED. */
-        FLAG_WINDOW_IS_OBSCURED = 0x04,
-
-        /* This flag indicates that a motion event is being split across multiple windows. */
-        FLAG_SPLIT = 0x08,
-    };
-
-    // The input channel to be targeted.
-    sp<InputChannel> inputChannel;
-
-    // Flags for the input target.
-    int32_t flags;
-
-    // The x and y offset to add to a MotionEvent as it is delivered.
-    // (ignored for KeyEvents)
-    float xOffset, yOffset;
-
-    // The subset of pointer ids to include in motion events dispatched to this input target
-    // if FLAG_SPLIT is set.
-    BitSet32 pointerIds;
-};
-
-
-/*
- * An input window describes the bounds of a window that can receive input.
- */
-struct InputWindow {
-    // Window flags from WindowManager.LayoutParams
-    enum {
-        FLAG_ALLOW_LOCK_WHILE_SCREEN_ON     = 0x00000001,
-        FLAG_DIM_BEHIND        = 0x00000002,
-        FLAG_BLUR_BEHIND        = 0x00000004,
-        FLAG_NOT_FOCUSABLE      = 0x00000008,
-        FLAG_NOT_TOUCHABLE      = 0x00000010,
-        FLAG_NOT_TOUCH_MODAL    = 0x00000020,
-        FLAG_TOUCHABLE_WHEN_WAKING = 0x00000040,
-        FLAG_KEEP_SCREEN_ON     = 0x00000080,
-        FLAG_LAYOUT_IN_SCREEN   = 0x00000100,
-        FLAG_LAYOUT_NO_LIMITS   = 0x00000200,
-        FLAG_FULLSCREEN      = 0x00000400,
-        FLAG_FORCE_NOT_FULLSCREEN   = 0x00000800,
-        FLAG_DITHER             = 0x00001000,
-        FLAG_SECURE             = 0x00002000,
-        FLAG_SCALED             = 0x00004000,
-        FLAG_IGNORE_CHEEK_PRESSES    = 0x00008000,
-        FLAG_LAYOUT_INSET_DECOR = 0x00010000,
-        FLAG_ALT_FOCUSABLE_IM = 0x00020000,
-        FLAG_WATCH_OUTSIDE_TOUCH = 0x00040000,
-        FLAG_SHOW_WHEN_LOCKED = 0x00080000,
-        FLAG_SHOW_WALLPAPER = 0x00100000,
-        FLAG_TURN_SCREEN_ON = 0x00200000,
-        FLAG_DISMISS_KEYGUARD = 0x00400000,
-        FLAG_SPLIT_TOUCH = 0x00800000,
-        FLAG_KEEP_SURFACE_WHILE_ANIMATING = 0x10000000,
-        FLAG_COMPATIBLE_WINDOW = 0x20000000,
-        FLAG_SYSTEM_ERROR = 0x40000000,
-    };
-
-    // Window types from WindowManager.LayoutParams
-    enum {
-        FIRST_APPLICATION_WINDOW = 1,
-        TYPE_BASE_APPLICATION   = 1,
-        TYPE_APPLICATION        = 2,
-        TYPE_APPLICATION_STARTING = 3,
-        LAST_APPLICATION_WINDOW = 99,
-        FIRST_SUB_WINDOW        = 1000,
-        TYPE_APPLICATION_PANEL  = FIRST_SUB_WINDOW,
-        TYPE_APPLICATION_MEDIA  = FIRST_SUB_WINDOW+1,
-        TYPE_APPLICATION_SUB_PANEL = FIRST_SUB_WINDOW+2,
-        TYPE_APPLICATION_ATTACHED_DIALOG = FIRST_SUB_WINDOW+3,
-        TYPE_APPLICATION_MEDIA_OVERLAY  = FIRST_SUB_WINDOW+4,
-        LAST_SUB_WINDOW         = 1999,
-        FIRST_SYSTEM_WINDOW     = 2000,
-        TYPE_STATUS_BAR         = FIRST_SYSTEM_WINDOW,
-        TYPE_SEARCH_BAR         = FIRST_SYSTEM_WINDOW+1,
-        TYPE_PHONE              = FIRST_SYSTEM_WINDOW+2,
-        TYPE_SYSTEM_ALERT       = FIRST_SYSTEM_WINDOW+3,
-        TYPE_KEYGUARD           = FIRST_SYSTEM_WINDOW+4,
-        TYPE_TOAST              = FIRST_SYSTEM_WINDOW+5,
-        TYPE_SYSTEM_OVERLAY     = FIRST_SYSTEM_WINDOW+6,
-        TYPE_PRIORITY_PHONE     = FIRST_SYSTEM_WINDOW+7,
-        TYPE_SYSTEM_DIALOG      = FIRST_SYSTEM_WINDOW+8,
-        TYPE_KEYGUARD_DIALOG    = FIRST_SYSTEM_WINDOW+9,
-        TYPE_SYSTEM_ERROR       = FIRST_SYSTEM_WINDOW+10,
-        TYPE_INPUT_METHOD       = FIRST_SYSTEM_WINDOW+11,
-        TYPE_INPUT_METHOD_DIALOG= FIRST_SYSTEM_WINDOW+12,
-        TYPE_WALLPAPER          = FIRST_SYSTEM_WINDOW+13,
-        TYPE_STATUS_BAR_SUB_PANEL  = FIRST_SYSTEM_WINDOW+14,
-        TYPE_SECURE_SYSTEM_OVERLAY = FIRST_SYSTEM_WINDOW+15,
-        TYPE_DRAG               = FIRST_SYSTEM_WINDOW+16,
-        TYPE_STATUS_BAR_PANEL   = FIRST_SYSTEM_WINDOW+17,
-        LAST_SYSTEM_WINDOW      = 2999,
-    };
-
-    sp<InputChannel> inputChannel;
-    String8 name;
-    int32_t layoutParamsFlags;
-    int32_t layoutParamsType;
-    nsecs_t dispatchingTimeout;
-    int32_t frameLeft;
-    int32_t frameTop;
-    int32_t frameRight;
-    int32_t frameBottom;
-    int32_t visibleFrameLeft;
-    int32_t visibleFrameTop;
-    int32_t visibleFrameRight;
-    int32_t visibleFrameBottom;
-    int32_t touchableAreaLeft;
-    int32_t touchableAreaTop;
-    int32_t touchableAreaRight;
-    int32_t touchableAreaBottom;
-    bool visible;
-    bool canReceiveKeys;
-    bool hasFocus;
-    bool hasWallpaper;
-    bool paused;
-    int32_t layer;
-    int32_t ownerPid;
-    int32_t ownerUid;
-
-    bool touchableAreaContainsPoint(int32_t x, int32_t y) const;
-    bool frameContainsPoint(int32_t x, int32_t y) const;
-
-    /* Returns true if the window is of a trusted type that is allowed to silently
-     * overlay other windows for the purpose of implementing the secure views feature.
-     * Trusted overlays, such as IME windows, can partly obscure other windows without causing
-     * motion events to be delivered to them with AMOTION_EVENT_FLAG_WINDOW_IS_OBSCURED.
-     */
-    bool isTrustedOverlay() const;
-
-    bool supportsSplitTouch() const;
-};
-
-
-/*
- * A private handle type used by the input manager to track the window.
- */
-class InputApplicationHandle : public RefBase {
-protected:
-    InputApplicationHandle() { }
-    virtual ~InputApplicationHandle() { }
-};
-
-
-/*
- * An input application describes properties of an application that can receive input.
- */
-struct InputApplication {
-    String8 name;
-    nsecs_t dispatchingTimeout;
-    sp<InputApplicationHandle> handle;
-};
-
-
-/*
- * Input dispatcher policy interface.
- *
- * The input reader policy is used by the input reader to interact with the Window Manager
- * and other system components.
- *
- * The actual implementation is partially supported by callbacks into the DVM
- * via JNI.  This interface is also mocked in the unit tests.
- */
-class InputDispatcherPolicyInterface : public virtual RefBase {
-protected:
-    InputDispatcherPolicyInterface() { }
-    virtual ~InputDispatcherPolicyInterface() { }
-
-public:
-    /* Notifies the system that a configuration change has occurred. */
-    virtual void notifyConfigurationChanged(nsecs_t when) = 0;
-
-    /* Notifies the system that an application is not responding.
-     * Returns a new timeout to continue waiting, or 0 to abort dispatch. */
-    virtual nsecs_t notifyANR(const sp<InputApplicationHandle>& inputApplicationHandle,
-            const sp<InputChannel>& inputChannel) = 0;
-
-    /* Notifies the system that an input channel is unrecoverably broken. */
-    virtual void notifyInputChannelBroken(const sp<InputChannel>& inputChannel) = 0;
-
-    /* Gets the key repeat initial timeout or -1 if automatic key repeating is disabled. */
-    virtual nsecs_t getKeyRepeatTimeout() = 0;
-
-    /* Gets the key repeat inter-key delay. */
-    virtual nsecs_t getKeyRepeatDelay() = 0;
-
-    /* Gets the maximum suggested event delivery rate per second.
-     * This value is used to throttle motion event movement actions on a per-device
-     * basis.  It is not intended to be a hard limit.
-     */
-    virtual int32_t getMaxEventsPerSecond() = 0;
-
-    /* Intercepts a key event immediately before queueing it.
-     * The policy can use this method as an opportunity to perform power management functions
-     * and early event preprocessing such as updating policy flags.
-     *
-     * This method is expected to set the POLICY_FLAG_PASS_TO_USER policy flag if the event
-     * should be dispatched to applications.
-     */
-    virtual void interceptKeyBeforeQueueing(const KeyEvent* keyEvent, uint32_t& policyFlags) = 0;
-
-    /* Intercepts a generic touch, trackball or other event before queueing it.
-     * The policy can use this method as an opportunity to perform power management functions
-     * and early event preprocessing such as updating policy flags.
-     *
-     * This method is expected to set the POLICY_FLAG_PASS_TO_USER policy flag if the event
-     * should be dispatched to applications.
-     */
-    virtual void interceptGenericBeforeQueueing(nsecs_t when, uint32_t& policyFlags) = 0;
-
-    /* Allows the policy a chance to intercept a key before dispatching. */
-    virtual bool interceptKeyBeforeDispatching(const sp<InputChannel>& inputChannel,
-            const KeyEvent* keyEvent, uint32_t policyFlags) = 0;
-
-    /* Allows the policy a chance to perform default processing for an unhandled key.
-     * Returns an alternate keycode to redispatch as a fallback, or 0 to give up. */
-    virtual bool dispatchUnhandledKey(const sp<InputChannel>& inputChannel,
-            const KeyEvent* keyEvent, uint32_t policyFlags, KeyEvent* outFallbackKeyEvent) = 0;
-
-    /* Notifies the policy about switch events.
-     */
-    virtual void notifySwitch(nsecs_t when,
-            int32_t switchCode, int32_t switchValue, uint32_t policyFlags) = 0;
-
-    /* Poke user activity for an event dispatched to a window. */
-    virtual void pokeUserActivity(nsecs_t eventTime, int32_t eventType) = 0;
-
-    /* Checks whether a given application pid/uid has permission to inject input events
-     * into other applications.
-     *
-     * This method is special in that its implementation promises to be non-reentrant and
-     * is safe to call while holding other locks.  (Most other methods make no such guarantees!)
-     */
-    virtual bool checkInjectEventsPermissionNonReentrant(
-            int32_t injectorPid, int32_t injectorUid) = 0;
-};
-
-
-/* Notifies the system about input events generated by the input reader.
- * The dispatcher is expected to be mostly asynchronous. */
-class InputDispatcherInterface : public virtual RefBase {
-protected:
-    InputDispatcherInterface() { }
-    virtual ~InputDispatcherInterface() { }
-
-public:
-    /* Dumps the state of the input dispatcher.
-     *
-     * This method may be called on any thread (usually by the input manager). */
-    virtual void dump(String8& dump) = 0;
-
-    /* Runs a single iteration of the dispatch loop.
-     * Nominally processes one queued event, a timeout, or a response from an input consumer.
-     *
-     * This method should only be called on the input dispatcher thread.
-     */
-    virtual void dispatchOnce() = 0;
-
-    /* Notifies the dispatcher about new events.
-     *
-     * These methods should only be called on the input reader thread.
-     */
-    virtual void notifyConfigurationChanged(nsecs_t eventTime) = 0;
-    virtual void notifyKey(nsecs_t eventTime, int32_t deviceId, int32_t source,
-            uint32_t policyFlags, int32_t action, int32_t flags, int32_t keyCode,
-            int32_t scanCode, int32_t metaState, nsecs_t downTime) = 0;
-    virtual void notifyMotion(nsecs_t eventTime, int32_t deviceId, int32_t source,
-            uint32_t policyFlags, int32_t action, int32_t flags,
-            int32_t metaState, int32_t edgeFlags,
-            uint32_t pointerCount, const int32_t* pointerIds, const PointerCoords* pointerCoords,
-            float xPrecision, float yPrecision, nsecs_t downTime) = 0;
-    virtual void notifySwitch(nsecs_t when,
-            int32_t switchCode, int32_t switchValue, uint32_t policyFlags) = 0;
-
-    /* Injects an input event and optionally waits for sync.
-     * The synchronization mode determines whether the method blocks while waiting for
-     * input injection to proceed.
-     * Returns one of the INPUT_EVENT_INJECTION_XXX constants.
-     *
-     * This method may be called on any thread (usually by the input manager).
-     */
-    virtual int32_t injectInputEvent(const InputEvent* event,
-            int32_t injectorPid, int32_t injectorUid, int32_t syncMode, int32_t timeoutMillis) = 0;
-
-    /* Sets the list of input windows.
-     *
-     * This method may be called on any thread (usually by the input manager).
-     */
-    virtual void setInputWindows(const Vector<InputWindow>& inputWindows) = 0;
-
-    /* Sets the focused application.
-     *
-     * This method may be called on any thread (usually by the input manager).
-     */
-    virtual void setFocusedApplication(const InputApplication* inputApplication) = 0;
-
-    /* Sets the input dispatching mode.
-     *
-     * This method may be called on any thread (usually by the input manager).
-     */
-    virtual void setInputDispatchMode(bool enabled, bool frozen) = 0;
-
-    /* Transfers touch focus from the window associated with one channel to the
-     * window associated with the other channel.
-     *
-     * Returns true on success.  False if the window did not actually have touch focus.
-     */
-    virtual bool transferTouchFocus(const sp<InputChannel>& fromChannel,
-            const sp<InputChannel>& toChannel) = 0;
-
-    /* Registers or unregister input channels that may be used as targets for input events.
-     * If monitor is true, the channel will receive a copy of all input events.
-     *
-     * These methods may be called on any thread (usually by the input manager).
-     */
-    virtual status_t registerInputChannel(const sp<InputChannel>& inputChannel, bool monitor) = 0;
-    virtual status_t unregisterInputChannel(const sp<InputChannel>& inputChannel) = 0;
-};
-
-/* Dispatches events to input targets.  Some functions of the input dispatcher, such as
- * identifying input targets, are controlled by a separate policy object.
- *
- * IMPORTANT INVARIANT:
- *     Because the policy can potentially block or cause re-entrance into the input dispatcher,
- *     the input dispatcher never calls into the policy while holding its internal locks.
- *     The implementation is also carefully designed to recover from scenarios such as an
- *     input channel becoming unregistered while identifying input targets or processing timeouts.
- *
- *     Methods marked 'Locked' must be called with the lock acquired.
- *
- *     Methods marked 'LockedInterruptible' must be called with the lock acquired but
- *     may during the course of their execution release the lock, call into the policy, and
- *     then reacquire the lock.  The caller is responsible for recovering gracefully.
- *
- *     A 'LockedInterruptible' method may called a 'Locked' method, but NOT vice-versa.
- */
-class InputDispatcher : public InputDispatcherInterface {
-protected:
-    virtual ~InputDispatcher();
-
-public:
-    explicit InputDispatcher(const sp<InputDispatcherPolicyInterface>& policy);
-
-    virtual void dump(String8& dump);
-
-    virtual void dispatchOnce();
-
-    virtual void notifyConfigurationChanged(nsecs_t eventTime);
-    virtual void notifyKey(nsecs_t eventTime, int32_t deviceId, int32_t source,
-            uint32_t policyFlags, int32_t action, int32_t flags, int32_t keyCode,
-            int32_t scanCode, int32_t metaState, nsecs_t downTime);
-    virtual void notifyMotion(nsecs_t eventTime, int32_t deviceId, int32_t source,
-            uint32_t policyFlags, int32_t action, int32_t flags,
-            int32_t metaState, int32_t edgeFlags,
-            uint32_t pointerCount, const int32_t* pointerIds, const PointerCoords* pointerCoords,
-            float xPrecision, float yPrecision, nsecs_t downTime);
-    virtual void notifySwitch(nsecs_t when,
-            int32_t switchCode, int32_t switchValue, uint32_t policyFlags) ;
-
-    virtual int32_t injectInputEvent(const InputEvent* event,
-            int32_t injectorPid, int32_t injectorUid, int32_t syncMode, int32_t timeoutMillis);
-
-    virtual void setInputWindows(const Vector<InputWindow>& inputWindows);
-    virtual void setFocusedApplication(const InputApplication* inputApplication);
-    virtual void setInputDispatchMode(bool enabled, bool frozen);
-
-    virtual bool transferTouchFocus(const sp<InputChannel>& fromChannel,
-            const sp<InputChannel>& toChannel);
-
-    virtual status_t registerInputChannel(const sp<InputChannel>& inputChannel, bool monitor);
-    virtual status_t unregisterInputChannel(const sp<InputChannel>& inputChannel);
-
-private:
-    template <typename T>
-    struct Link {
-        T* next;
-        T* prev;
-    };
-
-    struct InjectionState {
-        mutable int32_t refCount;
-
-        int32_t injectorPid;
-        int32_t injectorUid;
-        int32_t injectionResult;  // initially INPUT_EVENT_INJECTION_PENDING
-        bool injectionIsAsync; // set to true if injection is not waiting for the result
-        int32_t pendingForegroundDispatches; // the number of foreground dispatches in progress
-    };
-
-    struct EventEntry : Link<EventEntry> {
-        enum {
-            TYPE_SENTINEL,
-            TYPE_CONFIGURATION_CHANGED,
-            TYPE_KEY,
-            TYPE_MOTION
-        };
-
-        mutable int32_t refCount;
-        int32_t type;
-        nsecs_t eventTime;
-        uint32_t policyFlags;
-        InjectionState* injectionState;
-
-        bool dispatchInProgress; // initially false, set to true while dispatching
-
-        inline bool isInjected() { return injectionState != NULL; }
-    };
-
-    struct ConfigurationChangedEntry : EventEntry {
-    };
-
-    struct KeyEntry : EventEntry {
-        int32_t deviceId;
-        int32_t source;
-        int32_t action;
-        int32_t flags;
-        int32_t keyCode;
-        int32_t scanCode;
-        int32_t metaState;
-        int32_t repeatCount;
-        nsecs_t downTime;
-
-        bool syntheticRepeat; // set to true for synthetic key repeats
-
-        enum InterceptKeyResult {
-            INTERCEPT_KEY_RESULT_UNKNOWN,
-            INTERCEPT_KEY_RESULT_SKIP,
-            INTERCEPT_KEY_RESULT_CONTINUE,
-        };
-        InterceptKeyResult interceptKeyResult; // set based on the interception result
-    };
-
-    struct MotionSample {
-        MotionSample* next;
-
-        nsecs_t eventTime;
-        PointerCoords pointerCoords[MAX_POINTERS];
-    };
-
-    struct MotionEntry : EventEntry {
-        int32_t deviceId;
-        int32_t source;
-        int32_t action;
-        int32_t flags;
-        int32_t metaState;
-        int32_t edgeFlags;
-        float xPrecision;
-        float yPrecision;
-        nsecs_t downTime;
-        uint32_t pointerCount;
-        int32_t pointerIds[MAX_POINTERS];
-
-        // Linked list of motion samples associated with this motion event.
-        MotionSample firstSample;
-        MotionSample* lastSample;
-
-        uint32_t countSamples() const;
-    };
-
-    // Tracks the progress of dispatching a particular event to a particular connection.
-    struct DispatchEntry : Link<DispatchEntry> {
-        EventEntry* eventEntry; // the event to dispatch
-        int32_t targetFlags;
-        float xOffset;
-        float yOffset;
-
-        // True if dispatch has started.
-        bool inProgress;
-
-        // For motion events:
-        //   Pointer to the first motion sample to dispatch in this cycle.
-        //   Usually NULL to indicate that the list of motion samples begins at
-        //   MotionEntry::firstSample.  Otherwise, some samples were dispatched in a previous
-        //   cycle and this pointer indicates the location of the first remainining sample
-        //   to dispatch during the current cycle.
-        MotionSample* headMotionSample;
-        //   Pointer to a motion sample to dispatch in the next cycle if the dispatcher was
-        //   unable to send all motion samples during this cycle.  On the next cycle,
-        //   headMotionSample will be initialized to tailMotionSample and tailMotionSample
-        //   will be set to NULL.
-        MotionSample* tailMotionSample;
-
-        inline bool hasForegroundTarget() const {
-            return targetFlags & InputTarget::FLAG_FOREGROUND;
-        }
-
-        inline bool isSplit() const {
-            return targetFlags & InputTarget::FLAG_SPLIT;
-        }
-    };
-
-    // A command entry captures state and behavior for an action to be performed in the
-    // dispatch loop after the initial processing has taken place.  It is essentially
-    // a kind of continuation used to postpone sensitive policy interactions to a point
-    // in the dispatch loop where it is safe to release the lock (generally after finishing
-    // the critical parts of the dispatch cycle).
-    //
-    // The special thing about commands is that they can voluntarily release and reacquire
-    // the dispatcher lock at will.  Initially when the command starts running, the
-    // dispatcher lock is held.  However, if the command needs to call into the policy to
-    // do some work, it can release the lock, do the work, then reacquire the lock again
-    // before returning.
-    //
-    // This mechanism is a bit clunky but it helps to preserve the invariant that the dispatch
-    // never calls into the policy while holding its lock.
-    //
-    // Commands are implicitly 'LockedInterruptible'.
-    struct CommandEntry;
-    typedef void (InputDispatcher::*Command)(CommandEntry* commandEntry);
-
-    class Connection;
-    struct CommandEntry : Link<CommandEntry> {
-        CommandEntry();
-        ~CommandEntry();
-
-        Command command;
-
-        // parameters for the command (usage varies by command)
-        sp<Connection> connection;
-        nsecs_t eventTime;
-        KeyEntry* keyEntry;
-        sp<InputChannel> inputChannel;
-        sp<InputApplicationHandle> inputApplicationHandle;
-        int32_t userActivityEventType;
-        bool handled;
-    };
-
-    // Generic queue implementation.
-    template <typename T>
-    struct Queue {
-        T headSentinel;
-        T tailSentinel;
-
-        inline Queue() {
-            headSentinel.prev = NULL;
-            headSentinel.next = & tailSentinel;
-            tailSentinel.prev = & headSentinel;
-            tailSentinel.next = NULL;
-        }
-
-        inline bool isEmpty() const {
-            return headSentinel.next == & tailSentinel;
-        }
-
-        inline void enqueueAtTail(T* entry) {
-            T* last = tailSentinel.prev;
-            last->next = entry;
-            entry->prev = last;
-            entry->next = & tailSentinel;
-            tailSentinel.prev = entry;
-        }
-
-        inline void enqueueAtHead(T* entry) {
-            T* first = headSentinel.next;
-            headSentinel.next = entry;
-            entry->prev = & headSentinel;
-            entry->next = first;
-            first->prev = entry;
-        }
-
-        inline void dequeue(T* entry) {
-            entry->prev->next = entry->next;
-            entry->next->prev = entry->prev;
-        }
-
-        inline T* dequeueAtHead() {
-            T* first = headSentinel.next;
-            dequeue(first);
-            return first;
-        }
-
-        uint32_t count() const;
-    };
-
-    /* Allocates queue entries and performs reference counting as needed. */
-    class Allocator {
-    public:
-        Allocator();
-
-        InjectionState* obtainInjectionState(int32_t injectorPid, int32_t injectorUid);
-        ConfigurationChangedEntry* obtainConfigurationChangedEntry(nsecs_t eventTime);
-        KeyEntry* obtainKeyEntry(nsecs_t eventTime,
-                int32_t deviceId, int32_t source, uint32_t policyFlags, int32_t action,
-                int32_t flags, int32_t keyCode, int32_t scanCode, int32_t metaState,
-                int32_t repeatCount, nsecs_t downTime);
-        MotionEntry* obtainMotionEntry(nsecs_t eventTime,
-                int32_t deviceId, int32_t source, uint32_t policyFlags, int32_t action,
-                int32_t flags, int32_t metaState, int32_t edgeFlags,
-                float xPrecision, float yPrecision,
-                nsecs_t downTime, uint32_t pointerCount,
-                const int32_t* pointerIds, const PointerCoords* pointerCoords);
-        DispatchEntry* obtainDispatchEntry(EventEntry* eventEntry,
-                int32_t targetFlags, float xOffset, float yOffset);
-        CommandEntry* obtainCommandEntry(Command command);
-
-        void releaseInjectionState(InjectionState* injectionState);
-        void releaseEventEntry(EventEntry* entry);
-        void releaseConfigurationChangedEntry(ConfigurationChangedEntry* entry);
-        void releaseKeyEntry(KeyEntry* entry);
-        void releaseMotionEntry(MotionEntry* entry);
-        void releaseDispatchEntry(DispatchEntry* entry);
-        void releaseCommandEntry(CommandEntry* entry);
-
-        void recycleKeyEntry(KeyEntry* entry);
-
-        void appendMotionSample(MotionEntry* motionEntry,
-                nsecs_t eventTime, const PointerCoords* pointerCoords);
-
-    private:
-        Pool<InjectionState> mInjectionStatePool;
-        Pool<ConfigurationChangedEntry> mConfigurationChangeEntryPool;
-        Pool<KeyEntry> mKeyEntryPool;
-        Pool<MotionEntry> mMotionEntryPool;
-        Pool<MotionSample> mMotionSamplePool;
-        Pool<DispatchEntry> mDispatchEntryPool;
-        Pool<CommandEntry> mCommandEntryPool;
-
-        void initializeEventEntry(EventEntry* entry, int32_t type, nsecs_t eventTime,
-                uint32_t policyFlags);
-        void releaseEventEntryInjectionState(EventEntry* entry);
-    };
-
-    /* Tracks dispatched key and motion event state so that cancelation events can be
-     * synthesized when events are dropped. */
-    class InputState {
-    public:
-        // Specifies whether a given event will violate input state consistency.
-        enum Consistency {
-            // The event is consistent with the current input state.
-            CONSISTENT,
-            // The event is inconsistent with the current input state but applications
-            // will tolerate it.  eg. Down followed by another down.
-            TOLERABLE,
-            // The event is inconsistent with the current input state and will probably
-            // cause applications to crash.  eg. Up without prior down, move with
-            // unexpected number of pointers.
-            BROKEN
-        };
-
-        // Specifies the sources to cancel.
-        enum CancelationOptions {
-            CANCEL_ALL_EVENTS = 0,
-            CANCEL_POINTER_EVENTS = 1,
-            CANCEL_NON_POINTER_EVENTS = 2,
-            CANCEL_FALLBACK_EVENTS = 3,
-        };
-
-        InputState();
-        ~InputState();
-
-        // Returns true if there is no state to be canceled.
-        bool isNeutral() const;
-
-        // Records tracking information for an event that has just been published.
-        // Returns whether the event is consistent with the current input state.
-        Consistency trackEvent(const EventEntry* entry);
-
-        // Records tracking information for a key event that has just been published.
-        // Returns whether the event is consistent with the current input state.
-        Consistency trackKey(const KeyEntry* entry);
-
-        // Records tracking information for a motion event that has just been published.
-        // Returns whether the event is consistent with the current input state.
-        Consistency trackMotion(const MotionEntry* entry);
-
-        // Synthesizes cancelation events for the current state and resets the tracked state.
-        void synthesizeCancelationEvents(nsecs_t currentTime, Allocator* allocator,
-                Vector<EventEntry*>& outEvents, CancelationOptions options);
-
-        // Clears the current state.
-        void clear();
-
-        // Copies pointer-related parts of the input state to another instance.
-        void copyPointerStateTo(InputState& other) const;
-
-    private:
-        struct KeyMemento {
-            int32_t deviceId;
-            int32_t source;
-            int32_t keyCode;
-            int32_t scanCode;
-            int32_t flags;
-            nsecs_t downTime;
-        };
-
-        struct MotionMemento {
-            int32_t deviceId;
-            int32_t source;
-            float xPrecision;
-            float yPrecision;
-            nsecs_t downTime;
-            uint32_t pointerCount;
-            int32_t pointerIds[MAX_POINTERS];
-            PointerCoords pointerCoords[MAX_POINTERS];
-
-            void setPointers(const MotionEntry* entry);
-        };
-
-        Vector<KeyMemento> mKeyMementos;
-        Vector<MotionMemento> mMotionMementos;
-
-        static bool shouldCancelKey(const KeyMemento& memento,
-                CancelationOptions options);
-        static bool shouldCancelMotion(const MotionMemento& memento,
-                CancelationOptions options);
-    };
-
-    /* Manages the dispatch state associated with a single input channel. */
-    class Connection : public RefBase {
-    protected:
-        virtual ~Connection();
-
-    public:
-        enum Status {
-            // Everything is peachy.
-            STATUS_NORMAL,
-            // An unrecoverable communication error has occurred.
-            STATUS_BROKEN,
-            // The input channel has been unregistered.
-            STATUS_ZOMBIE
-        };
-
-        Status status;
-        sp<InputChannel> inputChannel;
-        InputPublisher inputPublisher;
-        InputState inputState;
-        Queue<DispatchEntry> outboundQueue;
-
-        nsecs_t lastEventTime; // the time when the event was originally captured
-        nsecs_t lastDispatchTime; // the time when the last event was dispatched
-
-        explicit Connection(const sp<InputChannel>& inputChannel);
-
-        inline const char* getInputChannelName() const { return inputChannel->getName().string(); }
-
-        const char* getStatusLabel() const;
-
-        // Finds a DispatchEntry in the outbound queue associated with the specified event.
-        // Returns NULL if not found.
-        DispatchEntry* findQueuedDispatchEntryForEvent(const EventEntry* eventEntry) const;
-
-        // Gets the time since the current event was originally obtained from the input driver.
-        inline double getEventLatencyMillis(nsecs_t currentTime) const {
-            return (currentTime - lastEventTime) / 1000000.0;
-        }
-
-        // Gets the time since the current event entered the outbound dispatch queue.
-        inline double getDispatchLatencyMillis(nsecs_t currentTime) const {
-            return (currentTime - lastDispatchTime) / 1000000.0;
-        }
-
-        status_t initialize();
-    };
-
-    enum DropReason {
-        DROP_REASON_NOT_DROPPED = 0,
-        DROP_REASON_POLICY = 1,
-        DROP_REASON_APP_SWITCH = 2,
-        DROP_REASON_DISABLED = 3,
-    };
-
-    sp<InputDispatcherPolicyInterface> mPolicy;
-
-    Mutex mLock;
-
-    Allocator mAllocator;
-    sp<Looper> mLooper;
-
-    EventEntry* mPendingEvent;
-    Queue<EventEntry> mInboundQueue;
-    Queue<CommandEntry> mCommandQueue;
-
-    Vector<EventEntry*> mTempCancelationEvents;
-
-    void dispatchOnceInnerLocked(nsecs_t keyRepeatTimeout, nsecs_t keyRepeatDelay,
-            nsecs_t* nextWakeupTime);
-
-    // Enqueues an inbound event.  Returns true if mLooper->wake() should be called.
-    bool enqueueInboundEventLocked(EventEntry* entry);
-
-    // Cleans up input state when dropping an inbound event.
-    void dropInboundEventLocked(EventEntry* entry, DropReason dropReason);
-
-    // App switch latency optimization.
-    bool mAppSwitchSawKeyDown;
-    nsecs_t mAppSwitchDueTime;
-
-    static bool isAppSwitchKeyCode(int32_t keyCode);
-    bool isAppSwitchKeyEventLocked(KeyEntry* keyEntry);
-    bool isAppSwitchPendingLocked();
-    void resetPendingAppSwitchLocked(bool handled);
-
-    // All registered connections mapped by receive pipe file descriptor.
-    KeyedVector<int, sp<Connection> > mConnectionsByReceiveFd;
-
-    ssize_t getConnectionIndexLocked(const sp<InputChannel>& inputChannel);
-
-    // Active connections are connections that have a non-empty outbound queue.
-    // We don't use a ref-counted pointer here because we explicitly abort connections
-    // during unregistration which causes the connection's outbound queue to be cleared
-    // and the connection itself to be deactivated.
-    Vector<Connection*> mActiveConnections;
-
-    // Input channels that will receive a copy of all input events.
-    Vector<sp<InputChannel> > mMonitoringChannels;
-
-    // Event injection and synchronization.
-    Condition mInjectionResultAvailableCondition;
-    bool hasInjectionPermission(int32_t injectorPid, int32_t injectorUid);
-    void setInjectionResultLocked(EventEntry* entry, int32_t injectionResult);
-
-    Condition mInjectionSyncFinishedCondition;
-    void incrementPendingForegroundDispatchesLocked(EventEntry* entry);
-    void decrementPendingForegroundDispatchesLocked(EventEntry* entry);
-
-    // Throttling state.
-    struct ThrottleState {
-        nsecs_t minTimeBetweenEvents;
-
-        nsecs_t lastEventTime;
-        int32_t lastDeviceId;
-        uint32_t lastSource;
-
-        uint32_t originalSampleCount; // only collected during debugging
-    } mThrottleState;
-
-    // Key repeat tracking.
-    struct KeyRepeatState {
-        KeyEntry* lastKeyEntry; // or null if no repeat
-        nsecs_t nextRepeatTime;
-    } mKeyRepeatState;
-
-    void resetKeyRepeatLocked();
-    KeyEntry* synthesizeKeyRepeatLocked(nsecs_t currentTime, nsecs_t keyRepeatTimeout);
-
-    // Deferred command processing.
-    bool runCommandsLockedInterruptible();
-    CommandEntry* postCommandLocked(Command command);
-
-    // Inbound event processing.
-    void drainInboundQueueLocked();
-    void releasePendingEventLocked();
-    void releaseInboundEventLocked(EventEntry* entry);
-
-    // Dispatch state.
-    bool mDispatchEnabled;
-    bool mDispatchFrozen;
-
-    Vector<InputWindow> mWindows;
-
-    const InputWindow* getWindowLocked(const sp<InputChannel>& inputChannel);
-
-    // Focus tracking for keys, trackball, etc.
-    const InputWindow* mFocusedWindow;
-
-    // Focus tracking for touch.
-    struct TouchedWindow {
-        const InputWindow* window;
-        int32_t targetFlags;
-        BitSet32 pointerIds;        // zero unless target flag FLAG_SPLIT is set
-        sp<InputChannel> channel;
-    };
-    struct TouchState {
-        bool down;
-        bool split;
-        Vector<TouchedWindow> windows;
-
-        TouchState();
-        ~TouchState();
-        void reset();
-        void copyFrom(const TouchState& other);
-        void addOrUpdateWindow(const InputWindow* window, int32_t targetFlags, BitSet32 pointerIds);
-        void removeOutsideTouchWindows();
-        const InputWindow* getFirstForegroundWindow();
-    };
-
-    TouchState mTouchState;
-    TouchState mTempTouchState;
-
-    // Focused application.
-    InputApplication* mFocusedApplication;
-    InputApplication mFocusedApplicationStorage; // preallocated storage for mFocusedApplication
-    void releaseFocusedApplicationLocked();
-
-    // Dispatch inbound events.
-    bool dispatchConfigurationChangedLocked(
-            nsecs_t currentTime, ConfigurationChangedEntry* entry);
-    bool dispatchKeyLocked(
-            nsecs_t currentTime, KeyEntry* entry, nsecs_t keyRepeatTimeout,
-            DropReason* dropReason, nsecs_t* nextWakeupTime);
-    bool dispatchMotionLocked(
-            nsecs_t currentTime, MotionEntry* entry,
-            DropReason* dropReason, nsecs_t* nextWakeupTime);
-    void dispatchEventToCurrentInputTargetsLocked(
-            nsecs_t currentTime, EventEntry* entry, bool resumeWithAppendedMotionSample);
-
-    void logOutboundKeyDetailsLocked(const char* prefix, const KeyEntry* entry);
-    void logOutboundMotionDetailsLocked(const char* prefix, const MotionEntry* entry);
-
-    // The input targets that were most recently identified for dispatch.
-    bool mCurrentInputTargetsValid; // false while targets are being recomputed
-    Vector<InputTarget> mCurrentInputTargets;
-
-    enum InputTargetWaitCause {
-        INPUT_TARGET_WAIT_CAUSE_NONE,
-        INPUT_TARGET_WAIT_CAUSE_SYSTEM_NOT_READY,
-        INPUT_TARGET_WAIT_CAUSE_APPLICATION_NOT_READY,
-    };
-
-    InputTargetWaitCause mInputTargetWaitCause;
-    nsecs_t mInputTargetWaitStartTime;
-    nsecs_t mInputTargetWaitTimeoutTime;
-    bool mInputTargetWaitTimeoutExpired;
-
-    // Finding targets for input events.
-    void resetTargetsLocked();
-    void commitTargetsLocked();
-    int32_t handleTargetsNotReadyLocked(nsecs_t currentTime, const EventEntry* entry,
-            const InputApplication* application, const InputWindow* window,
-            nsecs_t* nextWakeupTime);
-    void resumeAfterTargetsNotReadyTimeoutLocked(nsecs_t newTimeout,
-            const sp<InputChannel>& inputChannel);
-    nsecs_t getTimeSpentWaitingForApplicationLocked(nsecs_t currentTime);
-    void resetANRTimeoutsLocked();
-
-    int32_t findFocusedWindowTargetsLocked(nsecs_t currentTime, const EventEntry* entry,
-            nsecs_t* nextWakeupTime);
-    int32_t findTouchedWindowTargetsLocked(nsecs_t currentTime, const MotionEntry* entry,
-            nsecs_t* nextWakeupTime);
-
-    void addWindowTargetLocked(const InputWindow* window, int32_t targetFlags,
-            BitSet32 pointerIds);
-    void addMonitoringTargetsLocked();
-    void pokeUserActivityLocked(const EventEntry* eventEntry);
-    bool checkInjectionPermission(const InputWindow* window, const InjectionState* injectionState);
-    bool isWindowObscuredAtPointLocked(const InputWindow* window, int32_t x, int32_t y) const;
-    bool isWindowFinishedWithPreviousInputLocked(const InputWindow* window);
-    String8 getApplicationWindowLabelLocked(const InputApplication* application,
-            const InputWindow* window);
-
-    // Manage the dispatch cycle for a single connection.
-    // These methods are deliberately not Interruptible because doing all of the work
-    // with the mutex held makes it easier to ensure that connection invariants are maintained.
-    // If needed, the methods post commands to run later once the critical bits are done.
-    void prepareDispatchCycleLocked(nsecs_t currentTime, const sp<Connection>& connection,
-            EventEntry* eventEntry, const InputTarget* inputTarget,
-            bool resumeWithAppendedMotionSample);
-    void startDispatchCycleLocked(nsecs_t currentTime, const sp<Connection>& connection);
-    void finishDispatchCycleLocked(nsecs_t currentTime, const sp<Connection>& connection,
-            bool handled);
-    void startNextDispatchCycleLocked(nsecs_t currentTime, const sp<Connection>& connection);
-    void abortBrokenDispatchCycleLocked(nsecs_t currentTime, const sp<Connection>& connection);
-    void drainOutboundQueueLocked(Connection* connection);
-    static int handleReceiveCallback(int receiveFd, int events, void* data);
-
-    void synthesizeCancelationEventsForAllConnectionsLocked(
-            InputState::CancelationOptions options, const char* reason);
-    void synthesizeCancelationEventsForInputChannelLocked(const sp<InputChannel>& channel,
-            InputState::CancelationOptions options, const char* reason);
-    void synthesizeCancelationEventsForConnectionLocked(const sp<Connection>& connection,
-            InputState::CancelationOptions options, const char* reason);
-
-    // Splitting motion events across windows.
-    MotionEntry* splitMotionEvent(const MotionEntry* originalMotionEntry, BitSet32 pointerIds);
-
-    // Reset and drop everything the dispatcher is doing.
-    void resetAndDropEverythingLocked(const char* reason);
-
-    // Dump state.
-    void dumpDispatchStateLocked(String8& dump);
-    void logDispatchStateLocked();
-
-    // Add or remove a connection to the mActiveConnections vector.
-    void activateConnectionLocked(Connection* connection);
-    void deactivateConnectionLocked(Connection* connection);
-
-    // Interesting events that we might like to log or tell the framework about.
-    void onDispatchCycleStartedLocked(
-            nsecs_t currentTime, const sp<Connection>& connection);
-    void onDispatchCycleFinishedLocked(
-            nsecs_t currentTime, const sp<Connection>& connection, bool handled);
-    void onDispatchCycleBrokenLocked(
-            nsecs_t currentTime, const sp<Connection>& connection);
-    void onANRLocked(
-            nsecs_t currentTime, const InputApplication* application, const InputWindow* window,
-            nsecs_t eventTime, nsecs_t waitStartTime);
-
-    // Outbound policy interactions.
-    void doNotifyConfigurationChangedInterruptible(CommandEntry* commandEntry);
-    void doNotifyInputChannelBrokenLockedInterruptible(CommandEntry* commandEntry);
-    void doNotifyANRLockedInterruptible(CommandEntry* commandEntry);
-    void doInterceptKeyBeforeDispatchingLockedInterruptible(CommandEntry* commandEntry);
-    void doDispatchCycleFinishedLockedInterruptible(CommandEntry* commandEntry);
-    void doPokeUserActivityLockedInterruptible(CommandEntry* commandEntry);
-    void initializeKeyEvent(KeyEvent* event, const KeyEntry* entry);
-
-    // Statistics gathering.
-    void updateDispatchStatisticsLocked(nsecs_t currentTime, const EventEntry* entry,
-            int32_t injectionResult, nsecs_t timeSpentWaitingForApplication);
-};
-
-/* Enqueues and dispatches input events, endlessly. */
-class InputDispatcherThread : public Thread {
-public:
-    explicit InputDispatcherThread(const sp<InputDispatcherInterface>& dispatcher);
-    ~InputDispatcherThread();
-
-private:
-    virtual bool threadLoop();
-
-    sp<InputDispatcherInterface> mDispatcher;
-};
-
-} // namespace android
-
-#endif // _UI_INPUT_DISPATCHER_H
diff --git a/include/ui/InputManager.h b/include/ui/InputManager.h
deleted file mode 100644
index 568568b..0000000
--- a/include/ui/InputManager.h
+++ /dev/null
@@ -1,115 +0,0 @@
-/*
- * Copyright (C) 2010 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-#ifndef _UI_INPUT_MANAGER_H
-#define _UI_INPUT_MANAGER_H
-
-/**
- * Native input manager.
- */
-
-#include <ui/EventHub.h>
-#include <ui/Input.h>
-#include <utils/Errors.h>
-#include <utils/Vector.h>
-#include <utils/Timers.h>
-#include <utils/RefBase.h>
-#include <utils/String8.h>
-
-namespace android {
-
-class InputChannel;
-
-class InputReaderInterface;
-class InputReaderPolicyInterface;
-class InputReaderThread;
-
-class InputDispatcherInterface;
-class InputDispatcherPolicyInterface;
-class InputDispatcherThread;
-
-/*
- * The input manager is the core of the system event processing.
- *
- * The input manager uses two threads.
- *
- * 1. The InputReaderThread (called "InputReader") reads and preprocesses raw input events,
- *    applies policy, and posts messages to a queue managed by the DispatcherThread.
- * 2. The InputDispatcherThread (called "InputDispatcher") thread waits for new events on the
- *    queue and asynchronously dispatches them to applications.
- *
- * By design, the InputReaderThread class and InputDispatcherThread class do not share any
- * internal state.  Moreover, all communication is done one way from the InputReaderThread
- * into the InputDispatcherThread and never the reverse.  Both classes may interact with the
- * InputDispatchPolicy, however.
- *
- * The InputManager class never makes any calls into Java itself.  Instead, the
- * InputDispatchPolicy is responsible for performing all external interactions with the
- * system, including calling DVM services.
- */
-class InputManagerInterface : public virtual RefBase {
-protected:
-    InputManagerInterface() { }
-    virtual ~InputManagerInterface() { }
-
-public:
-    /* Starts the input manager threads. */
-    virtual status_t start() = 0;
-
-    /* Stops the input manager threads and waits for them to exit. */
-    virtual status_t stop() = 0;
-
-    /* Gets the input reader. */
-    virtual sp<InputReaderInterface> getReader() = 0;
-
-    /* Gets the input dispatcher. */
-    virtual sp<InputDispatcherInterface> getDispatcher() = 0;
-};
-
-class InputManager : public InputManagerInterface {
-protected:
-    virtual ~InputManager();
-
-public:
-    InputManager(
-            const sp<EventHubInterface>& eventHub,
-            const sp<InputReaderPolicyInterface>& readerPolicy,
-            const sp<InputDispatcherPolicyInterface>& dispatcherPolicy);
-
-    // (used for testing purposes)
-    InputManager(
-            const sp<InputReaderInterface>& reader,
-            const sp<InputDispatcherInterface>& dispatcher);
-
-    virtual status_t start();
-    virtual status_t stop();
-
-    virtual sp<InputReaderInterface> getReader();
-    virtual sp<InputDispatcherInterface> getDispatcher();
-
-private:
-    sp<InputReaderInterface> mReader;
-    sp<InputReaderThread> mReaderThread;
-
-    sp<InputDispatcherInterface> mDispatcher;
-    sp<InputDispatcherThread> mDispatcherThread;
-
-    void initialize();
-};
-
-} // namespace android
-
-#endif // _UI_INPUT_MANAGER_H
diff --git a/include/ui/InputReader.h b/include/ui/InputReader.h
deleted file mode 100644
index b466ff1..0000000
--- a/include/ui/InputReader.h
+++ /dev/null
@@ -1,938 +0,0 @@
-/*
- * Copyright (C) 2010 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-#ifndef _UI_INPUT_READER_H
-#define _UI_INPUT_READER_H
-
-#include <ui/EventHub.h>
-#include <ui/Input.h>
-#include <ui/InputDispatcher.h>
-#include <utils/KeyedVector.h>
-#include <utils/threads.h>
-#include <utils/Timers.h>
-#include <utils/RefBase.h>
-#include <utils/String8.h>
-#include <utils/BitSet.h>
-
-#include <stddef.h>
-#include <unistd.h>
-
-namespace android {
-
-class InputDevice;
-class InputMapper;
-
-
-/*
- * Input reader policy interface.
- *
- * The input reader policy is used by the input reader to interact with the Window Manager
- * and other system components.
- *
- * The actual implementation is partially supported by callbacks into the DVM
- * via JNI.  This interface is also mocked in the unit tests.
- */
-class InputReaderPolicyInterface : public virtual RefBase {
-protected:
-    InputReaderPolicyInterface() { }
-    virtual ~InputReaderPolicyInterface() { }
-
-public:
-    /* Display orientations. */
-    enum {
-        ROTATION_0 = 0,
-        ROTATION_90 = 1,
-        ROTATION_180 = 2,
-        ROTATION_270 = 3
-    };
-
-    /* Gets information about the display with the specified id.
-     * Returns true if the display info is available, false otherwise.
-     */
-    virtual bool getDisplayInfo(int32_t displayId,
-            int32_t* width, int32_t* height, int32_t* orientation) = 0;
-
-    /* Determines whether to turn on some hacks we have to improve the touch interaction with a
-     * certain device whose screen currently is not all that good.
-     */
-    virtual bool filterTouchEvents() = 0;
-
-    /* Determines whether to turn on some hacks to improve touch interaction with another device
-     * where touch coordinate data can get corrupted.
-     */
-    virtual bool filterJumpyTouchEvents() = 0;
-
-    /* Gets the excluded device names for the platform. */
-    virtual void getExcludedDeviceNames(Vector<String8>& outExcludedDeviceNames) = 0;
-};
-
-
-/* Processes raw input events and sends cooked event data to an input dispatcher. */
-class InputReaderInterface : public virtual RefBase {
-protected:
-    InputReaderInterface() { }
-    virtual ~InputReaderInterface() { }
-
-public:
-    /* Dumps the state of the input reader.
-     *
-     * This method may be called on any thread (usually by the input manager). */
-    virtual void dump(String8& dump) = 0;
-
-    /* Runs a single iteration of the processing loop.
-     * Nominally reads and processes one incoming message from the EventHub.
-     *
-     * This method should be called on the input reader thread.
-     */
-    virtual void loopOnce() = 0;
-
-    /* Gets the current input device configuration.
-     *
-     * This method may be called on any thread (usually by the input manager).
-     */
-    virtual void getInputConfiguration(InputConfiguration* outConfiguration) = 0;
-
-    /* Gets information about the specified input device.
-     * Returns OK if the device information was obtained or NAME_NOT_FOUND if there
-     * was no such device.
-     *
-     * This method may be called on any thread (usually by the input manager).
-     */
-    virtual status_t getInputDeviceInfo(int32_t deviceId, InputDeviceInfo* outDeviceInfo) = 0;
-
-    /* Gets the list of all registered device ids. */
-    virtual void getInputDeviceIds(Vector<int32_t>& outDeviceIds) = 0;
-
-    /* Query current input state. */
-    virtual int32_t getScanCodeState(int32_t deviceId, uint32_t sourceMask,
-            int32_t scanCode) = 0;
-    virtual int32_t getKeyCodeState(int32_t deviceId, uint32_t sourceMask,
-            int32_t keyCode) = 0;
-    virtual int32_t getSwitchState(int32_t deviceId, uint32_t sourceMask,
-            int32_t sw) = 0;
-
-    /* Determine whether physical keys exist for the given framework-domain key codes. */
-    virtual bool hasKeys(int32_t deviceId, uint32_t sourceMask,
-            size_t numCodes, const int32_t* keyCodes, uint8_t* outFlags) = 0;
-};
-
-
-/* Internal interface used by individual input devices to access global input device state
- * and parameters maintained by the input reader.
- */
-class InputReaderContext {
-public:
-    InputReaderContext() { }
-    virtual ~InputReaderContext() { }
-
-    virtual void updateGlobalMetaState() = 0;
-    virtual int32_t getGlobalMetaState() = 0;
-
-    virtual InputReaderPolicyInterface* getPolicy() = 0;
-    virtual InputDispatcherInterface* getDispatcher() = 0;
-    virtual EventHubInterface* getEventHub() = 0;
-};
-
-
-/* The input reader reads raw event data from the event hub and processes it into input events
- * that it sends to the input dispatcher.  Some functions of the input reader, such as early
- * event filtering in low power states, are controlled by a separate policy object.
- *
- * IMPORTANT INVARIANT:
- *     Because the policy and dispatcher can potentially block or cause re-entrance into
- *     the input reader, the input reader never calls into other components while holding
- *     an exclusive internal lock whenever re-entrance can happen.
- */
-class InputReader : public InputReaderInterface, protected InputReaderContext {
-public:
-    InputReader(const sp<EventHubInterface>& eventHub,
-            const sp<InputReaderPolicyInterface>& policy,
-            const sp<InputDispatcherInterface>& dispatcher);
-    virtual ~InputReader();
-
-    virtual void dump(String8& dump);
-
-    virtual void loopOnce();
-
-    virtual void getInputConfiguration(InputConfiguration* outConfiguration);
-
-    virtual status_t getInputDeviceInfo(int32_t deviceId, InputDeviceInfo* outDeviceInfo);
-    virtual void getInputDeviceIds(Vector<int32_t>& outDeviceIds);
-
-    virtual int32_t getScanCodeState(int32_t deviceId, uint32_t sourceMask,
-            int32_t scanCode);
-    virtual int32_t getKeyCodeState(int32_t deviceId, uint32_t sourceMask,
-            int32_t keyCode);
-    virtual int32_t getSwitchState(int32_t deviceId, uint32_t sourceMask,
-            int32_t sw);
-
-    virtual bool hasKeys(int32_t deviceId, uint32_t sourceMask,
-            size_t numCodes, const int32_t* keyCodes, uint8_t* outFlags);
-
-protected:
-    // These methods are protected virtual so they can be overridden and instrumented
-    // by test cases.
-    virtual InputDevice* createDevice(int32_t deviceId, const String8& name, uint32_t classes);
-
-private:
-    sp<EventHubInterface> mEventHub;
-    sp<InputReaderPolicyInterface> mPolicy;
-    sp<InputDispatcherInterface> mDispatcher;
-
-    virtual InputReaderPolicyInterface* getPolicy() { return mPolicy.get(); }
-    virtual InputDispatcherInterface* getDispatcher() { return mDispatcher.get(); }
-    virtual EventHubInterface* getEventHub() { return mEventHub.get(); }
-
-    // This reader/writer lock guards the list of input devices.
-    // The writer lock must be held whenever the list of input devices is modified
-    //   and then promptly released.
-    // The reader lock must be held whenever the list of input devices is traversed or an
-    //   input device in the list is accessed.
-    // This lock only protects the registry and prevents inadvertent deletion of device objects
-    // that are in use.  Individual devices are responsible for guarding their own internal state
-    // as needed for concurrent operation.
-    RWLock mDeviceRegistryLock;
-    KeyedVector<int32_t, InputDevice*> mDevices;
-
-    // low-level input event decoding and device management
-    void process(const RawEvent* rawEvent);
-
-    void addDevice(int32_t deviceId);
-    void removeDevice(int32_t deviceId);
-    void configureExcludedDevices();
-
-    void consumeEvent(const RawEvent* rawEvent);
-
-    void handleConfigurationChanged(nsecs_t when);
-
-    // state management for all devices
-    Mutex mStateLock;
-
-    int32_t mGlobalMetaState;
-    virtual void updateGlobalMetaState();
-    virtual int32_t getGlobalMetaState();
-
-    InputConfiguration mInputConfiguration;
-    void updateInputConfiguration();
-
-    // state queries
-    typedef int32_t (InputDevice::*GetStateFunc)(uint32_t sourceMask, int32_t code);
-    int32_t getState(int32_t deviceId, uint32_t sourceMask, int32_t code,
-            GetStateFunc getStateFunc);
-    bool markSupportedKeyCodes(int32_t deviceId, uint32_t sourceMask, size_t numCodes,
-            const int32_t* keyCodes, uint8_t* outFlags);
-};
-
-
-/* Reads raw events from the event hub and processes them, endlessly. */
-class InputReaderThread : public Thread {
-public:
-    InputReaderThread(const sp<InputReaderInterface>& reader);
-    virtual ~InputReaderThread();
-
-private:
-    sp<InputReaderInterface> mReader;
-
-    virtual bool threadLoop();
-};
-
-
-/* Represents the state of a single input device. */
-class InputDevice {
-public:
-    InputDevice(InputReaderContext* context, int32_t id, const String8& name);
-    ~InputDevice();
-
-    inline InputReaderContext* getContext() { return mContext; }
-    inline int32_t getId() { return mId; }
-    inline const String8& getName() { return mName; }
-    inline uint32_t getSources() { return mSources; }
-
-    inline bool isIgnored() { return mMappers.isEmpty(); }
-
-    void dump(String8& dump);
-    void addMapper(InputMapper* mapper);
-    void configure();
-    void reset();
-    void process(const RawEvent* rawEvent);
-
-    void getDeviceInfo(InputDeviceInfo* outDeviceInfo);
-    int32_t getKeyCodeState(uint32_t sourceMask, int32_t keyCode);
-    int32_t getScanCodeState(uint32_t sourceMask, int32_t scanCode);
-    int32_t getSwitchState(uint32_t sourceMask, int32_t switchCode);
-    bool markSupportedKeyCodes(uint32_t sourceMask, size_t numCodes,
-            const int32_t* keyCodes, uint8_t* outFlags);
-
-    int32_t getMetaState();
-
-    inline const PropertyMap& getConfiguration() {
-        return mConfiguration;
-    }
-
-private:
-    InputReaderContext* mContext;
-    int32_t mId;
-
-    Vector<InputMapper*> mMappers;
-
-    String8 mName;
-    uint32_t mSources;
-
-    typedef int32_t (InputMapper::*GetStateFunc)(uint32_t sourceMask, int32_t code);
-    int32_t getState(uint32_t sourceMask, int32_t code, GetStateFunc getStateFunc);
-
-    PropertyMap mConfiguration;
-};
-
-
-/* An input mapper transforms raw input events into cooked event data.
- * A single input device can have multiple associated input mappers in order to interpret
- * different classes of events.
- */
-class InputMapper {
-public:
-    InputMapper(InputDevice* device);
-    virtual ~InputMapper();
-
-    inline InputDevice* getDevice() { return mDevice; }
-    inline int32_t getDeviceId() { return mDevice->getId(); }
-    inline const String8 getDeviceName() { return mDevice->getName(); }
-    inline InputReaderContext* getContext() { return mContext; }
-    inline InputReaderPolicyInterface* getPolicy() { return mContext->getPolicy(); }
-    inline InputDispatcherInterface* getDispatcher() { return mContext->getDispatcher(); }
-    inline EventHubInterface* getEventHub() { return mContext->getEventHub(); }
-
-    virtual uint32_t getSources() = 0;
-    virtual void populateDeviceInfo(InputDeviceInfo* deviceInfo);
-    virtual void dump(String8& dump);
-    virtual void configure();
-    virtual void reset();
-    virtual void process(const RawEvent* rawEvent) = 0;
-
-    virtual int32_t getKeyCodeState(uint32_t sourceMask, int32_t keyCode);
-    virtual int32_t getScanCodeState(uint32_t sourceMask, int32_t scanCode);
-    virtual int32_t getSwitchState(uint32_t sourceMask, int32_t switchCode);
-    virtual bool markSupportedKeyCodes(uint32_t sourceMask, size_t numCodes,
-            const int32_t* keyCodes, uint8_t* outFlags);
-
-    virtual int32_t getMetaState();
-
-protected:
-    InputDevice* mDevice;
-    InputReaderContext* mContext;
-};
-
-
-class SwitchInputMapper : public InputMapper {
-public:
-    SwitchInputMapper(InputDevice* device);
-    virtual ~SwitchInputMapper();
-
-    virtual uint32_t getSources();
-    virtual void process(const RawEvent* rawEvent);
-
-    virtual int32_t getSwitchState(uint32_t sourceMask, int32_t switchCode);
-
-private:
-    void processSwitch(nsecs_t when, int32_t switchCode, int32_t switchValue);
-};
-
-
-class KeyboardInputMapper : public InputMapper {
-public:
-    KeyboardInputMapper(InputDevice* device, uint32_t sources, int32_t keyboardType);
-    virtual ~KeyboardInputMapper();
-
-    virtual uint32_t getSources();
-    virtual void populateDeviceInfo(InputDeviceInfo* deviceInfo);
-    virtual void dump(String8& dump);
-    virtual void configure();
-    virtual void reset();
-    virtual void process(const RawEvent* rawEvent);
-
-    virtual int32_t getKeyCodeState(uint32_t sourceMask, int32_t keyCode);
-    virtual int32_t getScanCodeState(uint32_t sourceMask, int32_t scanCode);
-    virtual bool markSupportedKeyCodes(uint32_t sourceMask, size_t numCodes,
-            const int32_t* keyCodes, uint8_t* outFlags);
-
-    virtual int32_t getMetaState();
-
-private:
-    Mutex mLock;
-
-    struct KeyDown {
-        int32_t keyCode;
-        int32_t scanCode;
-    };
-
-    uint32_t mSources;
-    int32_t mKeyboardType;
-
-    // Immutable configuration parameters.
-    struct Parameters {
-        int32_t associatedDisplayId;
-        bool orientationAware;
-    } mParameters;
-
-    struct LockedState {
-        Vector<KeyDown> keyDowns; // keys that are down
-        int32_t metaState;
-        nsecs_t downTime; // time of most recent key down
-
-        struct LedState {
-            bool avail; // led is available
-            bool on;    // we think the led is currently on
-        };
-        LedState capsLockLedState;
-        LedState numLockLedState;
-        LedState scrollLockLedState;
-    } mLocked;
-
-    void initializeLocked();
-
-    void configureParameters();
-    void dumpParameters(String8& dump);
-
-    bool isKeyboardOrGamepadKey(int32_t scanCode);
-
-    void processKey(nsecs_t when, bool down, int32_t keyCode, int32_t scanCode,
-            uint32_t policyFlags);
-
-    ssize_t findKeyDownLocked(int32_t scanCode);
-
-    void resetLedStateLocked();
-    void initializeLedStateLocked(LockedState::LedState& ledState, int32_t led);
-    void updateLedStateLocked(bool reset);
-    void updateLedStateForModifierLocked(LockedState::LedState& ledState, int32_t led,
-            int32_t modifier, bool reset);
-};
-
-
-class TrackballInputMapper : public InputMapper {
-public:
-    TrackballInputMapper(InputDevice* device);
-    virtual ~TrackballInputMapper();
-
-    virtual uint32_t getSources();
-    virtual void populateDeviceInfo(InputDeviceInfo* deviceInfo);
-    virtual void dump(String8& dump);
-    virtual void configure();
-    virtual void reset();
-    virtual void process(const RawEvent* rawEvent);
-
-    virtual int32_t getScanCodeState(uint32_t sourceMask, int32_t scanCode);
-
-private:
-    // Amount that trackball needs to move in order to generate a key event.
-    static const int32_t TRACKBALL_MOVEMENT_THRESHOLD = 6;
-
-    Mutex mLock;
-
-    // Immutable configuration parameters.
-    struct Parameters {
-        int32_t associatedDisplayId;
-        bool orientationAware;
-    } mParameters;
-
-    struct Accumulator {
-        enum {
-            FIELD_BTN_MOUSE = 1,
-            FIELD_REL_X = 2,
-            FIELD_REL_Y = 4
-        };
-
-        uint32_t fields;
-
-        bool btnMouse;
-        int32_t relX;
-        int32_t relY;
-
-        inline void clear() {
-            fields = 0;
-        }
-    } mAccumulator;
-
-    float mXScale;
-    float mYScale;
-    float mXPrecision;
-    float mYPrecision;
-
-    struct LockedState {
-        bool down;
-        nsecs_t downTime;
-    } mLocked;
-
-    void initializeLocked();
-
-    void configureParameters();
-    void dumpParameters(String8& dump);
-
-    void sync(nsecs_t when);
-};
-
-
-class TouchInputMapper : public InputMapper {
-public:
-    TouchInputMapper(InputDevice* device);
-    virtual ~TouchInputMapper();
-
-    virtual uint32_t getSources();
-    virtual void populateDeviceInfo(InputDeviceInfo* deviceInfo);
-    virtual void dump(String8& dump);
-    virtual void configure();
-    virtual void reset();
-
-    virtual int32_t getKeyCodeState(uint32_t sourceMask, int32_t keyCode);
-    virtual int32_t getScanCodeState(uint32_t sourceMask, int32_t scanCode);
-    virtual bool markSupportedKeyCodes(uint32_t sourceMask, size_t numCodes,
-            const int32_t* keyCodes, uint8_t* outFlags);
-
-protected:
-    Mutex mLock;
-
-    struct VirtualKey {
-        int32_t keyCode;
-        int32_t scanCode;
-        uint32_t flags;
-
-        // computed hit box, specified in touch screen coords based on known display size
-        int32_t hitLeft;
-        int32_t hitTop;
-        int32_t hitRight;
-        int32_t hitBottom;
-
-        inline bool isHit(int32_t x, int32_t y) const {
-            return x >= hitLeft && x <= hitRight && y >= hitTop && y <= hitBottom;
-        }
-    };
-
-    // Raw data for a single pointer.
-    struct PointerData {
-        uint32_t id;
-        int32_t x;
-        int32_t y;
-        int32_t pressure;
-        int32_t touchMajor;
-        int32_t touchMinor;
-        int32_t toolMajor;
-        int32_t toolMinor;
-        int32_t orientation;
-
-        inline bool operator== (const PointerData& other) const {
-            return id == other.id
-                    && x == other.x
-                    && y == other.y
-                    && pressure == other.pressure
-                    && touchMajor == other.touchMajor
-                    && touchMinor == other.touchMinor
-                    && toolMajor == other.toolMajor
-                    && toolMinor == other.toolMinor
-                    && orientation == other.orientation;
-        }
-        inline bool operator!= (const PointerData& other) const {
-            return !(*this == other);
-        }
-    };
-
-    // Raw data for a collection of pointers including a pointer id mapping table.
-    struct TouchData {
-        uint32_t pointerCount;
-        PointerData pointers[MAX_POINTERS];
-        BitSet32 idBits;
-        uint32_t idToIndex[MAX_POINTER_ID + 1];
-
-        void copyFrom(const TouchData& other) {
-            pointerCount = other.pointerCount;
-            idBits = other.idBits;
-
-            for (uint32_t i = 0; i < pointerCount; i++) {
-                pointers[i] = other.pointers[i];
-
-                int id = pointers[i].id;
-                idToIndex[id] = other.idToIndex[id];
-            }
-        }
-
-        inline void clear() {
-            pointerCount = 0;
-            idBits.clear();
-        }
-    };
-
-    // Immutable configuration parameters.
-    struct Parameters {
-        enum DeviceType {
-            DEVICE_TYPE_TOUCH_SCREEN,
-            DEVICE_TYPE_TOUCH_PAD,
-        };
-
-        DeviceType deviceType;
-        int32_t associatedDisplayId;
-        bool orientationAware;
-
-        bool useBadTouchFilter;
-        bool useJumpyTouchFilter;
-        bool useAveragingTouchFilter;
-    } mParameters;
-
-    // Immutable calibration parameters in parsed form.
-    struct Calibration {
-        // Position
-        bool haveXOrigin;
-        int32_t xOrigin;
-        bool haveYOrigin;
-        int32_t yOrigin;
-        bool haveXScale;
-        float xScale;
-        bool haveYScale;
-        float yScale;
-
-        // Touch Size
-        enum TouchSizeCalibration {
-            TOUCH_SIZE_CALIBRATION_DEFAULT,
-            TOUCH_SIZE_CALIBRATION_NONE,
-            TOUCH_SIZE_CALIBRATION_GEOMETRIC,
-            TOUCH_SIZE_CALIBRATION_PRESSURE,
-        };
-
-        TouchSizeCalibration touchSizeCalibration;
-
-        // Tool Size
-        enum ToolSizeCalibration {
-            TOOL_SIZE_CALIBRATION_DEFAULT,
-            TOOL_SIZE_CALIBRATION_NONE,
-            TOOL_SIZE_CALIBRATION_GEOMETRIC,
-            TOOL_SIZE_CALIBRATION_LINEAR,
-            TOOL_SIZE_CALIBRATION_AREA,
-        };
-
-        ToolSizeCalibration toolSizeCalibration;
-        bool haveToolSizeLinearScale;
-        float toolSizeLinearScale;
-        bool haveToolSizeLinearBias;
-        float toolSizeLinearBias;
-        bool haveToolSizeAreaScale;
-        float toolSizeAreaScale;
-        bool haveToolSizeAreaBias;
-        float toolSizeAreaBias;
-        bool haveToolSizeIsSummed;
-        bool toolSizeIsSummed;
-
-        // Pressure
-        enum PressureCalibration {
-            PRESSURE_CALIBRATION_DEFAULT,
-            PRESSURE_CALIBRATION_NONE,
-            PRESSURE_CALIBRATION_PHYSICAL,
-            PRESSURE_CALIBRATION_AMPLITUDE,
-        };
-        enum PressureSource {
-            PRESSURE_SOURCE_DEFAULT,
-            PRESSURE_SOURCE_PRESSURE,
-            PRESSURE_SOURCE_TOUCH,
-        };
-
-        PressureCalibration pressureCalibration;
-        PressureSource pressureSource;
-        bool havePressureScale;
-        float pressureScale;
-
-        // Size
-        enum SizeCalibration {
-            SIZE_CALIBRATION_DEFAULT,
-            SIZE_CALIBRATION_NONE,
-            SIZE_CALIBRATION_NORMALIZED,
-        };
-
-        SizeCalibration sizeCalibration;
-
-        // Orientation
-        enum OrientationCalibration {
-            ORIENTATION_CALIBRATION_DEFAULT,
-            ORIENTATION_CALIBRATION_NONE,
-            ORIENTATION_CALIBRATION_INTERPOLATED,
-        };
-
-        OrientationCalibration orientationCalibration;
-    } mCalibration;
-
-    // Raw axis information from the driver.
-    struct RawAxes {
-        RawAbsoluteAxisInfo x;
-        RawAbsoluteAxisInfo y;
-        RawAbsoluteAxisInfo pressure;
-        RawAbsoluteAxisInfo touchMajor;
-        RawAbsoluteAxisInfo touchMinor;
-        RawAbsoluteAxisInfo toolMajor;
-        RawAbsoluteAxisInfo toolMinor;
-        RawAbsoluteAxisInfo orientation;
-    } mRawAxes;
-
-    // Current and previous touch sample data.
-    TouchData mCurrentTouch;
-    TouchData mLastTouch;
-
-    // The time the primary pointer last went down.
-    nsecs_t mDownTime;
-
-    struct LockedState {
-        Vector<VirtualKey> virtualKeys;
-
-        // The surface orientation and width and height set by configureSurfaceLocked().
-        int32_t surfaceOrientation;
-        int32_t surfaceWidth, surfaceHeight;
-
-        // Translation and scaling factors, orientation-independent.
-        int32_t xOrigin;
-        float xScale;
-        float xPrecision;
-
-        int32_t yOrigin;
-        float yScale;
-        float yPrecision;
-
-        float geometricScale;
-
-        float toolSizeLinearScale;
-        float toolSizeLinearBias;
-        float toolSizeAreaScale;
-        float toolSizeAreaBias;
-
-        float pressureScale;
-
-        float sizeScale;
-
-        float orientationScale;
-
-        // Oriented motion ranges for input device info.
-        struct OrientedRanges {
-            InputDeviceInfo::MotionRange x;
-            InputDeviceInfo::MotionRange y;
-
-            bool havePressure;
-            InputDeviceInfo::MotionRange pressure;
-
-            bool haveSize;
-            InputDeviceInfo::MotionRange size;
-
-            bool haveTouchSize;
-            InputDeviceInfo::MotionRange touchMajor;
-            InputDeviceInfo::MotionRange touchMinor;
-
-            bool haveToolSize;
-            InputDeviceInfo::MotionRange toolMajor;
-            InputDeviceInfo::MotionRange toolMinor;
-
-            bool haveOrientation;
-            InputDeviceInfo::MotionRange orientation;
-        } orientedRanges;
-
-        // Oriented dimensions and precision.
-        float orientedSurfaceWidth, orientedSurfaceHeight;
-        float orientedXPrecision, orientedYPrecision;
-
-        struct CurrentVirtualKeyState {
-            bool down;
-            nsecs_t downTime;
-            int32_t keyCode;
-            int32_t scanCode;
-        } currentVirtualKey;
-    } mLocked;
-
-    virtual void configureParameters();
-    virtual void dumpParameters(String8& dump);
-    virtual void configureRawAxes();
-    virtual void dumpRawAxes(String8& dump);
-    virtual bool configureSurfaceLocked();
-    virtual void dumpSurfaceLocked(String8& dump);
-    virtual void configureVirtualKeysLocked();
-    virtual void dumpVirtualKeysLocked(String8& dump);
-    virtual void parseCalibration();
-    virtual void resolveCalibration();
-    virtual void dumpCalibration(String8& dump);
-
-    enum TouchResult {
-        // Dispatch the touch normally.
-        DISPATCH_TOUCH,
-        // Do not dispatch the touch, but keep tracking the current stroke.
-        SKIP_TOUCH,
-        // Do not dispatch the touch, and drop all information associated with the current stoke
-        // so the next movement will appear as a new down.
-        DROP_STROKE
-    };
-
-    void syncTouch(nsecs_t when, bool havePointerIds);
-
-private:
-    /* Maximum number of historical samples to average. */
-    static const uint32_t AVERAGING_HISTORY_SIZE = 5;
-
-    /* Slop distance for jumpy pointer detection.
-     * The vertical range of the screen divided by this is our epsilon value. */
-    static const uint32_t JUMPY_EPSILON_DIVISOR = 212;
-
-    /* Number of jumpy points to drop for touchscreens that need it. */
-    static const uint32_t JUMPY_TRANSITION_DROPS = 3;
-    static const uint32_t JUMPY_DROP_LIMIT = 3;
-
-    /* Maximum squared distance for averaging.
-     * If moving farther than this, turn of averaging to avoid lag in response. */
-    static const uint64_t AVERAGING_DISTANCE_LIMIT = 75 * 75;
-
-    struct AveragingTouchFilterState {
-        // Individual history tracks are stored by pointer id
-        uint32_t historyStart[MAX_POINTERS];
-        uint32_t historyEnd[MAX_POINTERS];
-        struct {
-            struct {
-                int32_t x;
-                int32_t y;
-                int32_t pressure;
-            } pointers[MAX_POINTERS];
-        } historyData[AVERAGING_HISTORY_SIZE];
-    } mAveragingTouchFilter;
-
-    struct JumpyTouchFilterState {
-        uint32_t jumpyPointsDropped;
-    } mJumpyTouchFilter;
-
-    struct PointerDistanceHeapElement {
-        uint32_t currentPointerIndex : 8;
-        uint32_t lastPointerIndex : 8;
-        uint64_t distance : 48; // squared distance
-    };
-
-    void initializeLocked();
-
-    TouchResult consumeOffScreenTouches(nsecs_t when, uint32_t policyFlags);
-    void dispatchTouches(nsecs_t when, uint32_t policyFlags);
-    void dispatchTouch(nsecs_t when, uint32_t policyFlags, TouchData* touch,
-            BitSet32 idBits, uint32_t changedId, uint32_t pointerCount,
-            int32_t motionEventAction);
-
-    bool isPointInsideSurfaceLocked(int32_t x, int32_t y);
-    const VirtualKey* findVirtualKeyHitLocked(int32_t x, int32_t y);
-
-    bool applyBadTouchFilter();
-    bool applyJumpyTouchFilter();
-    void applyAveragingTouchFilter();
-    void calculatePointerIds();
-};
-
-
-class SingleTouchInputMapper : public TouchInputMapper {
-public:
-    SingleTouchInputMapper(InputDevice* device);
-    virtual ~SingleTouchInputMapper();
-
-    virtual void reset();
-    virtual void process(const RawEvent* rawEvent);
-
-protected:
-    virtual void configureRawAxes();
-
-private:
-    struct Accumulator {
-        enum {
-            FIELD_BTN_TOUCH = 1,
-            FIELD_ABS_X = 2,
-            FIELD_ABS_Y = 4,
-            FIELD_ABS_PRESSURE = 8,
-            FIELD_ABS_TOOL_WIDTH = 16
-        };
-
-        uint32_t fields;
-
-        bool btnTouch;
-        int32_t absX;
-        int32_t absY;
-        int32_t absPressure;
-        int32_t absToolWidth;
-
-        inline void clear() {
-            fields = 0;
-        }
-    } mAccumulator;
-
-    bool mDown;
-    int32_t mX;
-    int32_t mY;
-    int32_t mPressure;
-    int32_t mToolWidth;
-
-    void initialize();
-
-    void sync(nsecs_t when);
-};
-
-
-class MultiTouchInputMapper : public TouchInputMapper {
-public:
-    MultiTouchInputMapper(InputDevice* device);
-    virtual ~MultiTouchInputMapper();
-
-    virtual void reset();
-    virtual void process(const RawEvent* rawEvent);
-
-protected:
-    virtual void configureRawAxes();
-
-private:
-    struct Accumulator {
-        enum {
-            FIELD_ABS_MT_POSITION_X = 1,
-            FIELD_ABS_MT_POSITION_Y = 2,
-            FIELD_ABS_MT_TOUCH_MAJOR = 4,
-            FIELD_ABS_MT_TOUCH_MINOR = 8,
-            FIELD_ABS_MT_WIDTH_MAJOR = 16,
-            FIELD_ABS_MT_WIDTH_MINOR = 32,
-            FIELD_ABS_MT_ORIENTATION = 64,
-            FIELD_ABS_MT_TRACKING_ID = 128,
-            FIELD_ABS_MT_PRESSURE = 256,
-        };
-
-        uint32_t pointerCount;
-        struct Pointer {
-            uint32_t fields;
-
-            int32_t absMTPositionX;
-            int32_t absMTPositionY;
-            int32_t absMTTouchMajor;
-            int32_t absMTTouchMinor;
-            int32_t absMTWidthMajor;
-            int32_t absMTWidthMinor;
-            int32_t absMTOrientation;
-            int32_t absMTTrackingId;
-            int32_t absMTPressure;
-
-            inline void clear() {
-                fields = 0;
-            }
-        } pointers[MAX_POINTERS + 1]; // + 1 to remove the need for extra range checks
-
-        inline void clear() {
-            pointerCount = 0;
-            pointers[0].clear();
-        }
-    } mAccumulator;
-
-    void initialize();
-
-    void sync(nsecs_t when);
-};
-
-} // namespace android
-
-#endif // _UI_INPUT_READER_H
diff --git a/include/utils/PropertyMap.h b/include/utils/PropertyMap.h
index a54f819..a9e674f 100644
--- a/include/utils/PropertyMap.h
+++ b/include/utils/PropertyMap.h
@@ -71,6 +71,12 @@
     bool tryGetProperty(const String8& key, int32_t& outValue) const;
     bool tryGetProperty(const String8& key, float& outValue) const;
 
+    /* Adds all values from the specified property map. */
+    void addAll(const PropertyMap* map);
+
+    /* Gets the underlying property map. */
+    inline const KeyedVector<String8, String8>& getProperties() const { return mProperties; }
+
     /* Loads a property map from a file. */
     static status_t load(const String8& filename, PropertyMap** outMap);
 
diff --git a/libs/binder/Parcel.cpp b/libs/binder/Parcel.cpp
index f329ac4..d57f2c9 100644
--- a/libs/binder/Parcel.cpp
+++ b/libs/binder/Parcel.cpp
@@ -619,7 +619,10 @@
 status_t Parcel::writeString8(const String8& str)
 {
     status_t err = writeInt32(str.bytes());
-    if (err == NO_ERROR) {
+    // only write string if its length is more than zero characters,
+    // as readString8 will only read if the length field is non-zero.
+    // this is slightly different from how writeString16 works.
+    if (str.bytes() > 0 && err == NO_ERROR) {
         err = write(str.string(), str.bytes()+1);
     }
     return err;
diff --git a/libs/gui/Android.mk b/libs/gui/Android.mk
index 249558a..d1a6af1 100644
--- a/libs/gui/Android.mk
+++ b/libs/gui/Android.mk
@@ -4,17 +4,25 @@
 LOCAL_SRC_FILES:= \
 	ISensorEventConnection.cpp \
 	ISensorServer.cpp \
+	ISurfaceTexture.cpp \
 	Sensor.cpp \
 	SensorChannel.cpp \
 	SensorEventQueue.cpp \
-	SensorManager.cpp
+	SensorManager.cpp \
+	SurfaceTexture.cpp \
+	SurfaceTextureClient.cpp
 
 LOCAL_SHARED_LIBRARIES := \
 	libcutils \
 	libutils \
 	libbinder \
 	libhardware \
-	libhardware_legacy
+	libhardware_legacy \
+	libui \
+	libEGL \
+	libGLESv2 \
+	libsurfaceflinger_client
+
 
 LOCAL_MODULE:= libgui
 
diff --git a/libs/gui/ISurfaceTexture.cpp b/libs/gui/ISurfaceTexture.cpp
new file mode 100644
index 0000000..90bca3c
--- /dev/null
+++ b/libs/gui/ISurfaceTexture.cpp
@@ -0,0 +1,204 @@
+/*
+ * Copyright (C) 2010 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include <stdint.h>
+#include <sys/types.h>
+
+#include <utils/Errors.h>
+#include <utils/RefBase.h>
+#include <utils/Vector.h>
+#include <utils/Timers.h>
+
+#include <binder/Parcel.h>
+#include <binder/IInterface.h>
+
+#include <gui/ISurfaceTexture.h>
+
+namespace android {
+// ----------------------------------------------------------------------------
+
+enum {
+    REQUEST_BUFFER = IBinder::FIRST_CALL_TRANSACTION,
+    SET_BUFFER_COUNT,
+    DEQUEUE_BUFFER,
+    QUEUE_BUFFER,
+    CANCEL_BUFFER,
+    SET_CROP,
+    SET_TRANSFORM,
+};
+
+
+class BpSurfaceTexture : public BpInterface<ISurfaceTexture>
+{
+public:
+    BpSurfaceTexture(const sp<IBinder>& impl)
+        : BpInterface<ISurfaceTexture>(impl)
+    {
+    }
+
+    virtual sp<GraphicBuffer> requestBuffer(int bufferIdx,
+            uint32_t w, uint32_t h, uint32_t format, uint32_t usage) {
+        Parcel data, reply;
+        data.writeInterfaceToken(ISurfaceTexture::getInterfaceDescriptor());
+        data.writeInt32(bufferIdx);
+        data.writeInt32(w);
+        data.writeInt32(h);
+        data.writeInt32(format);
+        data.writeInt32(usage);
+        remote()->transact(REQUEST_BUFFER, data, &reply);
+        sp<GraphicBuffer> buffer;
+        bool nonNull = reply.readInt32();
+        if (nonNull) {
+            buffer = new GraphicBuffer();
+            reply.read(*buffer);
+        }
+        return buffer;
+    }
+
+    virtual status_t setBufferCount(int bufferCount)
+    {
+        Parcel data, reply;
+        data.writeInterfaceToken(ISurfaceTexture::getInterfaceDescriptor());
+        data.writeInt32(bufferCount);
+        remote()->transact(SET_BUFFER_COUNT, data, &reply);
+        status_t err = reply.readInt32();
+        return err;
+    }
+
+    virtual status_t dequeueBuffer(int *buf) {
+        Parcel data, reply;
+        data.writeInterfaceToken(ISurfaceTexture::getInterfaceDescriptor());
+        remote()->transact(DEQUEUE_BUFFER, data, &reply);
+        *buf = reply.readInt32();
+        int result = reply.readInt32();
+        return result;
+    }
+
+    virtual status_t queueBuffer(int buf) {
+        Parcel data, reply;
+        data.writeInterfaceToken(ISurfaceTexture::getInterfaceDescriptor());
+        data.writeInt32(buf);
+        remote()->transact(QUEUE_BUFFER, data, &reply);
+        status_t result = reply.readInt32();
+        return result;
+    }
+
+    virtual void cancelBuffer(int buf) {
+        Parcel data, reply;
+        data.writeInterfaceToken(ISurfaceTexture::getInterfaceDescriptor());
+        data.writeInt32(buf);
+        remote()->transact(CANCEL_BUFFER, data, &reply);
+    }
+
+    virtual status_t setCrop(const Rect& reg) {
+        Parcel data, reply;
+        data.writeInterfaceToken(ISurfaceTexture::getInterfaceDescriptor());
+        data.writeFloat(reg.left);
+        data.writeFloat(reg.top);
+        data.writeFloat(reg.right);
+        data.writeFloat(reg.bottom);
+        remote()->transact(SET_CROP, data, &reply);
+        status_t result = reply.readInt32();
+        return result;
+    }
+
+    virtual status_t setTransform(uint32_t transform) {
+        Parcel data, reply;
+        data.writeInterfaceToken(ISurfaceTexture::getInterfaceDescriptor());
+        data.writeInt32(transform);
+        remote()->transact(SET_TRANSFORM, data, &reply);
+        status_t result = reply.readInt32();
+        return result;
+    }
+};
+
+IMPLEMENT_META_INTERFACE(SurfaceTexture, "android.gui.SurfaceTexture");
+
+// ----------------------------------------------------------------------
+
+status_t BnSurfaceTexture::onTransact(
+    uint32_t code, const Parcel& data, Parcel* reply, uint32_t flags)
+{
+    switch(code) {
+        case REQUEST_BUFFER: {
+            CHECK_INTERFACE(ISurfaceTexture, data, reply);
+            int bufferIdx   = data.readInt32();
+            uint32_t w      = data.readInt32();
+            uint32_t h      = data.readInt32();
+            uint32_t format = data.readInt32();
+            uint32_t usage  = data.readInt32();
+            sp<GraphicBuffer> buffer(requestBuffer(bufferIdx, w, h, format,
+                    usage));
+            reply->writeInt32(buffer != 0);
+            if (buffer != 0) {
+                reply->write(*buffer);
+            }
+            return NO_ERROR;
+        } break;
+        case SET_BUFFER_COUNT: {
+            CHECK_INTERFACE(ISurfaceTexture, data, reply);
+            int bufferCount = data.readInt32();
+            int result = setBufferCount(bufferCount);
+            reply->writeInt32(result);
+            return NO_ERROR;
+        } break;
+        case DEQUEUE_BUFFER: {
+            CHECK_INTERFACE(ISurfaceTexture, data, reply);
+            int buf;
+            int result = dequeueBuffer(&buf);
+            reply->writeInt32(buf);
+            reply->writeInt32(result);
+            return NO_ERROR;
+        } break;
+        case QUEUE_BUFFER: {
+            CHECK_INTERFACE(ISurfaceTexture, data, reply);
+            int buf = data.readInt32();
+            status_t result = queueBuffer(buf);
+            reply->writeInt32(result);
+            return NO_ERROR;
+        } break;
+        case CANCEL_BUFFER: {
+            CHECK_INTERFACE(ISurfaceTexture, data, reply);
+            int buf = data.readInt32();
+            cancelBuffer(buf);
+            return NO_ERROR;
+        } break;
+        case SET_CROP: {
+            Rect reg;
+            CHECK_INTERFACE(ISurfaceTexture, data, reply);
+            reg.left = data.readFloat();
+            reg.top = data.readFloat();
+            reg.right = data.readFloat();
+            reg.bottom = data.readFloat();
+            status_t result = setCrop(reg);
+            reply->writeInt32(result);
+            return NO_ERROR;
+        } break;
+        case SET_TRANSFORM: {
+            Rect reg;
+            CHECK_INTERFACE(ISurfaceTexture, data, reply);
+            uint32_t transform = data.readInt32();
+            status_t result = setTransform(transform);
+            reply->writeInt32(result);
+            return NO_ERROR;
+        } break;
+    }
+    return BBinder::onTransact(code, data, reply, flags);
+}
+
+// ----------------------------------------------------------------------------
+
+}; // namespace android
diff --git a/libs/gui/SurfaceTexture.cpp b/libs/gui/SurfaceTexture.cpp
new file mode 100644
index 0000000..447de76
--- /dev/null
+++ b/libs/gui/SurfaceTexture.cpp
@@ -0,0 +1,345 @@
+/*
+ * Copyright (C) 2010 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#define LOG_TAG "SurfaceTexture"
+//#define LOG_NDEBUG 0
+
+#define GL_GLEXT_PROTOTYPES
+#define EGL_EGLEXT_PROTOTYPES
+
+#include <EGL/egl.h>
+#include <EGL/eglext.h>
+#include <GLES2/gl2.h>
+#include <GLES2/gl2ext.h>
+
+#include <gui/SurfaceTexture.h>
+
+#include <surfaceflinger/ISurfaceComposer.h>
+#include <surfaceflinger/SurfaceComposerClient.h>
+#include <surfaceflinger/IGraphicBufferAlloc.h>
+
+#include <utils/Log.h>
+
+namespace android {
+
+// Transform matrices
+static float mtxIdentity[16] = {
+    1, 0, 0, 0,
+    0, 1, 0, 0,
+    0, 0, 1, 0,
+    0, 0, 0, 1,
+};
+static float mtxFlipH[16] = {
+    -1, 0, 0, 0,
+    0, 1, 0, 0,
+    0, 0, 1, 0,
+    1, 0, 0, 1,
+};
+static float mtxFlipV[16] = {
+    1, 0, 0, 0,
+    0, -1, 0, 0,
+    0, 0, 1, 0,
+    0, 1, 0, 1,
+};
+static float mtxRot90[16] = {
+    0, 1, 0, 0,
+    -1, 0, 0, 0,
+    0, 0, 1, 0,
+    1, 0, 0, 1,
+};
+static float mtxRot180[16] = {
+    -1, 0, 0, 0,
+    0, -1, 0, 0,
+    0, 0, 1, 0,
+    1, 1, 0, 1,
+};
+static float mtxRot270[16] = {
+    0, -1, 0, 0,
+    1, 0, 0, 0,
+    0, 0, 1, 0,
+    0, 1, 0, 1,
+};
+
+static void mtxMul(float out[16], const float a[16], const float b[16]);
+
+SurfaceTexture::SurfaceTexture(GLuint tex) :
+    mBufferCount(MIN_BUFFER_SLOTS), mCurrentTexture(INVALID_BUFFER_SLOT),
+    mLastQueued(INVALID_BUFFER_SLOT), mTexName(tex) {
+    LOGV("SurfaceTexture::SurfaceTexture");
+    for (int i = 0; i < NUM_BUFFER_SLOTS; i++) {
+        mSlots[i].mEglImage = EGL_NO_IMAGE_KHR;
+        mSlots[i].mEglDisplay = EGL_NO_DISPLAY;
+        mSlots[i].mOwnedByClient = false;
+    }
+    sp<ISurfaceComposer> composer(ComposerService::getComposerService());
+    mGraphicBufferAlloc = composer->createGraphicBufferAlloc();
+}
+
+SurfaceTexture::~SurfaceTexture() {
+    LOGV("SurfaceTexture::~SurfaceTexture");
+    freeAllBuffers();
+}
+
+status_t SurfaceTexture::setBufferCount(int bufferCount) {
+    LOGV("SurfaceTexture::setBufferCount");
+    Mutex::Autolock lock(mMutex);
+    freeAllBuffers();
+    mBufferCount = bufferCount;
+    mCurrentTexture = INVALID_BUFFER_SLOT;
+    mLastQueued = INVALID_BUFFER_SLOT;
+    return OK;
+}
+
+sp<GraphicBuffer> SurfaceTexture::requestBuffer(int buf,
+        uint32_t w, uint32_t h, uint32_t format, uint32_t usage) {
+    LOGV("SurfaceTexture::requestBuffer");
+    Mutex::Autolock lock(mMutex);
+    if (buf < 0 || mBufferCount <= buf) {
+        LOGE("requestBuffer: slot index out of range [0, %d]: %d",
+                mBufferCount, buf);
+        return 0;
+    }
+    usage |= GraphicBuffer::USAGE_HW_TEXTURE;
+    sp<GraphicBuffer> graphicBuffer(
+            mGraphicBufferAlloc->createGraphicBuffer(w, h, format, usage));
+    if (graphicBuffer == 0) {
+        LOGE("requestBuffer: SurfaceComposer::createGraphicBuffer failed");
+    } else {
+        mSlots[buf].mGraphicBuffer = graphicBuffer;
+        if (mSlots[buf].mEglImage != EGL_NO_IMAGE_KHR) {
+            eglDestroyImageKHR(mSlots[buf].mEglDisplay, mSlots[buf].mEglImage);
+            mSlots[buf].mEglImage = EGL_NO_IMAGE_KHR;
+            mSlots[buf].mEglDisplay = EGL_NO_DISPLAY;
+        }
+        mAllocdBuffers.add(graphicBuffer);
+    }
+    return graphicBuffer;
+}
+
+status_t SurfaceTexture::dequeueBuffer(int *buf) {
+    LOGV("SurfaceTexture::dequeueBuffer");
+    Mutex::Autolock lock(mMutex);
+    int found = INVALID_BUFFER_SLOT;
+    for (int i = 0; i < mBufferCount; i++) {
+        if (!mSlots[i].mOwnedByClient && i != mCurrentTexture && i != mLastQueued) {
+            mSlots[i].mOwnedByClient = true;
+            found = i;
+            break;
+        }
+    }
+    if (found == INVALID_BUFFER_SLOT) {
+        return -EBUSY;
+    }
+    *buf = found;
+    return OK;
+}
+
+status_t SurfaceTexture::queueBuffer(int buf) {
+    LOGV("SurfaceTexture::queueBuffer");
+    Mutex::Autolock lock(mMutex);
+    if (buf < 0 || mBufferCount <= buf) {
+        LOGE("queueBuffer: slot index out of range [0, %d]: %d",
+                mBufferCount, buf);
+        return -EINVAL;
+    } else if (!mSlots[buf].mOwnedByClient) {
+        LOGE("queueBuffer: slot %d is not owned by the client", buf);
+        return -EINVAL;
+    } else if (mSlots[buf].mGraphicBuffer == 0) {
+        LOGE("queueBuffer: slot %d was enqueued without requesting a buffer",
+                buf);
+        return -EINVAL;
+    }
+    mSlots[buf].mOwnedByClient = false;
+    mLastQueued = buf;
+    mLastQueuedCrop = mNextCrop;
+    mLastQueuedTransform = mNextTransform;
+    return OK;
+}
+
+void SurfaceTexture::cancelBuffer(int buf) {
+    LOGV("SurfaceTexture::cancelBuffer");
+    Mutex::Autolock lock(mMutex);
+    if (buf < 0 || mBufferCount <= buf) {
+        LOGE("cancelBuffer: slot index out of range [0, %d]: %d", mBufferCount,
+                buf);
+        return;
+    } else if (!mSlots[buf].mOwnedByClient) {
+        LOGE("cancelBuffer: slot %d is not owned by the client", buf);
+        return;
+    }
+    mSlots[buf].mOwnedByClient = false;
+}
+
+status_t SurfaceTexture::setCrop(const Rect& crop) {
+    LOGV("SurfaceTexture::setCrop");
+    Mutex::Autolock lock(mMutex);
+    mNextCrop = crop;
+    return OK;
+}
+
+status_t SurfaceTexture::setTransform(uint32_t transform) {
+    LOGV("SurfaceTexture::setTransform");
+    Mutex::Autolock lock(mMutex);
+    mNextTransform = transform;
+    return OK;
+}
+
+status_t SurfaceTexture::updateTexImage() {
+    LOGV("SurfaceTexture::updateTexImage");
+    Mutex::Autolock lock(mMutex);
+
+    // We always bind the texture even if we don't update its contents.
+    glBindTexture(GL_TEXTURE_EXTERNAL_OES, mTexName);
+
+    // Initially both mCurrentTexture and mLastQueued are INVALID_BUFFER_SLOT,
+    // so this check will fail until a buffer gets queued.
+    if (mCurrentTexture != mLastQueued) {
+        // Update the GL texture object.
+        EGLImageKHR image = mSlots[mLastQueued].mEglImage;
+        if (image == EGL_NO_IMAGE_KHR) {
+            EGLDisplay dpy = eglGetCurrentDisplay();
+            sp<GraphicBuffer> graphicBuffer = mSlots[mLastQueued].mGraphicBuffer;
+            image = createImage(dpy, graphicBuffer);
+            mSlots[mLastQueued].mEglImage = image;
+            mSlots[mLastQueued].mEglDisplay = dpy;
+        }
+        glEGLImageTargetTexture2DOES(GL_TEXTURE_EXTERNAL_OES, (GLeglImageOES)image);
+        GLint error = glGetError();
+        if (error != GL_NO_ERROR) {
+            LOGE("error binding external texture image %p (slot %d): %#04x",
+                    image, mLastQueued, error);
+            return -EINVAL;
+        }
+
+        // Update the SurfaceTexture state.
+        mCurrentTexture = mLastQueued;
+        mCurrentTextureBuf = mSlots[mCurrentTexture].mGraphicBuffer;
+        mCurrentCrop = mLastQueuedCrop;
+        mCurrentTransform = mLastQueuedTransform;
+    }
+    return OK;
+}
+
+void SurfaceTexture::getTransformMatrix(float mtx[16]) {
+    LOGV("SurfaceTexture::updateTexImage");
+    Mutex::Autolock lock(mMutex);
+
+    float* xform = mtxIdentity;
+    switch (mCurrentTransform) {
+        case 0:
+            xform = mtxIdentity;
+            break;
+        case NATIVE_WINDOW_TRANSFORM_FLIP_H:
+            xform = mtxFlipH;
+            break;
+        case NATIVE_WINDOW_TRANSFORM_FLIP_V:
+            xform = mtxFlipV;
+            break;
+        case NATIVE_WINDOW_TRANSFORM_ROT_90:
+            xform = mtxRot90;
+            break;
+        case NATIVE_WINDOW_TRANSFORM_ROT_180:
+            xform = mtxRot180;
+            break;
+        case NATIVE_WINDOW_TRANSFORM_ROT_270:
+            xform = mtxRot270;
+            break;
+        default:
+            LOGE("getTransformMatrix: unknown transform: %d", mCurrentTransform);
+    }
+
+    sp<GraphicBuffer>& buf(mSlots[mCurrentTexture].mGraphicBuffer);
+    float tx = float(mCurrentCrop.left) / float(buf->getWidth());
+    float ty = float(mCurrentCrop.bottom) / float(buf->getHeight());
+    float sx = float(mCurrentCrop.width()) / float(buf->getWidth());
+    float sy = float(mCurrentCrop.height()) / float(buf->getHeight());
+    float crop[16] = {
+        sx, 0, 0, sx*tx,
+        0, sy, 0, sy*ty,
+        0, 0, 1, 0,
+        0, 0, 0, 1,
+    };
+
+    mtxMul(mtx, crop, xform);
+}
+
+void SurfaceTexture::freeAllBuffers() {
+    for (int i = 0; i < NUM_BUFFER_SLOTS; i++) {
+        mSlots[i].mGraphicBuffer = 0;
+        mSlots[i].mOwnedByClient = false;
+        if (mSlots[i].mEglImage != EGL_NO_IMAGE_KHR) {
+            eglDestroyImageKHR(mSlots[i].mEglDisplay, mSlots[i].mEglImage);
+            mSlots[i].mEglImage = EGL_NO_IMAGE_KHR;
+            mSlots[i].mEglDisplay = EGL_NO_DISPLAY;
+        }
+    }
+
+    int exceptBuf = -1;
+    for (size_t i = 0; i < mAllocdBuffers.size(); i++) {
+        if (mAllocdBuffers[i] == mCurrentTextureBuf) {
+            exceptBuf = i;
+            break;
+        }
+    }
+    mAllocdBuffers.clear();
+    if (exceptBuf >= 0) {
+        mAllocdBuffers.add(mCurrentTextureBuf);
+    }
+    mGraphicBufferAlloc->freeAllGraphicBuffersExcept(exceptBuf);
+}
+
+EGLImageKHR SurfaceTexture::createImage(EGLDisplay dpy,
+        const sp<GraphicBuffer>& graphicBuffer) {
+    EGLClientBuffer cbuf = (EGLClientBuffer)graphicBuffer->getNativeBuffer();
+    EGLint attrs[] = {
+        EGL_IMAGE_PRESERVED_KHR,    EGL_TRUE,
+        EGL_NONE,
+    };
+    EGLImageKHR image = eglCreateImageKHR(dpy, EGL_NO_CONTEXT,
+            EGL_NATIVE_BUFFER_ANDROID, cbuf, attrs);
+    EGLint error = eglGetError();
+    if (error != EGL_SUCCESS) {
+        LOGE("error creating EGLImage: %#x", error);
+    } else if (image == EGL_NO_IMAGE_KHR) {
+        LOGE("no error reported, but no image was returned by "
+                "eglCreateImageKHR");
+    }
+    return image;
+}
+
+static void mtxMul(float out[16], const float a[16], const float b[16]) {
+    out[0] = a[0]*b[0] + a[4]*b[1] + a[8]*b[2] + a[12]*b[3];
+    out[1] = a[1]*b[0] + a[5]*b[1] + a[9]*b[2] + a[13]*b[3];
+    out[2] = a[2]*b[0] + a[6]*b[1] + a[10]*b[2] + a[14]*b[3];
+    out[3] = a[3]*b[0] + a[7]*b[1] + a[11]*b[2] + a[15]*b[3];
+
+    out[4] = a[0]*b[4] + a[4]*b[5] + a[8]*b[6] + a[12]*b[7];
+    out[5] = a[1]*b[4] + a[5]*b[5] + a[9]*b[6] + a[13]*b[7];
+    out[6] = a[2]*b[4] + a[6]*b[5] + a[10]*b[6] + a[14]*b[7];
+    out[7] = a[3]*b[4] + a[7]*b[5] + a[11]*b[6] + a[15]*b[7];
+
+    out[8] = a[0]*b[8] + a[4]*b[9] + a[8]*b[10] + a[12]*b[11];
+    out[9] = a[1]*b[8] + a[5]*b[9] + a[9]*b[10] + a[13]*b[11];
+    out[10] = a[2]*b[8] + a[6]*b[9] + a[10]*b[10] + a[14]*b[11];
+    out[11] = a[3]*b[8] + a[7]*b[9] + a[11]*b[10] + a[15]*b[11];
+
+    out[12] = a[0]*b[12] + a[4]*b[13] + a[8]*b[14] + a[12]*b[15];
+    out[13] = a[1]*b[12] + a[5]*b[13] + a[9]*b[14] + a[13]*b[15];
+    out[14] = a[2]*b[12] + a[6]*b[13] + a[10]*b[14] + a[14]*b[15];
+    out[15] = a[3]*b[12] + a[7]*b[13] + a[11]*b[14] + a[15]*b[15];
+}
+
+}; // namespace android
diff --git a/libs/gui/SurfaceTextureClient.cpp b/libs/gui/SurfaceTextureClient.cpp
new file mode 100644
index 0000000..0ed8be5
--- /dev/null
+++ b/libs/gui/SurfaceTextureClient.cpp
@@ -0,0 +1,300 @@
+/*
+ * Copyright (C) 2010 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#define LOG_TAG "SurfaceTextureClient"
+//#define LOG_NDEBUG 0
+
+#include <gui/SurfaceTextureClient.h>
+
+#include <utils/Log.h>
+
+namespace android {
+
+SurfaceTextureClient::SurfaceTextureClient(
+        const sp<ISurfaceTexture>& surfaceTexture):
+        mSurfaceTexture(surfaceTexture), mReqWidth(1), mReqHeight(1),
+        mReqFormat(DEFAULT_FORMAT), mReqUsage(0), mMutex() {
+    // Initialize the ANativeWindow function pointers.
+    ANativeWindow::setSwapInterval  = setSwapInterval;
+    ANativeWindow::dequeueBuffer    = dequeueBuffer;
+    ANativeWindow::cancelBuffer     = cancelBuffer;
+    ANativeWindow::lockBuffer       = lockBuffer;
+    ANativeWindow::queueBuffer      = queueBuffer;
+    ANativeWindow::query            = query;
+    ANativeWindow::perform          = perform;
+}
+
+int SurfaceTextureClient::setSwapInterval(ANativeWindow* window, int interval) {
+    SurfaceTextureClient* c = getSelf(window);
+    return c->setSwapInterval(interval);
+}
+
+int SurfaceTextureClient::dequeueBuffer(ANativeWindow* window,
+        android_native_buffer_t** buffer) {
+    SurfaceTextureClient* c = getSelf(window);
+    return c->dequeueBuffer(buffer);
+}
+
+int SurfaceTextureClient::cancelBuffer(ANativeWindow* window,
+        android_native_buffer_t* buffer) {
+    SurfaceTextureClient* c = getSelf(window);
+    return c->cancelBuffer(buffer);
+}
+
+int SurfaceTextureClient::lockBuffer(ANativeWindow* window,
+        android_native_buffer_t* buffer) {
+    SurfaceTextureClient* c = getSelf(window);
+    return c->lockBuffer(buffer);
+}
+
+int SurfaceTextureClient::queueBuffer(ANativeWindow* window,
+        android_native_buffer_t* buffer) {
+    SurfaceTextureClient* c = getSelf(window);
+    return c->queueBuffer(buffer);
+}
+
+int SurfaceTextureClient::query(ANativeWindow* window, int what, int* value) {
+    SurfaceTextureClient* c = getSelf(window);
+    return c->query(what, value);
+}
+
+int SurfaceTextureClient::perform(ANativeWindow* window, int operation, ...) {
+    va_list args;
+    va_start(args, operation);
+    SurfaceTextureClient* c = getSelf(window);
+    return c->perform(operation, args);
+}
+
+int SurfaceTextureClient::setSwapInterval(int interval) {
+    return INVALID_OPERATION;
+}
+
+int SurfaceTextureClient::dequeueBuffer(android_native_buffer_t** buffer) {
+    LOGV("SurfaceTextureClient::dequeueBuffer");
+    Mutex::Autolock lock(mMutex);
+    int buf = -1;
+    status_t err = mSurfaceTexture->dequeueBuffer(&buf);
+    if (err < 0) {
+        LOGE("dequeueBuffer: ISurfaceTexture::dequeueBuffer failed: %d", err);
+        return err;
+    }
+    sp<GraphicBuffer>& gbuf(mSlots[buf]);
+    if (gbuf == 0 || gbuf->getWidth() != mReqWidth ||
+        gbuf->getHeight() != mReqHeight ||
+        uint32_t(gbuf->getPixelFormat()) != mReqFormat ||
+        (gbuf->getUsage() & mReqUsage) != mReqUsage) {
+        gbuf = mSurfaceTexture->requestBuffer(buf, mReqWidth, mReqHeight,
+                mReqFormat, mReqUsage);
+        if (gbuf == 0) {
+            LOGE("dequeueBuffer: ISurfaceTexture::requestBuffer failed");
+            return NO_MEMORY;
+        }
+    }
+    *buffer = gbuf.get();
+    return OK;
+}
+
+int SurfaceTextureClient::cancelBuffer(android_native_buffer_t* buffer) {
+    LOGV("SurfaceTextureClient::cancelBuffer");
+    Mutex::Autolock lock(mMutex);
+    for (int i = 0; i < NUM_BUFFER_SLOTS; i++) {
+        if (mSlots[i]->handle == buffer->handle) {
+            mSurfaceTexture->cancelBuffer(i);
+            return OK;
+        }
+    }
+    return BAD_VALUE;
+}
+
+int SurfaceTextureClient::lockBuffer(android_native_buffer_t* buffer) {
+    LOGV("SurfaceTextureClient::lockBuffer");
+    Mutex::Autolock lock(mMutex);
+    return OK;
+}
+
+int SurfaceTextureClient::queueBuffer(android_native_buffer_t* buffer) {
+    LOGV("SurfaceTextureClient::queueBuffer");
+    Mutex::Autolock lock(mMutex);
+    for (int i = 0; i < NUM_BUFFER_SLOTS; i++) {
+        if (mSlots[i]->handle == buffer->handle) {
+            return mSurfaceTexture->queueBuffer(i);
+        }
+    }
+    LOGE("queueBuffer: unknown buffer queued");
+    return BAD_VALUE;
+}
+
+int SurfaceTextureClient::query(int what, int* value) {
+    LOGV("SurfaceTextureClient::query");
+    Mutex::Autolock lock(mMutex);
+    // XXX: Implement this!
+    return INVALID_OPERATION;
+}
+
+int SurfaceTextureClient::perform(int operation, va_list args)
+{
+    int res = NO_ERROR;
+    switch (operation) {
+    case NATIVE_WINDOW_CONNECT:
+        res = dispatchConnect(args);
+        break;
+    case NATIVE_WINDOW_DISCONNECT:
+        res = dispatchDisconnect(args);
+        break;
+    case NATIVE_WINDOW_SET_USAGE:
+        res = dispatchSetUsage(args);
+        break;
+    case NATIVE_WINDOW_SET_CROP:
+        res = dispatchSetCrop(args);
+        break;
+    case NATIVE_WINDOW_SET_BUFFER_COUNT:
+        res = dispatchSetBufferCount(args);
+        break;
+    case NATIVE_WINDOW_SET_BUFFERS_GEOMETRY:
+        res = dispatchSetBuffersGeometry(args);
+        break;
+    case NATIVE_WINDOW_SET_BUFFERS_TRANSFORM:
+        res = dispatchSetBuffersTransform(args);
+        break;
+    default:
+        res = NAME_NOT_FOUND;
+        break;
+    }
+    return res;
+}
+
+int SurfaceTextureClient::dispatchConnect(va_list args) {
+    int api = va_arg(args, int);
+    return connect(api);
+}
+
+int SurfaceTextureClient::dispatchDisconnect(va_list args) {
+    int api = va_arg(args, int);
+    return disconnect(api);
+}
+
+int SurfaceTextureClient::dispatchSetUsage(va_list args) {
+    int usage = va_arg(args, int);
+    return setUsage(usage);
+}
+
+int SurfaceTextureClient::dispatchSetCrop(va_list args) {
+    android_native_rect_t const* rect = va_arg(args, android_native_rect_t*);
+    return setCrop(reinterpret_cast<Rect const*>(rect));
+}
+
+int SurfaceTextureClient::dispatchSetBufferCount(va_list args) {
+    size_t bufferCount = va_arg(args, size_t);
+    return setBufferCount(bufferCount);
+}
+
+int SurfaceTextureClient::dispatchSetBuffersGeometry(va_list args) {
+    int w = va_arg(args, int);
+    int h = va_arg(args, int);
+    int f = va_arg(args, int);
+    return setBuffersGeometry(w, h, f);
+}
+
+int SurfaceTextureClient::dispatchSetBuffersTransform(va_list args) {
+    int transform = va_arg(args, int);
+    return setBuffersTransform(transform);
+}
+
+int SurfaceTextureClient::connect(int api) {
+    LOGV("SurfaceTextureClient::connect");
+    // XXX: Implement this!
+    return INVALID_OPERATION;
+}
+
+int SurfaceTextureClient::disconnect(int api) {
+    LOGV("SurfaceTextureClient::disconnect");
+    // XXX: Implement this!
+    return INVALID_OPERATION;
+}
+
+int SurfaceTextureClient::setUsage(uint32_t reqUsage)
+{
+    LOGV("SurfaceTextureClient::setUsage");
+    Mutex::Autolock lock(mMutex);
+    mReqUsage = reqUsage;
+    return OK;
+}
+
+int SurfaceTextureClient::setCrop(Rect const* rect)
+{
+    LOGV("SurfaceTextureClient::setCrop");
+    Mutex::Autolock lock(mMutex);
+
+    // empty/invalid rects are not allowed
+    if (rect->isEmpty())
+        return BAD_VALUE;
+
+    status_t err = mSurfaceTexture->setCrop(*rect);
+    LOGE_IF(err, "ISurfaceTexture::setCrop(...) returned %s",
+            strerror(-err));
+
+    return err;
+}
+
+int SurfaceTextureClient::setBufferCount(int bufferCount)
+{
+    LOGV("SurfaceTextureClient::setBufferCount");
+    Mutex::Autolock lock(mMutex);
+
+    status_t err = mSurfaceTexture->setBufferCount(bufferCount);
+    LOGE_IF(err, "ISurfaceTexture::setBufferCount(%d) returned %s",
+            bufferCount, strerror(-err));
+
+    if (err == NO_ERROR) {
+        freeAllBuffers();
+    }
+
+    return err;
+}
+
+int SurfaceTextureClient::setBuffersGeometry(int w, int h, int format)
+{
+    LOGV("SurfaceTextureClient::setBuffersGeometry");
+    Mutex::Autolock lock(mMutex);
+
+    if (w<0 || h<0 || format<0)
+        return BAD_VALUE;
+
+    if ((w && !h) || (!w && h))
+        return BAD_VALUE;
+
+    mReqWidth = w;
+    mReqHeight = h;
+    mReqFormat = format;
+
+    return NO_ERROR;
+}
+
+int SurfaceTextureClient::setBuffersTransform(int transform)
+{
+    LOGV("SurfaceTextureClient::setBuffersTransform");
+    Mutex::Autolock lock(mMutex);
+    status_t err = mSurfaceTexture->setTransform(transform);
+    return err;
+}
+
+void SurfaceTextureClient::freeAllBuffers() {
+    for (int i = 0; i < NUM_BUFFER_SLOTS; i++) {
+        mSlots[i] = 0;
+    }
+}
+
+}; // namespace android
diff --git a/libs/surfaceflinger_client/Android.mk b/libs/surfaceflinger_client/Android.mk
index ce3c71a..4a0faf0 100644
--- a/libs/surfaceflinger_client/Android.mk
+++ b/libs/surfaceflinger_client/Android.mk
@@ -5,6 +5,7 @@
 	ISurfaceComposer.cpp \
 	ISurface.cpp \
 	ISurfaceComposerClient.cpp \
+	IGraphicBufferAlloc.cpp \
 	LayerState.cpp \
 	SharedBufferStack.cpp \
 	Surface.cpp \
diff --git a/libs/surfaceflinger_client/IGraphicBufferAlloc.cpp b/libs/surfaceflinger_client/IGraphicBufferAlloc.cpp
new file mode 100644
index 0000000..e05da72
--- /dev/null
+++ b/libs/surfaceflinger_client/IGraphicBufferAlloc.cpp
@@ -0,0 +1,108 @@
+/*
+ * Copyright (C) 2011 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+// tag as surfaceflinger
+#define LOG_TAG "SurfaceFlinger"
+
+#include <stdint.h>
+#include <sys/types.h>
+
+#include <binder/Parcel.h>
+
+#include <ui/GraphicBuffer.h>
+
+#include <surfaceflinger/IGraphicBufferAlloc.h>
+
+// ---------------------------------------------------------------------------
+
+namespace android {
+
+enum {
+    CREATE_GRAPHIC_BUFFER = IBinder::FIRST_CALL_TRANSACTION,
+    FREE_ALL_GRAPHIC_BUFFERS_EXCEPT,
+};
+
+class BpGraphicBufferAlloc : public BpInterface<IGraphicBufferAlloc>
+{
+public:
+    BpGraphicBufferAlloc(const sp<IBinder>& impl)
+        : BpInterface<IGraphicBufferAlloc>(impl)
+    {
+    }
+
+    virtual sp<GraphicBuffer> createGraphicBuffer(uint32_t w, uint32_t h,
+            PixelFormat format, uint32_t usage) {
+        Parcel data, reply;
+        data.writeInterfaceToken(
+                IGraphicBufferAlloc::getInterfaceDescriptor());
+        data.writeInt32(w);
+        data.writeInt32(h);
+        data.writeInt32(format);
+        data.writeInt32(usage);
+        remote()->transact(CREATE_GRAPHIC_BUFFER, data, &reply);
+        sp<GraphicBuffer> graphicBuffer;
+        bool nonNull = (bool)reply.readInt32();
+        if (nonNull) {
+            graphicBuffer = new GraphicBuffer();
+            reply.read(*graphicBuffer);
+        }
+        return graphicBuffer;
+    }
+
+    virtual void freeAllGraphicBuffersExcept(int bufIdx) {
+        Parcel data, reply;
+        data.writeInterfaceToken(
+                IGraphicBufferAlloc::getInterfaceDescriptor());
+        data.writeInt32(bufIdx);
+        remote()->transact(FREE_ALL_GRAPHIC_BUFFERS_EXCEPT, data, &reply);
+    }
+};
+
+IMPLEMENT_META_INTERFACE(GraphicBufferAlloc, "android.ui.IGraphicBufferAlloc");
+
+// ----------------------------------------------------------------------
+
+status_t BnGraphicBufferAlloc::onTransact(
+    uint32_t code, const Parcel& data, Parcel* reply, uint32_t flags)
+{
+    // codes that don't require permission check
+
+    switch(code) {
+        case CREATE_GRAPHIC_BUFFER: {
+            CHECK_INTERFACE(IGraphicBufferAlloc, data, reply);
+            uint32_t w = data.readInt32();
+            uint32_t h = data.readInt32();
+            PixelFormat format = data.readInt32();
+            uint32_t usage = data.readInt32();
+            sp<GraphicBuffer> result(createGraphicBuffer(w, h, format, usage));
+            reply->writeInt32(result != 0);
+            if (result != 0) {
+                reply->write(*result);
+            }
+            return NO_ERROR;
+        } break;
+        case FREE_ALL_GRAPHIC_BUFFERS_EXCEPT: {
+            CHECK_INTERFACE(IGraphicBufferAlloc, data, reply);
+            int bufIdx = data.readInt32();
+            freeAllGraphicBuffersExcept(bufIdx);
+            return NO_ERROR;
+        } break;
+        default:
+            return BBinder::onTransact(code, data, reply, flags);
+    }
+}
+
+}; // namespace android
diff --git a/libs/surfaceflinger_client/ISurfaceComposer.cpp b/libs/surfaceflinger_client/ISurfaceComposer.cpp
index 0c5d1b4..01ae23f 100644
--- a/libs/surfaceflinger_client/ISurfaceComposer.cpp
+++ b/libs/surfaceflinger_client/ISurfaceComposer.cpp
@@ -64,6 +64,15 @@
         return interface_cast<ISurfaceComposerClient>(reply.readStrongBinder());
     }
 
+    virtual sp<IGraphicBufferAlloc> createGraphicBufferAlloc()
+    {
+        uint32_t n;
+        Parcel data, reply;
+        data.writeInterfaceToken(ISurfaceComposer::getInterfaceDescriptor());
+        remote()->transact(BnSurfaceComposer::CREATE_GRAPHIC_BUFFER_ALLOC, data, &reply);
+        return interface_cast<IGraphicBufferAlloc>(reply.readStrongBinder());
+    }
+
     virtual sp<IMemoryHeap> getCblk() const
     {
         Parcel data, reply;
@@ -189,6 +198,11 @@
             sp<IBinder> b = createClientConnection()->asBinder();
             reply->writeStrongBinder(b);
         } break;
+        case CREATE_GRAPHIC_BUFFER_ALLOC: {
+            CHECK_INTERFACE(ISurfaceComposer, data, reply);
+            sp<IBinder> b = createGraphicBufferAlloc()->asBinder();
+            reply->writeStrongBinder(b);
+        } break;
         case OPEN_GLOBAL_TRANSACTION: {
             CHECK_INTERFACE(ISurfaceComposer, data, reply);
             openGlobalTransaction();
diff --git a/libs/surfaceflinger_client/Surface.cpp b/libs/surfaceflinger_client/Surface.cpp
index aa0c2e8..e21bab7 100644
--- a/libs/surfaceflinger_client/Surface.cpp
+++ b/libs/surfaceflinger_client/Surface.cpp
@@ -466,7 +466,7 @@
     return mInitCheck == NO_ERROR;
 }
 
-status_t Surface::validate() const
+status_t Surface::validate(bool inCancelBuffer) const
 {
     // check that we initialized ourself properly
     if (mInitCheck != NO_ERROR) {
@@ -476,15 +476,6 @@
 
     // verify the identity of this surface
     uint32_t identity = mSharedBufferClient->getIdentity();
-
-    // this is a bit of a (temporary) special case, identity==0 means that
-    // no operation are allowed from the client (eg: dequeue/queue), this
-    // is used with PUSH_BUFFER surfaces for instance
-    if (identity == 0) {
-        LOGE("[Surface] invalid operation (identity=%u)", mIdentity);
-        return INVALID_OPERATION;
-    }
-
     if (mIdentity != identity) {
         LOGE("[Surface] using an invalid surface, "
                 "identity=%u should be %d",
@@ -492,17 +483,19 @@
         CallStack stack;
         stack.update();
         stack.dump("Surface");
-        return NO_INIT;
+        return BAD_INDEX;
     }
 
     // check the surface didn't become invalid
     status_t err = mSharedBufferClient->getStatus();
     if (err != NO_ERROR) {
-        LOGE("surface (identity=%u) is invalid, err=%d (%s)",
-                mIdentity, err, strerror(-err));
-        CallStack stack;
-        stack.update();
-        stack.dump("Surface");
+        if (!inCancelBuffer) {
+            LOGE("surface (identity=%u) is invalid, err=%d (%s)",
+                    mIdentity, err, strerror(-err));
+            CallStack stack;
+            stack.update();
+            stack.dump("Surface");
+        }
         return err;
     }
 
@@ -633,12 +626,12 @@
 
 int Surface::cancelBuffer(android_native_buffer_t* buffer)
 {
-    status_t err = validate();
+    status_t err = validate(true);
     switch (err) {
     case NO_ERROR:
         // no error, common case
         break;
-    case INVALID_OPERATION:
+    case BAD_INDEX:
         // legitimate errors here
         return err;
     default:
diff --git a/libs/ui/Android.mk b/libs/ui/Android.mk
index 4ba8b5b..0d55f08 100644
--- a/libs/ui/Android.mk
+++ b/libs/ui/Android.mk
@@ -43,16 +43,12 @@
 LOCAL_SRC_FILES:= \
 	$(commonSources) \
 	EGLUtils.cpp \
-	EventHub.cpp \
 	EventRecurrence.cpp \
 	FramebufferNativeWindow.cpp \
 	GraphicBuffer.cpp \
 	GraphicBufferAllocator.cpp \
 	GraphicBufferMapper.cpp \
 	GraphicLog.cpp \
-	InputDispatcher.cpp \
-	InputManager.cpp \
-	InputReader.cpp \
 	InputTransport.cpp \
 	PixelFormat.cpp \
 	Rect.cpp \
diff --git a/libs/ui/EventHub.cpp b/libs/ui/EventHub.cpp
deleted file mode 100644
index 8f4bac6..0000000
--- a/libs/ui/EventHub.cpp
+++ /dev/null
@@ -1,1092 +0,0 @@
-//
-// Copyright 2005 The Android Open Source Project
-//
-// Handle events, like key input and vsync.
-//
-// The goal is to provide an optimized solution for Linux, not an
-// implementation that works well across all platforms.  We expect
-// events to arrive on file descriptors, so that we can use a select()
-// select() call to sleep.
-//
-// We can't select() on anything but network sockets in Windows, so we
-// provide an alternative implementation of waitEvent for that platform.
-//
-#define LOG_TAG "EventHub"
-
-//#define LOG_NDEBUG 0
-
-#include <ui/EventHub.h>
-#include <hardware_legacy/power.h>
-
-#include <cutils/properties.h>
-#include <utils/Log.h>
-#include <utils/Timers.h>
-#include <utils/threads.h>
-#include <utils/Errors.h>
-
-#include <stdlib.h>
-#include <stdio.h>
-#include <unistd.h>
-#include <fcntl.h>
-#include <memory.h>
-#include <errno.h>
-#include <assert.h>
-
-#include <ui/KeyLayoutMap.h>
-#include <ui/KeyCharacterMap.h>
-#include <ui/VirtualKeyMap.h>
-
-#include <string.h>
-#include <stdint.h>
-#include <dirent.h>
-#ifdef HAVE_INOTIFY
-# include <sys/inotify.h>
-#endif
-#ifdef HAVE_ANDROID_OS
-# include <sys/limits.h>        /* not part of Linux */
-#endif
-#include <sys/poll.h>
-#include <sys/ioctl.h>
-
-/* this macro is used to tell if "bit" is set in "array"
- * it selects a byte from the array, and does a boolean AND
- * operation with a byte that only has the relevant bit set.
- * eg. to check for the 12th bit, we do (array[1] & 1<<4)
- */
-#define test_bit(bit, array)    (array[bit/8] & (1<<(bit%8)))
-
-/* this macro computes the number of bytes needed to represent a bit array of the specified size */
-#define sizeof_bit_array(bits)  ((bits + 7) / 8)
-
-#ifndef ABS_MT_TOUCH_MAJOR
-#define ABS_MT_TOUCH_MAJOR      0x30    /* Major axis of touching ellipse */
-#endif
-
-#ifndef ABS_MT_POSITION_X
-#define ABS_MT_POSITION_X       0x35    /* Center X ellipse position */
-#endif
-
-#ifndef ABS_MT_POSITION_Y
-#define ABS_MT_POSITION_Y       0x36    /* Center Y ellipse position */
-#endif
-
-// Fd at index 0 is always reserved for inotify
-#define FIRST_ACTUAL_DEVICE_INDEX 1
-
-#define INDENT "  "
-#define INDENT2 "    "
-#define INDENT3 "      "
-
-namespace android {
-
-static const char *WAKE_LOCK_ID = "KeyEvents";
-static const char *DEVICE_PATH = "/dev/input";
-
-/* return the larger integer */
-static inline int max(int v1, int v2)
-{
-    return (v1 > v2) ? v1 : v2;
-}
-
-static inline const char* toString(bool value) {
-    return value ? "true" : "false";
-}
-
-// --- EventHub::Device ---
-
-EventHub::Device::Device(int fd, int32_t id, const String8& path,
-        const InputDeviceIdentifier& identifier) :
-        next(NULL),
-        fd(fd), id(id), path(path), identifier(identifier),
-        classes(0), keyBitmask(NULL), configuration(NULL), virtualKeyMap(NULL) {
-}
-
-EventHub::Device::~Device() {
-    close();
-    delete[] keyBitmask;
-    delete configuration;
-    delete virtualKeyMap;
-}
-
-void EventHub::Device::close() {
-    if (fd >= 0) {
-        ::close(fd);
-        fd = -1;
-    }
-}
-
-
-// --- EventHub ---
-
-EventHub::EventHub(void) :
-        mError(NO_INIT), mBuiltInKeyboardId(-1), mNextDeviceId(1),
-        mOpeningDevices(0), mClosingDevices(0),
-        mOpened(false), mNeedToSendFinishedDeviceScan(false),
-        mInputBufferIndex(0), mInputBufferCount(0), mInputFdIndex(0) {
-    acquire_wake_lock(PARTIAL_WAKE_LOCK, WAKE_LOCK_ID);
-#ifdef EV_SW
-    memset(mSwitches, 0, sizeof(mSwitches));
-#endif
-}
-
-EventHub::~EventHub(void) {
-    release_wake_lock(WAKE_LOCK_ID);
-    // we should free stuff here...
-}
-
-status_t EventHub::errorCheck() const {
-    return mError;
-}
-
-String8 EventHub::getDeviceName(int32_t deviceId) const {
-    AutoMutex _l(mLock);
-    Device* device = getDeviceLocked(deviceId);
-    if (device == NULL) return String8();
-    return device->identifier.name;
-}
-
-uint32_t EventHub::getDeviceClasses(int32_t deviceId) const {
-    AutoMutex _l(mLock);
-    Device* device = getDeviceLocked(deviceId);
-    if (device == NULL) return 0;
-    return device->classes;
-}
-
-void EventHub::getConfiguration(int32_t deviceId, PropertyMap* outConfiguration) const {
-    AutoMutex _l(mLock);
-    Device* device = getDeviceLocked(deviceId);
-    if (device && device->configuration) {
-        *outConfiguration = *device->configuration;
-    } else {
-        outConfiguration->clear();
-    }
-}
-
-status_t EventHub::getAbsoluteAxisInfo(int32_t deviceId, int axis,
-        RawAbsoluteAxisInfo* outAxisInfo) const {
-    outAxisInfo->clear();
-
-    AutoMutex _l(mLock);
-    Device* device = getDeviceLocked(deviceId);
-    if (device == NULL) return -1;
-
-    struct input_absinfo info;
-
-    if(ioctl(device->fd, EVIOCGABS(axis), &info)) {
-        LOGW("Error reading absolute controller %d for device %s fd %d\n",
-             axis, device->identifier.name.string(), device->fd);
-        return -errno;
-    }
-
-    if (info.minimum != info.maximum) {
-        outAxisInfo->valid = true;
-        outAxisInfo->minValue = info.minimum;
-        outAxisInfo->maxValue = info.maximum;
-        outAxisInfo->flat = info.flat;
-        outAxisInfo->fuzz = info.fuzz;
-    }
-    return OK;
-}
-
-int32_t EventHub::getScanCodeState(int32_t deviceId, int32_t scanCode) const {
-    if (scanCode >= 0 && scanCode <= KEY_MAX) {
-        AutoMutex _l(mLock);
-
-        Device* device = getDeviceLocked(deviceId);
-        if (device != NULL) {
-            return getScanCodeStateLocked(device, scanCode);
-        }
-    }
-    return AKEY_STATE_UNKNOWN;
-}
-
-int32_t EventHub::getScanCodeStateLocked(Device* device, int32_t scanCode) const {
-    uint8_t key_bitmask[sizeof_bit_array(KEY_MAX + 1)];
-    memset(key_bitmask, 0, sizeof(key_bitmask));
-    if (ioctl(device->fd,
-               EVIOCGKEY(sizeof(key_bitmask)), key_bitmask) >= 0) {
-        return test_bit(scanCode, key_bitmask) ? AKEY_STATE_DOWN : AKEY_STATE_UP;
-    }
-    return AKEY_STATE_UNKNOWN;
-}
-
-int32_t EventHub::getKeyCodeState(int32_t deviceId, int32_t keyCode) const {
-    AutoMutex _l(mLock);
-
-    Device* device = getDeviceLocked(deviceId);
-    if (device != NULL) {
-        return getKeyCodeStateLocked(device, keyCode);
-    }
-    return AKEY_STATE_UNKNOWN;
-}
-
-int32_t EventHub::getKeyCodeStateLocked(Device* device, int32_t keyCode) const {
-    if (!device->keyMap.haveKeyLayout()) {
-        return AKEY_STATE_UNKNOWN;
-    }
-
-    Vector<int32_t> scanCodes;
-    device->keyMap.keyLayoutMap->findScanCodes(keyCode, &scanCodes);
-
-    uint8_t key_bitmask[sizeof_bit_array(KEY_MAX + 1)];
-    memset(key_bitmask, 0, sizeof(key_bitmask));
-    if (ioctl(device->fd, EVIOCGKEY(sizeof(key_bitmask)), key_bitmask) >= 0) {
-        #if 0
-        for (size_t i=0; i<=KEY_MAX; i++) {
-            LOGI("(Scan code %d: down=%d)", i, test_bit(i, key_bitmask));
-        }
-        #endif
-        const size_t N = scanCodes.size();
-        for (size_t i=0; i<N && i<=KEY_MAX; i++) {
-            int32_t sc = scanCodes.itemAt(i);
-            //LOGI("Code %d: down=%d", sc, test_bit(sc, key_bitmask));
-            if (sc >= 0 && sc <= KEY_MAX && test_bit(sc, key_bitmask)) {
-                return AKEY_STATE_DOWN;
-            }
-        }
-        return AKEY_STATE_UP;
-    }
-    return AKEY_STATE_UNKNOWN;
-}
-
-int32_t EventHub::getSwitchState(int32_t deviceId, int32_t sw) const {
-#ifdef EV_SW
-    if (sw >= 0 && sw <= SW_MAX) {
-        AutoMutex _l(mLock);
-
-        Device* device = getDeviceLocked(deviceId);
-        if (device != NULL) {
-            return getSwitchStateLocked(device, sw);
-        }
-    }
-#endif
-    return AKEY_STATE_UNKNOWN;
-}
-
-int32_t EventHub::getSwitchStateLocked(Device* device, int32_t sw) const {
-    uint8_t sw_bitmask[sizeof_bit_array(SW_MAX + 1)];
-    memset(sw_bitmask, 0, sizeof(sw_bitmask));
-    if (ioctl(device->fd,
-               EVIOCGSW(sizeof(sw_bitmask)), sw_bitmask) >= 0) {
-        return test_bit(sw, sw_bitmask) ? AKEY_STATE_DOWN : AKEY_STATE_UP;
-    }
-    return AKEY_STATE_UNKNOWN;
-}
-
-bool EventHub::markSupportedKeyCodes(int32_t deviceId, size_t numCodes,
-        const int32_t* keyCodes, uint8_t* outFlags) const {
-    AutoMutex _l(mLock);
-
-    Device* device = getDeviceLocked(deviceId);
-    if (device != NULL) {
-        return markSupportedKeyCodesLocked(device, numCodes, keyCodes, outFlags);
-    }
-    return false;
-}
-
-bool EventHub::markSupportedKeyCodesLocked(Device* device, size_t numCodes,
-        const int32_t* keyCodes, uint8_t* outFlags) const {
-    if (!device->keyMap.haveKeyLayout() || !device->keyBitmask) {
-        return false;
-    }
-
-    Vector<int32_t> scanCodes;
-    for (size_t codeIndex = 0; codeIndex < numCodes; codeIndex++) {
-        scanCodes.clear();
-
-        status_t err = device->keyMap.keyLayoutMap->findScanCodes(keyCodes[codeIndex], &scanCodes);
-        if (! err) {
-            // check the possible scan codes identified by the layout map against the
-            // map of codes actually emitted by the driver
-            for (size_t sc = 0; sc < scanCodes.size(); sc++) {
-                if (test_bit(scanCodes[sc], device->keyBitmask)) {
-                    outFlags[codeIndex] = 1;
-                    break;
-                }
-            }
-        }
-    }
-    return true;
-}
-
-status_t EventHub::scancodeToKeycode(int32_t deviceId, int scancode,
-        int32_t* outKeycode, uint32_t* outFlags) const
-{
-    AutoMutex _l(mLock);
-    Device* device = getDeviceLocked(deviceId);
-    
-    if (device && device->keyMap.haveKeyLayout()) {
-        status_t err = device->keyMap.keyLayoutMap->map(scancode, outKeycode, outFlags);
-        if (err == NO_ERROR) {
-            return NO_ERROR;
-        }
-    }
-    
-    if (mBuiltInKeyboardId != -1) {
-        device = getDeviceLocked(mBuiltInKeyboardId);
-        
-        if (device && device->keyMap.haveKeyLayout()) {
-            status_t err = device->keyMap.keyLayoutMap->map(scancode, outKeycode, outFlags);
-            if (err == NO_ERROR) {
-                return NO_ERROR;
-            }
-        }
-    }
-    
-    *outKeycode = 0;
-    *outFlags = 0;
-    return NAME_NOT_FOUND;
-}
-
-void EventHub::addExcludedDevice(const char* deviceName)
-{
-    AutoMutex _l(mLock);
-
-    String8 name(deviceName);
-    mExcludedDevices.push_back(name);
-}
-
-bool EventHub::hasLed(int32_t deviceId, int32_t led) const {
-    AutoMutex _l(mLock);
-    Device* device = getDeviceLocked(deviceId);
-    if (device) {
-        uint8_t bitmask[sizeof_bit_array(LED_MAX + 1)];
-        memset(bitmask, 0, sizeof(bitmask));
-        if (ioctl(device->fd, EVIOCGBIT(EV_LED, sizeof(bitmask)), bitmask) >= 0) {
-            if (test_bit(led, bitmask)) {
-                return true;
-            }
-        }
-    }
-    return false;
-}
-
-void EventHub::setLedState(int32_t deviceId, int32_t led, bool on) {
-    AutoMutex _l(mLock);
-    Device* device = getDeviceLocked(deviceId);
-    if (device) {
-        struct input_event ev;
-        ev.time.tv_sec = 0;
-        ev.time.tv_usec = 0;
-        ev.type = EV_LED;
-        ev.code = led;
-        ev.value = on ? 1 : 0;
-
-        ssize_t nWrite;
-        do {
-            nWrite = write(device->fd, &ev, sizeof(struct input_event));
-        } while (nWrite == -1 && errno == EINTR);
-    }
-}
-
-void EventHub::getVirtualKeyDefinitions(int32_t deviceId,
-        Vector<VirtualKeyDefinition>& outVirtualKeys) const {
-    outVirtualKeys.clear();
-
-    AutoMutex _l(mLock);
-    Device* device = getDeviceLocked(deviceId);
-    if (device && device->virtualKeyMap) {
-        outVirtualKeys.appendVector(device->virtualKeyMap->getVirtualKeys());
-    }
-}
-
-EventHub::Device* EventHub::getDeviceLocked(int32_t deviceId) const {
-    if (deviceId == 0) {
-        deviceId = mBuiltInKeyboardId;
-    }
-
-    size_t numDevices = mDevices.size();
-    for (size_t i = FIRST_ACTUAL_DEVICE_INDEX; i < numDevices; i++) {
-        Device* device = mDevices[i];
-        if (device->id == deviceId) {
-            return device;
-        }
-    }
-    return NULL;
-}
-
-bool EventHub::getEvent(RawEvent* outEvent) {
-    outEvent->deviceId = 0;
-    outEvent->type = 0;
-    outEvent->scanCode = 0;
-    outEvent->keyCode = 0;
-    outEvent->flags = 0;
-    outEvent->value = 0;
-    outEvent->when = 0;
-
-    // Note that we only allow one caller to getEvent(), so don't need
-    // to do locking here...  only when adding/removing devices.
-
-    if (!mOpened) {
-        mError = openPlatformInput() ? NO_ERROR : UNKNOWN_ERROR;
-        mOpened = true;
-        mNeedToSendFinishedDeviceScan = true;
-    }
-
-    for (;;) {
-        // Report any devices that had last been added/removed.
-        if (mClosingDevices != NULL) {
-            Device* device = mClosingDevices;
-            LOGV("Reporting device closed: id=%d, name=%s\n",
-                 device->id, device->path.string());
-            mClosingDevices = device->next;
-            if (device->id == mBuiltInKeyboardId) {
-                outEvent->deviceId = 0;
-            } else {
-                outEvent->deviceId = device->id;
-            }
-            outEvent->type = DEVICE_REMOVED;
-            outEvent->when = systemTime(SYSTEM_TIME_MONOTONIC);
-            delete device;
-            mNeedToSendFinishedDeviceScan = true;
-            return true;
-        }
-
-        if (mOpeningDevices != NULL) {
-            Device* device = mOpeningDevices;
-            LOGV("Reporting device opened: id=%d, name=%s\n",
-                 device->id, device->path.string());
-            mOpeningDevices = device->next;
-            if (device->id == mBuiltInKeyboardId) {
-                outEvent->deviceId = 0;
-            } else {
-                outEvent->deviceId = device->id;
-            }
-            outEvent->type = DEVICE_ADDED;
-            outEvent->when = systemTime(SYSTEM_TIME_MONOTONIC);
-            mNeedToSendFinishedDeviceScan = true;
-            return true;
-        }
-
-        if (mNeedToSendFinishedDeviceScan) {
-            mNeedToSendFinishedDeviceScan = false;
-            outEvent->type = FINISHED_DEVICE_SCAN;
-            outEvent->when = systemTime(SYSTEM_TIME_MONOTONIC);
-            return true;
-        }
-
-        // Grab the next input event.
-        for (;;) {
-            // Consume buffered input events, if any.
-            if (mInputBufferIndex < mInputBufferCount) {
-                const struct input_event& iev = mInputBufferData[mInputBufferIndex++];
-                const Device* device = mDevices[mInputFdIndex];
-
-                LOGV("%s got: t0=%d, t1=%d, type=%d, code=%d, v=%d", device->path.string(),
-                     (int) iev.time.tv_sec, (int) iev.time.tv_usec, iev.type, iev.code, iev.value);
-                if (device->id == mBuiltInKeyboardId) {
-                    outEvent->deviceId = 0;
-                } else {
-                    outEvent->deviceId = device->id;
-                }
-                outEvent->type = iev.type;
-                outEvent->scanCode = iev.code;
-                outEvent->flags = 0;
-                if (iev.type == EV_KEY) {
-                    outEvent->keyCode = AKEYCODE_UNKNOWN;
-                    if (device->keyMap.haveKeyLayout()) {
-                        status_t err = device->keyMap.keyLayoutMap->map(iev.code,
-                                &outEvent->keyCode, &outEvent->flags);
-                        LOGV("iev.code=%d keyCode=%d flags=0x%08x err=%d\n",
-                                iev.code, outEvent->keyCode, outEvent->flags, err);
-                    }
-                } else {
-                    outEvent->keyCode = iev.code;
-                }
-                outEvent->value = iev.value;
-
-                // Use an event timestamp in the same timebase as
-                // java.lang.System.nanoTime() and android.os.SystemClock.uptimeMillis()
-                // as expected by the rest of the system.
-                outEvent->when = systemTime(SYSTEM_TIME_MONOTONIC);
-                return true;
-            }
-
-            // Finish reading all events from devices identified in previous poll().
-            // This code assumes that mInputDeviceIndex is initially 0 and that the
-            // revents member of pollfd is initialized to 0 when the device is first added.
-            // Since mFds[0] is used for inotify, we process regular events starting at index 1.
-            mInputFdIndex += 1;
-            if (mInputFdIndex >= mFds.size()) {
-                break;
-            }
-
-            const struct pollfd& pfd = mFds[mInputFdIndex];
-            if (pfd.revents & POLLIN) {
-                int32_t readSize = read(pfd.fd, mInputBufferData,
-                        sizeof(struct input_event) * INPUT_BUFFER_SIZE);
-                if (readSize < 0) {
-                    if (errno != EAGAIN && errno != EINTR) {
-                        LOGW("could not get event (errno=%d)", errno);
-                    }
-                } else if ((readSize % sizeof(struct input_event)) != 0) {
-                    LOGE("could not get event (wrong size: %d)", readSize);
-                } else {
-                    mInputBufferCount = size_t(readSize) / sizeof(struct input_event);
-                    mInputBufferIndex = 0;
-                }
-            }
-        }
-
-#if HAVE_INOTIFY
-        // readNotify() will modify mFDs and mFDCount, so this must be done after
-        // processing all other events.
-        if(mFds[0].revents & POLLIN) {
-            readNotify(mFds[0].fd);
-            mFds.editItemAt(0).revents = 0;
-            continue; // report added or removed devices immediately
-        }
-#endif
-
-        mInputFdIndex = 0;
-
-        // Poll for events.  Mind the wake lock dance!
-        // We hold a wake lock at all times except during poll().  This works due to some
-        // subtle choreography.  When a device driver has pending (unread) events, it acquires
-        // a kernel wake lock.  However, once the last pending event has been read, the device
-        // driver will release the kernel wake lock.  To prevent the system from going to sleep
-        // when this happens, the EventHub holds onto its own user wake lock while the client
-        // is processing events.  Thus the system can only sleep if there are no events
-        // pending or currently being processed.
-        release_wake_lock(WAKE_LOCK_ID);
-
-        int pollResult = poll(mFds.editArray(), mFds.size(), -1);
-
-        acquire_wake_lock(PARTIAL_WAKE_LOCK, WAKE_LOCK_ID);
-
-        if (pollResult <= 0) {
-            if (errno != EINTR) {
-                LOGW("poll failed (errno=%d)\n", errno);
-                usleep(100000);
-            }
-        }
-    }
-}
-
-/*
- * Open the platform-specific input device.
- */
-bool EventHub::openPlatformInput(void) {
-    /*
-     * Open platform-specific input device(s).
-     */
-    int res, fd;
-
-#ifdef HAVE_INOTIFY
-    fd = inotify_init();
-    res = inotify_add_watch(fd, DEVICE_PATH, IN_DELETE | IN_CREATE);
-    if(res < 0) {
-        LOGE("could not add watch for %s, %s\n", DEVICE_PATH, strerror(errno));
-    }
-#else
-    /*
-     * The code in EventHub::getEvent assumes that mFDs[0] is an inotify fd.
-     * We allocate space for it and set it to something invalid.
-     */
-    fd = -1;
-#endif
-
-    // Reserve fd index 0 for inotify.
-    struct pollfd pollfd;
-    pollfd.fd = fd;
-    pollfd.events = POLLIN;
-    pollfd.revents = 0;
-    mFds.push(pollfd);
-    mDevices.push(NULL);
-
-    res = scanDir(DEVICE_PATH);
-    if(res < 0) {
-        LOGE("scan dir failed for %s\n", DEVICE_PATH);
-    }
-
-    return true;
-}
-
-// ----------------------------------------------------------------------------
-
-static bool containsNonZeroByte(const uint8_t* array, uint32_t startIndex, uint32_t endIndex) {
-    const uint8_t* end = array + endIndex;
-    array += startIndex;
-    while (array != end) {
-        if (*(array++) != 0) {
-            return true;
-        }
-    }
-    return false;
-}
-
-static const int32_t GAMEPAD_KEYCODES[] = {
-        AKEYCODE_BUTTON_A, AKEYCODE_BUTTON_B, AKEYCODE_BUTTON_C,
-        AKEYCODE_BUTTON_X, AKEYCODE_BUTTON_Y, AKEYCODE_BUTTON_Z,
-        AKEYCODE_BUTTON_L1, AKEYCODE_BUTTON_R1,
-        AKEYCODE_BUTTON_L2, AKEYCODE_BUTTON_R2,
-        AKEYCODE_BUTTON_THUMBL, AKEYCODE_BUTTON_THUMBR,
-        AKEYCODE_BUTTON_START, AKEYCODE_BUTTON_SELECT, AKEYCODE_BUTTON_MODE
-};
-
-int EventHub::openDevice(const char *devicePath) {
-    char buffer[80];
-
-    LOGV("Opening device: %s", devicePath);
-
-    AutoMutex _l(mLock);
-
-    int fd = open(devicePath, O_RDWR);
-    if(fd < 0) {
-        LOGE("could not open %s, %s\n", devicePath, strerror(errno));
-        return -1;
-    }
-
-    InputDeviceIdentifier identifier;
-
-    // Get device name.
-    if(ioctl(fd, EVIOCGNAME(sizeof(buffer) - 1), &buffer) < 1) {
-        //fprintf(stderr, "could not get device name for %s, %s\n", devicePath, strerror(errno));
-    } else {
-        buffer[sizeof(buffer) - 1] = '\0';
-        identifier.name.setTo(buffer);
-    }
-
-    // Check to see if the device is on our excluded list
-    List<String8>::iterator iter = mExcludedDevices.begin();
-    List<String8>::iterator end = mExcludedDevices.end();
-    for ( ; iter != end; iter++) {
-        const char* test = *iter;
-        if (identifier.name == test) {
-            LOGI("ignoring event id %s driver %s\n", devicePath, test);
-            close(fd);
-            return -1;
-        }
-    }
-
-    // Get device driver version.
-    int driverVersion;
-    if(ioctl(fd, EVIOCGVERSION, &driverVersion)) {
-        LOGE("could not get driver version for %s, %s\n", devicePath, strerror(errno));
-        close(fd);
-        return -1;
-    }
-
-    // Get device identifier.
-    struct input_id inputId;
-    if(ioctl(fd, EVIOCGID, &inputId)) {
-        LOGE("could not get device input id for %s, %s\n", devicePath, strerror(errno));
-        close(fd);
-        return -1;
-    }
-    identifier.bus = inputId.bustype;
-    identifier.product = inputId.product;
-    identifier.vendor = inputId.vendor;
-    identifier.version = inputId.version;
-
-    // Get device physical location.
-    if(ioctl(fd, EVIOCGPHYS(sizeof(buffer) - 1), &buffer) < 1) {
-        //fprintf(stderr, "could not get location for %s, %s\n", devicePath, strerror(errno));
-    } else {
-        buffer[sizeof(buffer) - 1] = '\0';
-        identifier.location.setTo(buffer);
-    }
-
-    // Get device unique id.
-    if(ioctl(fd, EVIOCGUNIQ(sizeof(buffer) - 1), &buffer) < 1) {
-        //fprintf(stderr, "could not get idstring for %s, %s\n", devicePath, strerror(errno));
-    } else {
-        buffer[sizeof(buffer) - 1] = '\0';
-        identifier.uniqueId.setTo(buffer);
-    }
-
-    // Make file descriptor non-blocking for use with poll().
-    if (fcntl(fd, F_SETFL, O_NONBLOCK)) {
-        LOGE("Error %d making device file descriptor non-blocking.", errno);
-        close(fd);
-        return -1;
-    }
-
-    // Allocate device.  (The device object takes ownership of the fd at this point.)
-    int32_t deviceId = mNextDeviceId++;
-    Device* device = new Device(fd, deviceId, String8(devicePath), identifier);
-
-#if 0
-    LOGI("add device %d: %s\n", deviceId, devicePath);
-    LOGI("  bus:       %04x\n"
-         "  vendor     %04x\n"
-         "  product    %04x\n"
-         "  version    %04x\n",
-        identifier.bus, identifier.vendor, identifier.product, identifier.version);
-    LOGI("  name:      \"%s\"\n", identifier.name.string());
-    LOGI("  location:  \"%s\"\n", identifier.location.string());
-    LOGI("  unique id: \"%s\"\n", identifier.uniqueId.string());
-    LOGI("  driver:    v%d.%d.%d\n",
-        driverVersion >> 16, (driverVersion >> 8) & 0xff, driverVersion & 0xff);
-#endif
-
-    // Load the configuration file for the device.
-    loadConfiguration(device);
-
-    // Figure out the kinds of events the device reports.
-    
-    uint8_t key_bitmask[sizeof_bit_array(KEY_MAX + 1)];
-    memset(key_bitmask, 0, sizeof(key_bitmask));
-
-    LOGV("Getting keys...");
-    if (ioctl(fd, EVIOCGBIT(EV_KEY, sizeof(key_bitmask)), key_bitmask) >= 0) {
-        //LOGI("MAP\n");
-        //for (int i = 0; i < sizeof(key_bitmask); i++) {
-        //    LOGI("%d: 0x%02x\n", i, key_bitmask[i]);
-        //}
-
-        // See if this is a keyboard.  Ignore everything in the button range except for
-        // gamepads which are also considered keyboards.
-        if (containsNonZeroByte(key_bitmask, 0, sizeof_bit_array(BTN_MISC))
-                || containsNonZeroByte(key_bitmask, sizeof_bit_array(BTN_GAMEPAD),
-                        sizeof_bit_array(BTN_DIGI))
-                || containsNonZeroByte(key_bitmask, sizeof_bit_array(KEY_OK),
-                        sizeof_bit_array(KEY_MAX + 1))) {
-            device->classes |= INPUT_DEVICE_CLASS_KEYBOARD;
-
-            device->keyBitmask = new uint8_t[sizeof(key_bitmask)];
-            if (device->keyBitmask != NULL) {
-                memcpy(device->keyBitmask, key_bitmask, sizeof(key_bitmask));
-            } else {
-                delete device;
-                LOGE("out of memory allocating key bitmask");
-                return -1;
-            }
-        }
-    }
-    
-    // See if this is a trackball (or mouse).
-    if (test_bit(BTN_MOUSE, key_bitmask)) {
-        uint8_t rel_bitmask[sizeof_bit_array(REL_MAX + 1)];
-        memset(rel_bitmask, 0, sizeof(rel_bitmask));
-        LOGV("Getting relative controllers...");
-        if (ioctl(fd, EVIOCGBIT(EV_REL, sizeof(rel_bitmask)), rel_bitmask) >= 0) {
-            if (test_bit(REL_X, rel_bitmask) && test_bit(REL_Y, rel_bitmask)) {
-                device->classes |= INPUT_DEVICE_CLASS_TRACKBALL;
-            }
-        }
-    }
-
-    // See if this is a touch pad.
-    uint8_t abs_bitmask[sizeof_bit_array(ABS_MAX + 1)];
-    memset(abs_bitmask, 0, sizeof(abs_bitmask));
-    LOGV("Getting absolute controllers...");
-    if (ioctl(fd, EVIOCGBIT(EV_ABS, sizeof(abs_bitmask)), abs_bitmask) >= 0) {
-        // Is this a new modern multi-touch driver?
-        if (test_bit(ABS_MT_POSITION_X, abs_bitmask)
-                && test_bit(ABS_MT_POSITION_Y, abs_bitmask)) {
-            device->classes |= INPUT_DEVICE_CLASS_TOUCHSCREEN | INPUT_DEVICE_CLASS_TOUCHSCREEN_MT;
-
-        // Is this an old style single-touch driver?
-        } else if (test_bit(BTN_TOUCH, key_bitmask)
-                && test_bit(ABS_X, abs_bitmask) && test_bit(ABS_Y, abs_bitmask)) {
-            device->classes |= INPUT_DEVICE_CLASS_TOUCHSCREEN;
-        }
-    }
-
-#ifdef EV_SW
-    // figure out the switches this device reports
-    uint8_t sw_bitmask[sizeof_bit_array(SW_MAX + 1)];
-    memset(sw_bitmask, 0, sizeof(sw_bitmask));
-    bool hasSwitches = false;
-    if (ioctl(fd, EVIOCGBIT(EV_SW, sizeof(sw_bitmask)), sw_bitmask) >= 0) {
-        for (int i=0; i<EV_SW; i++) {
-            //LOGI("Device %d sw %d: has=%d", device->id, i, test_bit(i, sw_bitmask));
-            if (test_bit(i, sw_bitmask)) {
-                hasSwitches = true;
-                if (mSwitches[i] == 0) {
-                    mSwitches[i] = device->id;
-                }
-            }
-        }
-    }
-    if (hasSwitches) {
-        device->classes |= INPUT_DEVICE_CLASS_SWITCH;
-    }
-#endif
-
-    if ((device->classes & INPUT_DEVICE_CLASS_TOUCHSCREEN)) {
-        // Load the virtual keys for the touch screen, if any.
-        // We do this now so that we can make sure to load the keymap if necessary.
-        status_t status = loadVirtualKeyMap(device);
-        if (!status) {
-            device->classes |= INPUT_DEVICE_CLASS_KEYBOARD;
-        }
-    }
-
-    if ((device->classes & INPUT_DEVICE_CLASS_KEYBOARD) != 0) {
-        // Load the keymap for the device.
-        status_t status = loadKeyMap(device);
-
-        // Set system properties for the keyboard.
-        setKeyboardProperties(device, false);
-
-        // Register the keyboard as a built-in keyboard if it is eligible.
-        if (!status
-                && mBuiltInKeyboardId == -1
-                && isEligibleBuiltInKeyboard(device->identifier,
-                        device->configuration, &device->keyMap)) {
-            mBuiltInKeyboardId = device->id;
-            setKeyboardProperties(device, true);
-        }
-
-        // 'Q' key support = cheap test of whether this is an alpha-capable kbd
-        if (hasKeycodeLocked(device, AKEYCODE_Q)) {
-            device->classes |= INPUT_DEVICE_CLASS_ALPHAKEY;
-        }
-
-        // See if this device has a DPAD.
-        if (hasKeycodeLocked(device, AKEYCODE_DPAD_UP) &&
-                hasKeycodeLocked(device, AKEYCODE_DPAD_DOWN) &&
-                hasKeycodeLocked(device, AKEYCODE_DPAD_LEFT) &&
-                hasKeycodeLocked(device, AKEYCODE_DPAD_RIGHT) &&
-                hasKeycodeLocked(device, AKEYCODE_DPAD_CENTER)) {
-            device->classes |= INPUT_DEVICE_CLASS_DPAD;
-        }
-
-        // See if this device has a gamepad.
-        for (size_t i = 0; i < sizeof(GAMEPAD_KEYCODES)/sizeof(GAMEPAD_KEYCODES[0]); i++) {
-            if (hasKeycodeLocked(device, GAMEPAD_KEYCODES[i])) {
-                device->classes |= INPUT_DEVICE_CLASS_GAMEPAD;
-                break;
-            }
-        }
-    }
-
-    // If the device isn't recognized as something we handle, don't monitor it.
-    if (device->classes == 0) {
-        LOGV("Dropping device: id=%d, path='%s', name='%s'",
-                deviceId, devicePath, device->identifier.name.string());
-        delete device;
-        return -1;
-    }
-
-    LOGI("New device: id=%d, fd=%d, path='%s', name='%s', classes=0x%x, "
-            "configuration='%s', keyLayout='%s', keyCharacterMap='%s', builtinKeyboard=%s",
-         deviceId, fd, devicePath, device->identifier.name.string(),
-         device->classes,
-         device->configurationFile.string(),
-         device->keyMap.keyLayoutFile.string(),
-         device->keyMap.keyCharacterMapFile.string(),
-         toString(mBuiltInKeyboardId == deviceId));
-
-    struct pollfd pollfd;
-    pollfd.fd = fd;
-    pollfd.events = POLLIN;
-    pollfd.revents = 0;
-    mFds.push(pollfd);
-    mDevices.push(device);
-
-    device->next = mOpeningDevices;
-    mOpeningDevices = device;
-    return 0;
-}
-
-void EventHub::loadConfiguration(Device* device) {
-    device->configurationFile = getInputDeviceConfigurationFilePathByDeviceIdentifier(
-            device->identifier, INPUT_DEVICE_CONFIGURATION_FILE_TYPE_CONFIGURATION);
-    if (device->configurationFile.isEmpty()) {
-        LOGD("No input device configuration file found for device '%s'.",
-                device->identifier.name.string());
-    } else {
-        status_t status = PropertyMap::load(device->configurationFile,
-                &device->configuration);
-        if (status) {
-            LOGE("Error loading input device configuration file for device '%s'.  "
-                    "Using default configuration.",
-                    device->identifier.name.string());
-        }
-    }
-}
-
-status_t EventHub::loadVirtualKeyMap(Device* device) {
-    // The virtual key map is supplied by the kernel as a system board property file.
-    String8 path;
-    path.append("/sys/board_properties/virtualkeys.");
-    path.append(device->identifier.name);
-    if (access(path.string(), R_OK)) {
-        return NAME_NOT_FOUND;
-    }
-    return VirtualKeyMap::load(path, &device->virtualKeyMap);
-}
-
-status_t EventHub::loadKeyMap(Device* device) {
-    return device->keyMap.load(device->identifier, device->configuration);
-}
-
-void EventHub::setKeyboardProperties(Device* device, bool builtInKeyboard) {
-    int32_t id = builtInKeyboard ? 0 : device->id;
-    android::setKeyboardProperties(id, device->identifier,
-            device->keyMap.keyLayoutFile, device->keyMap.keyCharacterMapFile);
-}
-
-void EventHub::clearKeyboardProperties(Device* device, bool builtInKeyboard) {
-    int32_t id = builtInKeyboard ? 0 : device->id;
-    android::clearKeyboardProperties(id);
-}
-
-bool EventHub::hasKeycodeLocked(Device* device, int keycode) const {
-    if (!device->keyMap.haveKeyLayout() || !device->keyBitmask) {
-        return false;
-    }
-    
-    Vector<int32_t> scanCodes;
-    device->keyMap.keyLayoutMap->findScanCodes(keycode, &scanCodes);
-    const size_t N = scanCodes.size();
-    for (size_t i=0; i<N && i<=KEY_MAX; i++) {
-        int32_t sc = scanCodes.itemAt(i);
-        if (sc >= 0 && sc <= KEY_MAX && test_bit(sc, device->keyBitmask)) {
-            return true;
-        }
-    }
-    
-    return false;
-}
-
-int EventHub::closeDevice(const char *devicePath) {
-    AutoMutex _l(mLock);
-
-    for (size_t i = FIRST_ACTUAL_DEVICE_INDEX; i < mDevices.size(); i++) {
-        Device* device = mDevices[i];
-        if (device->path == devicePath) {
-            LOGI("Removed device: path=%s name=%s id=%d fd=%d classes=0x%x\n",
-                 device->path.string(), device->identifier.name.string(), device->id,
-                 device->fd, device->classes);
-
-#ifdef EV_SW
-            for (int j=0; j<EV_SW; j++) {
-                if (mSwitches[j] == device->id) {
-                    mSwitches[j] = 0;
-                }
-            }
-#endif
-
-            if (device->id == mBuiltInKeyboardId) {
-                LOGW("built-in keyboard device %s (id=%d) is closing! the apps will not like this",
-                        device->path.string(), mBuiltInKeyboardId);
-                mBuiltInKeyboardId = -1;
-                clearKeyboardProperties(device, true);
-            }
-            clearKeyboardProperties(device, false);
-
-            mFds.removeAt(i);
-            mDevices.removeAt(i);
-            device->close();
-
-            device->next = mClosingDevices;
-            mClosingDevices = device;
-            return 0;
-        }
-    }
-    LOGE("remove device: %s not found\n", devicePath);
-    return -1;
-}
-
-int EventHub::readNotify(int nfd) {
-#ifdef HAVE_INOTIFY
-    int res;
-    char devname[PATH_MAX];
-    char *filename;
-    char event_buf[512];
-    int event_size;
-    int event_pos = 0;
-    struct inotify_event *event;
-
-    LOGV("EventHub::readNotify nfd: %d\n", nfd);
-    res = read(nfd, event_buf, sizeof(event_buf));
-    if(res < (int)sizeof(*event)) {
-        if(errno == EINTR)
-            return 0;
-        LOGW("could not get event, %s\n", strerror(errno));
-        return 1;
-    }
-    //printf("got %d bytes of event information\n", res);
-
-    strcpy(devname, DEVICE_PATH);
-    filename = devname + strlen(devname);
-    *filename++ = '/';
-
-    while(res >= (int)sizeof(*event)) {
-        event = (struct inotify_event *)(event_buf + event_pos);
-        //printf("%d: %08x \"%s\"\n", event->wd, event->mask, event->len ? event->name : "");
-        if(event->len) {
-            strcpy(filename, event->name);
-            if(event->mask & IN_CREATE) {
-                openDevice(devname);
-            }
-            else {
-                closeDevice(devname);
-            }
-        }
-        event_size = sizeof(*event) + event->len;
-        res -= event_size;
-        event_pos += event_size;
-    }
-#endif
-    return 0;
-}
-
-int EventHub::scanDir(const char *dirname)
-{
-    char devname[PATH_MAX];
-    char *filename;
-    DIR *dir;
-    struct dirent *de;
-    dir = opendir(dirname);
-    if(dir == NULL)
-        return -1;
-    strcpy(devname, dirname);
-    filename = devname + strlen(devname);
-    *filename++ = '/';
-    while((de = readdir(dir))) {
-        if(de->d_name[0] == '.' &&
-           (de->d_name[1] == '\0' ||
-            (de->d_name[1] == '.' && de->d_name[2] == '\0')))
-            continue;
-        strcpy(filename, de->d_name);
-        openDevice(devname);
-    }
-    closedir(dir);
-    return 0;
-}
-
-void EventHub::dump(String8& dump) {
-    dump.append("Event Hub State:\n");
-
-    { // acquire lock
-        AutoMutex _l(mLock);
-
-        dump.appendFormat(INDENT "BuiltInKeyboardId: %d\n", mBuiltInKeyboardId);
-
-        dump.append(INDENT "Devices:\n");
-
-        for (size_t i = FIRST_ACTUAL_DEVICE_INDEX; i < mDevices.size(); i++) {
-            const Device* device = mDevices[i];
-            if (device) {
-                if (mBuiltInKeyboardId == device->id) {
-                    dump.appendFormat(INDENT2 "%d: %s (aka device 0 - built-in keyboard)\n",
-                            device->id, device->identifier.name.string());
-                } else {
-                    dump.appendFormat(INDENT2 "%d: %s\n", device->id,
-                            device->identifier.name.string());
-                }
-                dump.appendFormat(INDENT3 "Classes: 0x%08x\n", device->classes);
-                dump.appendFormat(INDENT3 "Path: %s\n", device->path.string());
-                dump.appendFormat(INDENT3 "Location: %s\n", device->identifier.location.string());
-                dump.appendFormat(INDENT3 "UniqueId: %s\n", device->identifier.uniqueId.string());
-                dump.appendFormat(INDENT3 "Identifier: bus=0x%04x, vendor=0x%04x, "
-                        "product=0x%04x, version=0x%04x\n",
-                        device->identifier.bus, device->identifier.vendor,
-                        device->identifier.product, device->identifier.version);
-                dump.appendFormat(INDENT3 "KeyLayoutFile: %s\n",
-                        device->keyMap.keyLayoutFile.string());
-                dump.appendFormat(INDENT3 "KeyCharacterMapFile: %s\n",
-                        device->keyMap.keyCharacterMapFile.string());
-                dump.appendFormat(INDENT3 "ConfigurationFile: %s\n",
-                        device->configurationFile.string());
-            }
-        }
-    } // release lock
-}
-
-}; // namespace android
diff --git a/libs/ui/InputDispatcher.cpp b/libs/ui/InputDispatcher.cpp
deleted file mode 100644
index ed0cb8e..0000000
--- a/libs/ui/InputDispatcher.cpp
+++ /dev/null
@@ -1,3710 +0,0 @@
-//
-// Copyright 2010 The Android Open Source Project
-//
-// The input dispatcher.
-//
-#define LOG_TAG "InputDispatcher"
-
-//#define LOG_NDEBUG 0
-
-// Log detailed debug messages about each inbound event notification to the dispatcher.
-#define DEBUG_INBOUND_EVENT_DETAILS 0
-
-// Log detailed debug messages about each outbound event processed by the dispatcher.
-#define DEBUG_OUTBOUND_EVENT_DETAILS 0
-
-// Log debug messages about batching.
-#define DEBUG_BATCHING 0
-
-// Log debug messages about the dispatch cycle.
-#define DEBUG_DISPATCH_CYCLE 0
-
-// Log debug messages about registrations.
-#define DEBUG_REGISTRATION 0
-
-// Log debug messages about performance statistics.
-#define DEBUG_PERFORMANCE_STATISTICS 0
-
-// Log debug messages about input event injection.
-#define DEBUG_INJECTION 0
-
-// Log debug messages about input event throttling.
-#define DEBUG_THROTTLING 0
-
-// Log debug messages about input focus tracking.
-#define DEBUG_FOCUS 0
-
-// Log debug messages about the app switch latency optimization.
-#define DEBUG_APP_SWITCH 0
-
-#include <cutils/log.h>
-#include <ui/InputDispatcher.h>
-#include <ui/PowerManager.h>
-
-#include <stddef.h>
-#include <unistd.h>
-#include <errno.h>
-#include <limits.h>
-
-#define INDENT "  "
-#define INDENT2 "    "
-
-namespace android {
-
-// Default input dispatching timeout if there is no focused application or paused window
-// from which to determine an appropriate dispatching timeout.
-const nsecs_t DEFAULT_INPUT_DISPATCHING_TIMEOUT = 5000 * 1000000LL; // 5 sec
-
-// Amount of time to allow for all pending events to be processed when an app switch
-// key is on the way.  This is used to preempt input dispatch and drop input events
-// when an application takes too long to respond and the user has pressed an app switch key.
-const nsecs_t APP_SWITCH_TIMEOUT = 500 * 1000000LL; // 0.5sec
-
-
-static inline nsecs_t now() {
-    return systemTime(SYSTEM_TIME_MONOTONIC);
-}
-
-static inline const char* toString(bool value) {
-    return value ? "true" : "false";
-}
-
-static inline int32_t getMotionEventActionPointerIndex(int32_t action) {
-    return (action & AMOTION_EVENT_ACTION_POINTER_INDEX_MASK)
-            >> AMOTION_EVENT_ACTION_POINTER_INDEX_SHIFT;
-}
-
-static bool isValidKeyAction(int32_t action) {
-    switch (action) {
-    case AKEY_EVENT_ACTION_DOWN:
-    case AKEY_EVENT_ACTION_UP:
-        return true;
-    default:
-        return false;
-    }
-}
-
-static bool validateKeyEvent(int32_t action) {
-    if (! isValidKeyAction(action)) {
-        LOGE("Key event has invalid action code 0x%x", action);
-        return false;
-    }
-    return true;
-}
-
-static bool isValidMotionAction(int32_t action, size_t pointerCount) {
-    switch (action & AMOTION_EVENT_ACTION_MASK) {
-    case AMOTION_EVENT_ACTION_DOWN:
-    case AMOTION_EVENT_ACTION_UP:
-    case AMOTION_EVENT_ACTION_CANCEL:
-    case AMOTION_EVENT_ACTION_MOVE:
-    case AMOTION_EVENT_ACTION_OUTSIDE:
-        return true;
-    case AMOTION_EVENT_ACTION_POINTER_DOWN:
-    case AMOTION_EVENT_ACTION_POINTER_UP: {
-        int32_t index = getMotionEventActionPointerIndex(action);
-        return index >= 0 && size_t(index) < pointerCount;
-    }
-    default:
-        return false;
-    }
-}
-
-static bool validateMotionEvent(int32_t action, size_t pointerCount,
-        const int32_t* pointerIds) {
-    if (! isValidMotionAction(action, pointerCount)) {
-        LOGE("Motion event has invalid action code 0x%x", action);
-        return false;
-    }
-    if (pointerCount < 1 || pointerCount > MAX_POINTERS) {
-        LOGE("Motion event has invalid pointer count %d; value must be between 1 and %d.",
-                pointerCount, MAX_POINTERS);
-        return false;
-    }
-    BitSet32 pointerIdBits;
-    for (size_t i = 0; i < pointerCount; i++) {
-        int32_t id = pointerIds[i];
-        if (id < 0 || id > MAX_POINTER_ID) {
-            LOGE("Motion event has invalid pointer id %d; value must be between 0 and %d",
-                    id, MAX_POINTER_ID);
-            return false;
-        }
-        if (pointerIdBits.hasBit(id)) {
-            LOGE("Motion event has duplicate pointer id %d", id);
-            return false;
-        }
-        pointerIdBits.markBit(id);
-    }
-    return true;
-}
-
-
-// --- InputWindow ---
-
-bool InputWindow::touchableAreaContainsPoint(int32_t x, int32_t y) const {
-    return x >= touchableAreaLeft && x <= touchableAreaRight
-            && y >= touchableAreaTop && y <= touchableAreaBottom;
-}
-
-bool InputWindow::frameContainsPoint(int32_t x, int32_t y) const {
-    return x >= frameLeft && x <= frameRight
-            && y >= frameTop && y <= frameBottom;
-}
-
-bool InputWindow::isTrustedOverlay() const {
-    return layoutParamsType == TYPE_INPUT_METHOD
-            || layoutParamsType == TYPE_INPUT_METHOD_DIALOG
-            || layoutParamsType == TYPE_SECURE_SYSTEM_OVERLAY;
-}
-
-bool InputWindow::supportsSplitTouch() const {
-    return layoutParamsFlags & InputWindow::FLAG_SPLIT_TOUCH;
-}
-
-
-// --- InputDispatcher ---
-
-InputDispatcher::InputDispatcher(const sp<InputDispatcherPolicyInterface>& policy) :
-    mPolicy(policy),
-    mPendingEvent(NULL), mAppSwitchDueTime(LONG_LONG_MAX),
-    mDispatchEnabled(true), mDispatchFrozen(false),
-    mFocusedWindow(NULL),
-    mFocusedApplication(NULL),
-    mCurrentInputTargetsValid(false),
-    mInputTargetWaitCause(INPUT_TARGET_WAIT_CAUSE_NONE) {
-    mLooper = new Looper(false);
-
-    mInboundQueue.headSentinel.refCount = -1;
-    mInboundQueue.headSentinel.type = EventEntry::TYPE_SENTINEL;
-    mInboundQueue.headSentinel.eventTime = LONG_LONG_MIN;
-
-    mInboundQueue.tailSentinel.refCount = -1;
-    mInboundQueue.tailSentinel.type = EventEntry::TYPE_SENTINEL;
-    mInboundQueue.tailSentinel.eventTime = LONG_LONG_MAX;
-
-    mKeyRepeatState.lastKeyEntry = NULL;
-
-    int32_t maxEventsPerSecond = policy->getMaxEventsPerSecond();
-    mThrottleState.minTimeBetweenEvents = 1000000000LL / maxEventsPerSecond;
-    mThrottleState.lastDeviceId = -1;
-
-#if DEBUG_THROTTLING
-    mThrottleState.originalSampleCount = 0;
-    LOGD("Throttling - Max events per second = %d", maxEventsPerSecond);
-#endif
-}
-
-InputDispatcher::~InputDispatcher() {
-    { // acquire lock
-        AutoMutex _l(mLock);
-
-        resetKeyRepeatLocked();
-        releasePendingEventLocked();
-        drainInboundQueueLocked();
-    }
-
-    while (mConnectionsByReceiveFd.size() != 0) {
-        unregisterInputChannel(mConnectionsByReceiveFd.valueAt(0)->inputChannel);
-    }
-}
-
-void InputDispatcher::dispatchOnce() {
-    nsecs_t keyRepeatTimeout = mPolicy->getKeyRepeatTimeout();
-    nsecs_t keyRepeatDelay = mPolicy->getKeyRepeatDelay();
-
-    nsecs_t nextWakeupTime = LONG_LONG_MAX;
-    { // acquire lock
-        AutoMutex _l(mLock);
-        dispatchOnceInnerLocked(keyRepeatTimeout, keyRepeatDelay, & nextWakeupTime);
-
-        if (runCommandsLockedInterruptible()) {
-            nextWakeupTime = LONG_LONG_MIN;  // force next poll to wake up immediately
-        }
-    } // release lock
-
-    // Wait for callback or timeout or wake.  (make sure we round up, not down)
-    nsecs_t currentTime = now();
-    int32_t timeoutMillis;
-    if (nextWakeupTime > currentTime) {
-        uint64_t timeout = uint64_t(nextWakeupTime - currentTime);
-        timeout = (timeout + 999999LL) / 1000000LL;
-        timeoutMillis = timeout > INT_MAX ? -1 : int32_t(timeout);
-    } else {
-        timeoutMillis = 0;
-    }
-
-    mLooper->pollOnce(timeoutMillis);
-}
-
-void InputDispatcher::dispatchOnceInnerLocked(nsecs_t keyRepeatTimeout,
-        nsecs_t keyRepeatDelay, nsecs_t* nextWakeupTime) {
-    nsecs_t currentTime = now();
-
-    // Reset the key repeat timer whenever we disallow key events, even if the next event
-    // is not a key.  This is to ensure that we abort a key repeat if the device is just coming
-    // out of sleep.
-    if (keyRepeatTimeout < 0) {
-        resetKeyRepeatLocked();
-    }
-
-    // If dispatching is frozen, do not process timeouts or try to deliver any new events.
-    if (mDispatchFrozen) {
-#if DEBUG_FOCUS
-        LOGD("Dispatch frozen.  Waiting some more.");
-#endif
-        return;
-    }
-
-    // Optimize latency of app switches.
-    // Essentially we start a short timeout when an app switch key (HOME / ENDCALL) has
-    // been pressed.  When it expires, we preempt dispatch and drop all other pending events.
-    bool isAppSwitchDue = mAppSwitchDueTime <= currentTime;
-    if (mAppSwitchDueTime < *nextWakeupTime) {
-        *nextWakeupTime = mAppSwitchDueTime;
-    }
-
-    // Ready to start a new event.
-    // If we don't already have a pending event, go grab one.
-    if (! mPendingEvent) {
-        if (mInboundQueue.isEmpty()) {
-            if (isAppSwitchDue) {
-                // The inbound queue is empty so the app switch key we were waiting
-                // for will never arrive.  Stop waiting for it.
-                resetPendingAppSwitchLocked(false);
-                isAppSwitchDue = false;
-            }
-
-            // Synthesize a key repeat if appropriate.
-            if (mKeyRepeatState.lastKeyEntry) {
-                if (currentTime >= mKeyRepeatState.nextRepeatTime) {
-                    mPendingEvent = synthesizeKeyRepeatLocked(currentTime, keyRepeatDelay);
-                } else {
-                    if (mKeyRepeatState.nextRepeatTime < *nextWakeupTime) {
-                        *nextWakeupTime = mKeyRepeatState.nextRepeatTime;
-                    }
-                }
-            }
-            if (! mPendingEvent) {
-                return;
-            }
-        } else {
-            // Inbound queue has at least one entry.
-            EventEntry* entry = mInboundQueue.headSentinel.next;
-
-            // Throttle the entry if it is a move event and there are no
-            // other events behind it in the queue.  Due to movement batching, additional
-            // samples may be appended to this event by the time the throttling timeout
-            // expires.
-            // TODO Make this smarter and consider throttling per device independently.
-            if (entry->type == EventEntry::TYPE_MOTION
-                    && !isAppSwitchDue
-                    && mDispatchEnabled
-                    && (entry->policyFlags & POLICY_FLAG_PASS_TO_USER)
-                    && !entry->isInjected()) {
-                MotionEntry* motionEntry = static_cast<MotionEntry*>(entry);
-                int32_t deviceId = motionEntry->deviceId;
-                uint32_t source = motionEntry->source;
-                if (! isAppSwitchDue
-                        && motionEntry->next == & mInboundQueue.tailSentinel // exactly one event
-                        && motionEntry->action == AMOTION_EVENT_ACTION_MOVE
-                        && deviceId == mThrottleState.lastDeviceId
-                        && source == mThrottleState.lastSource) {
-                    nsecs_t nextTime = mThrottleState.lastEventTime
-                            + mThrottleState.minTimeBetweenEvents;
-                    if (currentTime < nextTime) {
-                        // Throttle it!
-#if DEBUG_THROTTLING
-                        LOGD("Throttling - Delaying motion event for "
-                                "device %d, source 0x%08x by up to %0.3fms.",
-                                deviceId, source, (nextTime - currentTime) * 0.000001);
-#endif
-                        if (nextTime < *nextWakeupTime) {
-                            *nextWakeupTime = nextTime;
-                        }
-                        if (mThrottleState.originalSampleCount == 0) {
-                            mThrottleState.originalSampleCount =
-                                    motionEntry->countSamples();
-                        }
-                        return;
-                    }
-                }
-
-#if DEBUG_THROTTLING
-                if (mThrottleState.originalSampleCount != 0) {
-                    uint32_t count = motionEntry->countSamples();
-                    LOGD("Throttling - Motion event sample count grew by %d from %d to %d.",
-                            count - mThrottleState.originalSampleCount,
-                            mThrottleState.originalSampleCount, count);
-                    mThrottleState.originalSampleCount = 0;
-                }
-#endif
-
-                mThrottleState.lastEventTime = entry->eventTime < currentTime
-                        ? entry->eventTime : currentTime;
-                mThrottleState.lastDeviceId = deviceId;
-                mThrottleState.lastSource = source;
-            }
-
-            mInboundQueue.dequeue(entry);
-            mPendingEvent = entry;
-        }
-
-        // Poke user activity for this event.
-        if (mPendingEvent->policyFlags & POLICY_FLAG_PASS_TO_USER) {
-            pokeUserActivityLocked(mPendingEvent);
-        }
-    }
-
-    // Now we have an event to dispatch.
-    assert(mPendingEvent != NULL);
-    bool done = false;
-    DropReason dropReason = DROP_REASON_NOT_DROPPED;
-    if (!(mPendingEvent->policyFlags & POLICY_FLAG_PASS_TO_USER)) {
-        dropReason = DROP_REASON_POLICY;
-    } else if (!mDispatchEnabled) {
-        dropReason = DROP_REASON_DISABLED;
-    }
-    switch (mPendingEvent->type) {
-    case EventEntry::TYPE_CONFIGURATION_CHANGED: {
-        ConfigurationChangedEntry* typedEntry =
-                static_cast<ConfigurationChangedEntry*>(mPendingEvent);
-        done = dispatchConfigurationChangedLocked(currentTime, typedEntry);
-        dropReason = DROP_REASON_NOT_DROPPED; // configuration changes are never dropped
-        break;
-    }
-
-    case EventEntry::TYPE_KEY: {
-        KeyEntry* typedEntry = static_cast<KeyEntry*>(mPendingEvent);
-        if (isAppSwitchDue) {
-            if (isAppSwitchKeyEventLocked(typedEntry)) {
-                resetPendingAppSwitchLocked(true);
-                isAppSwitchDue = false;
-            } else if (dropReason == DROP_REASON_NOT_DROPPED) {
-                dropReason = DROP_REASON_APP_SWITCH;
-            }
-        }
-        done = dispatchKeyLocked(currentTime, typedEntry, keyRepeatTimeout,
-                &dropReason, nextWakeupTime);
-        break;
-    }
-
-    case EventEntry::TYPE_MOTION: {
-        MotionEntry* typedEntry = static_cast<MotionEntry*>(mPendingEvent);
-        if (dropReason == DROP_REASON_NOT_DROPPED && isAppSwitchDue) {
-            dropReason = DROP_REASON_APP_SWITCH;
-        }
-        done = dispatchMotionLocked(currentTime, typedEntry,
-                &dropReason, nextWakeupTime);
-        break;
-    }
-
-    default:
-        assert(false);
-        break;
-    }
-
-    if (done) {
-        if (dropReason != DROP_REASON_NOT_DROPPED) {
-            dropInboundEventLocked(mPendingEvent, dropReason);
-        }
-
-        releasePendingEventLocked();
-        *nextWakeupTime = LONG_LONG_MIN;  // force next poll to wake up immediately
-    }
-}
-
-bool InputDispatcher::enqueueInboundEventLocked(EventEntry* entry) {
-    bool needWake = mInboundQueue.isEmpty();
-    mInboundQueue.enqueueAtTail(entry);
-
-    switch (entry->type) {
-    case EventEntry::TYPE_KEY: {
-        KeyEntry* keyEntry = static_cast<KeyEntry*>(entry);
-        if (isAppSwitchKeyEventLocked(keyEntry)) {
-            if (keyEntry->action == AKEY_EVENT_ACTION_DOWN) {
-                mAppSwitchSawKeyDown = true;
-            } else if (keyEntry->action == AKEY_EVENT_ACTION_UP) {
-                if (mAppSwitchSawKeyDown) {
-#if DEBUG_APP_SWITCH
-                    LOGD("App switch is pending!");
-#endif
-                    mAppSwitchDueTime = keyEntry->eventTime + APP_SWITCH_TIMEOUT;
-                    mAppSwitchSawKeyDown = false;
-                    needWake = true;
-                }
-            }
-        }
-        break;
-    }
-    }
-
-    return needWake;
-}
-
-void InputDispatcher::dropInboundEventLocked(EventEntry* entry, DropReason dropReason) {
-    const char* reason;
-    switch (dropReason) {
-    case DROP_REASON_POLICY:
-#if DEBUG_INBOUND_EVENT_DETAILS
-        LOGD("Dropped event because policy consumed it.");
-#endif
-        reason = "inbound event was dropped because the policy consumed it";
-        break;
-    case DROP_REASON_DISABLED:
-        LOGI("Dropped event because input dispatch is disabled.");
-        reason = "inbound event was dropped because input dispatch is disabled";
-        break;
-    case DROP_REASON_APP_SWITCH:
-        LOGI("Dropped event because of pending overdue app switch.");
-        reason = "inbound event was dropped because of pending overdue app switch";
-        break;
-    default:
-        assert(false);
-        return;
-    }
-
-    switch (entry->type) {
-    case EventEntry::TYPE_KEY:
-        synthesizeCancelationEventsForAllConnectionsLocked(
-                InputState::CANCEL_NON_POINTER_EVENTS, reason);
-        break;
-    case EventEntry::TYPE_MOTION: {
-        MotionEntry* motionEntry = static_cast<MotionEntry*>(entry);
-        if (motionEntry->source & AINPUT_SOURCE_CLASS_POINTER) {
-            synthesizeCancelationEventsForAllConnectionsLocked(
-                    InputState::CANCEL_POINTER_EVENTS, reason);
-        } else {
-            synthesizeCancelationEventsForAllConnectionsLocked(
-                    InputState::CANCEL_NON_POINTER_EVENTS, reason);
-        }
-        break;
-    }
-    }
-}
-
-bool InputDispatcher::isAppSwitchKeyCode(int32_t keyCode) {
-    return keyCode == AKEYCODE_HOME || keyCode == AKEYCODE_ENDCALL;
-}
-
-bool InputDispatcher::isAppSwitchKeyEventLocked(KeyEntry* keyEntry) {
-    return ! (keyEntry->flags & AKEY_EVENT_FLAG_CANCELED)
-            && isAppSwitchKeyCode(keyEntry->keyCode)
-            && (keyEntry->policyFlags & POLICY_FLAG_TRUSTED)
-            && (keyEntry->policyFlags & POLICY_FLAG_PASS_TO_USER);
-}
-
-bool InputDispatcher::isAppSwitchPendingLocked() {
-    return mAppSwitchDueTime != LONG_LONG_MAX;
-}
-
-void InputDispatcher::resetPendingAppSwitchLocked(bool handled) {
-    mAppSwitchDueTime = LONG_LONG_MAX;
-
-#if DEBUG_APP_SWITCH
-    if (handled) {
-        LOGD("App switch has arrived.");
-    } else {
-        LOGD("App switch was abandoned.");
-    }
-#endif
-}
-
-bool InputDispatcher::runCommandsLockedInterruptible() {
-    if (mCommandQueue.isEmpty()) {
-        return false;
-    }
-
-    do {
-        CommandEntry* commandEntry = mCommandQueue.dequeueAtHead();
-
-        Command command = commandEntry->command;
-        (this->*command)(commandEntry); // commands are implicitly 'LockedInterruptible'
-
-        commandEntry->connection.clear();
-        mAllocator.releaseCommandEntry(commandEntry);
-    } while (! mCommandQueue.isEmpty());
-    return true;
-}
-
-InputDispatcher::CommandEntry* InputDispatcher::postCommandLocked(Command command) {
-    CommandEntry* commandEntry = mAllocator.obtainCommandEntry(command);
-    mCommandQueue.enqueueAtTail(commandEntry);
-    return commandEntry;
-}
-
-void InputDispatcher::drainInboundQueueLocked() {
-    while (! mInboundQueue.isEmpty()) {
-        EventEntry* entry = mInboundQueue.dequeueAtHead();
-        releaseInboundEventLocked(entry);
-    }
-}
-
-void InputDispatcher::releasePendingEventLocked() {
-    if (mPendingEvent) {
-        releaseInboundEventLocked(mPendingEvent);
-        mPendingEvent = NULL;
-    }
-}
-
-void InputDispatcher::releaseInboundEventLocked(EventEntry* entry) {
-    InjectionState* injectionState = entry->injectionState;
-    if (injectionState && injectionState->injectionResult == INPUT_EVENT_INJECTION_PENDING) {
-#if DEBUG_DISPATCH_CYCLE
-        LOGD("Injected inbound event was dropped.");
-#endif
-        setInjectionResultLocked(entry, INPUT_EVENT_INJECTION_FAILED);
-    }
-    mAllocator.releaseEventEntry(entry);
-}
-
-void InputDispatcher::resetKeyRepeatLocked() {
-    if (mKeyRepeatState.lastKeyEntry) {
-        mAllocator.releaseKeyEntry(mKeyRepeatState.lastKeyEntry);
-        mKeyRepeatState.lastKeyEntry = NULL;
-    }
-}
-
-InputDispatcher::KeyEntry* InputDispatcher::synthesizeKeyRepeatLocked(
-        nsecs_t currentTime, nsecs_t keyRepeatDelay) {
-    KeyEntry* entry = mKeyRepeatState.lastKeyEntry;
-
-    // Reuse the repeated key entry if it is otherwise unreferenced.
-    uint32_t policyFlags = (entry->policyFlags & POLICY_FLAG_RAW_MASK)
-            | POLICY_FLAG_PASS_TO_USER | POLICY_FLAG_TRUSTED;
-    if (entry->refCount == 1) {
-        mAllocator.recycleKeyEntry(entry);
-        entry->eventTime = currentTime;
-        entry->policyFlags = policyFlags;
-        entry->repeatCount += 1;
-    } else {
-        KeyEntry* newEntry = mAllocator.obtainKeyEntry(currentTime,
-                entry->deviceId, entry->source, policyFlags,
-                entry->action, entry->flags, entry->keyCode, entry->scanCode,
-                entry->metaState, entry->repeatCount + 1, entry->downTime);
-
-        mKeyRepeatState.lastKeyEntry = newEntry;
-        mAllocator.releaseKeyEntry(entry);
-
-        entry = newEntry;
-    }
-    entry->syntheticRepeat = true;
-
-    // Increment reference count since we keep a reference to the event in
-    // mKeyRepeatState.lastKeyEntry in addition to the one we return.
-    entry->refCount += 1;
-
-    if (entry->repeatCount == 1) {
-        entry->flags |= AKEY_EVENT_FLAG_LONG_PRESS;
-    }
-
-    mKeyRepeatState.nextRepeatTime = currentTime + keyRepeatDelay;
-    return entry;
-}
-
-bool InputDispatcher::dispatchConfigurationChangedLocked(
-        nsecs_t currentTime, ConfigurationChangedEntry* entry) {
-#if DEBUG_OUTBOUND_EVENT_DETAILS
-    LOGD("dispatchConfigurationChanged - eventTime=%lld", entry->eventTime);
-#endif
-
-    // Reset key repeating in case a keyboard device was added or removed or something.
-    resetKeyRepeatLocked();
-
-    // Enqueue a command to run outside the lock to tell the policy that the configuration changed.
-    CommandEntry* commandEntry = postCommandLocked(
-            & InputDispatcher::doNotifyConfigurationChangedInterruptible);
-    commandEntry->eventTime = entry->eventTime;
-    return true;
-}
-
-bool InputDispatcher::dispatchKeyLocked(
-        nsecs_t currentTime, KeyEntry* entry, nsecs_t keyRepeatTimeout,
-        DropReason* dropReason, nsecs_t* nextWakeupTime) {
-    // Preprocessing.
-    if (! entry->dispatchInProgress) {
-        if (entry->repeatCount == 0
-                && entry->action == AKEY_EVENT_ACTION_DOWN
-                && (entry->policyFlags & POLICY_FLAG_TRUSTED)
-                && !entry->isInjected()) {
-            if (mKeyRepeatState.lastKeyEntry
-                    && mKeyRepeatState.lastKeyEntry->keyCode == entry->keyCode) {
-                // We have seen two identical key downs in a row which indicates that the device
-                // driver is automatically generating key repeats itself.  We take note of the
-                // repeat here, but we disable our own next key repeat timer since it is clear that
-                // we will not need to synthesize key repeats ourselves.
-                entry->repeatCount = mKeyRepeatState.lastKeyEntry->repeatCount + 1;
-                resetKeyRepeatLocked();
-                mKeyRepeatState.nextRepeatTime = LONG_LONG_MAX; // don't generate repeats ourselves
-            } else {
-                // Not a repeat.  Save key down state in case we do see a repeat later.
-                resetKeyRepeatLocked();
-                mKeyRepeatState.nextRepeatTime = entry->eventTime + keyRepeatTimeout;
-            }
-            mKeyRepeatState.lastKeyEntry = entry;
-            entry->refCount += 1;
-        } else if (! entry->syntheticRepeat) {
-            resetKeyRepeatLocked();
-        }
-
-        entry->dispatchInProgress = true;
-        resetTargetsLocked();
-
-        logOutboundKeyDetailsLocked("dispatchKey - ", entry);
-    }
-
-    // Give the policy a chance to intercept the key.
-    if (entry->interceptKeyResult == KeyEntry::INTERCEPT_KEY_RESULT_UNKNOWN) {
-        if (entry->policyFlags & POLICY_FLAG_PASS_TO_USER) {
-            CommandEntry* commandEntry = postCommandLocked(
-                    & InputDispatcher::doInterceptKeyBeforeDispatchingLockedInterruptible);
-            if (mFocusedWindow) {
-                commandEntry->inputChannel = mFocusedWindow->inputChannel;
-            }
-            commandEntry->keyEntry = entry;
-            entry->refCount += 1;
-            return false; // wait for the command to run
-        } else {
-            entry->interceptKeyResult = KeyEntry::INTERCEPT_KEY_RESULT_CONTINUE;
-        }
-    } else if (entry->interceptKeyResult == KeyEntry::INTERCEPT_KEY_RESULT_SKIP) {
-        if (*dropReason == DROP_REASON_NOT_DROPPED) {
-            *dropReason = DROP_REASON_POLICY;
-        }
-    }
-
-    // Clean up if dropping the event.
-    if (*dropReason != DROP_REASON_NOT_DROPPED) {
-        resetTargetsLocked();
-        setInjectionResultLocked(entry, *dropReason == DROP_REASON_POLICY
-                ? INPUT_EVENT_INJECTION_SUCCEEDED : INPUT_EVENT_INJECTION_FAILED);
-        return true;
-    }
-
-    // Identify targets.
-    if (! mCurrentInputTargetsValid) {
-        int32_t injectionResult = findFocusedWindowTargetsLocked(currentTime,
-                entry, nextWakeupTime);
-        if (injectionResult == INPUT_EVENT_INJECTION_PENDING) {
-            return false;
-        }
-
-        setInjectionResultLocked(entry, injectionResult);
-        if (injectionResult != INPUT_EVENT_INJECTION_SUCCEEDED) {
-            return true;
-        }
-
-        addMonitoringTargetsLocked();
-        commitTargetsLocked();
-    }
-
-    // Dispatch the key.
-    dispatchEventToCurrentInputTargetsLocked(currentTime, entry, false);
-    return true;
-}
-
-void InputDispatcher::logOutboundKeyDetailsLocked(const char* prefix, const KeyEntry* entry) {
-#if DEBUG_OUTBOUND_EVENT_DETAILS
-    LOGD("%seventTime=%lld, deviceId=%d, source=0x%x, policyFlags=0x%x, "
-            "action=0x%x, flags=0x%x, keyCode=0x%x, scanCode=0x%x, metaState=0x%x, "
-            "repeatCount=%d, downTime=%lld",
-            prefix,
-            entry->eventTime, entry->deviceId, entry->source, entry->policyFlags,
-            entry->action, entry->flags, entry->keyCode, entry->scanCode, entry->metaState,
-            entry->repeatCount, entry->downTime);
-#endif
-}
-
-bool InputDispatcher::dispatchMotionLocked(
-        nsecs_t currentTime, MotionEntry* entry, DropReason* dropReason, nsecs_t* nextWakeupTime) {
-    // Preprocessing.
-    if (! entry->dispatchInProgress) {
-        entry->dispatchInProgress = true;
-        resetTargetsLocked();
-
-        logOutboundMotionDetailsLocked("dispatchMotion - ", entry);
-    }
-
-    // Clean up if dropping the event.
-    if (*dropReason != DROP_REASON_NOT_DROPPED) {
-        resetTargetsLocked();
-        setInjectionResultLocked(entry, *dropReason == DROP_REASON_POLICY
-                ? INPUT_EVENT_INJECTION_SUCCEEDED : INPUT_EVENT_INJECTION_FAILED);
-        return true;
-    }
-
-    bool isPointerEvent = entry->source & AINPUT_SOURCE_CLASS_POINTER;
-
-    // Identify targets.
-    if (! mCurrentInputTargetsValid) {
-        int32_t injectionResult;
-        if (isPointerEvent) {
-            // Pointer event.  (eg. touchscreen)
-            injectionResult = findTouchedWindowTargetsLocked(currentTime,
-                    entry, nextWakeupTime);
-        } else {
-            // Non touch event.  (eg. trackball)
-            injectionResult = findFocusedWindowTargetsLocked(currentTime,
-                    entry, nextWakeupTime);
-        }
-        if (injectionResult == INPUT_EVENT_INJECTION_PENDING) {
-            return false;
-        }
-
-        setInjectionResultLocked(entry, injectionResult);
-        if (injectionResult != INPUT_EVENT_INJECTION_SUCCEEDED) {
-            return true;
-        }
-
-        addMonitoringTargetsLocked();
-        commitTargetsLocked();
-    }
-
-    // Dispatch the motion.
-    dispatchEventToCurrentInputTargetsLocked(currentTime, entry, false);
-    return true;
-}
-
-
-void InputDispatcher::logOutboundMotionDetailsLocked(const char* prefix, const MotionEntry* entry) {
-#if DEBUG_OUTBOUND_EVENT_DETAILS
-    LOGD("%seventTime=%lld, deviceId=%d, source=0x%x, policyFlags=0x%x, "
-            "action=0x%x, flags=0x%x, "
-            "metaState=0x%x, edgeFlags=0x%x, xPrecision=%f, yPrecision=%f, downTime=%lld",
-            prefix,
-            entry->eventTime, entry->deviceId, entry->source, entry->policyFlags,
-            entry->action, entry->flags,
-            entry->metaState, entry->edgeFlags, entry->xPrecision, entry->yPrecision,
-            entry->downTime);
-
-    // Print the most recent sample that we have available, this may change due to batching.
-    size_t sampleCount = 1;
-    const MotionSample* sample = & entry->firstSample;
-    for (; sample->next != NULL; sample = sample->next) {
-        sampleCount += 1;
-    }
-    for (uint32_t i = 0; i < entry->pointerCount; i++) {
-        LOGD("  Pointer %d: id=%d, x=%f, y=%f, pressure=%f, size=%f, "
-                "touchMajor=%f, touchMinor=%f, toolMajor=%f, toolMinor=%f, "
-                "orientation=%f",
-                i, entry->pointerIds[i],
-                sample->pointerCoords[i].x, sample->pointerCoords[i].y,
-                sample->pointerCoords[i].pressure, sample->pointerCoords[i].size,
-                sample->pointerCoords[i].touchMajor, sample->pointerCoords[i].touchMinor,
-                sample->pointerCoords[i].toolMajor, sample->pointerCoords[i].toolMinor,
-                sample->pointerCoords[i].orientation);
-    }
-
-    // Keep in mind that due to batching, it is possible for the number of samples actually
-    // dispatched to change before the application finally consumed them.
-    if (entry->action == AMOTION_EVENT_ACTION_MOVE) {
-        LOGD("  ... Total movement samples currently batched %d ...", sampleCount);
-    }
-#endif
-}
-
-void InputDispatcher::dispatchEventToCurrentInputTargetsLocked(nsecs_t currentTime,
-        EventEntry* eventEntry, bool resumeWithAppendedMotionSample) {
-#if DEBUG_DISPATCH_CYCLE
-    LOGD("dispatchEventToCurrentInputTargets - "
-            "resumeWithAppendedMotionSample=%s",
-            toString(resumeWithAppendedMotionSample));
-#endif
-
-    assert(eventEntry->dispatchInProgress); // should already have been set to true
-
-    pokeUserActivityLocked(eventEntry);
-
-    for (size_t i = 0; i < mCurrentInputTargets.size(); i++) {
-        const InputTarget& inputTarget = mCurrentInputTargets.itemAt(i);
-
-        ssize_t connectionIndex = getConnectionIndexLocked(inputTarget.inputChannel);
-        if (connectionIndex >= 0) {
-            sp<Connection> connection = mConnectionsByReceiveFd.valueAt(connectionIndex);
-            prepareDispatchCycleLocked(currentTime, connection, eventEntry, & inputTarget,
-                    resumeWithAppendedMotionSample);
-        } else {
-#if DEBUG_FOCUS
-            LOGD("Dropping event delivery to target with channel '%s' because it "
-                    "is no longer registered with the input dispatcher.",
-                    inputTarget.inputChannel->getName().string());
-#endif
-        }
-    }
-}
-
-void InputDispatcher::resetTargetsLocked() {
-    mCurrentInputTargetsValid = false;
-    mCurrentInputTargets.clear();
-    mInputTargetWaitCause = INPUT_TARGET_WAIT_CAUSE_NONE;
-}
-
-void InputDispatcher::commitTargetsLocked() {
-    mCurrentInputTargetsValid = true;
-}
-
-int32_t InputDispatcher::handleTargetsNotReadyLocked(nsecs_t currentTime,
-        const EventEntry* entry, const InputApplication* application, const InputWindow* window,
-        nsecs_t* nextWakeupTime) {
-    if (application == NULL && window == NULL) {
-        if (mInputTargetWaitCause != INPUT_TARGET_WAIT_CAUSE_SYSTEM_NOT_READY) {
-#if DEBUG_FOCUS
-            LOGD("Waiting for system to become ready for input.");
-#endif
-            mInputTargetWaitCause = INPUT_TARGET_WAIT_CAUSE_SYSTEM_NOT_READY;
-            mInputTargetWaitStartTime = currentTime;
-            mInputTargetWaitTimeoutTime = LONG_LONG_MAX;
-            mInputTargetWaitTimeoutExpired = false;
-        }
-    } else {
-        if (mInputTargetWaitCause != INPUT_TARGET_WAIT_CAUSE_APPLICATION_NOT_READY) {
-#if DEBUG_FOCUS
-            LOGD("Waiting for application to become ready for input: %s",
-                    getApplicationWindowLabelLocked(application, window).string());
-#endif
-            nsecs_t timeout = window ? window->dispatchingTimeout :
-                application ? application->dispatchingTimeout : DEFAULT_INPUT_DISPATCHING_TIMEOUT;
-
-            mInputTargetWaitCause = INPUT_TARGET_WAIT_CAUSE_APPLICATION_NOT_READY;
-            mInputTargetWaitStartTime = currentTime;
-            mInputTargetWaitTimeoutTime = currentTime + timeout;
-            mInputTargetWaitTimeoutExpired = false;
-        }
-    }
-
-    if (mInputTargetWaitTimeoutExpired) {
-        return INPUT_EVENT_INJECTION_TIMED_OUT;
-    }
-
-    if (currentTime >= mInputTargetWaitTimeoutTime) {
-        onANRLocked(currentTime, application, window, entry->eventTime, mInputTargetWaitStartTime);
-
-        // Force poll loop to wake up immediately on next iteration once we get the
-        // ANR response back from the policy.
-        *nextWakeupTime = LONG_LONG_MIN;
-        return INPUT_EVENT_INJECTION_PENDING;
-    } else {
-        // Force poll loop to wake up when timeout is due.
-        if (mInputTargetWaitTimeoutTime < *nextWakeupTime) {
-            *nextWakeupTime = mInputTargetWaitTimeoutTime;
-        }
-        return INPUT_EVENT_INJECTION_PENDING;
-    }
-}
-
-void InputDispatcher::resumeAfterTargetsNotReadyTimeoutLocked(nsecs_t newTimeout,
-        const sp<InputChannel>& inputChannel) {
-    if (newTimeout > 0) {
-        // Extend the timeout.
-        mInputTargetWaitTimeoutTime = now() + newTimeout;
-    } else {
-        // Give up.
-        mInputTargetWaitTimeoutExpired = true;
-
-        // Release the touch targets.
-        mTouchState.reset();
-
-        // Input state will not be realistic.  Mark it out of sync.
-        if (inputChannel.get()) {
-            ssize_t connectionIndex = getConnectionIndexLocked(inputChannel);
-            if (connectionIndex >= 0) {
-                sp<Connection> connection = mConnectionsByReceiveFd.valueAt(connectionIndex);
-                if (connection->status == Connection::STATUS_NORMAL) {
-                    synthesizeCancelationEventsForConnectionLocked(
-                            connection, InputState::CANCEL_ALL_EVENTS,
-                            "application not responding");
-                }
-            }
-        }
-    }
-}
-
-nsecs_t InputDispatcher::getTimeSpentWaitingForApplicationLocked(
-        nsecs_t currentTime) {
-    if (mInputTargetWaitCause == INPUT_TARGET_WAIT_CAUSE_APPLICATION_NOT_READY) {
-        return currentTime - mInputTargetWaitStartTime;
-    }
-    return 0;
-}
-
-void InputDispatcher::resetANRTimeoutsLocked() {
-#if DEBUG_FOCUS
-        LOGD("Resetting ANR timeouts.");
-#endif
-
-    // Reset input target wait timeout.
-    mInputTargetWaitCause = INPUT_TARGET_WAIT_CAUSE_NONE;
-}
-
-int32_t InputDispatcher::findFocusedWindowTargetsLocked(nsecs_t currentTime,
-        const EventEntry* entry, nsecs_t* nextWakeupTime) {
-    mCurrentInputTargets.clear();
-
-    int32_t injectionResult;
-
-    // If there is no currently focused window and no focused application
-    // then drop the event.
-    if (! mFocusedWindow) {
-        if (mFocusedApplication) {
-#if DEBUG_FOCUS
-            LOGD("Waiting because there is no focused window but there is a "
-                    "focused application that may eventually add a window: %s.",
-                    getApplicationWindowLabelLocked(mFocusedApplication, NULL).string());
-#endif
-            injectionResult = handleTargetsNotReadyLocked(currentTime, entry,
-                    mFocusedApplication, NULL, nextWakeupTime);
-            goto Unresponsive;
-        }
-
-        LOGI("Dropping event because there is no focused window or focused application.");
-        injectionResult = INPUT_EVENT_INJECTION_FAILED;
-        goto Failed;
-    }
-
-    // Check permissions.
-    if (! checkInjectionPermission(mFocusedWindow, entry->injectionState)) {
-        injectionResult = INPUT_EVENT_INJECTION_PERMISSION_DENIED;
-        goto Failed;
-    }
-
-    // If the currently focused window is paused then keep waiting.
-    if (mFocusedWindow->paused) {
-#if DEBUG_FOCUS
-        LOGD("Waiting because focused window is paused.");
-#endif
-        injectionResult = handleTargetsNotReadyLocked(currentTime, entry,
-                mFocusedApplication, mFocusedWindow, nextWakeupTime);
-        goto Unresponsive;
-    }
-
-    // If the currently focused window is still working on previous events then keep waiting.
-    if (! isWindowFinishedWithPreviousInputLocked(mFocusedWindow)) {
-#if DEBUG_FOCUS
-        LOGD("Waiting because focused window still processing previous input.");
-#endif
-        injectionResult = handleTargetsNotReadyLocked(currentTime, entry,
-                mFocusedApplication, mFocusedWindow, nextWakeupTime);
-        goto Unresponsive;
-    }
-
-    // Success!  Output targets.
-    injectionResult = INPUT_EVENT_INJECTION_SUCCEEDED;
-    addWindowTargetLocked(mFocusedWindow, InputTarget::FLAG_FOREGROUND, BitSet32(0));
-
-    // Done.
-Failed:
-Unresponsive:
-    nsecs_t timeSpentWaitingForApplication = getTimeSpentWaitingForApplicationLocked(currentTime);
-    updateDispatchStatisticsLocked(currentTime, entry,
-            injectionResult, timeSpentWaitingForApplication);
-#if DEBUG_FOCUS
-    LOGD("findFocusedWindow finished: injectionResult=%d, "
-            "timeSpendWaitingForApplication=%0.1fms",
-            injectionResult, timeSpentWaitingForApplication / 1000000.0);
-#endif
-    return injectionResult;
-}
-
-int32_t InputDispatcher::findTouchedWindowTargetsLocked(nsecs_t currentTime,
-        const MotionEntry* entry, nsecs_t* nextWakeupTime) {
-    enum InjectionPermission {
-        INJECTION_PERMISSION_UNKNOWN,
-        INJECTION_PERMISSION_GRANTED,
-        INJECTION_PERMISSION_DENIED
-    };
-
-    mCurrentInputTargets.clear();
-
-    nsecs_t startTime = now();
-
-    // For security reasons, we defer updating the touch state until we are sure that
-    // event injection will be allowed.
-    //
-    // FIXME In the original code, screenWasOff could never be set to true.
-    //       The reason is that the POLICY_FLAG_WOKE_HERE
-    //       and POLICY_FLAG_BRIGHT_HERE flags were set only when preprocessing raw
-    //       EV_KEY, EV_REL and EV_ABS events.  As it happens, the touch event was
-    //       actually enqueued using the policyFlags that appeared in the final EV_SYN
-    //       events upon which no preprocessing took place.  So policyFlags was always 0.
-    //       In the new native input dispatcher we're a bit more careful about event
-    //       preprocessing so the touches we receive can actually have non-zero policyFlags.
-    //       Unfortunately we obtain undesirable behavior.
-    //
-    //       Here's what happens:
-    //
-    //       When the device dims in anticipation of going to sleep, touches
-    //       in windows which have FLAG_TOUCHABLE_WHEN_WAKING cause
-    //       the device to brighten and reset the user activity timer.
-    //       Touches on other windows (such as the launcher window)
-    //       are dropped.  Then after a moment, the device goes to sleep.  Oops.
-    //
-    //       Also notice how screenWasOff was being initialized using POLICY_FLAG_BRIGHT_HERE
-    //       instead of POLICY_FLAG_WOKE_HERE...
-    //
-    bool screenWasOff = false; // original policy: policyFlags & POLICY_FLAG_BRIGHT_HERE;
-
-    int32_t action = entry->action;
-    int32_t maskedAction = action & AMOTION_EVENT_ACTION_MASK;
-
-    // Update the touch state as needed based on the properties of the touch event.
-    int32_t injectionResult = INPUT_EVENT_INJECTION_PENDING;
-    InjectionPermission injectionPermission = INJECTION_PERMISSION_UNKNOWN;
-    if (maskedAction == AMOTION_EVENT_ACTION_DOWN) {
-        mTempTouchState.reset();
-        mTempTouchState.down = true;
-    } else {
-        mTempTouchState.copyFrom(mTouchState);
-    }
-
-    bool isSplit = mTempTouchState.split && mTempTouchState.down;
-    if (maskedAction == AMOTION_EVENT_ACTION_DOWN
-            || (isSplit && maskedAction == AMOTION_EVENT_ACTION_POINTER_DOWN)) {
-        /* Case 1: New splittable pointer going down. */
-
-        int32_t pointerIndex = getMotionEventActionPointerIndex(action);
-        int32_t x = int32_t(entry->firstSample.pointerCoords[pointerIndex].x);
-        int32_t y = int32_t(entry->firstSample.pointerCoords[pointerIndex].y);
-        const InputWindow* newTouchedWindow = NULL;
-        const InputWindow* topErrorWindow = NULL;
-
-        // Traverse windows from front to back to find touched window and outside targets.
-        size_t numWindows = mWindows.size();
-        for (size_t i = 0; i < numWindows; i++) {
-            const InputWindow* window = & mWindows.editItemAt(i);
-            int32_t flags = window->layoutParamsFlags;
-
-            if (flags & InputWindow::FLAG_SYSTEM_ERROR) {
-                if (! topErrorWindow) {
-                    topErrorWindow = window;
-                }
-            }
-
-            if (window->visible) {
-                if (! (flags & InputWindow::FLAG_NOT_TOUCHABLE)) {
-                    bool isTouchModal = (flags & (InputWindow::FLAG_NOT_FOCUSABLE
-                            | InputWindow::FLAG_NOT_TOUCH_MODAL)) == 0;
-                    if (isTouchModal || window->touchableAreaContainsPoint(x, y)) {
-                        if (! screenWasOff || flags & InputWindow::FLAG_TOUCHABLE_WHEN_WAKING) {
-                            newTouchedWindow = window;
-                        }
-                        break; // found touched window, exit window loop
-                    }
-                }
-
-                if (maskedAction == AMOTION_EVENT_ACTION_DOWN
-                        && (flags & InputWindow::FLAG_WATCH_OUTSIDE_TOUCH)) {
-                    int32_t outsideTargetFlags = InputTarget::FLAG_OUTSIDE;
-                    if (isWindowObscuredAtPointLocked(window, x, y)) {
-                        outsideTargetFlags |= InputTarget::FLAG_WINDOW_IS_OBSCURED;
-                    }
-
-                    mTempTouchState.addOrUpdateWindow(window, outsideTargetFlags, BitSet32(0));
-                }
-            }
-        }
-
-        // If there is an error window but it is not taking focus (typically because
-        // it is invisible) then wait for it.  Any other focused window may in
-        // fact be in ANR state.
-        if (topErrorWindow && newTouchedWindow != topErrorWindow) {
-#if DEBUG_FOCUS
-            LOGD("Waiting because system error window is pending.");
-#endif
-            injectionResult = handleTargetsNotReadyLocked(currentTime, entry,
-                    NULL, NULL, nextWakeupTime);
-            injectionPermission = INJECTION_PERMISSION_UNKNOWN;
-            goto Unresponsive;
-        }
-
-        // Figure out whether splitting will be allowed for this window.
-        if (newTouchedWindow && newTouchedWindow->supportsSplitTouch()) {
-            // New window supports splitting.
-            isSplit = true;
-        } else if (isSplit) {
-            // New window does not support splitting but we have already split events.
-            // Assign the pointer to the first foreground window we find.
-            // (May be NULL which is why we put this code block before the next check.)
-            newTouchedWindow = mTempTouchState.getFirstForegroundWindow();
-        }
-
-        // If we did not find a touched window then fail.
-        if (! newTouchedWindow) {
-            if (mFocusedApplication) {
-#if DEBUG_FOCUS
-                LOGD("Waiting because there is no touched window but there is a "
-                        "focused application that may eventually add a new window: %s.",
-                        getApplicationWindowLabelLocked(mFocusedApplication, NULL).string());
-#endif
-                injectionResult = handleTargetsNotReadyLocked(currentTime, entry,
-                        mFocusedApplication, NULL, nextWakeupTime);
-                goto Unresponsive;
-            }
-
-            LOGI("Dropping event because there is no touched window or focused application.");
-            injectionResult = INPUT_EVENT_INJECTION_FAILED;
-            goto Failed;
-        }
-
-        // Set target flags.
-        int32_t targetFlags = InputTarget::FLAG_FOREGROUND;
-        if (isSplit) {
-            targetFlags |= InputTarget::FLAG_SPLIT;
-        }
-        if (isWindowObscuredAtPointLocked(newTouchedWindow, x, y)) {
-            targetFlags |= InputTarget::FLAG_WINDOW_IS_OBSCURED;
-        }
-
-        // Update the temporary touch state.
-        BitSet32 pointerIds;
-        if (isSplit) {
-            uint32_t pointerId = entry->pointerIds[pointerIndex];
-            pointerIds.markBit(pointerId);
-        }
-        mTempTouchState.addOrUpdateWindow(newTouchedWindow, targetFlags, pointerIds);
-    } else {
-        /* Case 2: Pointer move, up, cancel or non-splittable pointer down. */
-
-        // If the pointer is not currently down, then ignore the event.
-        if (! mTempTouchState.down) {
-#if DEBUG_INPUT_DISPATCHER_POLICY
-            LOGD("Dropping event because the pointer is not down or we previously "
-                    "dropped the pointer down event.");
-#endif
-            injectionResult = INPUT_EVENT_INJECTION_FAILED;
-            goto Failed;
-        }
-    }
-
-    // Check permission to inject into all touched foreground windows and ensure there
-    // is at least one touched foreground window.
-    {
-        bool haveForegroundWindow = false;
-        for (size_t i = 0; i < mTempTouchState.windows.size(); i++) {
-            const TouchedWindow& touchedWindow = mTempTouchState.windows[i];
-            if (touchedWindow.targetFlags & InputTarget::FLAG_FOREGROUND) {
-                haveForegroundWindow = true;
-                if (! checkInjectionPermission(touchedWindow.window, entry->injectionState)) {
-                    injectionResult = INPUT_EVENT_INJECTION_PERMISSION_DENIED;
-                    injectionPermission = INJECTION_PERMISSION_DENIED;
-                    goto Failed;
-                }
-            }
-        }
-        if (! haveForegroundWindow) {
-#if DEBUG_INPUT_DISPATCHER_POLICY
-            LOGD("Dropping event because there is no touched foreground window to receive it.");
-#endif
-            injectionResult = INPUT_EVENT_INJECTION_FAILED;
-            goto Failed;
-        }
-
-        // Permission granted to injection into all touched foreground windows.
-        injectionPermission = INJECTION_PERMISSION_GRANTED;
-    }
-
-    // Ensure all touched foreground windows are ready for new input.
-    for (size_t i = 0; i < mTempTouchState.windows.size(); i++) {
-        const TouchedWindow& touchedWindow = mTempTouchState.windows[i];
-        if (touchedWindow.targetFlags & InputTarget::FLAG_FOREGROUND) {
-            // If the touched window is paused then keep waiting.
-            if (touchedWindow.window->paused) {
-#if DEBUG_INPUT_DISPATCHER_POLICY
-                LOGD("Waiting because touched window is paused.");
-#endif
-                injectionResult = handleTargetsNotReadyLocked(currentTime, entry,
-                        NULL, touchedWindow.window, nextWakeupTime);
-                goto Unresponsive;
-            }
-
-            // If the touched window is still working on previous events then keep waiting.
-            if (! isWindowFinishedWithPreviousInputLocked(touchedWindow.window)) {
-#if DEBUG_FOCUS
-                LOGD("Waiting because touched window still processing previous input.");
-#endif
-                injectionResult = handleTargetsNotReadyLocked(currentTime, entry,
-                        NULL, touchedWindow.window, nextWakeupTime);
-                goto Unresponsive;
-            }
-        }
-    }
-
-    // If this is the first pointer going down and the touched window has a wallpaper
-    // then also add the touched wallpaper windows so they are locked in for the duration
-    // of the touch gesture.
-    if (maskedAction == AMOTION_EVENT_ACTION_DOWN) {
-        const InputWindow* foregroundWindow = mTempTouchState.getFirstForegroundWindow();
-        if (foregroundWindow->hasWallpaper) {
-            for (size_t i = 0; i < mWindows.size(); i++) {
-                const InputWindow* window = & mWindows[i];
-                if (window->layoutParamsType == InputWindow::TYPE_WALLPAPER) {
-                    mTempTouchState.addOrUpdateWindow(window,
-                            InputTarget::FLAG_WINDOW_IS_OBSCURED, BitSet32(0));
-                }
-            }
-        }
-    }
-
-    // Success!  Output targets.
-    injectionResult = INPUT_EVENT_INJECTION_SUCCEEDED;
-
-    for (size_t i = 0; i < mTempTouchState.windows.size(); i++) {
-        const TouchedWindow& touchedWindow = mTempTouchState.windows.itemAt(i);
-        addWindowTargetLocked(touchedWindow.window, touchedWindow.targetFlags,
-                touchedWindow.pointerIds);
-    }
-
-    // Drop the outside touch window since we will not care about them in the next iteration.
-    mTempTouchState.removeOutsideTouchWindows();
-
-Failed:
-    // Check injection permission once and for all.
-    if (injectionPermission == INJECTION_PERMISSION_UNKNOWN) {
-        if (checkInjectionPermission(NULL, entry->injectionState)) {
-            injectionPermission = INJECTION_PERMISSION_GRANTED;
-        } else {
-            injectionPermission = INJECTION_PERMISSION_DENIED;
-        }
-    }
-
-    // Update final pieces of touch state if the injector had permission.
-    if (injectionPermission == INJECTION_PERMISSION_GRANTED) {
-        if (maskedAction == AMOTION_EVENT_ACTION_UP
-                || maskedAction == AMOTION_EVENT_ACTION_CANCEL) {
-            // All pointers up or canceled.
-            mTempTouchState.reset();
-        } else if (maskedAction == AMOTION_EVENT_ACTION_DOWN) {
-            // First pointer went down.
-            if (mTouchState.down) {
-#if DEBUG_FOCUS
-                LOGD("Pointer down received while already down.");
-#endif
-            }
-        } else if (maskedAction == AMOTION_EVENT_ACTION_POINTER_UP) {
-            // One pointer went up.
-            if (isSplit) {
-                int32_t pointerIndex = getMotionEventActionPointerIndex(action);
-                uint32_t pointerId = entry->pointerIds[pointerIndex];
-
-                for (size_t i = 0; i < mTempTouchState.windows.size(); ) {
-                    TouchedWindow& touchedWindow = mTempTouchState.windows.editItemAt(i);
-                    if (touchedWindow.targetFlags & InputTarget::FLAG_SPLIT) {
-                        touchedWindow.pointerIds.clearBit(pointerId);
-                        if (touchedWindow.pointerIds.isEmpty()) {
-                            mTempTouchState.windows.removeAt(i);
-                            continue;
-                        }
-                    }
-                    i += 1;
-                }
-            }
-        }
-
-        // Save changes to touch state.
-        mTouchState.copyFrom(mTempTouchState);
-    } else {
-#if DEBUG_FOCUS
-        LOGD("Not updating touch focus because injection was denied.");
-#endif
-    }
-
-Unresponsive:
-    // Reset temporary touch state to ensure we release unnecessary references to input channels.
-    mTempTouchState.reset();
-
-    nsecs_t timeSpentWaitingForApplication = getTimeSpentWaitingForApplicationLocked(currentTime);
-    updateDispatchStatisticsLocked(currentTime, entry,
-            injectionResult, timeSpentWaitingForApplication);
-#if DEBUG_FOCUS
-    LOGD("findTouchedWindow finished: injectionResult=%d, injectionPermission=%d, "
-            "timeSpentWaitingForApplication=%0.1fms",
-            injectionResult, injectionPermission, timeSpentWaitingForApplication / 1000000.0);
-#endif
-    return injectionResult;
-}
-
-void InputDispatcher::addWindowTargetLocked(const InputWindow* window, int32_t targetFlags,
-        BitSet32 pointerIds) {
-    mCurrentInputTargets.push();
-
-    InputTarget& target = mCurrentInputTargets.editTop();
-    target.inputChannel = window->inputChannel;
-    target.flags = targetFlags;
-    target.xOffset = - window->frameLeft;
-    target.yOffset = - window->frameTop;
-    target.pointerIds = pointerIds;
-}
-
-void InputDispatcher::addMonitoringTargetsLocked() {
-    for (size_t i = 0; i < mMonitoringChannels.size(); i++) {
-        mCurrentInputTargets.push();
-
-        InputTarget& target = mCurrentInputTargets.editTop();
-        target.inputChannel = mMonitoringChannels[i];
-        target.flags = 0;
-        target.xOffset = 0;
-        target.yOffset = 0;
-    }
-}
-
-bool InputDispatcher::checkInjectionPermission(const InputWindow* window,
-        const InjectionState* injectionState) {
-    if (injectionState
-            && (window == NULL || window->ownerUid != injectionState->injectorUid)
-            && !hasInjectionPermission(injectionState->injectorPid, injectionState->injectorUid)) {
-        if (window) {
-            LOGW("Permission denied: injecting event from pid %d uid %d to window "
-                    "with input channel %s owned by uid %d",
-                    injectionState->injectorPid, injectionState->injectorUid,
-                    window->inputChannel->getName().string(),
-                    window->ownerUid);
-        } else {
-            LOGW("Permission denied: injecting event from pid %d uid %d",
-                    injectionState->injectorPid, injectionState->injectorUid);
-        }
-        return false;
-    }
-    return true;
-}
-
-bool InputDispatcher::isWindowObscuredAtPointLocked(
-        const InputWindow* window, int32_t x, int32_t y) const {
-    size_t numWindows = mWindows.size();
-    for (size_t i = 0; i < numWindows; i++) {
-        const InputWindow* other = & mWindows.itemAt(i);
-        if (other == window) {
-            break;
-        }
-        if (other->visible && ! other->isTrustedOverlay() && other->frameContainsPoint(x, y)) {
-            return true;
-        }
-    }
-    return false;
-}
-
-bool InputDispatcher::isWindowFinishedWithPreviousInputLocked(const InputWindow* window) {
-    ssize_t connectionIndex = getConnectionIndexLocked(window->inputChannel);
-    if (connectionIndex >= 0) {
-        sp<Connection> connection = mConnectionsByReceiveFd.valueAt(connectionIndex);
-        return connection->outboundQueue.isEmpty();
-    } else {
-        return true;
-    }
-}
-
-String8 InputDispatcher::getApplicationWindowLabelLocked(const InputApplication* application,
-        const InputWindow* window) {
-    if (application) {
-        if (window) {
-            String8 label(application->name);
-            label.append(" - ");
-            label.append(window->name);
-            return label;
-        } else {
-            return application->name;
-        }
-    } else if (window) {
-        return window->name;
-    } else {
-        return String8("<unknown application or window>");
-    }
-}
-
-void InputDispatcher::pokeUserActivityLocked(const EventEntry* eventEntry) {
-    int32_t eventType = POWER_MANAGER_BUTTON_EVENT;
-    switch (eventEntry->type) {
-    case EventEntry::TYPE_MOTION: {
-        const MotionEntry* motionEntry = static_cast<const MotionEntry*>(eventEntry);
-        if (motionEntry->action == AMOTION_EVENT_ACTION_CANCEL) {
-            return;
-        }
-
-        if (motionEntry->source & AINPUT_SOURCE_CLASS_POINTER) {
-            eventType = POWER_MANAGER_TOUCH_EVENT;
-        }
-        break;
-    }
-    case EventEntry::TYPE_KEY: {
-        const KeyEntry* keyEntry = static_cast<const KeyEntry*>(eventEntry);
-        if (keyEntry->flags & AKEY_EVENT_FLAG_CANCELED) {
-            return;
-        }
-        break;
-    }
-    }
-
-    CommandEntry* commandEntry = postCommandLocked(
-            & InputDispatcher::doPokeUserActivityLockedInterruptible);
-    commandEntry->eventTime = eventEntry->eventTime;
-    commandEntry->userActivityEventType = eventType;
-}
-
-void InputDispatcher::prepareDispatchCycleLocked(nsecs_t currentTime,
-        const sp<Connection>& connection, EventEntry* eventEntry, const InputTarget* inputTarget,
-        bool resumeWithAppendedMotionSample) {
-#if DEBUG_DISPATCH_CYCLE
-    LOGD("channel '%s' ~ prepareDispatchCycle - flags=%d, "
-            "xOffset=%f, yOffset=%f, "
-            "windowType=%d, pointerIds=0x%x, "
-            "resumeWithAppendedMotionSample=%s",
-            connection->getInputChannelName(), inputTarget->flags,
-            inputTarget->xOffset, inputTarget->yOffset,
-            inputTarget->windowType, inputTarget->pointerIds.value,
-            toString(resumeWithAppendedMotionSample));
-#endif
-
-    // Make sure we are never called for streaming when splitting across multiple windows.
-    bool isSplit = inputTarget->flags & InputTarget::FLAG_SPLIT;
-    assert(! (resumeWithAppendedMotionSample && isSplit));
-
-    // Skip this event if the connection status is not normal.
-    // We don't want to enqueue additional outbound events if the connection is broken.
-    if (connection->status != Connection::STATUS_NORMAL) {
-#if DEBUG_DISPATCH_CYCLE
-        LOGD("channel '%s' ~ Dropping event because the channel status is %s",
-                connection->getInputChannelName(), connection->getStatusLabel());
-#endif
-        return;
-    }
-
-    // Split a motion event if needed.
-    if (isSplit) {
-        assert(eventEntry->type == EventEntry::TYPE_MOTION);
-
-        MotionEntry* originalMotionEntry = static_cast<MotionEntry*>(eventEntry);
-        if (inputTarget->pointerIds.count() != originalMotionEntry->pointerCount) {
-            MotionEntry* splitMotionEntry = splitMotionEvent(
-                    originalMotionEntry, inputTarget->pointerIds);
-#if DEBUG_FOCUS
-            LOGD("channel '%s' ~ Split motion event.",
-                    connection->getInputChannelName());
-            logOutboundMotionDetailsLocked("  ", splitMotionEntry);
-#endif
-            eventEntry = splitMotionEntry;
-        }
-    }
-
-    // Resume the dispatch cycle with a freshly appended motion sample.
-    // First we check that the last dispatch entry in the outbound queue is for the same
-    // motion event to which we appended the motion sample.  If we find such a dispatch
-    // entry, and if it is currently in progress then we try to stream the new sample.
-    bool wasEmpty = connection->outboundQueue.isEmpty();
-
-    if (! wasEmpty && resumeWithAppendedMotionSample) {
-        DispatchEntry* motionEventDispatchEntry =
-                connection->findQueuedDispatchEntryForEvent(eventEntry);
-        if (motionEventDispatchEntry) {
-            // If the dispatch entry is not in progress, then we must be busy dispatching an
-            // earlier event.  Not a problem, the motion event is on the outbound queue and will
-            // be dispatched later.
-            if (! motionEventDispatchEntry->inProgress) {
-#if DEBUG_BATCHING
-                LOGD("channel '%s' ~ Not streaming because the motion event has "
-                        "not yet been dispatched.  "
-                        "(Waiting for earlier events to be consumed.)",
-                        connection->getInputChannelName());
-#endif
-                return;
-            }
-
-            // If the dispatch entry is in progress but it already has a tail of pending
-            // motion samples, then it must mean that the shared memory buffer filled up.
-            // Not a problem, when this dispatch cycle is finished, we will eventually start
-            // a new dispatch cycle to process the tail and that tail includes the newly
-            // appended motion sample.
-            if (motionEventDispatchEntry->tailMotionSample) {
-#if DEBUG_BATCHING
-                LOGD("channel '%s' ~ Not streaming because no new samples can "
-                        "be appended to the motion event in this dispatch cycle.  "
-                        "(Waiting for next dispatch cycle to start.)",
-                        connection->getInputChannelName());
-#endif
-                return;
-            }
-
-            // The dispatch entry is in progress and is still potentially open for streaming.
-            // Try to stream the new motion sample.  This might fail if the consumer has already
-            // consumed the motion event (or if the channel is broken).
-            MotionEntry* motionEntry = static_cast<MotionEntry*>(eventEntry);
-            MotionSample* appendedMotionSample = motionEntry->lastSample;
-            status_t status = connection->inputPublisher.appendMotionSample(
-                    appendedMotionSample->eventTime, appendedMotionSample->pointerCoords);
-            if (status == OK) {
-#if DEBUG_BATCHING
-                LOGD("channel '%s' ~ Successfully streamed new motion sample.",
-                        connection->getInputChannelName());
-#endif
-                return;
-            }
-
-#if DEBUG_BATCHING
-            if (status == NO_MEMORY) {
-                LOGD("channel '%s' ~ Could not append motion sample to currently "
-                        "dispatched move event because the shared memory buffer is full.  "
-                        "(Waiting for next dispatch cycle to start.)",
-                        connection->getInputChannelName());
-            } else if (status == status_t(FAILED_TRANSACTION)) {
-                LOGD("channel '%s' ~ Could not append motion sample to currently "
-                        "dispatched move event because the event has already been consumed.  "
-                        "(Waiting for next dispatch cycle to start.)",
-                        connection->getInputChannelName());
-            } else {
-                LOGD("channel '%s' ~ Could not append motion sample to currently "
-                        "dispatched move event due to an error, status=%d.  "
-                        "(Waiting for next dispatch cycle to start.)",
-                        connection->getInputChannelName(), status);
-            }
-#endif
-            // Failed to stream.  Start a new tail of pending motion samples to dispatch
-            // in the next cycle.
-            motionEventDispatchEntry->tailMotionSample = appendedMotionSample;
-            return;
-        }
-    }
-
-    // This is a new event.
-    // Enqueue a new dispatch entry onto the outbound queue for this connection.
-    DispatchEntry* dispatchEntry = mAllocator.obtainDispatchEntry(eventEntry, // increments ref
-            inputTarget->flags, inputTarget->xOffset, inputTarget->yOffset);
-    if (dispatchEntry->hasForegroundTarget()) {
-        incrementPendingForegroundDispatchesLocked(eventEntry);
-    }
-
-    // Handle the case where we could not stream a new motion sample because the consumer has
-    // already consumed the motion event (otherwise the corresponding dispatch entry would
-    // still be in the outbound queue for this connection).  We set the head motion sample
-    // to the list starting with the newly appended motion sample.
-    if (resumeWithAppendedMotionSample) {
-#if DEBUG_BATCHING
-        LOGD("channel '%s' ~ Preparing a new dispatch cycle for additional motion samples "
-                "that cannot be streamed because the motion event has already been consumed.",
-                connection->getInputChannelName());
-#endif
-        MotionSample* appendedMotionSample = static_cast<MotionEntry*>(eventEntry)->lastSample;
-        dispatchEntry->headMotionSample = appendedMotionSample;
-    }
-
-    // Enqueue the dispatch entry.
-    connection->outboundQueue.enqueueAtTail(dispatchEntry);
-
-    // If the outbound queue was previously empty, start the dispatch cycle going.
-    if (wasEmpty) {
-        activateConnectionLocked(connection.get());
-        startDispatchCycleLocked(currentTime, connection);
-    }
-}
-
-void InputDispatcher::startDispatchCycleLocked(nsecs_t currentTime,
-        const sp<Connection>& connection) {
-#if DEBUG_DISPATCH_CYCLE
-    LOGD("channel '%s' ~ startDispatchCycle",
-            connection->getInputChannelName());
-#endif
-
-    assert(connection->status == Connection::STATUS_NORMAL);
-    assert(! connection->outboundQueue.isEmpty());
-
-    DispatchEntry* dispatchEntry = connection->outboundQueue.headSentinel.next;
-    assert(! dispatchEntry->inProgress);
-
-    // Mark the dispatch entry as in progress.
-    dispatchEntry->inProgress = true;
-
-    // Update the connection's input state.
-    EventEntry* eventEntry = dispatchEntry->eventEntry;
-    InputState::Consistency consistency = connection->inputState.trackEvent(eventEntry);
-
-#if FILTER_INPUT_EVENTS
-    // Filter out inconsistent sequences of input events.
-    // The input system may drop or inject events in a way that could violate implicit
-    // invariants on input state and potentially cause an application to crash
-    // or think that a key or pointer is stuck down.  Technically we make no guarantees
-    // of consistency but it would be nice to improve on this where possible.
-    // XXX: This code is a proof of concept only.  Not ready for prime time.
-    if (consistency == InputState::TOLERABLE) {
-#if DEBUG_DISPATCH_CYCLE
-        LOGD("channel '%s' ~ Sending an event that is inconsistent with the connection's "
-                "current input state but that is likely to be tolerated by the application.",
-                connection->getInputChannelName());
-#endif
-    } else if (consistency == InputState::BROKEN) {
-        LOGI("channel '%s' ~ Dropping an event that is inconsistent with the connection's "
-                "current input state and that is likely to cause the application to crash.",
-                connection->getInputChannelName());
-        startNextDispatchCycleLocked(currentTime, connection);
-        return;
-    }
-#endif
-
-    // Publish the event.
-    status_t status;
-    switch (eventEntry->type) {
-    case EventEntry::TYPE_KEY: {
-        KeyEntry* keyEntry = static_cast<KeyEntry*>(eventEntry);
-
-        // Apply target flags.
-        int32_t action = keyEntry->action;
-        int32_t flags = keyEntry->flags;
-
-        // Publish the key event.
-        status = connection->inputPublisher.publishKeyEvent(keyEntry->deviceId, keyEntry->source,
-                action, flags, keyEntry->keyCode, keyEntry->scanCode,
-                keyEntry->metaState, keyEntry->repeatCount, keyEntry->downTime,
-                keyEntry->eventTime);
-
-        if (status) {
-            LOGE("channel '%s' ~ Could not publish key event, "
-                    "status=%d", connection->getInputChannelName(), status);
-            abortBrokenDispatchCycleLocked(currentTime, connection);
-            return;
-        }
-        break;
-    }
-
-    case EventEntry::TYPE_MOTION: {
-        MotionEntry* motionEntry = static_cast<MotionEntry*>(eventEntry);
-
-        // Apply target flags.
-        int32_t action = motionEntry->action;
-        int32_t flags = motionEntry->flags;
-        if (dispatchEntry->targetFlags & InputTarget::FLAG_OUTSIDE) {
-            action = AMOTION_EVENT_ACTION_OUTSIDE;
-        }
-        if (dispatchEntry->targetFlags & InputTarget::FLAG_WINDOW_IS_OBSCURED) {
-            flags |= AMOTION_EVENT_FLAG_WINDOW_IS_OBSCURED;
-        }
-
-        // If headMotionSample is non-NULL, then it points to the first new sample that we
-        // were unable to dispatch during the previous cycle so we resume dispatching from
-        // that point in the list of motion samples.
-        // Otherwise, we just start from the first sample of the motion event.
-        MotionSample* firstMotionSample = dispatchEntry->headMotionSample;
-        if (! firstMotionSample) {
-            firstMotionSample = & motionEntry->firstSample;
-        }
-
-        // Set the X and Y offset depending on the input source.
-        float xOffset, yOffset;
-        if (motionEntry->source & AINPUT_SOURCE_CLASS_POINTER) {
-            xOffset = dispatchEntry->xOffset;
-            yOffset = dispatchEntry->yOffset;
-        } else {
-            xOffset = 0.0f;
-            yOffset = 0.0f;
-        }
-
-        // Publish the motion event and the first motion sample.
-        status = connection->inputPublisher.publishMotionEvent(motionEntry->deviceId,
-                motionEntry->source, action, flags, motionEntry->edgeFlags, motionEntry->metaState,
-                xOffset, yOffset,
-                motionEntry->xPrecision, motionEntry->yPrecision,
-                motionEntry->downTime, firstMotionSample->eventTime,
-                motionEntry->pointerCount, motionEntry->pointerIds,
-                firstMotionSample->pointerCoords);
-
-        if (status) {
-            LOGE("channel '%s' ~ Could not publish motion event, "
-                    "status=%d", connection->getInputChannelName(), status);
-            abortBrokenDispatchCycleLocked(currentTime, connection);
-            return;
-        }
-
-        // Append additional motion samples.
-        MotionSample* nextMotionSample = firstMotionSample->next;
-        for (; nextMotionSample != NULL; nextMotionSample = nextMotionSample->next) {
-            status = connection->inputPublisher.appendMotionSample(
-                    nextMotionSample->eventTime, nextMotionSample->pointerCoords);
-            if (status == NO_MEMORY) {
-#if DEBUG_DISPATCH_CYCLE
-                    LOGD("channel '%s' ~ Shared memory buffer full.  Some motion samples will "
-                            "be sent in the next dispatch cycle.",
-                            connection->getInputChannelName());
-#endif
-                break;
-            }
-            if (status != OK) {
-                LOGE("channel '%s' ~ Could not append motion sample "
-                        "for a reason other than out of memory, status=%d",
-                        connection->getInputChannelName(), status);
-                abortBrokenDispatchCycleLocked(currentTime, connection);
-                return;
-            }
-        }
-
-        // Remember the next motion sample that we could not dispatch, in case we ran out
-        // of space in the shared memory buffer.
-        dispatchEntry->tailMotionSample = nextMotionSample;
-        break;
-    }
-
-    default: {
-        assert(false);
-    }
-    }
-
-    // Send the dispatch signal.
-    status = connection->inputPublisher.sendDispatchSignal();
-    if (status) {
-        LOGE("channel '%s' ~ Could not send dispatch signal, status=%d",
-                connection->getInputChannelName(), status);
-        abortBrokenDispatchCycleLocked(currentTime, connection);
-        return;
-    }
-
-    // Record information about the newly started dispatch cycle.
-    connection->lastEventTime = eventEntry->eventTime;
-    connection->lastDispatchTime = currentTime;
-
-    // Notify other system components.
-    onDispatchCycleStartedLocked(currentTime, connection);
-}
-
-void InputDispatcher::finishDispatchCycleLocked(nsecs_t currentTime,
-        const sp<Connection>& connection, bool handled) {
-#if DEBUG_DISPATCH_CYCLE
-    LOGD("channel '%s' ~ finishDispatchCycle - %01.1fms since event, "
-            "%01.1fms since dispatch, handled=%s",
-            connection->getInputChannelName(),
-            connection->getEventLatencyMillis(currentTime),
-            connection->getDispatchLatencyMillis(currentTime),
-            toString(handled));
-#endif
-
-    if (connection->status == Connection::STATUS_BROKEN
-            || connection->status == Connection::STATUS_ZOMBIE) {
-        return;
-    }
-
-    // Reset the publisher since the event has been consumed.
-    // We do this now so that the publisher can release some of its internal resources
-    // while waiting for the next dispatch cycle to begin.
-    status_t status = connection->inputPublisher.reset();
-    if (status) {
-        LOGE("channel '%s' ~ Could not reset publisher, status=%d",
-                connection->getInputChannelName(), status);
-        abortBrokenDispatchCycleLocked(currentTime, connection);
-        return;
-    }
-
-    // Notify other system components and prepare to start the next dispatch cycle.
-    onDispatchCycleFinishedLocked(currentTime, connection, handled);
-}
-
-void InputDispatcher::startNextDispatchCycleLocked(nsecs_t currentTime,
-        const sp<Connection>& connection) {
-    // Start the next dispatch cycle for this connection.
-    while (! connection->outboundQueue.isEmpty()) {
-        DispatchEntry* dispatchEntry = connection->outboundQueue.headSentinel.next;
-        if (dispatchEntry->inProgress) {
-             // Finish or resume current event in progress.
-            if (dispatchEntry->tailMotionSample) {
-                // We have a tail of undispatched motion samples.
-                // Reuse the same DispatchEntry and start a new cycle.
-                dispatchEntry->inProgress = false;
-                dispatchEntry->headMotionSample = dispatchEntry->tailMotionSample;
-                dispatchEntry->tailMotionSample = NULL;
-                startDispatchCycleLocked(currentTime, connection);
-                return;
-            }
-            // Finished.
-            connection->outboundQueue.dequeueAtHead();
-            if (dispatchEntry->hasForegroundTarget()) {
-                decrementPendingForegroundDispatchesLocked(dispatchEntry->eventEntry);
-            }
-            mAllocator.releaseDispatchEntry(dispatchEntry);
-        } else {
-            // If the head is not in progress, then we must have already dequeued the in
-            // progress event, which means we actually aborted it.
-            // So just start the next event for this connection.
-            startDispatchCycleLocked(currentTime, connection);
-            return;
-        }
-    }
-
-    // Outbound queue is empty, deactivate the connection.
-    deactivateConnectionLocked(connection.get());
-}
-
-void InputDispatcher::abortBrokenDispatchCycleLocked(nsecs_t currentTime,
-        const sp<Connection>& connection) {
-#if DEBUG_DISPATCH_CYCLE
-    LOGD("channel '%s' ~ abortBrokenDispatchCycle - broken=%s",
-            connection->getInputChannelName(), toString(broken));
-#endif
-
-    // Clear the outbound queue.
-    drainOutboundQueueLocked(connection.get());
-
-    // The connection appears to be unrecoverably broken.
-    // Ignore already broken or zombie connections.
-    if (connection->status == Connection::STATUS_NORMAL) {
-        connection->status = Connection::STATUS_BROKEN;
-
-        // Notify other system components.
-        onDispatchCycleBrokenLocked(currentTime, connection);
-    }
-}
-
-void InputDispatcher::drainOutboundQueueLocked(Connection* connection) {
-    while (! connection->outboundQueue.isEmpty()) {
-        DispatchEntry* dispatchEntry = connection->outboundQueue.dequeueAtHead();
-        if (dispatchEntry->hasForegroundTarget()) {
-            decrementPendingForegroundDispatchesLocked(dispatchEntry->eventEntry);
-        }
-        mAllocator.releaseDispatchEntry(dispatchEntry);
-    }
-
-    deactivateConnectionLocked(connection);
-}
-
-int InputDispatcher::handleReceiveCallback(int receiveFd, int events, void* data) {
-    InputDispatcher* d = static_cast<InputDispatcher*>(data);
-
-    { // acquire lock
-        AutoMutex _l(d->mLock);
-
-        ssize_t connectionIndex = d->mConnectionsByReceiveFd.indexOfKey(receiveFd);
-        if (connectionIndex < 0) {
-            LOGE("Received spurious receive callback for unknown input channel.  "
-                    "fd=%d, events=0x%x", receiveFd, events);
-            return 0; // remove the callback
-        }
-
-        nsecs_t currentTime = now();
-
-        sp<Connection> connection = d->mConnectionsByReceiveFd.valueAt(connectionIndex);
-        if (events & (ALOOPER_EVENT_ERROR | ALOOPER_EVENT_HANGUP)) {
-            LOGE("channel '%s' ~ Consumer closed input channel or an error occurred.  "
-                    "events=0x%x", connection->getInputChannelName(), events);
-            d->abortBrokenDispatchCycleLocked(currentTime, connection);
-            d->runCommandsLockedInterruptible();
-            return 0; // remove the callback
-        }
-
-        if (! (events & ALOOPER_EVENT_INPUT)) {
-            LOGW("channel '%s' ~ Received spurious callback for unhandled poll event.  "
-                    "events=0x%x", connection->getInputChannelName(), events);
-            return 1;
-        }
-
-        bool handled = false;
-        status_t status = connection->inputPublisher.receiveFinishedSignal(&handled);
-        if (status) {
-            LOGE("channel '%s' ~ Failed to receive finished signal.  status=%d",
-                    connection->getInputChannelName(), status);
-            d->abortBrokenDispatchCycleLocked(currentTime, connection);
-            d->runCommandsLockedInterruptible();
-            return 0; // remove the callback
-        }
-
-        d->finishDispatchCycleLocked(currentTime, connection, handled);
-        d->runCommandsLockedInterruptible();
-        return 1;
-    } // release lock
-}
-
-void InputDispatcher::synthesizeCancelationEventsForAllConnectionsLocked(
-        InputState::CancelationOptions options, const char* reason) {
-    for (size_t i = 0; i < mConnectionsByReceiveFd.size(); i++) {
-        synthesizeCancelationEventsForConnectionLocked(
-                mConnectionsByReceiveFd.valueAt(i), options, reason);
-    }
-}
-
-void InputDispatcher::synthesizeCancelationEventsForInputChannelLocked(
-        const sp<InputChannel>& channel, InputState::CancelationOptions options,
-        const char* reason) {
-    ssize_t index = getConnectionIndexLocked(channel);
-    if (index >= 0) {
-        synthesizeCancelationEventsForConnectionLocked(
-                mConnectionsByReceiveFd.valueAt(index), options, reason);
-    }
-}
-
-void InputDispatcher::synthesizeCancelationEventsForConnectionLocked(
-        const sp<Connection>& connection, InputState::CancelationOptions options,
-        const char* reason) {
-    nsecs_t currentTime = now();
-
-    mTempCancelationEvents.clear();
-    connection->inputState.synthesizeCancelationEvents(currentTime, & mAllocator,
-            mTempCancelationEvents, options);
-
-    if (! mTempCancelationEvents.isEmpty()
-            && connection->status != Connection::STATUS_BROKEN) {
-#if DEBUG_OUTBOUND_EVENT_DETAILS
-        LOGD("channel '%s' ~ Synthesized %d cancelation events to bring channel back in sync "
-                "with reality: %s, options=%d.",
-                connection->getInputChannelName(), mTempCancelationEvents.size(), reason, options);
-#endif
-        for (size_t i = 0; i < mTempCancelationEvents.size(); i++) {
-            EventEntry* cancelationEventEntry = mTempCancelationEvents.itemAt(i);
-            switch (cancelationEventEntry->type) {
-            case EventEntry::TYPE_KEY:
-                logOutboundKeyDetailsLocked("cancel - ",
-                        static_cast<KeyEntry*>(cancelationEventEntry));
-                break;
-            case EventEntry::TYPE_MOTION:
-                logOutboundMotionDetailsLocked("cancel - ",
-                        static_cast<MotionEntry*>(cancelationEventEntry));
-                break;
-            }
-
-            int32_t xOffset, yOffset;
-            const InputWindow* window = getWindowLocked(connection->inputChannel);
-            if (window) {
-                xOffset = -window->frameLeft;
-                yOffset = -window->frameTop;
-            } else {
-                xOffset = 0;
-                yOffset = 0;
-            }
-
-            DispatchEntry* cancelationDispatchEntry =
-                    mAllocator.obtainDispatchEntry(cancelationEventEntry, // increments ref
-                    0, xOffset, yOffset);
-            connection->outboundQueue.enqueueAtTail(cancelationDispatchEntry);
-
-            mAllocator.releaseEventEntry(cancelationEventEntry);
-        }
-
-        if (!connection->outboundQueue.headSentinel.next->inProgress) {
-            startDispatchCycleLocked(currentTime, connection);
-        }
-    }
-}
-
-InputDispatcher::MotionEntry*
-InputDispatcher::splitMotionEvent(const MotionEntry* originalMotionEntry, BitSet32 pointerIds) {
-    assert(pointerIds.value != 0);
-
-    uint32_t splitPointerIndexMap[MAX_POINTERS];
-    int32_t splitPointerIds[MAX_POINTERS];
-    PointerCoords splitPointerCoords[MAX_POINTERS];
-
-    uint32_t originalPointerCount = originalMotionEntry->pointerCount;
-    uint32_t splitPointerCount = 0;
-
-    for (uint32_t originalPointerIndex = 0; originalPointerIndex < originalPointerCount;
-            originalPointerIndex++) {
-        int32_t pointerId = uint32_t(originalMotionEntry->pointerIds[originalPointerIndex]);
-        if (pointerIds.hasBit(pointerId)) {
-            splitPointerIndexMap[splitPointerCount] = originalPointerIndex;
-            splitPointerIds[splitPointerCount] = pointerId;
-            splitPointerCoords[splitPointerCount] =
-                    originalMotionEntry->firstSample.pointerCoords[originalPointerIndex];
-            splitPointerCount += 1;
-        }
-    }
-    assert(splitPointerCount == pointerIds.count());
-
-    int32_t action = originalMotionEntry->action;
-    int32_t maskedAction = action & AMOTION_EVENT_ACTION_MASK;
-    if (maskedAction == AMOTION_EVENT_ACTION_POINTER_DOWN
-            || maskedAction == AMOTION_EVENT_ACTION_POINTER_UP) {
-        int32_t originalPointerIndex = getMotionEventActionPointerIndex(action);
-        int32_t pointerId = originalMotionEntry->pointerIds[originalPointerIndex];
-        if (pointerIds.hasBit(pointerId)) {
-            if (pointerIds.count() == 1) {
-                // The first/last pointer went down/up.
-                action = maskedAction == AMOTION_EVENT_ACTION_POINTER_DOWN
-                        ? AMOTION_EVENT_ACTION_DOWN : AMOTION_EVENT_ACTION_UP;
-            } else {
-                // A secondary pointer went down/up.
-                uint32_t splitPointerIndex = 0;
-                while (pointerId != splitPointerIds[splitPointerIndex]) {
-                    splitPointerIndex += 1;
-                }
-                action = maskedAction | (splitPointerIndex
-                        << AMOTION_EVENT_ACTION_POINTER_INDEX_SHIFT);
-            }
-        } else {
-            // An unrelated pointer changed.
-            action = AMOTION_EVENT_ACTION_MOVE;
-        }
-    }
-
-    MotionEntry* splitMotionEntry = mAllocator.obtainMotionEntry(
-            originalMotionEntry->eventTime,
-            originalMotionEntry->deviceId,
-            originalMotionEntry->source,
-            originalMotionEntry->policyFlags,
-            action,
-            originalMotionEntry->flags,
-            originalMotionEntry->metaState,
-            originalMotionEntry->edgeFlags,
-            originalMotionEntry->xPrecision,
-            originalMotionEntry->yPrecision,
-            originalMotionEntry->downTime,
-            splitPointerCount, splitPointerIds, splitPointerCoords);
-
-    for (MotionSample* originalMotionSample = originalMotionEntry->firstSample.next;
-            originalMotionSample != NULL; originalMotionSample = originalMotionSample->next) {
-        for (uint32_t splitPointerIndex = 0; splitPointerIndex < splitPointerCount;
-                splitPointerIndex++) {
-            uint32_t originalPointerIndex = splitPointerIndexMap[splitPointerIndex];
-            splitPointerCoords[splitPointerIndex] =
-                    originalMotionSample->pointerCoords[originalPointerIndex];
-        }
-
-        mAllocator.appendMotionSample(splitMotionEntry, originalMotionSample->eventTime,
-                splitPointerCoords);
-    }
-
-    return splitMotionEntry;
-}
-
-void InputDispatcher::notifyConfigurationChanged(nsecs_t eventTime) {
-#if DEBUG_INBOUND_EVENT_DETAILS
-    LOGD("notifyConfigurationChanged - eventTime=%lld", eventTime);
-#endif
-
-    bool needWake;
-    { // acquire lock
-        AutoMutex _l(mLock);
-
-        ConfigurationChangedEntry* newEntry = mAllocator.obtainConfigurationChangedEntry(eventTime);
-        needWake = enqueueInboundEventLocked(newEntry);
-    } // release lock
-
-    if (needWake) {
-        mLooper->wake();
-    }
-}
-
-void InputDispatcher::notifyKey(nsecs_t eventTime, int32_t deviceId, int32_t source,
-        uint32_t policyFlags, int32_t action, int32_t flags,
-        int32_t keyCode, int32_t scanCode, int32_t metaState, nsecs_t downTime) {
-#if DEBUG_INBOUND_EVENT_DETAILS
-    LOGD("notifyKey - eventTime=%lld, deviceId=%d, source=0x%x, policyFlags=0x%x, action=0x%x, "
-            "flags=0x%x, keyCode=0x%x, scanCode=0x%x, metaState=0x%x, downTime=%lld",
-            eventTime, deviceId, source, policyFlags, action, flags,
-            keyCode, scanCode, metaState, downTime);
-#endif
-    if (! validateKeyEvent(action)) {
-        return;
-    }
-
-    if ((policyFlags & POLICY_FLAG_VIRTUAL) || (flags & AKEY_EVENT_FLAG_VIRTUAL_HARD_KEY)) {
-        policyFlags |= POLICY_FLAG_VIRTUAL;
-        flags |= AKEY_EVENT_FLAG_VIRTUAL_HARD_KEY;
-    }
-
-    policyFlags |= POLICY_FLAG_TRUSTED;
-
-    KeyEvent event;
-    event.initialize(deviceId, source, action, flags, keyCode, scanCode,
-            metaState, 0, downTime, eventTime);
-
-    mPolicy->interceptKeyBeforeQueueing(&event, /*byref*/ policyFlags);
-
-    if (policyFlags & POLICY_FLAG_WOKE_HERE) {
-        flags |= AKEY_EVENT_FLAG_WOKE_HERE;
-    }
-
-    bool needWake;
-    { // acquire lock
-        AutoMutex _l(mLock);
-
-        int32_t repeatCount = 0;
-        KeyEntry* newEntry = mAllocator.obtainKeyEntry(eventTime,
-                deviceId, source, policyFlags, action, flags, keyCode, scanCode,
-                metaState, repeatCount, downTime);
-
-        needWake = enqueueInboundEventLocked(newEntry);
-    } // release lock
-
-    if (needWake) {
-        mLooper->wake();
-    }
-}
-
-void InputDispatcher::notifyMotion(nsecs_t eventTime, int32_t deviceId, int32_t source,
-        uint32_t policyFlags, int32_t action, int32_t flags, int32_t metaState, int32_t edgeFlags,
-        uint32_t pointerCount, const int32_t* pointerIds, const PointerCoords* pointerCoords,
-        float xPrecision, float yPrecision, nsecs_t downTime) {
-#if DEBUG_INBOUND_EVENT_DETAILS
-    LOGD("notifyMotion - eventTime=%lld, deviceId=%d, source=0x%x, policyFlags=0x%x, "
-            "action=0x%x, flags=0x%x, metaState=0x%x, edgeFlags=0x%x, "
-            "xPrecision=%f, yPrecision=%f, downTime=%lld",
-            eventTime, deviceId, source, policyFlags, action, flags, metaState, edgeFlags,
-            xPrecision, yPrecision, downTime);
-    for (uint32_t i = 0; i < pointerCount; i++) {
-        LOGD("  Pointer %d: id=%d, x=%f, y=%f, pressure=%f, size=%f, "
-                "touchMajor=%f, touchMinor=%f, toolMajor=%f, toolMinor=%f, "
-                "orientation=%f",
-                i, pointerIds[i], pointerCoords[i].x, pointerCoords[i].y,
-                pointerCoords[i].pressure, pointerCoords[i].size,
-                pointerCoords[i].touchMajor, pointerCoords[i].touchMinor,
-                pointerCoords[i].toolMajor, pointerCoords[i].toolMinor,
-                pointerCoords[i].orientation);
-    }
-#endif
-    if (! validateMotionEvent(action, pointerCount, pointerIds)) {
-        return;
-    }
-
-    policyFlags |= POLICY_FLAG_TRUSTED;
-    mPolicy->interceptGenericBeforeQueueing(eventTime, /*byref*/ policyFlags);
-
-    bool needWake;
-    { // acquire lock
-        AutoMutex _l(mLock);
-
-        // Attempt batching and streaming of move events.
-        if (action == AMOTION_EVENT_ACTION_MOVE) {
-            // BATCHING CASE
-            //
-            // Try to append a move sample to the tail of the inbound queue for this device.
-            // Give up if we encounter a non-move motion event for this device since that
-            // means we cannot append any new samples until a new motion event has started.
-            for (EventEntry* entry = mInboundQueue.tailSentinel.prev;
-                    entry != & mInboundQueue.headSentinel; entry = entry->prev) {
-                if (entry->type != EventEntry::TYPE_MOTION) {
-                    // Keep looking for motion events.
-                    continue;
-                }
-
-                MotionEntry* motionEntry = static_cast<MotionEntry*>(entry);
-                if (motionEntry->deviceId != deviceId) {
-                    // Keep looking for this device.
-                    continue;
-                }
-
-                if (motionEntry->action != AMOTION_EVENT_ACTION_MOVE
-                        || motionEntry->pointerCount != pointerCount
-                        || motionEntry->isInjected()) {
-                    // Last motion event in the queue for this device is not compatible for
-                    // appending new samples.  Stop here.
-                    goto NoBatchingOrStreaming;
-                }
-
-                // The last motion event is a move and is compatible for appending.
-                // Do the batching magic.
-                mAllocator.appendMotionSample(motionEntry, eventTime, pointerCoords);
-#if DEBUG_BATCHING
-                LOGD("Appended motion sample onto batch for most recent "
-                        "motion event for this device in the inbound queue.");
-#endif
-                return; // done!
-            }
-
-            // STREAMING CASE
-            //
-            // There is no pending motion event (of any kind) for this device in the inbound queue.
-            // Search the outbound queue for the current foreground targets to find a dispatched
-            // motion event that is still in progress.  If found, then, appen the new sample to
-            // that event and push it out to all current targets.  The logic in
-            // prepareDispatchCycleLocked takes care of the case where some targets may
-            // already have consumed the motion event by starting a new dispatch cycle if needed.
-            if (mCurrentInputTargetsValid) {
-                for (size_t i = 0; i < mCurrentInputTargets.size(); i++) {
-                    const InputTarget& inputTarget = mCurrentInputTargets[i];
-                    if ((inputTarget.flags & InputTarget::FLAG_FOREGROUND) == 0) {
-                        // Skip non-foreground targets.  We only want to stream if there is at
-                        // least one foreground target whose dispatch is still in progress.
-                        continue;
-                    }
-
-                    ssize_t connectionIndex = getConnectionIndexLocked(inputTarget.inputChannel);
-                    if (connectionIndex < 0) {
-                        // Connection must no longer be valid.
-                        continue;
-                    }
-
-                    sp<Connection> connection = mConnectionsByReceiveFd.valueAt(connectionIndex);
-                    if (connection->outboundQueue.isEmpty()) {
-                        // This foreground target has an empty outbound queue.
-                        continue;
-                    }
-
-                    DispatchEntry* dispatchEntry = connection->outboundQueue.headSentinel.next;
-                    if (! dispatchEntry->inProgress
-                            || dispatchEntry->eventEntry->type != EventEntry::TYPE_MOTION
-                            || dispatchEntry->isSplit()) {
-                        // No motion event is being dispatched, or it is being split across
-                        // windows in which case we cannot stream.
-                        continue;
-                    }
-
-                    MotionEntry* motionEntry = static_cast<MotionEntry*>(
-                            dispatchEntry->eventEntry);
-                    if (motionEntry->action != AMOTION_EVENT_ACTION_MOVE
-                            || motionEntry->deviceId != deviceId
-                            || motionEntry->pointerCount != pointerCount
-                            || motionEntry->isInjected()) {
-                        // The motion event is not compatible with this move.
-                        continue;
-                    }
-
-                    // Hurray!  This foreground target is currently dispatching a move event
-                    // that we can stream onto.  Append the motion sample and resume dispatch.
-                    mAllocator.appendMotionSample(motionEntry, eventTime, pointerCoords);
-#if DEBUG_BATCHING
-                    LOGD("Appended motion sample onto batch for most recently dispatched "
-                            "motion event for this device in the outbound queues.  "
-                            "Attempting to stream the motion sample.");
-#endif
-                    nsecs_t currentTime = now();
-                    dispatchEventToCurrentInputTargetsLocked(currentTime, motionEntry,
-                            true /*resumeWithAppendedMotionSample*/);
-
-                    runCommandsLockedInterruptible();
-                    return; // done!
-                }
-            }
-
-NoBatchingOrStreaming:;
-        }
-
-        // Just enqueue a new motion event.
-        MotionEntry* newEntry = mAllocator.obtainMotionEntry(eventTime,
-                deviceId, source, policyFlags, action, flags, metaState, edgeFlags,
-                xPrecision, yPrecision, downTime,
-                pointerCount, pointerIds, pointerCoords);
-
-        needWake = enqueueInboundEventLocked(newEntry);
-    } // release lock
-
-    if (needWake) {
-        mLooper->wake();
-    }
-}
-
-void InputDispatcher::notifySwitch(nsecs_t when, int32_t switchCode, int32_t switchValue,
-        uint32_t policyFlags) {
-#if DEBUG_INBOUND_EVENT_DETAILS
-    LOGD("notifySwitch - switchCode=%d, switchValue=%d, policyFlags=0x%x",
-            switchCode, switchValue, policyFlags);
-#endif
-
-    policyFlags |= POLICY_FLAG_TRUSTED;
-    mPolicy->notifySwitch(when, switchCode, switchValue, policyFlags);
-}
-
-int32_t InputDispatcher::injectInputEvent(const InputEvent* event,
-        int32_t injectorPid, int32_t injectorUid, int32_t syncMode, int32_t timeoutMillis) {
-#if DEBUG_INBOUND_EVENT_DETAILS
-    LOGD("injectInputEvent - eventType=%d, injectorPid=%d, injectorUid=%d, "
-            "syncMode=%d, timeoutMillis=%d",
-            event->getType(), injectorPid, injectorUid, syncMode, timeoutMillis);
-#endif
-
-    nsecs_t endTime = now() + milliseconds_to_nanoseconds(timeoutMillis);
-
-    uint32_t policyFlags = POLICY_FLAG_INJECTED;
-    if (hasInjectionPermission(injectorPid, injectorUid)) {
-        policyFlags |= POLICY_FLAG_TRUSTED;
-    }
-
-    EventEntry* injectedEntry;
-    switch (event->getType()) {
-    case AINPUT_EVENT_TYPE_KEY: {
-        const KeyEvent* keyEvent = static_cast<const KeyEvent*>(event);
-        int32_t action = keyEvent->getAction();
-        if (! validateKeyEvent(action)) {
-            return INPUT_EVENT_INJECTION_FAILED;
-        }
-
-        int32_t flags = keyEvent->getFlags();
-        if (flags & AKEY_EVENT_FLAG_VIRTUAL_HARD_KEY) {
-            policyFlags |= POLICY_FLAG_VIRTUAL;
-        }
-
-        mPolicy->interceptKeyBeforeQueueing(keyEvent, /*byref*/ policyFlags);
-
-        if (policyFlags & POLICY_FLAG_WOKE_HERE) {
-            flags |= AKEY_EVENT_FLAG_WOKE_HERE;
-        }
-
-        mLock.lock();
-        injectedEntry = mAllocator.obtainKeyEntry(keyEvent->getEventTime(),
-                keyEvent->getDeviceId(), keyEvent->getSource(),
-                policyFlags, action, flags,
-                keyEvent->getKeyCode(), keyEvent->getScanCode(), keyEvent->getMetaState(),
-                keyEvent->getRepeatCount(), keyEvent->getDownTime());
-        break;
-    }
-
-    case AINPUT_EVENT_TYPE_MOTION: {
-        const MotionEvent* motionEvent = static_cast<const MotionEvent*>(event);
-        int32_t action = motionEvent->getAction();
-        size_t pointerCount = motionEvent->getPointerCount();
-        const int32_t* pointerIds = motionEvent->getPointerIds();
-        if (! validateMotionEvent(action, pointerCount, pointerIds)) {
-            return INPUT_EVENT_INJECTION_FAILED;
-        }
-
-        nsecs_t eventTime = motionEvent->getEventTime();
-        mPolicy->interceptGenericBeforeQueueing(eventTime, /*byref*/ policyFlags);
-
-        mLock.lock();
-        const nsecs_t* sampleEventTimes = motionEvent->getSampleEventTimes();
-        const PointerCoords* samplePointerCoords = motionEvent->getSamplePointerCoords();
-        MotionEntry* motionEntry = mAllocator.obtainMotionEntry(*sampleEventTimes,
-                motionEvent->getDeviceId(), motionEvent->getSource(), policyFlags,
-                action, motionEvent->getFlags(),
-                motionEvent->getMetaState(), motionEvent->getEdgeFlags(),
-                motionEvent->getXPrecision(), motionEvent->getYPrecision(),
-                motionEvent->getDownTime(), uint32_t(pointerCount),
-                pointerIds, samplePointerCoords);
-        for (size_t i = motionEvent->getHistorySize(); i > 0; i--) {
-            sampleEventTimes += 1;
-            samplePointerCoords += pointerCount;
-            mAllocator.appendMotionSample(motionEntry, *sampleEventTimes, samplePointerCoords);
-        }
-        injectedEntry = motionEntry;
-        break;
-    }
-
-    default:
-        LOGW("Cannot inject event of type %d", event->getType());
-        return INPUT_EVENT_INJECTION_FAILED;
-    }
-
-    InjectionState* injectionState = mAllocator.obtainInjectionState(injectorPid, injectorUid);
-    if (syncMode == INPUT_EVENT_INJECTION_SYNC_NONE) {
-        injectionState->injectionIsAsync = true;
-    }
-
-    injectionState->refCount += 1;
-    injectedEntry->injectionState = injectionState;
-
-    bool needWake = enqueueInboundEventLocked(injectedEntry);
-    mLock.unlock();
-
-    if (needWake) {
-        mLooper->wake();
-    }
-
-    int32_t injectionResult;
-    { // acquire lock
-        AutoMutex _l(mLock);
-
-        if (syncMode == INPUT_EVENT_INJECTION_SYNC_NONE) {
-            injectionResult = INPUT_EVENT_INJECTION_SUCCEEDED;
-        } else {
-            for (;;) {
-                injectionResult = injectionState->injectionResult;
-                if (injectionResult != INPUT_EVENT_INJECTION_PENDING) {
-                    break;
-                }
-
-                nsecs_t remainingTimeout = endTime - now();
-                if (remainingTimeout <= 0) {
-#if DEBUG_INJECTION
-                    LOGD("injectInputEvent - Timed out waiting for injection result "
-                            "to become available.");
-#endif
-                    injectionResult = INPUT_EVENT_INJECTION_TIMED_OUT;
-                    break;
-                }
-
-                mInjectionResultAvailableCondition.waitRelative(mLock, remainingTimeout);
-            }
-
-            if (injectionResult == INPUT_EVENT_INJECTION_SUCCEEDED
-                    && syncMode == INPUT_EVENT_INJECTION_SYNC_WAIT_FOR_FINISHED) {
-                while (injectionState->pendingForegroundDispatches != 0) {
-#if DEBUG_INJECTION
-                    LOGD("injectInputEvent - Waiting for %d pending foreground dispatches.",
-                            injectionState->pendingForegroundDispatches);
-#endif
-                    nsecs_t remainingTimeout = endTime - now();
-                    if (remainingTimeout <= 0) {
-#if DEBUG_INJECTION
-                    LOGD("injectInputEvent - Timed out waiting for pending foreground "
-                            "dispatches to finish.");
-#endif
-                        injectionResult = INPUT_EVENT_INJECTION_TIMED_OUT;
-                        break;
-                    }
-
-                    mInjectionSyncFinishedCondition.waitRelative(mLock, remainingTimeout);
-                }
-            }
-        }
-
-        mAllocator.releaseInjectionState(injectionState);
-    } // release lock
-
-#if DEBUG_INJECTION
-    LOGD("injectInputEvent - Finished with result %d.  "
-            "injectorPid=%d, injectorUid=%d",
-            injectionResult, injectorPid, injectorUid);
-#endif
-
-    return injectionResult;
-}
-
-bool InputDispatcher::hasInjectionPermission(int32_t injectorPid, int32_t injectorUid) {
-    return injectorUid == 0
-            || mPolicy->checkInjectEventsPermissionNonReentrant(injectorPid, injectorUid);
-}
-
-void InputDispatcher::setInjectionResultLocked(EventEntry* entry, int32_t injectionResult) {
-    InjectionState* injectionState = entry->injectionState;
-    if (injectionState) {
-#if DEBUG_INJECTION
-        LOGD("Setting input event injection result to %d.  "
-                "injectorPid=%d, injectorUid=%d",
-                 injectionResult, injectionState->injectorPid, injectionState->injectorUid);
-#endif
-
-        if (injectionState->injectionIsAsync) {
-            // Log the outcome since the injector did not wait for the injection result.
-            switch (injectionResult) {
-            case INPUT_EVENT_INJECTION_SUCCEEDED:
-                LOGV("Asynchronous input event injection succeeded.");
-                break;
-            case INPUT_EVENT_INJECTION_FAILED:
-                LOGW("Asynchronous input event injection failed.");
-                break;
-            case INPUT_EVENT_INJECTION_PERMISSION_DENIED:
-                LOGW("Asynchronous input event injection permission denied.");
-                break;
-            case INPUT_EVENT_INJECTION_TIMED_OUT:
-                LOGW("Asynchronous input event injection timed out.");
-                break;
-            }
-        }
-
-        injectionState->injectionResult = injectionResult;
-        mInjectionResultAvailableCondition.broadcast();
-    }
-}
-
-void InputDispatcher::incrementPendingForegroundDispatchesLocked(EventEntry* entry) {
-    InjectionState* injectionState = entry->injectionState;
-    if (injectionState) {
-        injectionState->pendingForegroundDispatches += 1;
-    }
-}
-
-void InputDispatcher::decrementPendingForegroundDispatchesLocked(EventEntry* entry) {
-    InjectionState* injectionState = entry->injectionState;
-    if (injectionState) {
-        injectionState->pendingForegroundDispatches -= 1;
-
-        if (injectionState->pendingForegroundDispatches == 0) {
-            mInjectionSyncFinishedCondition.broadcast();
-        }
-    }
-}
-
-const InputWindow* InputDispatcher::getWindowLocked(const sp<InputChannel>& inputChannel) {
-    for (size_t i = 0; i < mWindows.size(); i++) {
-        const InputWindow* window = & mWindows[i];
-        if (window->inputChannel == inputChannel) {
-            return window;
-        }
-    }
-    return NULL;
-}
-
-void InputDispatcher::setInputWindows(const Vector<InputWindow>& inputWindows) {
-#if DEBUG_FOCUS
-    LOGD("setInputWindows");
-#endif
-    { // acquire lock
-        AutoMutex _l(mLock);
-
-        // Clear old window pointers.
-        sp<InputChannel> oldFocusedWindowChannel;
-        if (mFocusedWindow) {
-            oldFocusedWindowChannel = mFocusedWindow->inputChannel;
-            mFocusedWindow = NULL;
-        }
-
-        mWindows.clear();
-
-        // Loop over new windows and rebuild the necessary window pointers for
-        // tracking focus and touch.
-        mWindows.appendVector(inputWindows);
-
-        size_t numWindows = mWindows.size();
-        for (size_t i = 0; i < numWindows; i++) {
-            const InputWindow* window = & mWindows.itemAt(i);
-            if (window->hasFocus) {
-                mFocusedWindow = window;
-                break;
-            }
-        }
-
-        if (oldFocusedWindowChannel != NULL) {
-            if (!mFocusedWindow || oldFocusedWindowChannel != mFocusedWindow->inputChannel) {
-#if DEBUG_FOCUS
-                LOGD("Focus left window: %s",
-                        oldFocusedWindowChannel->getName().string());
-#endif
-                synthesizeCancelationEventsForInputChannelLocked(oldFocusedWindowChannel,
-                        InputState::CANCEL_NON_POINTER_EVENTS, "focus left window");
-                oldFocusedWindowChannel.clear();
-            }
-        }
-        if (mFocusedWindow && oldFocusedWindowChannel == NULL) {
-#if DEBUG_FOCUS
-            LOGD("Focus entered window: %s",
-                    mFocusedWindow->inputChannel->getName().string());
-#endif
-        }
-
-        for (size_t i = 0; i < mTouchState.windows.size(); ) {
-            TouchedWindow& touchedWindow = mTouchState.windows.editItemAt(i);
-            const InputWindow* window = getWindowLocked(touchedWindow.channel);
-            if (window) {
-                touchedWindow.window = window;
-                i += 1;
-            } else {
-#if DEBUG_FOCUS
-                LOGD("Touched window was removed: %s", touchedWindow.channel->getName().string());
-#endif
-                synthesizeCancelationEventsForInputChannelLocked(touchedWindow.channel,
-                        InputState::CANCEL_POINTER_EVENTS, "touched window was removed");
-                mTouchState.windows.removeAt(i);
-            }
-        }
-
-#if DEBUG_FOCUS
-        //logDispatchStateLocked();
-#endif
-    } // release lock
-
-    // Wake up poll loop since it may need to make new input dispatching choices.
-    mLooper->wake();
-}
-
-void InputDispatcher::setFocusedApplication(const InputApplication* inputApplication) {
-#if DEBUG_FOCUS
-    LOGD("setFocusedApplication");
-#endif
-    { // acquire lock
-        AutoMutex _l(mLock);
-
-        releaseFocusedApplicationLocked();
-
-        if (inputApplication) {
-            mFocusedApplicationStorage = *inputApplication;
-            mFocusedApplication = & mFocusedApplicationStorage;
-        }
-
-#if DEBUG_FOCUS
-        //logDispatchStateLocked();
-#endif
-    } // release lock
-
-    // Wake up poll loop since it may need to make new input dispatching choices.
-    mLooper->wake();
-}
-
-void InputDispatcher::releaseFocusedApplicationLocked() {
-    if (mFocusedApplication) {
-        mFocusedApplication = NULL;
-        mFocusedApplicationStorage.handle.clear();
-    }
-}
-
-void InputDispatcher::setInputDispatchMode(bool enabled, bool frozen) {
-#if DEBUG_FOCUS
-    LOGD("setInputDispatchMode: enabled=%d, frozen=%d", enabled, frozen);
-#endif
-
-    bool changed;
-    { // acquire lock
-        AutoMutex _l(mLock);
-
-        if (mDispatchEnabled != enabled || mDispatchFrozen != frozen) {
-            if (mDispatchFrozen && !frozen) {
-                resetANRTimeoutsLocked();
-            }
-
-            if (mDispatchEnabled && !enabled) {
-                resetAndDropEverythingLocked("dispatcher is being disabled");
-            }
-
-            mDispatchEnabled = enabled;
-            mDispatchFrozen = frozen;
-            changed = true;
-        } else {
-            changed = false;
-        }
-
-#if DEBUG_FOCUS
-        //logDispatchStateLocked();
-#endif
-    } // release lock
-
-    if (changed) {
-        // Wake up poll loop since it may need to make new input dispatching choices.
-        mLooper->wake();
-    }
-}
-
-bool InputDispatcher::transferTouchFocus(const sp<InputChannel>& fromChannel,
-        const sp<InputChannel>& toChannel) {
-#if DEBUG_FOCUS
-    LOGD("transferTouchFocus: fromChannel=%s, toChannel=%s",
-            fromChannel->getName().string(), toChannel->getName().string());
-#endif
-    { // acquire lock
-        AutoMutex _l(mLock);
-
-        const InputWindow* fromWindow = getWindowLocked(fromChannel);
-        const InputWindow* toWindow = getWindowLocked(toChannel);
-        if (! fromWindow || ! toWindow) {
-#if DEBUG_FOCUS
-            LOGD("Cannot transfer focus because from or to window not found.");
-#endif
-            return false;
-        }
-        if (fromWindow == toWindow) {
-#if DEBUG_FOCUS
-            LOGD("Trivial transfer to same window.");
-#endif
-            return true;
-        }
-
-        bool found = false;
-        for (size_t i = 0; i < mTouchState.windows.size(); i++) {
-            const TouchedWindow& touchedWindow = mTouchState.windows[i];
-            if (touchedWindow.window == fromWindow) {
-                int32_t oldTargetFlags = touchedWindow.targetFlags;
-                BitSet32 pointerIds = touchedWindow.pointerIds;
-
-                mTouchState.windows.removeAt(i);
-
-                int32_t newTargetFlags = oldTargetFlags
-                        & (InputTarget::FLAG_FOREGROUND | InputTarget::FLAG_SPLIT);
-                mTouchState.addOrUpdateWindow(toWindow, newTargetFlags, pointerIds);
-
-                found = true;
-                break;
-            }
-        }
-
-        if (! found) {
-#if DEBUG_FOCUS
-            LOGD("Focus transfer failed because from window did not have focus.");
-#endif
-            return false;
-        }
-
-        ssize_t fromConnectionIndex = getConnectionIndexLocked(fromChannel);
-        ssize_t toConnectionIndex = getConnectionIndexLocked(toChannel);
-        if (fromConnectionIndex >= 0 && toConnectionIndex >= 0) {
-            sp<Connection> fromConnection = mConnectionsByReceiveFd.valueAt(fromConnectionIndex);
-            sp<Connection> toConnection = mConnectionsByReceiveFd.valueAt(toConnectionIndex);
-
-            fromConnection->inputState.copyPointerStateTo(toConnection->inputState);
-            synthesizeCancelationEventsForConnectionLocked(fromConnection,
-                    InputState::CANCEL_POINTER_EVENTS,
-                    "transferring touch focus from this window to another window");
-        }
-
-#if DEBUG_FOCUS
-        logDispatchStateLocked();
-#endif
-    } // release lock
-
-    // Wake up poll loop since it may need to make new input dispatching choices.
-    mLooper->wake();
-    return true;
-}
-
-void InputDispatcher::resetAndDropEverythingLocked(const char* reason) {
-#if DEBUG_FOCUS
-    LOGD("Resetting and dropping all events (%s).", reason);
-#endif
-
-    synthesizeCancelationEventsForAllConnectionsLocked(InputState::CANCEL_ALL_EVENTS, reason);
-
-    resetKeyRepeatLocked();
-    releasePendingEventLocked();
-    drainInboundQueueLocked();
-    resetTargetsLocked();
-
-    mTouchState.reset();
-}
-
-void InputDispatcher::logDispatchStateLocked() {
-    String8 dump;
-    dumpDispatchStateLocked(dump);
-
-    char* text = dump.lockBuffer(dump.size());
-    char* start = text;
-    while (*start != '\0') {
-        char* end = strchr(start, '\n');
-        if (*end == '\n') {
-            *(end++) = '\0';
-        }
-        LOGD("%s", start);
-        start = end;
-    }
-}
-
-void InputDispatcher::dumpDispatchStateLocked(String8& dump) {
-    dump.appendFormat(INDENT "DispatchEnabled: %d\n", mDispatchEnabled);
-    dump.appendFormat(INDENT "DispatchFrozen: %d\n", mDispatchFrozen);
-
-    if (mFocusedApplication) {
-        dump.appendFormat(INDENT "FocusedApplication: name='%s', dispatchingTimeout=%0.3fms\n",
-                mFocusedApplication->name.string(),
-                mFocusedApplication->dispatchingTimeout / 1000000.0);
-    } else {
-        dump.append(INDENT "FocusedApplication: <null>\n");
-    }
-    dump.appendFormat(INDENT "FocusedWindow: name='%s'\n",
-            mFocusedWindow != NULL ? mFocusedWindow->name.string() : "<null>");
-
-    dump.appendFormat(INDENT "TouchDown: %s\n", toString(mTouchState.down));
-    dump.appendFormat(INDENT "TouchSplit: %s\n", toString(mTouchState.split));
-    if (!mTouchState.windows.isEmpty()) {
-        dump.append(INDENT "TouchedWindows:\n");
-        for (size_t i = 0; i < mTouchState.windows.size(); i++) {
-            const TouchedWindow& touchedWindow = mTouchState.windows[i];
-            dump.appendFormat(INDENT2 "%d: name='%s', pointerIds=0x%0x, targetFlags=0x%x\n",
-                    i, touchedWindow.window->name.string(), touchedWindow.pointerIds.value,
-                    touchedWindow.targetFlags);
-        }
-    } else {
-        dump.append(INDENT "TouchedWindows: <none>\n");
-    }
-
-    if (!mWindows.isEmpty()) {
-        dump.append(INDENT "Windows:\n");
-        for (size_t i = 0; i < mWindows.size(); i++) {
-            const InputWindow& window = mWindows[i];
-            dump.appendFormat(INDENT2 "%d: name='%s', paused=%s, hasFocus=%s, hasWallpaper=%s, "
-                    "visible=%s, canReceiveKeys=%s, flags=0x%08x, type=0x%08x, layer=%d, "
-                    "frame=[%d,%d][%d,%d], "
-                    "visibleFrame=[%d,%d][%d,%d], "
-                    "touchableArea=[%d,%d][%d,%d], "
-                    "ownerPid=%d, ownerUid=%d, dispatchingTimeout=%0.3fms\n",
-                    i, window.name.string(),
-                    toString(window.paused),
-                    toString(window.hasFocus),
-                    toString(window.hasWallpaper),
-                    toString(window.visible),
-                    toString(window.canReceiveKeys),
-                    window.layoutParamsFlags, window.layoutParamsType,
-                    window.layer,
-                    window.frameLeft, window.frameTop,
-                    window.frameRight, window.frameBottom,
-                    window.visibleFrameLeft, window.visibleFrameTop,
-                    window.visibleFrameRight, window.visibleFrameBottom,
-                    window.touchableAreaLeft, window.touchableAreaTop,
-                    window.touchableAreaRight, window.touchableAreaBottom,
-                    window.ownerPid, window.ownerUid,
-                    window.dispatchingTimeout / 1000000.0);
-        }
-    } else {
-        dump.append(INDENT "Windows: <none>\n");
-    }
-
-    if (!mMonitoringChannels.isEmpty()) {
-        dump.append(INDENT "MonitoringChannels:\n");
-        for (size_t i = 0; i < mMonitoringChannels.size(); i++) {
-            const sp<InputChannel>& channel = mMonitoringChannels[i];
-            dump.appendFormat(INDENT2 "%d: '%s'\n", i, channel->getName().string());
-        }
-    } else {
-        dump.append(INDENT "MonitoringChannels: <none>\n");
-    }
-
-    dump.appendFormat(INDENT "InboundQueue: length=%u\n", mInboundQueue.count());
-
-    if (!mActiveConnections.isEmpty()) {
-        dump.append(INDENT "ActiveConnections:\n");
-        for (size_t i = 0; i < mActiveConnections.size(); i++) {
-            const Connection* connection = mActiveConnections[i];
-            dump.appendFormat(INDENT2 "%d: '%s', status=%s, outboundQueueLength=%u, "
-                    "inputState.isNeutral=%s\n",
-                    i, connection->getInputChannelName(), connection->getStatusLabel(),
-                    connection->outboundQueue.count(),
-                    toString(connection->inputState.isNeutral()));
-        }
-    } else {
-        dump.append(INDENT "ActiveConnections: <none>\n");
-    }
-
-    if (isAppSwitchPendingLocked()) {
-        dump.appendFormat(INDENT "AppSwitch: pending, due in %01.1fms\n",
-                (mAppSwitchDueTime - now()) / 1000000.0);
-    } else {
-        dump.append(INDENT "AppSwitch: not pending\n");
-    }
-}
-
-status_t InputDispatcher::registerInputChannel(const sp<InputChannel>& inputChannel, bool monitor) {
-#if DEBUG_REGISTRATION
-    LOGD("channel '%s' ~ registerInputChannel - monitor=%s", inputChannel->getName().string(),
-            toString(monitor));
-#endif
-
-    { // acquire lock
-        AutoMutex _l(mLock);
-
-        if (getConnectionIndexLocked(inputChannel) >= 0) {
-            LOGW("Attempted to register already registered input channel '%s'",
-                    inputChannel->getName().string());
-            return BAD_VALUE;
-        }
-
-        sp<Connection> connection = new Connection(inputChannel);
-        status_t status = connection->initialize();
-        if (status) {
-            LOGE("Failed to initialize input publisher for input channel '%s', status=%d",
-                    inputChannel->getName().string(), status);
-            return status;
-        }
-
-        int32_t receiveFd = inputChannel->getReceivePipeFd();
-        mConnectionsByReceiveFd.add(receiveFd, connection);
-
-        if (monitor) {
-            mMonitoringChannels.push(inputChannel);
-        }
-
-        mLooper->addFd(receiveFd, 0, ALOOPER_EVENT_INPUT, handleReceiveCallback, this);
-
-        runCommandsLockedInterruptible();
-    } // release lock
-    return OK;
-}
-
-status_t InputDispatcher::unregisterInputChannel(const sp<InputChannel>& inputChannel) {
-#if DEBUG_REGISTRATION
-    LOGD("channel '%s' ~ unregisterInputChannel", inputChannel->getName().string());
-#endif
-
-    { // acquire lock
-        AutoMutex _l(mLock);
-
-        ssize_t connectionIndex = getConnectionIndexLocked(inputChannel);
-        if (connectionIndex < 0) {
-            LOGW("Attempted to unregister already unregistered input channel '%s'",
-                    inputChannel->getName().string());
-            return BAD_VALUE;
-        }
-
-        sp<Connection> connection = mConnectionsByReceiveFd.valueAt(connectionIndex);
-        mConnectionsByReceiveFd.removeItemsAt(connectionIndex);
-
-        connection->status = Connection::STATUS_ZOMBIE;
-
-        for (size_t i = 0; i < mMonitoringChannels.size(); i++) {
-            if (mMonitoringChannels[i] == inputChannel) {
-                mMonitoringChannels.removeAt(i);
-                break;
-            }
-        }
-
-        mLooper->removeFd(inputChannel->getReceivePipeFd());
-
-        nsecs_t currentTime = now();
-        abortBrokenDispatchCycleLocked(currentTime, connection);
-
-        runCommandsLockedInterruptible();
-    } // release lock
-
-    // Wake the poll loop because removing the connection may have changed the current
-    // synchronization state.
-    mLooper->wake();
-    return OK;
-}
-
-ssize_t InputDispatcher::getConnectionIndexLocked(const sp<InputChannel>& inputChannel) {
-    ssize_t connectionIndex = mConnectionsByReceiveFd.indexOfKey(inputChannel->getReceivePipeFd());
-    if (connectionIndex >= 0) {
-        sp<Connection> connection = mConnectionsByReceiveFd.valueAt(connectionIndex);
-        if (connection->inputChannel.get() == inputChannel.get()) {
-            return connectionIndex;
-        }
-    }
-
-    return -1;
-}
-
-void InputDispatcher::activateConnectionLocked(Connection* connection) {
-    for (size_t i = 0; i < mActiveConnections.size(); i++) {
-        if (mActiveConnections.itemAt(i) == connection) {
-            return;
-        }
-    }
-    mActiveConnections.add(connection);
-}
-
-void InputDispatcher::deactivateConnectionLocked(Connection* connection) {
-    for (size_t i = 0; i < mActiveConnections.size(); i++) {
-        if (mActiveConnections.itemAt(i) == connection) {
-            mActiveConnections.removeAt(i);
-            return;
-        }
-    }
-}
-
-void InputDispatcher::onDispatchCycleStartedLocked(
-        nsecs_t currentTime, const sp<Connection>& connection) {
-}
-
-void InputDispatcher::onDispatchCycleFinishedLocked(
-        nsecs_t currentTime, const sp<Connection>& connection, bool handled) {
-    CommandEntry* commandEntry = postCommandLocked(
-            & InputDispatcher::doDispatchCycleFinishedLockedInterruptible);
-    commandEntry->connection = connection;
-    commandEntry->handled = handled;
-}
-
-void InputDispatcher::onDispatchCycleBrokenLocked(
-        nsecs_t currentTime, const sp<Connection>& connection) {
-    LOGE("channel '%s' ~ Channel is unrecoverably broken and will be disposed!",
-            connection->getInputChannelName());
-
-    CommandEntry* commandEntry = postCommandLocked(
-            & InputDispatcher::doNotifyInputChannelBrokenLockedInterruptible);
-    commandEntry->connection = connection;
-}
-
-void InputDispatcher::onANRLocked(
-        nsecs_t currentTime, const InputApplication* application, const InputWindow* window,
-        nsecs_t eventTime, nsecs_t waitStartTime) {
-    LOGI("Application is not responding: %s.  "
-            "%01.1fms since event, %01.1fms since wait started",
-            getApplicationWindowLabelLocked(application, window).string(),
-            (currentTime - eventTime) / 1000000.0,
-            (currentTime - waitStartTime) / 1000000.0);
-
-    CommandEntry* commandEntry = postCommandLocked(
-            & InputDispatcher::doNotifyANRLockedInterruptible);
-    if (application) {
-        commandEntry->inputApplicationHandle = application->handle;
-    }
-    if (window) {
-        commandEntry->inputChannel = window->inputChannel;
-    }
-}
-
-void InputDispatcher::doNotifyConfigurationChangedInterruptible(
-        CommandEntry* commandEntry) {
-    mLock.unlock();
-
-    mPolicy->notifyConfigurationChanged(commandEntry->eventTime);
-
-    mLock.lock();
-}
-
-void InputDispatcher::doNotifyInputChannelBrokenLockedInterruptible(
-        CommandEntry* commandEntry) {
-    sp<Connection> connection = commandEntry->connection;
-
-    if (connection->status != Connection::STATUS_ZOMBIE) {
-        mLock.unlock();
-
-        mPolicy->notifyInputChannelBroken(connection->inputChannel);
-
-        mLock.lock();
-    }
-}
-
-void InputDispatcher::doNotifyANRLockedInterruptible(
-        CommandEntry* commandEntry) {
-    mLock.unlock();
-
-    nsecs_t newTimeout = mPolicy->notifyANR(
-            commandEntry->inputApplicationHandle, commandEntry->inputChannel);
-
-    mLock.lock();
-
-    resumeAfterTargetsNotReadyTimeoutLocked(newTimeout, commandEntry->inputChannel);
-}
-
-void InputDispatcher::doInterceptKeyBeforeDispatchingLockedInterruptible(
-        CommandEntry* commandEntry) {
-    KeyEntry* entry = commandEntry->keyEntry;
-
-    KeyEvent event;
-    initializeKeyEvent(&event, entry);
-
-    mLock.unlock();
-
-    bool consumed = mPolicy->interceptKeyBeforeDispatching(commandEntry->inputChannel,
-            &event, entry->policyFlags);
-
-    mLock.lock();
-
-    entry->interceptKeyResult = consumed
-            ? KeyEntry::INTERCEPT_KEY_RESULT_SKIP
-            : KeyEntry::INTERCEPT_KEY_RESULT_CONTINUE;
-    mAllocator.releaseKeyEntry(entry);
-}
-
-void InputDispatcher::doDispatchCycleFinishedLockedInterruptible(
-        CommandEntry* commandEntry) {
-    sp<Connection> connection = commandEntry->connection;
-    bool handled = commandEntry->handled;
-
-    if (!connection->outboundQueue.isEmpty()) {
-        DispatchEntry* dispatchEntry = connection->outboundQueue.headSentinel.next;
-        if (dispatchEntry->inProgress
-                && dispatchEntry->hasForegroundTarget()
-                && dispatchEntry->eventEntry->type == EventEntry::TYPE_KEY) {
-            KeyEntry* keyEntry = static_cast<KeyEntry*>(dispatchEntry->eventEntry);
-            if (!(keyEntry->flags & AKEY_EVENT_FLAG_FALLBACK)) {
-                if (handled) {
-                    // If the application handled a non-fallback key, then immediately
-                    // cancel all fallback keys previously dispatched to the application.
-                    // This behavior will prevent chording with fallback keys (so they cannot
-                    // be used as modifiers) but it will ensure that fallback keys do not
-                    // get stuck.  This takes care of the case where the application does not handle
-                    // the original DOWN so we generate a fallback DOWN but it does handle
-                    // the original UP in which case we would not generate the fallback UP.
-                    synthesizeCancelationEventsForConnectionLocked(connection,
-                            InputState::CANCEL_FALLBACK_EVENTS,
-                            "application handled a non-fallback event, canceling all fallback events");
-                } else {
-                    // If the application did not handle a non-fallback key, then ask
-                    // the policy what to do with it.  We might generate a fallback key
-                    // event here.
-                    KeyEvent event;
-                    initializeKeyEvent(&event, keyEntry);
-
-                    mLock.unlock();
-
-                    bool fallback = mPolicy->dispatchUnhandledKey(connection->inputChannel,
-                            &event, keyEntry->policyFlags, &event);
-
-                    mLock.lock();
-
-                    if (connection->status != Connection::STATUS_NORMAL) {
-                        return;
-                    }
-
-                    assert(connection->outboundQueue.headSentinel.next == dispatchEntry);
-
-                    if (fallback) {
-                        // Restart the dispatch cycle using the fallback key.
-                        keyEntry->eventTime = event.getEventTime();
-                        keyEntry->deviceId = event.getDeviceId();
-                        keyEntry->source = event.getSource();
-                        keyEntry->flags = event.getFlags() | AKEY_EVENT_FLAG_FALLBACK;
-                        keyEntry->keyCode = event.getKeyCode();
-                        keyEntry->scanCode = event.getScanCode();
-                        keyEntry->metaState = event.getMetaState();
-                        keyEntry->repeatCount = event.getRepeatCount();
-                        keyEntry->downTime = event.getDownTime();
-                        keyEntry->syntheticRepeat = false;
-
-                        dispatchEntry->inProgress = false;
-                        startDispatchCycleLocked(now(), connection);
-                        return;
-                    }
-                }
-            }
-        }
-    }
-
-    startNextDispatchCycleLocked(now(), connection);
-}
-
-void InputDispatcher::doPokeUserActivityLockedInterruptible(CommandEntry* commandEntry) {
-    mLock.unlock();
-
-    mPolicy->pokeUserActivity(commandEntry->eventTime, commandEntry->userActivityEventType);
-
-    mLock.lock();
-}
-
-void InputDispatcher::initializeKeyEvent(KeyEvent* event, const KeyEntry* entry) {
-    event->initialize(entry->deviceId, entry->source, entry->action, entry->flags,
-            entry->keyCode, entry->scanCode, entry->metaState, entry->repeatCount,
-            entry->downTime, entry->eventTime);
-}
-
-void InputDispatcher::updateDispatchStatisticsLocked(nsecs_t currentTime, const EventEntry* entry,
-        int32_t injectionResult, nsecs_t timeSpentWaitingForApplication) {
-    // TODO Write some statistics about how long we spend waiting.
-}
-
-void InputDispatcher::dump(String8& dump) {
-    dump.append("Input Dispatcher State:\n");
-    dumpDispatchStateLocked(dump);
-}
-
-
-// --- InputDispatcher::Queue ---
-
-template <typename T>
-uint32_t InputDispatcher::Queue<T>::count() const {
-    uint32_t result = 0;
-    for (const T* entry = headSentinel.next; entry != & tailSentinel; entry = entry->next) {
-        result += 1;
-    }
-    return result;
-}
-
-
-// --- InputDispatcher::Allocator ---
-
-InputDispatcher::Allocator::Allocator() {
-}
-
-InputDispatcher::InjectionState*
-InputDispatcher::Allocator::obtainInjectionState(int32_t injectorPid, int32_t injectorUid) {
-    InjectionState* injectionState = mInjectionStatePool.alloc();
-    injectionState->refCount = 1;
-    injectionState->injectorPid = injectorPid;
-    injectionState->injectorUid = injectorUid;
-    injectionState->injectionIsAsync = false;
-    injectionState->injectionResult = INPUT_EVENT_INJECTION_PENDING;
-    injectionState->pendingForegroundDispatches = 0;
-    return injectionState;
-}
-
-void InputDispatcher::Allocator::initializeEventEntry(EventEntry* entry, int32_t type,
-        nsecs_t eventTime, uint32_t policyFlags) {
-    entry->type = type;
-    entry->refCount = 1;
-    entry->dispatchInProgress = false;
-    entry->eventTime = eventTime;
-    entry->policyFlags = policyFlags;
-    entry->injectionState = NULL;
-}
-
-void InputDispatcher::Allocator::releaseEventEntryInjectionState(EventEntry* entry) {
-    if (entry->injectionState) {
-        releaseInjectionState(entry->injectionState);
-        entry->injectionState = NULL;
-    }
-}
-
-InputDispatcher::ConfigurationChangedEntry*
-InputDispatcher::Allocator::obtainConfigurationChangedEntry(nsecs_t eventTime) {
-    ConfigurationChangedEntry* entry = mConfigurationChangeEntryPool.alloc();
-    initializeEventEntry(entry, EventEntry::TYPE_CONFIGURATION_CHANGED, eventTime, 0);
-    return entry;
-}
-
-InputDispatcher::KeyEntry* InputDispatcher::Allocator::obtainKeyEntry(nsecs_t eventTime,
-        int32_t deviceId, int32_t source, uint32_t policyFlags, int32_t action,
-        int32_t flags, int32_t keyCode, int32_t scanCode, int32_t metaState,
-        int32_t repeatCount, nsecs_t downTime) {
-    KeyEntry* entry = mKeyEntryPool.alloc();
-    initializeEventEntry(entry, EventEntry::TYPE_KEY, eventTime, policyFlags);
-
-    entry->deviceId = deviceId;
-    entry->source = source;
-    entry->action = action;
-    entry->flags = flags;
-    entry->keyCode = keyCode;
-    entry->scanCode = scanCode;
-    entry->metaState = metaState;
-    entry->repeatCount = repeatCount;
-    entry->downTime = downTime;
-    entry->syntheticRepeat = false;
-    entry->interceptKeyResult = KeyEntry::INTERCEPT_KEY_RESULT_UNKNOWN;
-    return entry;
-}
-
-InputDispatcher::MotionEntry* InputDispatcher::Allocator::obtainMotionEntry(nsecs_t eventTime,
-        int32_t deviceId, int32_t source, uint32_t policyFlags, int32_t action, int32_t flags,
-        int32_t metaState, int32_t edgeFlags, float xPrecision, float yPrecision,
-        nsecs_t downTime, uint32_t pointerCount,
-        const int32_t* pointerIds, const PointerCoords* pointerCoords) {
-    MotionEntry* entry = mMotionEntryPool.alloc();
-    initializeEventEntry(entry, EventEntry::TYPE_MOTION, eventTime, policyFlags);
-
-    entry->eventTime = eventTime;
-    entry->deviceId = deviceId;
-    entry->source = source;
-    entry->action = action;
-    entry->flags = flags;
-    entry->metaState = metaState;
-    entry->edgeFlags = edgeFlags;
-    entry->xPrecision = xPrecision;
-    entry->yPrecision = yPrecision;
-    entry->downTime = downTime;
-    entry->pointerCount = pointerCount;
-    entry->firstSample.eventTime = eventTime;
-    entry->firstSample.next = NULL;
-    entry->lastSample = & entry->firstSample;
-    for (uint32_t i = 0; i < pointerCount; i++) {
-        entry->pointerIds[i] = pointerIds[i];
-        entry->firstSample.pointerCoords[i] = pointerCoords[i];
-    }
-    return entry;
-}
-
-InputDispatcher::DispatchEntry* InputDispatcher::Allocator::obtainDispatchEntry(
-        EventEntry* eventEntry,
-        int32_t targetFlags, float xOffset, float yOffset) {
-    DispatchEntry* entry = mDispatchEntryPool.alloc();
-    entry->eventEntry = eventEntry;
-    eventEntry->refCount += 1;
-    entry->targetFlags = targetFlags;
-    entry->xOffset = xOffset;
-    entry->yOffset = yOffset;
-    entry->inProgress = false;
-    entry->headMotionSample = NULL;
-    entry->tailMotionSample = NULL;
-    return entry;
-}
-
-InputDispatcher::CommandEntry* InputDispatcher::Allocator::obtainCommandEntry(Command command) {
-    CommandEntry* entry = mCommandEntryPool.alloc();
-    entry->command = command;
-    return entry;
-}
-
-void InputDispatcher::Allocator::releaseInjectionState(InjectionState* injectionState) {
-    injectionState->refCount -= 1;
-    if (injectionState->refCount == 0) {
-        mInjectionStatePool.free(injectionState);
-    } else {
-        assert(injectionState->refCount > 0);
-    }
-}
-
-void InputDispatcher::Allocator::releaseEventEntry(EventEntry* entry) {
-    switch (entry->type) {
-    case EventEntry::TYPE_CONFIGURATION_CHANGED:
-        releaseConfigurationChangedEntry(static_cast<ConfigurationChangedEntry*>(entry));
-        break;
-    case EventEntry::TYPE_KEY:
-        releaseKeyEntry(static_cast<KeyEntry*>(entry));
-        break;
-    case EventEntry::TYPE_MOTION:
-        releaseMotionEntry(static_cast<MotionEntry*>(entry));
-        break;
-    default:
-        assert(false);
-        break;
-    }
-}
-
-void InputDispatcher::Allocator::releaseConfigurationChangedEntry(
-        ConfigurationChangedEntry* entry) {
-    entry->refCount -= 1;
-    if (entry->refCount == 0) {
-        releaseEventEntryInjectionState(entry);
-        mConfigurationChangeEntryPool.free(entry);
-    } else {
-        assert(entry->refCount > 0);
-    }
-}
-
-void InputDispatcher::Allocator::releaseKeyEntry(KeyEntry* entry) {
-    entry->refCount -= 1;
-    if (entry->refCount == 0) {
-        releaseEventEntryInjectionState(entry);
-        mKeyEntryPool.free(entry);
-    } else {
-        assert(entry->refCount > 0);
-    }
-}
-
-void InputDispatcher::Allocator::releaseMotionEntry(MotionEntry* entry) {
-    entry->refCount -= 1;
-    if (entry->refCount == 0) {
-        releaseEventEntryInjectionState(entry);
-        for (MotionSample* sample = entry->firstSample.next; sample != NULL; ) {
-            MotionSample* next = sample->next;
-            mMotionSamplePool.free(sample);
-            sample = next;
-        }
-        mMotionEntryPool.free(entry);
-    } else {
-        assert(entry->refCount > 0);
-    }
-}
-
-void InputDispatcher::Allocator::releaseDispatchEntry(DispatchEntry* entry) {
-    releaseEventEntry(entry->eventEntry);
-    mDispatchEntryPool.free(entry);
-}
-
-void InputDispatcher::Allocator::releaseCommandEntry(CommandEntry* entry) {
-    mCommandEntryPool.free(entry);
-}
-
-void InputDispatcher::Allocator::appendMotionSample(MotionEntry* motionEntry,
-        nsecs_t eventTime, const PointerCoords* pointerCoords) {
-    MotionSample* sample = mMotionSamplePool.alloc();
-    sample->eventTime = eventTime;
-    uint32_t pointerCount = motionEntry->pointerCount;
-    for (uint32_t i = 0; i < pointerCount; i++) {
-        sample->pointerCoords[i] = pointerCoords[i];
-    }
-
-    sample->next = NULL;
-    motionEntry->lastSample->next = sample;
-    motionEntry->lastSample = sample;
-}
-
-void InputDispatcher::Allocator::recycleKeyEntry(KeyEntry* keyEntry) {
-    releaseEventEntryInjectionState(keyEntry);
-
-    keyEntry->dispatchInProgress = false;
-    keyEntry->syntheticRepeat = false;
-    keyEntry->interceptKeyResult = KeyEntry::INTERCEPT_KEY_RESULT_UNKNOWN;
-}
-
-
-// --- InputDispatcher::MotionEntry ---
-
-uint32_t InputDispatcher::MotionEntry::countSamples() const {
-    uint32_t count = 1;
-    for (MotionSample* sample = firstSample.next; sample != NULL; sample = sample->next) {
-        count += 1;
-    }
-    return count;
-}
-
-
-// --- InputDispatcher::InputState ---
-
-InputDispatcher::InputState::InputState() {
-}
-
-InputDispatcher::InputState::~InputState() {
-}
-
-bool InputDispatcher::InputState::isNeutral() const {
-    return mKeyMementos.isEmpty() && mMotionMementos.isEmpty();
-}
-
-InputDispatcher::InputState::Consistency InputDispatcher::InputState::trackEvent(
-        const EventEntry* entry) {
-    switch (entry->type) {
-    case EventEntry::TYPE_KEY:
-        return trackKey(static_cast<const KeyEntry*>(entry));
-
-    case EventEntry::TYPE_MOTION:
-        return trackMotion(static_cast<const MotionEntry*>(entry));
-
-    default:
-        return CONSISTENT;
-    }
-}
-
-InputDispatcher::InputState::Consistency InputDispatcher::InputState::trackKey(
-        const KeyEntry* entry) {
-    int32_t action = entry->action;
-    for (size_t i = 0; i < mKeyMementos.size(); i++) {
-        KeyMemento& memento = mKeyMementos.editItemAt(i);
-        if (memento.deviceId == entry->deviceId
-                && memento.source == entry->source
-                && memento.keyCode == entry->keyCode
-                && memento.scanCode == entry->scanCode) {
-            switch (action) {
-            case AKEY_EVENT_ACTION_UP:
-                mKeyMementos.removeAt(i);
-                return CONSISTENT;
-
-            case AKEY_EVENT_ACTION_DOWN:
-                return TOLERABLE;
-
-            default:
-                return BROKEN;
-            }
-        }
-    }
-
-    switch (action) {
-    case AKEY_EVENT_ACTION_DOWN: {
-        mKeyMementos.push();
-        KeyMemento& memento = mKeyMementos.editTop();
-        memento.deviceId = entry->deviceId;
-        memento.source = entry->source;
-        memento.keyCode = entry->keyCode;
-        memento.scanCode = entry->scanCode;
-        memento.flags = entry->flags;
-        memento.downTime = entry->downTime;
-        return CONSISTENT;
-    }
-
-    default:
-        return BROKEN;
-    }
-}
-
-InputDispatcher::InputState::Consistency InputDispatcher::InputState::trackMotion(
-        const MotionEntry* entry) {
-    int32_t action = entry->action & AMOTION_EVENT_ACTION_MASK;
-    for (size_t i = 0; i < mMotionMementos.size(); i++) {
-        MotionMemento& memento = mMotionMementos.editItemAt(i);
-        if (memento.deviceId == entry->deviceId
-                && memento.source == entry->source) {
-            switch (action) {
-            case AMOTION_EVENT_ACTION_UP:
-            case AMOTION_EVENT_ACTION_CANCEL:
-                mMotionMementos.removeAt(i);
-                return CONSISTENT;
-
-            case AMOTION_EVENT_ACTION_DOWN:
-                return TOLERABLE;
-
-            case AMOTION_EVENT_ACTION_POINTER_DOWN:
-                if (entry->pointerCount == memento.pointerCount + 1) {
-                    memento.setPointers(entry);
-                    return CONSISTENT;
-                }
-                return BROKEN;
-
-            case AMOTION_EVENT_ACTION_POINTER_UP:
-                if (entry->pointerCount == memento.pointerCount - 1) {
-                    memento.setPointers(entry);
-                    return CONSISTENT;
-                }
-                return BROKEN;
-
-            case AMOTION_EVENT_ACTION_MOVE:
-                if (entry->pointerCount == memento.pointerCount) {
-                    return CONSISTENT;
-                }
-                return BROKEN;
-
-            default:
-                return BROKEN;
-            }
-        }
-    }
-
-    switch (action) {
-    case AMOTION_EVENT_ACTION_DOWN: {
-        mMotionMementos.push();
-        MotionMemento& memento = mMotionMementos.editTop();
-        memento.deviceId = entry->deviceId;
-        memento.source = entry->source;
-        memento.xPrecision = entry->xPrecision;
-        memento.yPrecision = entry->yPrecision;
-        memento.downTime = entry->downTime;
-        memento.setPointers(entry);
-        return CONSISTENT;
-    }
-
-    default:
-        return BROKEN;
-    }
-}
-
-void InputDispatcher::InputState::MotionMemento::setPointers(const MotionEntry* entry) {
-    pointerCount = entry->pointerCount;
-    for (uint32_t i = 0; i < entry->pointerCount; i++) {
-        pointerIds[i] = entry->pointerIds[i];
-        pointerCoords[i] = entry->lastSample->pointerCoords[i];
-    }
-}
-
-void InputDispatcher::InputState::synthesizeCancelationEvents(nsecs_t currentTime,
-        Allocator* allocator, Vector<EventEntry*>& outEvents,
-        CancelationOptions options) {
-    for (size_t i = 0; i < mKeyMementos.size(); ) {
-        const KeyMemento& memento = mKeyMementos.itemAt(i);
-        if (shouldCancelKey(memento, options)) {
-            outEvents.push(allocator->obtainKeyEntry(currentTime,
-                    memento.deviceId, memento.source, 0,
-                    AKEY_EVENT_ACTION_UP, memento.flags | AKEY_EVENT_FLAG_CANCELED,
-                    memento.keyCode, memento.scanCode, 0, 0, memento.downTime));
-            mKeyMementos.removeAt(i);
-        } else {
-            i += 1;
-        }
-    }
-
-    for (size_t i = 0; i < mMotionMementos.size(); ) {
-        const MotionMemento& memento = mMotionMementos.itemAt(i);
-        if (shouldCancelMotion(memento, options)) {
-            outEvents.push(allocator->obtainMotionEntry(currentTime,
-                    memento.deviceId, memento.source, 0,
-                    AMOTION_EVENT_ACTION_CANCEL, 0, 0, 0,
-                    memento.xPrecision, memento.yPrecision, memento.downTime,
-                    memento.pointerCount, memento.pointerIds, memento.pointerCoords));
-            mMotionMementos.removeAt(i);
-        } else {
-            i += 1;
-        }
-    }
-}
-
-void InputDispatcher::InputState::clear() {
-    mKeyMementos.clear();
-    mMotionMementos.clear();
-}
-
-void InputDispatcher::InputState::copyPointerStateTo(InputState& other) const {
-    for (size_t i = 0; i < mMotionMementos.size(); i++) {
-        const MotionMemento& memento = mMotionMementos.itemAt(i);
-        if (memento.source & AINPUT_SOURCE_CLASS_POINTER) {
-            for (size_t j = 0; j < other.mMotionMementos.size(); ) {
-                const MotionMemento& otherMemento = other.mMotionMementos.itemAt(j);
-                if (memento.deviceId == otherMemento.deviceId
-                        && memento.source == otherMemento.source) {
-                    other.mMotionMementos.removeAt(j);
-                } else {
-                    j += 1;
-                }
-            }
-            other.mMotionMementos.push(memento);
-        }
-    }
-}
-
-bool InputDispatcher::InputState::shouldCancelKey(const KeyMemento& memento,
-        CancelationOptions options) {
-    switch (options) {
-    case CANCEL_ALL_EVENTS:
-    case CANCEL_NON_POINTER_EVENTS:
-        return true;
-    case CANCEL_FALLBACK_EVENTS:
-        return memento.flags & AKEY_EVENT_FLAG_FALLBACK;
-    default:
-        return false;
-    }
-}
-
-bool InputDispatcher::InputState::shouldCancelMotion(const MotionMemento& memento,
-        CancelationOptions options) {
-    switch (options) {
-    case CANCEL_ALL_EVENTS:
-        return true;
-    case CANCEL_POINTER_EVENTS:
-        return memento.source & AINPUT_SOURCE_CLASS_POINTER;
-    case CANCEL_NON_POINTER_EVENTS:
-        return !(memento.source & AINPUT_SOURCE_CLASS_POINTER);
-    default:
-        return false;
-    }
-}
-
-
-// --- InputDispatcher::Connection ---
-
-InputDispatcher::Connection::Connection(const sp<InputChannel>& inputChannel) :
-        status(STATUS_NORMAL), inputChannel(inputChannel), inputPublisher(inputChannel),
-        lastEventTime(LONG_LONG_MAX), lastDispatchTime(LONG_LONG_MAX) {
-}
-
-InputDispatcher::Connection::~Connection() {
-}
-
-status_t InputDispatcher::Connection::initialize() {
-    return inputPublisher.initialize();
-}
-
-const char* InputDispatcher::Connection::getStatusLabel() const {
-    switch (status) {
-    case STATUS_NORMAL:
-        return "NORMAL";
-
-    case STATUS_BROKEN:
-        return "BROKEN";
-
-    case STATUS_ZOMBIE:
-        return "ZOMBIE";
-
-    default:
-        return "UNKNOWN";
-    }
-}
-
-InputDispatcher::DispatchEntry* InputDispatcher::Connection::findQueuedDispatchEntryForEvent(
-        const EventEntry* eventEntry) const {
-    for (DispatchEntry* dispatchEntry = outboundQueue.tailSentinel.prev;
-            dispatchEntry != & outboundQueue.headSentinel; dispatchEntry = dispatchEntry->prev) {
-        if (dispatchEntry->eventEntry == eventEntry) {
-            return dispatchEntry;
-        }
-    }
-    return NULL;
-}
-
-
-// --- InputDispatcher::CommandEntry ---
-
-InputDispatcher::CommandEntry::CommandEntry() :
-    keyEntry(NULL) {
-}
-
-InputDispatcher::CommandEntry::~CommandEntry() {
-}
-
-
-// --- InputDispatcher::TouchState ---
-
-InputDispatcher::TouchState::TouchState() :
-    down(false), split(false) {
-}
-
-InputDispatcher::TouchState::~TouchState() {
-}
-
-void InputDispatcher::TouchState::reset() {
-    down = false;
-    split = false;
-    windows.clear();
-}
-
-void InputDispatcher::TouchState::copyFrom(const TouchState& other) {
-    down = other.down;
-    split = other.split;
-    windows.clear();
-    windows.appendVector(other.windows);
-}
-
-void InputDispatcher::TouchState::addOrUpdateWindow(const InputWindow* window,
-        int32_t targetFlags, BitSet32 pointerIds) {
-    if (targetFlags & InputTarget::FLAG_SPLIT) {
-        split = true;
-    }
-
-    for (size_t i = 0; i < windows.size(); i++) {
-        TouchedWindow& touchedWindow = windows.editItemAt(i);
-        if (touchedWindow.window == window) {
-            touchedWindow.targetFlags |= targetFlags;
-            touchedWindow.pointerIds.value |= pointerIds.value;
-            return;
-        }
-    }
-
-    windows.push();
-
-    TouchedWindow& touchedWindow = windows.editTop();
-    touchedWindow.window = window;
-    touchedWindow.targetFlags = targetFlags;
-    touchedWindow.pointerIds = pointerIds;
-    touchedWindow.channel = window->inputChannel;
-}
-
-void InputDispatcher::TouchState::removeOutsideTouchWindows() {
-    for (size_t i = 0 ; i < windows.size(); ) {
-        if (windows[i].targetFlags & InputTarget::FLAG_OUTSIDE) {
-            windows.removeAt(i);
-        } else {
-            i += 1;
-        }
-    }
-}
-
-const InputWindow* InputDispatcher::TouchState::getFirstForegroundWindow() {
-    for (size_t i = 0; i < windows.size(); i++) {
-        if (windows[i].targetFlags & InputTarget::FLAG_FOREGROUND) {
-            return windows[i].window;
-        }
-    }
-    return NULL;
-}
-
-
-// --- InputDispatcherThread ---
-
-InputDispatcherThread::InputDispatcherThread(const sp<InputDispatcherInterface>& dispatcher) :
-        Thread(/*canCallJava*/ true), mDispatcher(dispatcher) {
-}
-
-InputDispatcherThread::~InputDispatcherThread() {
-}
-
-bool InputDispatcherThread::threadLoop() {
-    mDispatcher->dispatchOnce();
-    return true;
-}
-
-} // namespace android
diff --git a/libs/ui/InputManager.cpp b/libs/ui/InputManager.cpp
deleted file mode 100644
index 09fce38..0000000
--- a/libs/ui/InputManager.cpp
+++ /dev/null
@@ -1,83 +0,0 @@
-//
-// Copyright 2010 The Android Open Source Project
-//
-// The input manager.
-//
-#define LOG_TAG "InputManager"
-
-//#define LOG_NDEBUG 0
-
-#include <cutils/log.h>
-#include <ui/InputManager.h>
-#include <ui/InputReader.h>
-#include <ui/InputDispatcher.h>
-
-namespace android {
-
-InputManager::InputManager(
-        const sp<EventHubInterface>& eventHub,
-        const sp<InputReaderPolicyInterface>& readerPolicy,
-        const sp<InputDispatcherPolicyInterface>& dispatcherPolicy) {
-    mDispatcher = new InputDispatcher(dispatcherPolicy);
-    mReader = new InputReader(eventHub, readerPolicy, mDispatcher);
-    initialize();
-}
-
-InputManager::InputManager(
-        const sp<InputReaderInterface>& reader,
-        const sp<InputDispatcherInterface>& dispatcher) :
-        mReader(reader),
-        mDispatcher(dispatcher) {
-    initialize();
-}
-
-InputManager::~InputManager() {
-    stop();
-}
-
-void InputManager::initialize() {
-    mReaderThread = new InputReaderThread(mReader);
-    mDispatcherThread = new InputDispatcherThread(mDispatcher);
-}
-
-status_t InputManager::start() {
-    status_t result = mDispatcherThread->run("InputDispatcher", PRIORITY_URGENT_DISPLAY);
-    if (result) {
-        LOGE("Could not start InputDispatcher thread due to error %d.", result);
-        return result;
-    }
-
-    result = mReaderThread->run("InputReader", PRIORITY_URGENT_DISPLAY);
-    if (result) {
-        LOGE("Could not start InputReader thread due to error %d.", result);
-
-        mDispatcherThread->requestExit();
-        return result;
-    }
-
-    return OK;
-}
-
-status_t InputManager::stop() {
-    status_t result = mReaderThread->requestExitAndWait();
-    if (result) {
-        LOGW("Could not stop InputReader thread due to error %d.", result);
-    }
-
-    result = mDispatcherThread->requestExitAndWait();
-    if (result) {
-        LOGW("Could not stop InputDispatcher thread due to error %d.", result);
-    }
-
-    return OK;
-}
-
-sp<InputReaderInterface> InputManager::getReader() {
-    return mReader;
-}
-
-sp<InputDispatcherInterface> InputManager::getDispatcher() {
-    return mDispatcher;
-}
-
-} // namespace android
diff --git a/libs/ui/InputReader.cpp b/libs/ui/InputReader.cpp
deleted file mode 100644
index 51ed09f..0000000
--- a/libs/ui/InputReader.cpp
+++ /dev/null
@@ -1,3549 +0,0 @@
-//
-// Copyright 2010 The Android Open Source Project
-//
-// The input reader.
-//
-#define LOG_TAG "InputReader"
-
-//#define LOG_NDEBUG 0
-
-// Log debug messages for each raw event received from the EventHub.
-#define DEBUG_RAW_EVENTS 0
-
-// Log debug messages about touch screen filtering hacks.
-#define DEBUG_HACKS 0
-
-// Log debug messages about virtual key processing.
-#define DEBUG_VIRTUAL_KEYS 0
-
-// Log debug messages about pointers.
-#define DEBUG_POINTERS 0
-
-// Log debug messages about pointer assignment calculations.
-#define DEBUG_POINTER_ASSIGNMENT 0
-
-#include <cutils/log.h>
-#include <ui/InputReader.h>
-#include <ui/Keyboard.h>
-#include <ui/VirtualKeyMap.h>
-
-#include <stddef.h>
-#include <stdlib.h>
-#include <unistd.h>
-#include <errno.h>
-#include <limits.h>
-#include <math.h>
-
-#define INDENT "  "
-#define INDENT2 "    "
-#define INDENT3 "      "
-#define INDENT4 "        "
-
-namespace android {
-
-// --- Static Functions ---
-
-template<typename T>
-inline static T abs(const T& value) {
-    return value < 0 ? - value : value;
-}
-
-template<typename T>
-inline static T min(const T& a, const T& b) {
-    return a < b ? a : b;
-}
-
-template<typename T>
-inline static void swap(T& a, T& b) {
-    T temp = a;
-    a = b;
-    b = temp;
-}
-
-inline static float avg(float x, float y) {
-    return (x + y) / 2;
-}
-
-inline static float pythag(float x, float y) {
-    return sqrtf(x * x + y * y);
-}
-
-static inline const char* toString(bool value) {
-    return value ? "true" : "false";
-}
-
-static const int32_t keyCodeRotationMap[][4] = {
-        // key codes enumerated counter-clockwise with the original (unrotated) key first
-        // no rotation,        90 degree rotation,  180 degree rotation, 270 degree rotation
-        { AKEYCODE_DPAD_DOWN,   AKEYCODE_DPAD_RIGHT,  AKEYCODE_DPAD_UP,     AKEYCODE_DPAD_LEFT },
-        { AKEYCODE_DPAD_RIGHT,  AKEYCODE_DPAD_UP,     AKEYCODE_DPAD_LEFT,   AKEYCODE_DPAD_DOWN },
-        { AKEYCODE_DPAD_UP,     AKEYCODE_DPAD_LEFT,   AKEYCODE_DPAD_DOWN,   AKEYCODE_DPAD_RIGHT },
-        { AKEYCODE_DPAD_LEFT,   AKEYCODE_DPAD_DOWN,   AKEYCODE_DPAD_RIGHT,  AKEYCODE_DPAD_UP },
-};
-static const int keyCodeRotationMapSize =
-        sizeof(keyCodeRotationMap) / sizeof(keyCodeRotationMap[0]);
-
-int32_t rotateKeyCode(int32_t keyCode, int32_t orientation) {
-    if (orientation != InputReaderPolicyInterface::ROTATION_0) {
-        for (int i = 0; i < keyCodeRotationMapSize; i++) {
-            if (keyCode == keyCodeRotationMap[i][0]) {
-                return keyCodeRotationMap[i][orientation];
-            }
-        }
-    }
-    return keyCode;
-}
-
-static inline bool sourcesMatchMask(uint32_t sources, uint32_t sourceMask) {
-    return (sources & sourceMask & ~ AINPUT_SOURCE_CLASS_MASK) != 0;
-}
-
-
-// --- InputReader ---
-
-InputReader::InputReader(const sp<EventHubInterface>& eventHub,
-        const sp<InputReaderPolicyInterface>& policy,
-        const sp<InputDispatcherInterface>& dispatcher) :
-        mEventHub(eventHub), mPolicy(policy), mDispatcher(dispatcher),
-        mGlobalMetaState(0) {
-    configureExcludedDevices();
-    updateGlobalMetaState();
-    updateInputConfiguration();
-}
-
-InputReader::~InputReader() {
-    for (size_t i = 0; i < mDevices.size(); i++) {
-        delete mDevices.valueAt(i);
-    }
-}
-
-void InputReader::loopOnce() {
-    RawEvent rawEvent;
-    mEventHub->getEvent(& rawEvent);
-
-#if DEBUG_RAW_EVENTS
-    LOGD("Input event: device=%d type=0x%x scancode=%d keycode=%d value=%d",
-            rawEvent.deviceId, rawEvent.type, rawEvent.scanCode, rawEvent.keyCode,
-            rawEvent.value);
-#endif
-
-    process(& rawEvent);
-}
-
-void InputReader::process(const RawEvent* rawEvent) {
-    switch (rawEvent->type) {
-    case EventHubInterface::DEVICE_ADDED:
-        addDevice(rawEvent->deviceId);
-        break;
-
-    case EventHubInterface::DEVICE_REMOVED:
-        removeDevice(rawEvent->deviceId);
-        break;
-
-    case EventHubInterface::FINISHED_DEVICE_SCAN:
-        handleConfigurationChanged(rawEvent->when);
-        break;
-
-    default:
-        consumeEvent(rawEvent);
-        break;
-    }
-}
-
-void InputReader::addDevice(int32_t deviceId) {
-    String8 name = mEventHub->getDeviceName(deviceId);
-    uint32_t classes = mEventHub->getDeviceClasses(deviceId);
-
-    InputDevice* device = createDevice(deviceId, name, classes);
-    device->configure();
-
-    if (device->isIgnored()) {
-        LOGI("Device added: id=%d, name='%s' (ignored non-input device)", deviceId, name.string());
-    } else {
-        LOGI("Device added: id=%d, name='%s', sources=0x%08x", deviceId, name.string(),
-                device->getSources());
-    }
-
-    bool added = false;
-    { // acquire device registry writer lock
-        RWLock::AutoWLock _wl(mDeviceRegistryLock);
-
-        ssize_t deviceIndex = mDevices.indexOfKey(deviceId);
-        if (deviceIndex < 0) {
-            mDevices.add(deviceId, device);
-            added = true;
-        }
-    } // release device registry writer lock
-
-    if (! added) {
-        LOGW("Ignoring spurious device added event for deviceId %d.", deviceId);
-        delete device;
-        return;
-    }
-}
-
-void InputReader::removeDevice(int32_t deviceId) {
-    bool removed = false;
-    InputDevice* device = NULL;
-    { // acquire device registry writer lock
-        RWLock::AutoWLock _wl(mDeviceRegistryLock);
-
-        ssize_t deviceIndex = mDevices.indexOfKey(deviceId);
-        if (deviceIndex >= 0) {
-            device = mDevices.valueAt(deviceIndex);
-            mDevices.removeItemsAt(deviceIndex, 1);
-            removed = true;
-        }
-    } // release device registry writer lock
-
-    if (! removed) {
-        LOGW("Ignoring spurious device removed event for deviceId %d.", deviceId);
-        return;
-    }
-
-    if (device->isIgnored()) {
-        LOGI("Device removed: id=%d, name='%s' (ignored non-input device)",
-                device->getId(), device->getName().string());
-    } else {
-        LOGI("Device removed: id=%d, name='%s', sources=0x%08x",
-                device->getId(), device->getName().string(), device->getSources());
-    }
-
-    device->reset();
-
-    delete device;
-}
-
-InputDevice* InputReader::createDevice(int32_t deviceId, const String8& name, uint32_t classes) {
-    InputDevice* device = new InputDevice(this, deviceId, name);
-
-    // Switch-like devices.
-    if (classes & INPUT_DEVICE_CLASS_SWITCH) {
-        device->addMapper(new SwitchInputMapper(device));
-    }
-
-    // Keyboard-like devices.
-    uint32_t keyboardSources = 0;
-    int32_t keyboardType = AINPUT_KEYBOARD_TYPE_NON_ALPHABETIC;
-    if (classes & INPUT_DEVICE_CLASS_KEYBOARD) {
-        keyboardSources |= AINPUT_SOURCE_KEYBOARD;
-    }
-    if (classes & INPUT_DEVICE_CLASS_ALPHAKEY) {
-        keyboardType = AINPUT_KEYBOARD_TYPE_ALPHABETIC;
-    }
-    if (classes & INPUT_DEVICE_CLASS_DPAD) {
-        keyboardSources |= AINPUT_SOURCE_DPAD;
-    }
-
-    if (keyboardSources != 0) {
-        device->addMapper(new KeyboardInputMapper(device, keyboardSources, keyboardType));
-    }
-
-    // Trackball-like devices.
-    if (classes & INPUT_DEVICE_CLASS_TRACKBALL) {
-        device->addMapper(new TrackballInputMapper(device));
-    }
-
-    // Touchscreen-like devices.
-    if (classes & INPUT_DEVICE_CLASS_TOUCHSCREEN_MT) {
-        device->addMapper(new MultiTouchInputMapper(device));
-    } else if (classes & INPUT_DEVICE_CLASS_TOUCHSCREEN) {
-        device->addMapper(new SingleTouchInputMapper(device));
-    }
-
-    return device;
-}
-
-void InputReader::consumeEvent(const RawEvent* rawEvent) {
-    int32_t deviceId = rawEvent->deviceId;
-
-    { // acquire device registry reader lock
-        RWLock::AutoRLock _rl(mDeviceRegistryLock);
-
-        ssize_t deviceIndex = mDevices.indexOfKey(deviceId);
-        if (deviceIndex < 0) {
-            LOGW("Discarding event for unknown deviceId %d.", deviceId);
-            return;
-        }
-
-        InputDevice* device = mDevices.valueAt(deviceIndex);
-        if (device->isIgnored()) {
-            //LOGD("Discarding event for ignored deviceId %d.", deviceId);
-            return;
-        }
-
-        device->process(rawEvent);
-    } // release device registry reader lock
-}
-
-void InputReader::handleConfigurationChanged(nsecs_t when) {
-    // Reset global meta state because it depends on the list of all configured devices.
-    updateGlobalMetaState();
-
-    // Update input configuration.
-    updateInputConfiguration();
-
-    // Enqueue configuration changed.
-    mDispatcher->notifyConfigurationChanged(when);
-}
-
-void InputReader::configureExcludedDevices() {
-    Vector<String8> excludedDeviceNames;
-    mPolicy->getExcludedDeviceNames(excludedDeviceNames);
-
-    for (size_t i = 0; i < excludedDeviceNames.size(); i++) {
-        mEventHub->addExcludedDevice(excludedDeviceNames[i]);
-    }
-}
-
-void InputReader::updateGlobalMetaState() {
-    { // acquire state lock
-        AutoMutex _l(mStateLock);
-
-        mGlobalMetaState = 0;
-
-        { // acquire device registry reader lock
-            RWLock::AutoRLock _rl(mDeviceRegistryLock);
-
-            for (size_t i = 0; i < mDevices.size(); i++) {
-                InputDevice* device = mDevices.valueAt(i);
-                mGlobalMetaState |= device->getMetaState();
-            }
-        } // release device registry reader lock
-    } // release state lock
-}
-
-int32_t InputReader::getGlobalMetaState() {
-    { // acquire state lock
-        AutoMutex _l(mStateLock);
-
-        return mGlobalMetaState;
-    } // release state lock
-}
-
-void InputReader::updateInputConfiguration() {
-    { // acquire state lock
-        AutoMutex _l(mStateLock);
-
-        int32_t touchScreenConfig = InputConfiguration::TOUCHSCREEN_NOTOUCH;
-        int32_t keyboardConfig = InputConfiguration::KEYBOARD_NOKEYS;
-        int32_t navigationConfig = InputConfiguration::NAVIGATION_NONAV;
-        { // acquire device registry reader lock
-            RWLock::AutoRLock _rl(mDeviceRegistryLock);
-
-            InputDeviceInfo deviceInfo;
-            for (size_t i = 0; i < mDevices.size(); i++) {
-                InputDevice* device = mDevices.valueAt(i);
-                device->getDeviceInfo(& deviceInfo);
-                uint32_t sources = deviceInfo.getSources();
-
-                if ((sources & AINPUT_SOURCE_TOUCHSCREEN) == AINPUT_SOURCE_TOUCHSCREEN) {
-                    touchScreenConfig = InputConfiguration::TOUCHSCREEN_FINGER;
-                }
-                if ((sources & AINPUT_SOURCE_TRACKBALL) == AINPUT_SOURCE_TRACKBALL) {
-                    navigationConfig = InputConfiguration::NAVIGATION_TRACKBALL;
-                } else if ((sources & AINPUT_SOURCE_DPAD) == AINPUT_SOURCE_DPAD) {
-                    navigationConfig = InputConfiguration::NAVIGATION_DPAD;
-                }
-                if (deviceInfo.getKeyboardType() == AINPUT_KEYBOARD_TYPE_ALPHABETIC) {
-                    keyboardConfig = InputConfiguration::KEYBOARD_QWERTY;
-                }
-            }
-        } // release device registry reader lock
-
-        mInputConfiguration.touchScreen = touchScreenConfig;
-        mInputConfiguration.keyboard = keyboardConfig;
-        mInputConfiguration.navigation = navigationConfig;
-    } // release state lock
-}
-
-void InputReader::getInputConfiguration(InputConfiguration* outConfiguration) {
-    { // acquire state lock
-        AutoMutex _l(mStateLock);
-
-        *outConfiguration = mInputConfiguration;
-    } // release state lock
-}
-
-status_t InputReader::getInputDeviceInfo(int32_t deviceId, InputDeviceInfo* outDeviceInfo) {
-    { // acquire device registry reader lock
-        RWLock::AutoRLock _rl(mDeviceRegistryLock);
-
-        ssize_t deviceIndex = mDevices.indexOfKey(deviceId);
-        if (deviceIndex < 0) {
-            return NAME_NOT_FOUND;
-        }
-
-        InputDevice* device = mDevices.valueAt(deviceIndex);
-        if (device->isIgnored()) {
-            return NAME_NOT_FOUND;
-        }
-
-        device->getDeviceInfo(outDeviceInfo);
-        return OK;
-    } // release device registy reader lock
-}
-
-void InputReader::getInputDeviceIds(Vector<int32_t>& outDeviceIds) {
-    outDeviceIds.clear();
-
-    { // acquire device registry reader lock
-        RWLock::AutoRLock _rl(mDeviceRegistryLock);
-
-        size_t numDevices = mDevices.size();
-        for (size_t i = 0; i < numDevices; i++) {
-            InputDevice* device = mDevices.valueAt(i);
-            if (! device->isIgnored()) {
-                outDeviceIds.add(device->getId());
-            }
-        }
-    } // release device registy reader lock
-}
-
-int32_t InputReader::getKeyCodeState(int32_t deviceId, uint32_t sourceMask,
-        int32_t keyCode) {
-    return getState(deviceId, sourceMask, keyCode, & InputDevice::getKeyCodeState);
-}
-
-int32_t InputReader::getScanCodeState(int32_t deviceId, uint32_t sourceMask,
-        int32_t scanCode) {
-    return getState(deviceId, sourceMask, scanCode, & InputDevice::getScanCodeState);
-}
-
-int32_t InputReader::getSwitchState(int32_t deviceId, uint32_t sourceMask, int32_t switchCode) {
-    return getState(deviceId, sourceMask, switchCode, & InputDevice::getSwitchState);
-}
-
-int32_t InputReader::getState(int32_t deviceId, uint32_t sourceMask, int32_t code,
-        GetStateFunc getStateFunc) {
-    { // acquire device registry reader lock
-        RWLock::AutoRLock _rl(mDeviceRegistryLock);
-
-        int32_t result = AKEY_STATE_UNKNOWN;
-        if (deviceId >= 0) {
-            ssize_t deviceIndex = mDevices.indexOfKey(deviceId);
-            if (deviceIndex >= 0) {
-                InputDevice* device = mDevices.valueAt(deviceIndex);
-                if (! device->isIgnored() && sourcesMatchMask(device->getSources(), sourceMask)) {
-                    result = (device->*getStateFunc)(sourceMask, code);
-                }
-            }
-        } else {
-            size_t numDevices = mDevices.size();
-            for (size_t i = 0; i < numDevices; i++) {
-                InputDevice* device = mDevices.valueAt(i);
-                if (! device->isIgnored() && sourcesMatchMask(device->getSources(), sourceMask)) {
-                    result = (device->*getStateFunc)(sourceMask, code);
-                    if (result >= AKEY_STATE_DOWN) {
-                        return result;
-                    }
-                }
-            }
-        }
-        return result;
-    } // release device registy reader lock
-}
-
-bool InputReader::hasKeys(int32_t deviceId, uint32_t sourceMask,
-        size_t numCodes, const int32_t* keyCodes, uint8_t* outFlags) {
-    memset(outFlags, 0, numCodes);
-    return markSupportedKeyCodes(deviceId, sourceMask, numCodes, keyCodes, outFlags);
-}
-
-bool InputReader::markSupportedKeyCodes(int32_t deviceId, uint32_t sourceMask, size_t numCodes,
-        const int32_t* keyCodes, uint8_t* outFlags) {
-    { // acquire device registry reader lock
-        RWLock::AutoRLock _rl(mDeviceRegistryLock);
-        bool result = false;
-        if (deviceId >= 0) {
-            ssize_t deviceIndex = mDevices.indexOfKey(deviceId);
-            if (deviceIndex >= 0) {
-                InputDevice* device = mDevices.valueAt(deviceIndex);
-                if (! device->isIgnored() && sourcesMatchMask(device->getSources(), sourceMask)) {
-                    result = device->markSupportedKeyCodes(sourceMask,
-                            numCodes, keyCodes, outFlags);
-                }
-            }
-        } else {
-            size_t numDevices = mDevices.size();
-            for (size_t i = 0; i < numDevices; i++) {
-                InputDevice* device = mDevices.valueAt(i);
-                if (! device->isIgnored() && sourcesMatchMask(device->getSources(), sourceMask)) {
-                    result |= device->markSupportedKeyCodes(sourceMask,
-                            numCodes, keyCodes, outFlags);
-                }
-            }
-        }
-        return result;
-    } // release device registy reader lock
-}
-
-void InputReader::dump(String8& dump) {
-    mEventHub->dump(dump);
-    dump.append("\n");
-
-    dump.append("Input Reader State:\n");
-
-    { // acquire device registry reader lock
-        RWLock::AutoRLock _rl(mDeviceRegistryLock);
-
-        for (size_t i = 0; i < mDevices.size(); i++) {
-            mDevices.valueAt(i)->dump(dump);
-        }
-    } // release device registy reader lock
-}
-
-
-// --- InputReaderThread ---
-
-InputReaderThread::InputReaderThread(const sp<InputReaderInterface>& reader) :
-        Thread(/*canCallJava*/ true), mReader(reader) {
-}
-
-InputReaderThread::~InputReaderThread() {
-}
-
-bool InputReaderThread::threadLoop() {
-    mReader->loopOnce();
-    return true;
-}
-
-
-// --- InputDevice ---
-
-InputDevice::InputDevice(InputReaderContext* context, int32_t id, const String8& name) :
-        mContext(context), mId(id), mName(name), mSources(0) {
-}
-
-InputDevice::~InputDevice() {
-    size_t numMappers = mMappers.size();
-    for (size_t i = 0; i < numMappers; i++) {
-        delete mMappers[i];
-    }
-    mMappers.clear();
-}
-
-static void dumpMotionRange(String8& dump, const InputDeviceInfo& deviceInfo,
-        int32_t rangeType, const char* name) {
-    const InputDeviceInfo::MotionRange* range = deviceInfo.getMotionRange(rangeType);
-    if (range) {
-        dump.appendFormat(INDENT3 "%s: min=%0.3f, max=%0.3f, flat=%0.3f, fuzz=%0.3f\n",
-                name, range->min, range->max, range->flat, range->fuzz);
-    }
-}
-
-void InputDevice::dump(String8& dump) {
-    InputDeviceInfo deviceInfo;
-    getDeviceInfo(& deviceInfo);
-
-    dump.appendFormat(INDENT "Device %d: %s\n", deviceInfo.getId(),
-            deviceInfo.getName().string());
-    dump.appendFormat(INDENT2 "Sources: 0x%08x\n", deviceInfo.getSources());
-    dump.appendFormat(INDENT2 "KeyboardType: %d\n", deviceInfo.getKeyboardType());
-    if (!deviceInfo.getMotionRanges().isEmpty()) {
-        dump.append(INDENT2 "Motion Ranges:\n");
-        dumpMotionRange(dump, deviceInfo, AINPUT_MOTION_RANGE_X, "X");
-        dumpMotionRange(dump, deviceInfo, AINPUT_MOTION_RANGE_Y, "Y");
-        dumpMotionRange(dump, deviceInfo, AINPUT_MOTION_RANGE_PRESSURE, "Pressure");
-        dumpMotionRange(dump, deviceInfo, AINPUT_MOTION_RANGE_SIZE, "Size");
-        dumpMotionRange(dump, deviceInfo, AINPUT_MOTION_RANGE_TOUCH_MAJOR, "TouchMajor");
-        dumpMotionRange(dump, deviceInfo, AINPUT_MOTION_RANGE_TOUCH_MINOR, "TouchMinor");
-        dumpMotionRange(dump, deviceInfo, AINPUT_MOTION_RANGE_TOOL_MAJOR, "ToolMajor");
-        dumpMotionRange(dump, deviceInfo, AINPUT_MOTION_RANGE_TOOL_MINOR, "ToolMinor");
-        dumpMotionRange(dump, deviceInfo, AINPUT_MOTION_RANGE_ORIENTATION, "Orientation");
-    }
-
-    size_t numMappers = mMappers.size();
-    for (size_t i = 0; i < numMappers; i++) {
-        InputMapper* mapper = mMappers[i];
-        mapper->dump(dump);
-    }
-}
-
-void InputDevice::addMapper(InputMapper* mapper) {
-    mMappers.add(mapper);
-}
-
-void InputDevice::configure() {
-    if (! isIgnored()) {
-        mContext->getEventHub()->getConfiguration(mId, &mConfiguration);
-    }
-
-    mSources = 0;
-
-    size_t numMappers = mMappers.size();
-    for (size_t i = 0; i < numMappers; i++) {
-        InputMapper* mapper = mMappers[i];
-        mapper->configure();
-        mSources |= mapper->getSources();
-    }
-}
-
-void InputDevice::reset() {
-    size_t numMappers = mMappers.size();
-    for (size_t i = 0; i < numMappers; i++) {
-        InputMapper* mapper = mMappers[i];
-        mapper->reset();
-    }
-}
-
-void InputDevice::process(const RawEvent* rawEvent) {
-    size_t numMappers = mMappers.size();
-    for (size_t i = 0; i < numMappers; i++) {
-        InputMapper* mapper = mMappers[i];
-        mapper->process(rawEvent);
-    }
-}
-
-void InputDevice::getDeviceInfo(InputDeviceInfo* outDeviceInfo) {
-    outDeviceInfo->initialize(mId, mName);
-
-    size_t numMappers = mMappers.size();
-    for (size_t i = 0; i < numMappers; i++) {
-        InputMapper* mapper = mMappers[i];
-        mapper->populateDeviceInfo(outDeviceInfo);
-    }
-}
-
-int32_t InputDevice::getKeyCodeState(uint32_t sourceMask, int32_t keyCode) {
-    return getState(sourceMask, keyCode, & InputMapper::getKeyCodeState);
-}
-
-int32_t InputDevice::getScanCodeState(uint32_t sourceMask, int32_t scanCode) {
-    return getState(sourceMask, scanCode, & InputMapper::getScanCodeState);
-}
-
-int32_t InputDevice::getSwitchState(uint32_t sourceMask, int32_t switchCode) {
-    return getState(sourceMask, switchCode, & InputMapper::getSwitchState);
-}
-
-int32_t InputDevice::getState(uint32_t sourceMask, int32_t code, GetStateFunc getStateFunc) {
-    int32_t result = AKEY_STATE_UNKNOWN;
-    size_t numMappers = mMappers.size();
-    for (size_t i = 0; i < numMappers; i++) {
-        InputMapper* mapper = mMappers[i];
-        if (sourcesMatchMask(mapper->getSources(), sourceMask)) {
-            result = (mapper->*getStateFunc)(sourceMask, code);
-            if (result >= AKEY_STATE_DOWN) {
-                return result;
-            }
-        }
-    }
-    return result;
-}
-
-bool InputDevice::markSupportedKeyCodes(uint32_t sourceMask, size_t numCodes,
-        const int32_t* keyCodes, uint8_t* outFlags) {
-    bool result = false;
-    size_t numMappers = mMappers.size();
-    for (size_t i = 0; i < numMappers; i++) {
-        InputMapper* mapper = mMappers[i];
-        if (sourcesMatchMask(mapper->getSources(), sourceMask)) {
-            result |= mapper->markSupportedKeyCodes(sourceMask, numCodes, keyCodes, outFlags);
-        }
-    }
-    return result;
-}
-
-int32_t InputDevice::getMetaState() {
-    int32_t result = 0;
-    size_t numMappers = mMappers.size();
-    for (size_t i = 0; i < numMappers; i++) {
-        InputMapper* mapper = mMappers[i];
-        result |= mapper->getMetaState();
-    }
-    return result;
-}
-
-
-// --- InputMapper ---
-
-InputMapper::InputMapper(InputDevice* device) :
-        mDevice(device), mContext(device->getContext()) {
-}
-
-InputMapper::~InputMapper() {
-}
-
-void InputMapper::populateDeviceInfo(InputDeviceInfo* info) {
-    info->addSource(getSources());
-}
-
-void InputMapper::dump(String8& dump) {
-}
-
-void InputMapper::configure() {
-}
-
-void InputMapper::reset() {
-}
-
-int32_t InputMapper::getKeyCodeState(uint32_t sourceMask, int32_t keyCode) {
-    return AKEY_STATE_UNKNOWN;
-}
-
-int32_t InputMapper::getScanCodeState(uint32_t sourceMask, int32_t scanCode) {
-    return AKEY_STATE_UNKNOWN;
-}
-
-int32_t InputMapper::getSwitchState(uint32_t sourceMask, int32_t switchCode) {
-    return AKEY_STATE_UNKNOWN;
-}
-
-bool InputMapper::markSupportedKeyCodes(uint32_t sourceMask, size_t numCodes,
-        const int32_t* keyCodes, uint8_t* outFlags) {
-    return false;
-}
-
-int32_t InputMapper::getMetaState() {
-    return 0;
-}
-
-
-// --- SwitchInputMapper ---
-
-SwitchInputMapper::SwitchInputMapper(InputDevice* device) :
-        InputMapper(device) {
-}
-
-SwitchInputMapper::~SwitchInputMapper() {
-}
-
-uint32_t SwitchInputMapper::getSources() {
-    return 0;
-}
-
-void SwitchInputMapper::process(const RawEvent* rawEvent) {
-    switch (rawEvent->type) {
-    case EV_SW:
-        processSwitch(rawEvent->when, rawEvent->scanCode, rawEvent->value);
-        break;
-    }
-}
-
-void SwitchInputMapper::processSwitch(nsecs_t when, int32_t switchCode, int32_t switchValue) {
-    getDispatcher()->notifySwitch(when, switchCode, switchValue, 0);
-}
-
-int32_t SwitchInputMapper::getSwitchState(uint32_t sourceMask, int32_t switchCode) {
-    return getEventHub()->getSwitchState(getDeviceId(), switchCode);
-}
-
-
-// --- KeyboardInputMapper ---
-
-KeyboardInputMapper::KeyboardInputMapper(InputDevice* device,
-        uint32_t sources, int32_t keyboardType) :
-        InputMapper(device), mSources(sources),
-        mKeyboardType(keyboardType) {
-    initializeLocked();
-}
-
-KeyboardInputMapper::~KeyboardInputMapper() {
-}
-
-void KeyboardInputMapper::initializeLocked() {
-    mLocked.metaState = AMETA_NONE;
-    mLocked.downTime = 0;
-}
-
-uint32_t KeyboardInputMapper::getSources() {
-    return mSources;
-}
-
-void KeyboardInputMapper::populateDeviceInfo(InputDeviceInfo* info) {
-    InputMapper::populateDeviceInfo(info);
-
-    info->setKeyboardType(mKeyboardType);
-}
-
-void KeyboardInputMapper::dump(String8& dump) {
-    { // acquire lock
-        AutoMutex _l(mLock);
-        dump.append(INDENT2 "Keyboard Input Mapper:\n");
-        dumpParameters(dump);
-        dump.appendFormat(INDENT3 "KeyboardType: %d\n", mKeyboardType);
-        dump.appendFormat(INDENT3 "KeyDowns: %d keys currently down\n", mLocked.keyDowns.size());
-        dump.appendFormat(INDENT3 "MetaState: 0x%0x\n", mLocked.metaState);
-        dump.appendFormat(INDENT3 "DownTime: %lld\n", mLocked.downTime);
-    } // release lock
-}
-
-
-void KeyboardInputMapper::configure() {
-    InputMapper::configure();
-
-    // Configure basic parameters.
-    configureParameters();
-
-    // Reset LEDs.
-    {
-        AutoMutex _l(mLock);
-        resetLedStateLocked();
-    }
-}
-
-void KeyboardInputMapper::configureParameters() {
-    mParameters.orientationAware = false;
-    getDevice()->getConfiguration().tryGetProperty(String8("keyboard.orientationAware"),
-            mParameters.orientationAware);
-
-    mParameters.associatedDisplayId = mParameters.orientationAware ? 0 : -1;
-}
-
-void KeyboardInputMapper::dumpParameters(String8& dump) {
-    dump.append(INDENT3 "Parameters:\n");
-    dump.appendFormat(INDENT4 "AssociatedDisplayId: %d\n",
-            mParameters.associatedDisplayId);
-    dump.appendFormat(INDENT4 "OrientationAware: %s\n",
-            toString(mParameters.orientationAware));
-}
-
-void KeyboardInputMapper::reset() {
-    for (;;) {
-        int32_t keyCode, scanCode;
-        { // acquire lock
-            AutoMutex _l(mLock);
-
-            // Synthesize key up event on reset if keys are currently down.
-            if (mLocked.keyDowns.isEmpty()) {
-                initializeLocked();
-                resetLedStateLocked();
-                break; // done
-            }
-
-            const KeyDown& keyDown = mLocked.keyDowns.top();
-            keyCode = keyDown.keyCode;
-            scanCode = keyDown.scanCode;
-        } // release lock
-
-        nsecs_t when = systemTime(SYSTEM_TIME_MONOTONIC);
-        processKey(when, false, keyCode, scanCode, 0);
-    }
-
-    InputMapper::reset();
-    getContext()->updateGlobalMetaState();
-}
-
-void KeyboardInputMapper::process(const RawEvent* rawEvent) {
-    switch (rawEvent->type) {
-    case EV_KEY: {
-        int32_t scanCode = rawEvent->scanCode;
-        if (isKeyboardOrGamepadKey(scanCode)) {
-            processKey(rawEvent->when, rawEvent->value != 0, rawEvent->keyCode, scanCode,
-                    rawEvent->flags);
-        }
-        break;
-    }
-    }
-}
-
-bool KeyboardInputMapper::isKeyboardOrGamepadKey(int32_t scanCode) {
-    return scanCode < BTN_MOUSE
-        || scanCode >= KEY_OK
-        || (scanCode >= BTN_GAMEPAD && scanCode < BTN_DIGI);
-}
-
-void KeyboardInputMapper::processKey(nsecs_t when, bool down, int32_t keyCode,
-        int32_t scanCode, uint32_t policyFlags) {
-    int32_t newMetaState;
-    nsecs_t downTime;
-    bool metaStateChanged = false;
-
-    { // acquire lock
-        AutoMutex _l(mLock);
-
-        if (down) {
-            // Rotate key codes according to orientation if needed.
-            // Note: getDisplayInfo is non-reentrant so we can continue holding the lock.
-            if (mParameters.orientationAware && mParameters.associatedDisplayId >= 0) {
-                int32_t orientation;
-                if (!getPolicy()->getDisplayInfo(mParameters.associatedDisplayId,
-                        NULL, NULL, & orientation)) {
-                    orientation = InputReaderPolicyInterface::ROTATION_0;
-                }
-
-                keyCode = rotateKeyCode(keyCode, orientation);
-            }
-
-            // Add key down.
-            ssize_t keyDownIndex = findKeyDownLocked(scanCode);
-            if (keyDownIndex >= 0) {
-                // key repeat, be sure to use same keycode as before in case of rotation
-                keyCode = mLocked.keyDowns.itemAt(keyDownIndex).keyCode;
-            } else {
-                // key down
-                mLocked.keyDowns.push();
-                KeyDown& keyDown = mLocked.keyDowns.editTop();
-                keyDown.keyCode = keyCode;
-                keyDown.scanCode = scanCode;
-            }
-
-            mLocked.downTime = when;
-        } else {
-            // Remove key down.
-            ssize_t keyDownIndex = findKeyDownLocked(scanCode);
-            if (keyDownIndex >= 0) {
-                // key up, be sure to use same keycode as before in case of rotation
-                keyCode = mLocked.keyDowns.itemAt(keyDownIndex).keyCode;
-                mLocked.keyDowns.removeAt(size_t(keyDownIndex));
-            } else {
-                // key was not actually down
-                LOGI("Dropping key up from device %s because the key was not down.  "
-                        "keyCode=%d, scanCode=%d",
-                        getDeviceName().string(), keyCode, scanCode);
-                return;
-            }
-        }
-
-        int32_t oldMetaState = mLocked.metaState;
-        newMetaState = updateMetaState(keyCode, down, oldMetaState);
-        if (oldMetaState != newMetaState) {
-            mLocked.metaState = newMetaState;
-            metaStateChanged = true;
-            updateLedStateLocked(false);
-        }
-
-        downTime = mLocked.downTime;
-    } // release lock
-
-    if (metaStateChanged) {
-        getContext()->updateGlobalMetaState();
-    }
-
-    if (policyFlags & POLICY_FLAG_FUNCTION) {
-        newMetaState |= AMETA_FUNCTION_ON;
-    }
-    getDispatcher()->notifyKey(when, getDeviceId(), AINPUT_SOURCE_KEYBOARD, policyFlags,
-            down ? AKEY_EVENT_ACTION_DOWN : AKEY_EVENT_ACTION_UP,
-            AKEY_EVENT_FLAG_FROM_SYSTEM, keyCode, scanCode, newMetaState, downTime);
-}
-
-ssize_t KeyboardInputMapper::findKeyDownLocked(int32_t scanCode) {
-    size_t n = mLocked.keyDowns.size();
-    for (size_t i = 0; i < n; i++) {
-        if (mLocked.keyDowns[i].scanCode == scanCode) {
-            return i;
-        }
-    }
-    return -1;
-}
-
-int32_t KeyboardInputMapper::getKeyCodeState(uint32_t sourceMask, int32_t keyCode) {
-    return getEventHub()->getKeyCodeState(getDeviceId(), keyCode);
-}
-
-int32_t KeyboardInputMapper::getScanCodeState(uint32_t sourceMask, int32_t scanCode) {
-    return getEventHub()->getScanCodeState(getDeviceId(), scanCode);
-}
-
-bool KeyboardInputMapper::markSupportedKeyCodes(uint32_t sourceMask, size_t numCodes,
-        const int32_t* keyCodes, uint8_t* outFlags) {
-    return getEventHub()->markSupportedKeyCodes(getDeviceId(), numCodes, keyCodes, outFlags);
-}
-
-int32_t KeyboardInputMapper::getMetaState() {
-    { // acquire lock
-        AutoMutex _l(mLock);
-        return mLocked.metaState;
-    } // release lock
-}
-
-void KeyboardInputMapper::resetLedStateLocked() {
-    initializeLedStateLocked(mLocked.capsLockLedState, LED_CAPSL);
-    initializeLedStateLocked(mLocked.numLockLedState, LED_NUML);
-    initializeLedStateLocked(mLocked.scrollLockLedState, LED_SCROLLL);
-
-    updateLedStateLocked(true);
-}
-
-void KeyboardInputMapper::initializeLedStateLocked(LockedState::LedState& ledState, int32_t led) {
-    ledState.avail = getEventHub()->hasLed(getDeviceId(), led);
-    ledState.on = false;
-}
-
-void KeyboardInputMapper::updateLedStateLocked(bool reset) {
-    updateLedStateForModifierLocked(mLocked.capsLockLedState, LED_CAPSL,
-            AMETA_CAPS_LOCK_ON, reset);
-    updateLedStateForModifierLocked(mLocked.numLockLedState, LED_NUML,
-            AMETA_NUM_LOCK_ON, reset);
-    updateLedStateForModifierLocked(mLocked.scrollLockLedState, LED_SCROLLL,
-            AMETA_SCROLL_LOCK_ON, reset);
-}
-
-void KeyboardInputMapper::updateLedStateForModifierLocked(LockedState::LedState& ledState,
-        int32_t led, int32_t modifier, bool reset) {
-    if (ledState.avail) {
-        bool desiredState = (mLocked.metaState & modifier) != 0;
-        if (reset || ledState.on != desiredState) {
-            getEventHub()->setLedState(getDeviceId(), led, desiredState);
-            ledState.on = desiredState;
-        }
-    }
-}
-
-
-// --- TrackballInputMapper ---
-
-TrackballInputMapper::TrackballInputMapper(InputDevice* device) :
-        InputMapper(device) {
-    mXPrecision = TRACKBALL_MOVEMENT_THRESHOLD;
-    mYPrecision = TRACKBALL_MOVEMENT_THRESHOLD;
-    mXScale = 1.0f / TRACKBALL_MOVEMENT_THRESHOLD;
-    mYScale = 1.0f / TRACKBALL_MOVEMENT_THRESHOLD;
-
-    initializeLocked();
-}
-
-TrackballInputMapper::~TrackballInputMapper() {
-}
-
-uint32_t TrackballInputMapper::getSources() {
-    return AINPUT_SOURCE_TRACKBALL;
-}
-
-void TrackballInputMapper::populateDeviceInfo(InputDeviceInfo* info) {
-    InputMapper::populateDeviceInfo(info);
-
-    info->addMotionRange(AINPUT_MOTION_RANGE_X, -1.0f, 1.0f, 0.0f, mXScale);
-    info->addMotionRange(AINPUT_MOTION_RANGE_Y, -1.0f, 1.0f, 0.0f, mYScale);
-}
-
-void TrackballInputMapper::dump(String8& dump) {
-    { // acquire lock
-        AutoMutex _l(mLock);
-        dump.append(INDENT2 "Trackball Input Mapper:\n");
-        dumpParameters(dump);
-        dump.appendFormat(INDENT3 "XPrecision: %0.3f\n", mXPrecision);
-        dump.appendFormat(INDENT3 "YPrecision: %0.3f\n", mYPrecision);
-        dump.appendFormat(INDENT3 "Down: %s\n", toString(mLocked.down));
-        dump.appendFormat(INDENT3 "DownTime: %lld\n", mLocked.downTime);
-    } // release lock
-}
-
-void TrackballInputMapper::configure() {
-    InputMapper::configure();
-
-    // Configure basic parameters.
-    configureParameters();
-}
-
-void TrackballInputMapper::configureParameters() {
-    mParameters.orientationAware = false;
-    getDevice()->getConfiguration().tryGetProperty(String8("trackball.orientationAware"),
-            mParameters.orientationAware);
-
-    mParameters.associatedDisplayId = mParameters.orientationAware ? 0 : -1;
-}
-
-void TrackballInputMapper::dumpParameters(String8& dump) {
-    dump.append(INDENT3 "Parameters:\n");
-    dump.appendFormat(INDENT4 "AssociatedDisplayId: %d\n",
-            mParameters.associatedDisplayId);
-    dump.appendFormat(INDENT4 "OrientationAware: %s\n",
-            toString(mParameters.orientationAware));
-}
-
-void TrackballInputMapper::initializeLocked() {
-    mAccumulator.clear();
-
-    mLocked.down = false;
-    mLocked.downTime = 0;
-}
-
-void TrackballInputMapper::reset() {
-    for (;;) {
-        { // acquire lock
-            AutoMutex _l(mLock);
-
-            if (! mLocked.down) {
-                initializeLocked();
-                break; // done
-            }
-        } // release lock
-
-        // Synthesize trackball button up event on reset.
-        nsecs_t when = systemTime(SYSTEM_TIME_MONOTONIC);
-        mAccumulator.fields = Accumulator::FIELD_BTN_MOUSE;
-        mAccumulator.btnMouse = false;
-        sync(when);
-    }
-
-    InputMapper::reset();
-}
-
-void TrackballInputMapper::process(const RawEvent* rawEvent) {
-    switch (rawEvent->type) {
-    case EV_KEY:
-        switch (rawEvent->scanCode) {
-        case BTN_MOUSE:
-            mAccumulator.fields |= Accumulator::FIELD_BTN_MOUSE;
-            mAccumulator.btnMouse = rawEvent->value != 0;
-            // Sync now since BTN_MOUSE is not necessarily followed by SYN_REPORT and
-            // we need to ensure that we report the up/down promptly.
-            sync(rawEvent->when);
-            break;
-        }
-        break;
-
-    case EV_REL:
-        switch (rawEvent->scanCode) {
-        case REL_X:
-            mAccumulator.fields |= Accumulator::FIELD_REL_X;
-            mAccumulator.relX = rawEvent->value;
-            break;
-        case REL_Y:
-            mAccumulator.fields |= Accumulator::FIELD_REL_Y;
-            mAccumulator.relY = rawEvent->value;
-            break;
-        }
-        break;
-
-    case EV_SYN:
-        switch (rawEvent->scanCode) {
-        case SYN_REPORT:
-            sync(rawEvent->when);
-            break;
-        }
-        break;
-    }
-}
-
-void TrackballInputMapper::sync(nsecs_t when) {
-    uint32_t fields = mAccumulator.fields;
-    if (fields == 0) {
-        return; // no new state changes, so nothing to do
-    }
-
-    int motionEventAction;
-    PointerCoords pointerCoords;
-    nsecs_t downTime;
-    { // acquire lock
-        AutoMutex _l(mLock);
-
-        bool downChanged = fields & Accumulator::FIELD_BTN_MOUSE;
-
-        if (downChanged) {
-            if (mAccumulator.btnMouse) {
-                mLocked.down = true;
-                mLocked.downTime = when;
-            } else {
-                mLocked.down = false;
-            }
-        }
-
-        downTime = mLocked.downTime;
-        float x = fields & Accumulator::FIELD_REL_X ? mAccumulator.relX * mXScale : 0.0f;
-        float y = fields & Accumulator::FIELD_REL_Y ? mAccumulator.relY * mYScale : 0.0f;
-
-        if (downChanged) {
-            motionEventAction = mLocked.down ? AMOTION_EVENT_ACTION_DOWN : AMOTION_EVENT_ACTION_UP;
-        } else {
-            motionEventAction = AMOTION_EVENT_ACTION_MOVE;
-        }
-
-        pointerCoords.x = x;
-        pointerCoords.y = y;
-        pointerCoords.pressure = mLocked.down ? 1.0f : 0.0f;
-        pointerCoords.size = 0;
-        pointerCoords.touchMajor = 0;
-        pointerCoords.touchMinor = 0;
-        pointerCoords.toolMajor = 0;
-        pointerCoords.toolMinor = 0;
-        pointerCoords.orientation = 0;
-
-        if (mParameters.orientationAware && mParameters.associatedDisplayId >= 0
-                && (x != 0.0f || y != 0.0f)) {
-            // Rotate motion based on display orientation if needed.
-            // Note: getDisplayInfo is non-reentrant so we can continue holding the lock.
-            int32_t orientation;
-            if (! getPolicy()->getDisplayInfo(mParameters.associatedDisplayId,
-                    NULL, NULL, & orientation)) {
-                orientation = InputReaderPolicyInterface::ROTATION_0;
-            }
-
-            float temp;
-            switch (orientation) {
-            case InputReaderPolicyInterface::ROTATION_90:
-                temp = pointerCoords.x;
-                pointerCoords.x = pointerCoords.y;
-                pointerCoords.y = - temp;
-                break;
-
-            case InputReaderPolicyInterface::ROTATION_180:
-                pointerCoords.x = - pointerCoords.x;
-                pointerCoords.y = - pointerCoords.y;
-                break;
-
-            case InputReaderPolicyInterface::ROTATION_270:
-                temp = pointerCoords.x;
-                pointerCoords.x = - pointerCoords.y;
-                pointerCoords.y = temp;
-                break;
-            }
-        }
-    } // release lock
-
-    int32_t metaState = mContext->getGlobalMetaState();
-    int32_t pointerId = 0;
-    getDispatcher()->notifyMotion(when, getDeviceId(), AINPUT_SOURCE_TRACKBALL, 0,
-            motionEventAction, 0, metaState, AMOTION_EVENT_EDGE_FLAG_NONE,
-            1, &pointerId, &pointerCoords, mXPrecision, mYPrecision, downTime);
-
-    mAccumulator.clear();
-}
-
-int32_t TrackballInputMapper::getScanCodeState(uint32_t sourceMask, int32_t scanCode) {
-    if (scanCode >= BTN_MOUSE && scanCode < BTN_JOYSTICK) {
-        return getEventHub()->getScanCodeState(getDeviceId(), scanCode);
-    } else {
-        return AKEY_STATE_UNKNOWN;
-    }
-}
-
-
-// --- TouchInputMapper ---
-
-TouchInputMapper::TouchInputMapper(InputDevice* device) :
-        InputMapper(device) {
-    mLocked.surfaceOrientation = -1;
-    mLocked.surfaceWidth = -1;
-    mLocked.surfaceHeight = -1;
-
-    initializeLocked();
-}
-
-TouchInputMapper::~TouchInputMapper() {
-}
-
-uint32_t TouchInputMapper::getSources() {
-    switch (mParameters.deviceType) {
-    case Parameters::DEVICE_TYPE_TOUCH_SCREEN:
-        return AINPUT_SOURCE_TOUCHSCREEN;
-    case Parameters::DEVICE_TYPE_TOUCH_PAD:
-        return AINPUT_SOURCE_TOUCHPAD;
-    default:
-        assert(false);
-        return AINPUT_SOURCE_UNKNOWN;
-    }
-}
-
-void TouchInputMapper::populateDeviceInfo(InputDeviceInfo* info) {
-    InputMapper::populateDeviceInfo(info);
-
-    { // acquire lock
-        AutoMutex _l(mLock);
-
-        // Ensure surface information is up to date so that orientation changes are
-        // noticed immediately.
-        configureSurfaceLocked();
-
-        info->addMotionRange(AINPUT_MOTION_RANGE_X, mLocked.orientedRanges.x);
-        info->addMotionRange(AINPUT_MOTION_RANGE_Y, mLocked.orientedRanges.y);
-
-        if (mLocked.orientedRanges.havePressure) {
-            info->addMotionRange(AINPUT_MOTION_RANGE_PRESSURE,
-                    mLocked.orientedRanges.pressure);
-        }
-
-        if (mLocked.orientedRanges.haveSize) {
-            info->addMotionRange(AINPUT_MOTION_RANGE_SIZE,
-                    mLocked.orientedRanges.size);
-        }
-
-        if (mLocked.orientedRanges.haveTouchSize) {
-            info->addMotionRange(AINPUT_MOTION_RANGE_TOUCH_MAJOR,
-                    mLocked.orientedRanges.touchMajor);
-            info->addMotionRange(AINPUT_MOTION_RANGE_TOUCH_MINOR,
-                    mLocked.orientedRanges.touchMinor);
-        }
-
-        if (mLocked.orientedRanges.haveToolSize) {
-            info->addMotionRange(AINPUT_MOTION_RANGE_TOOL_MAJOR,
-                    mLocked.orientedRanges.toolMajor);
-            info->addMotionRange(AINPUT_MOTION_RANGE_TOOL_MINOR,
-                    mLocked.orientedRanges.toolMinor);
-        }
-
-        if (mLocked.orientedRanges.haveOrientation) {
-            info->addMotionRange(AINPUT_MOTION_RANGE_ORIENTATION,
-                    mLocked.orientedRanges.orientation);
-        }
-    } // release lock
-}
-
-void TouchInputMapper::dump(String8& dump) {
-    { // acquire lock
-        AutoMutex _l(mLock);
-        dump.append(INDENT2 "Touch Input Mapper:\n");
-        dumpParameters(dump);
-        dumpVirtualKeysLocked(dump);
-        dumpRawAxes(dump);
-        dumpCalibration(dump);
-        dumpSurfaceLocked(dump);
-        dump.appendFormat(INDENT3 "Translation and Scaling Factors:\n");
-        dump.appendFormat(INDENT4 "XOrigin: %d\n", mLocked.xOrigin);
-        dump.appendFormat(INDENT4 "YOrigin: %d\n", mLocked.yOrigin);
-        dump.appendFormat(INDENT4 "XScale: %0.3f\n", mLocked.xScale);
-        dump.appendFormat(INDENT4 "YScale: %0.3f\n", mLocked.yScale);
-        dump.appendFormat(INDENT4 "XPrecision: %0.3f\n", mLocked.xPrecision);
-        dump.appendFormat(INDENT4 "YPrecision: %0.3f\n", mLocked.yPrecision);
-        dump.appendFormat(INDENT4 "GeometricScale: %0.3f\n", mLocked.geometricScale);
-        dump.appendFormat(INDENT4 "ToolSizeLinearScale: %0.3f\n", mLocked.toolSizeLinearScale);
-        dump.appendFormat(INDENT4 "ToolSizeLinearBias: %0.3f\n", mLocked.toolSizeLinearBias);
-        dump.appendFormat(INDENT4 "ToolSizeAreaScale: %0.3f\n", mLocked.toolSizeAreaScale);
-        dump.appendFormat(INDENT4 "ToolSizeAreaBias: %0.3f\n", mLocked.toolSizeAreaBias);
-        dump.appendFormat(INDENT4 "PressureScale: %0.3f\n", mLocked.pressureScale);
-        dump.appendFormat(INDENT4 "SizeScale: %0.3f\n", mLocked.sizeScale);
-        dump.appendFormat(INDENT4 "OrientationSCale: %0.3f\n", mLocked.orientationScale);
-    } // release lock
-}
-
-void TouchInputMapper::initializeLocked() {
-    mCurrentTouch.clear();
-    mLastTouch.clear();
-    mDownTime = 0;
-
-    for (uint32_t i = 0; i < MAX_POINTERS; i++) {
-        mAveragingTouchFilter.historyStart[i] = 0;
-        mAveragingTouchFilter.historyEnd[i] = 0;
-    }
-
-    mJumpyTouchFilter.jumpyPointsDropped = 0;
-
-    mLocked.currentVirtualKey.down = false;
-
-    mLocked.orientedRanges.havePressure = false;
-    mLocked.orientedRanges.haveSize = false;
-    mLocked.orientedRanges.haveTouchSize = false;
-    mLocked.orientedRanges.haveToolSize = false;
-    mLocked.orientedRanges.haveOrientation = false;
-}
-
-void TouchInputMapper::configure() {
-    InputMapper::configure();
-
-    // Configure basic parameters.
-    configureParameters();
-
-    // Configure absolute axis information.
-    configureRawAxes();
-
-    // Prepare input device calibration.
-    parseCalibration();
-    resolveCalibration();
-
-    { // acquire lock
-        AutoMutex _l(mLock);
-
-         // Configure surface dimensions and orientation.
-        configureSurfaceLocked();
-    } // release lock
-}
-
-void TouchInputMapper::configureParameters() {
-    mParameters.useBadTouchFilter = getPolicy()->filterTouchEvents();
-    mParameters.useAveragingTouchFilter = getPolicy()->filterTouchEvents();
-    mParameters.useJumpyTouchFilter = getPolicy()->filterJumpyTouchEvents();
-
-    String8 deviceTypeString;
-    mParameters.deviceType = Parameters::DEVICE_TYPE_TOUCH_SCREEN;
-    if (getDevice()->getConfiguration().tryGetProperty(String8("touch.deviceType"),
-            deviceTypeString)) {
-        if (deviceTypeString == "touchPad") {
-            mParameters.deviceType = Parameters::DEVICE_TYPE_TOUCH_PAD;
-        } else if (deviceTypeString != "touchScreen") {
-            LOGW("Invalid value for touch.deviceType: '%s'", deviceTypeString.string());
-        }
-    }
-    bool isTouchScreen = mParameters.deviceType == Parameters::DEVICE_TYPE_TOUCH_SCREEN;
-
-    mParameters.orientationAware = isTouchScreen;
-    getDevice()->getConfiguration().tryGetProperty(String8("touch.orientationAware"),
-            mParameters.orientationAware);
-
-    mParameters.associatedDisplayId = mParameters.orientationAware || isTouchScreen ? 0 : -1;
-}
-
-void TouchInputMapper::dumpParameters(String8& dump) {
-    dump.append(INDENT3 "Parameters:\n");
-
-    switch (mParameters.deviceType) {
-    case Parameters::DEVICE_TYPE_TOUCH_SCREEN:
-        dump.append(INDENT4 "DeviceType: touchScreen\n");
-        break;
-    case Parameters::DEVICE_TYPE_TOUCH_PAD:
-        dump.append(INDENT4 "DeviceType: touchPad\n");
-        break;
-    default:
-        assert(false);
-    }
-
-    dump.appendFormat(INDENT4 "AssociatedDisplayId: %d\n",
-            mParameters.associatedDisplayId);
-    dump.appendFormat(INDENT4 "OrientationAware: %s\n",
-            toString(mParameters.orientationAware));
-
-    dump.appendFormat(INDENT4 "UseBadTouchFilter: %s\n",
-            toString(mParameters.useBadTouchFilter));
-    dump.appendFormat(INDENT4 "UseAveragingTouchFilter: %s\n",
-            toString(mParameters.useAveragingTouchFilter));
-    dump.appendFormat(INDENT4 "UseJumpyTouchFilter: %s\n",
-            toString(mParameters.useJumpyTouchFilter));
-}
-
-void TouchInputMapper::configureRawAxes() {
-    mRawAxes.x.clear();
-    mRawAxes.y.clear();
-    mRawAxes.pressure.clear();
-    mRawAxes.touchMajor.clear();
-    mRawAxes.touchMinor.clear();
-    mRawAxes.toolMajor.clear();
-    mRawAxes.toolMinor.clear();
-    mRawAxes.orientation.clear();
-}
-
-static void dumpAxisInfo(String8& dump, RawAbsoluteAxisInfo axis, const char* name) {
-    if (axis.valid) {
-        dump.appendFormat(INDENT4 "%s: min=%d, max=%d, flat=%d, fuzz=%d\n",
-                name, axis.minValue, axis.maxValue, axis.flat, axis.fuzz);
-    } else {
-        dump.appendFormat(INDENT4 "%s: unknown range\n", name);
-    }
-}
-
-void TouchInputMapper::dumpRawAxes(String8& dump) {
-    dump.append(INDENT3 "Raw Axes:\n");
-    dumpAxisInfo(dump, mRawAxes.x, "X");
-    dumpAxisInfo(dump, mRawAxes.y, "Y");
-    dumpAxisInfo(dump, mRawAxes.pressure, "Pressure");
-    dumpAxisInfo(dump, mRawAxes.touchMajor, "TouchMajor");
-    dumpAxisInfo(dump, mRawAxes.touchMinor, "TouchMinor");
-    dumpAxisInfo(dump, mRawAxes.toolMajor, "ToolMajor");
-    dumpAxisInfo(dump, mRawAxes.toolMinor, "ToolMinor");
-    dumpAxisInfo(dump, mRawAxes.orientation, "Orientation");
-}
-
-bool TouchInputMapper::configureSurfaceLocked() {
-    // Update orientation and dimensions if needed.
-    int32_t orientation = InputReaderPolicyInterface::ROTATION_0;
-    int32_t width = mRawAxes.x.getRange();
-    int32_t height = mRawAxes.y.getRange();
-
-    if (mParameters.associatedDisplayId >= 0) {
-        bool wantSize = mParameters.deviceType == Parameters::DEVICE_TYPE_TOUCH_SCREEN;
-        bool wantOrientation = mParameters.orientationAware;
-
-        // Note: getDisplayInfo is non-reentrant so we can continue holding the lock.
-        if (! getPolicy()->getDisplayInfo(mParameters.associatedDisplayId,
-                wantSize ? &width : NULL, wantSize ? &height : NULL,
-                wantOrientation ? &orientation : NULL)) {
-            return false;
-        }
-    }
-
-    bool orientationChanged = mLocked.surfaceOrientation != orientation;
-    if (orientationChanged) {
-        mLocked.surfaceOrientation = orientation;
-    }
-
-    bool sizeChanged = mLocked.surfaceWidth != width || mLocked.surfaceHeight != height;
-    if (sizeChanged) {
-        LOGI("Device reconfigured: id=%d, name='%s', display size is now %dx%d",
-                getDeviceId(), getDeviceName().string(), width, height);
-
-        mLocked.surfaceWidth = width;
-        mLocked.surfaceHeight = height;
-
-        // Configure X and Y factors.
-        if (mRawAxes.x.valid && mRawAxes.y.valid) {
-            mLocked.xOrigin = mCalibration.haveXOrigin
-                    ? mCalibration.xOrigin
-                    : mRawAxes.x.minValue;
-            mLocked.yOrigin = mCalibration.haveYOrigin
-                    ? mCalibration.yOrigin
-                    : mRawAxes.y.minValue;
-            mLocked.xScale = mCalibration.haveXScale
-                    ? mCalibration.xScale
-                    : float(width) / mRawAxes.x.getRange();
-            mLocked.yScale = mCalibration.haveYScale
-                    ? mCalibration.yScale
-                    : float(height) / mRawAxes.y.getRange();
-            mLocked.xPrecision = 1.0f / mLocked.xScale;
-            mLocked.yPrecision = 1.0f / mLocked.yScale;
-
-            configureVirtualKeysLocked();
-        } else {
-            LOGW(INDENT "Touch device did not report support for X or Y axis!");
-            mLocked.xOrigin = 0;
-            mLocked.yOrigin = 0;
-            mLocked.xScale = 1.0f;
-            mLocked.yScale = 1.0f;
-            mLocked.xPrecision = 1.0f;
-            mLocked.yPrecision = 1.0f;
-        }
-
-        // Scale factor for terms that are not oriented in a particular axis.
-        // If the pixels are square then xScale == yScale otherwise we fake it
-        // by choosing an average.
-        mLocked.geometricScale = avg(mLocked.xScale, mLocked.yScale);
-
-        // Size of diagonal axis.
-        float diagonalSize = pythag(width, height);
-
-        // TouchMajor and TouchMinor factors.
-        if (mCalibration.touchSizeCalibration != Calibration::TOUCH_SIZE_CALIBRATION_NONE) {
-            mLocked.orientedRanges.haveTouchSize = true;
-            mLocked.orientedRanges.touchMajor.min = 0;
-            mLocked.orientedRanges.touchMajor.max = diagonalSize;
-            mLocked.orientedRanges.touchMajor.flat = 0;
-            mLocked.orientedRanges.touchMajor.fuzz = 0;
-            mLocked.orientedRanges.touchMinor = mLocked.orientedRanges.touchMajor;
-        }
-
-        // ToolMajor and ToolMinor factors.
-        mLocked.toolSizeLinearScale = 0;
-        mLocked.toolSizeLinearBias = 0;
-        mLocked.toolSizeAreaScale = 0;
-        mLocked.toolSizeAreaBias = 0;
-        if (mCalibration.toolSizeCalibration != Calibration::TOOL_SIZE_CALIBRATION_NONE) {
-            if (mCalibration.toolSizeCalibration == Calibration::TOOL_SIZE_CALIBRATION_LINEAR) {
-                if (mCalibration.haveToolSizeLinearScale) {
-                    mLocked.toolSizeLinearScale = mCalibration.toolSizeLinearScale;
-                } else if (mRawAxes.toolMajor.valid && mRawAxes.toolMajor.maxValue != 0) {
-                    mLocked.toolSizeLinearScale = float(min(width, height))
-                            / mRawAxes.toolMajor.maxValue;
-                }
-
-                if (mCalibration.haveToolSizeLinearBias) {
-                    mLocked.toolSizeLinearBias = mCalibration.toolSizeLinearBias;
-                }
-            } else if (mCalibration.toolSizeCalibration ==
-                    Calibration::TOOL_SIZE_CALIBRATION_AREA) {
-                if (mCalibration.haveToolSizeLinearScale) {
-                    mLocked.toolSizeLinearScale = mCalibration.toolSizeLinearScale;
-                } else {
-                    mLocked.toolSizeLinearScale = min(width, height);
-                }
-
-                if (mCalibration.haveToolSizeLinearBias) {
-                    mLocked.toolSizeLinearBias = mCalibration.toolSizeLinearBias;
-                }
-
-                if (mCalibration.haveToolSizeAreaScale) {
-                    mLocked.toolSizeAreaScale = mCalibration.toolSizeAreaScale;
-                } else if (mRawAxes.toolMajor.valid && mRawAxes.toolMajor.maxValue != 0) {
-                    mLocked.toolSizeAreaScale = 1.0f / mRawAxes.toolMajor.maxValue;
-                }
-
-                if (mCalibration.haveToolSizeAreaBias) {
-                    mLocked.toolSizeAreaBias = mCalibration.toolSizeAreaBias;
-                }
-            }
-
-            mLocked.orientedRanges.haveToolSize = true;
-            mLocked.orientedRanges.toolMajor.min = 0;
-            mLocked.orientedRanges.toolMajor.max = diagonalSize;
-            mLocked.orientedRanges.toolMajor.flat = 0;
-            mLocked.orientedRanges.toolMajor.fuzz = 0;
-            mLocked.orientedRanges.toolMinor = mLocked.orientedRanges.toolMajor;
-        }
-
-        // Pressure factors.
-        mLocked.pressureScale = 0;
-        if (mCalibration.pressureCalibration != Calibration::PRESSURE_CALIBRATION_NONE) {
-            RawAbsoluteAxisInfo rawPressureAxis;
-            switch (mCalibration.pressureSource) {
-            case Calibration::PRESSURE_SOURCE_PRESSURE:
-                rawPressureAxis = mRawAxes.pressure;
-                break;
-            case Calibration::PRESSURE_SOURCE_TOUCH:
-                rawPressureAxis = mRawAxes.touchMajor;
-                break;
-            default:
-                rawPressureAxis.clear();
-            }
-
-            if (mCalibration.pressureCalibration == Calibration::PRESSURE_CALIBRATION_PHYSICAL
-                    || mCalibration.pressureCalibration
-                            == Calibration::PRESSURE_CALIBRATION_AMPLITUDE) {
-                if (mCalibration.havePressureScale) {
-                    mLocked.pressureScale = mCalibration.pressureScale;
-                } else if (rawPressureAxis.valid && rawPressureAxis.maxValue != 0) {
-                    mLocked.pressureScale = 1.0f / rawPressureAxis.maxValue;
-                }
-            }
-
-            mLocked.orientedRanges.havePressure = true;
-            mLocked.orientedRanges.pressure.min = 0;
-            mLocked.orientedRanges.pressure.max = 1.0;
-            mLocked.orientedRanges.pressure.flat = 0;
-            mLocked.orientedRanges.pressure.fuzz = 0;
-        }
-
-        // Size factors.
-        mLocked.sizeScale = 0;
-        if (mCalibration.sizeCalibration != Calibration::SIZE_CALIBRATION_NONE) {
-            if (mCalibration.sizeCalibration == Calibration::SIZE_CALIBRATION_NORMALIZED) {
-                if (mRawAxes.toolMajor.valid && mRawAxes.toolMajor.maxValue != 0) {
-                    mLocked.sizeScale = 1.0f / mRawAxes.toolMajor.maxValue;
-                }
-            }
-
-            mLocked.orientedRanges.haveSize = true;
-            mLocked.orientedRanges.size.min = 0;
-            mLocked.orientedRanges.size.max = 1.0;
-            mLocked.orientedRanges.size.flat = 0;
-            mLocked.orientedRanges.size.fuzz = 0;
-        }
-
-        // Orientation
-        mLocked.orientationScale = 0;
-        if (mCalibration.orientationCalibration != Calibration::ORIENTATION_CALIBRATION_NONE) {
-            if (mCalibration.orientationCalibration
-                    == Calibration::ORIENTATION_CALIBRATION_INTERPOLATED) {
-                if (mRawAxes.orientation.valid && mRawAxes.orientation.maxValue != 0) {
-                    mLocked.orientationScale = float(M_PI_2) / mRawAxes.orientation.maxValue;
-                }
-            }
-
-            mLocked.orientedRanges.orientation.min = - M_PI_2;
-            mLocked.orientedRanges.orientation.max = M_PI_2;
-            mLocked.orientedRanges.orientation.flat = 0;
-            mLocked.orientedRanges.orientation.fuzz = 0;
-        }
-    }
-
-    if (orientationChanged || sizeChanged) {
-        // Compute oriented surface dimensions, precision, and scales.
-        float orientedXScale, orientedYScale;
-        switch (mLocked.surfaceOrientation) {
-        case InputReaderPolicyInterface::ROTATION_90:
-        case InputReaderPolicyInterface::ROTATION_270:
-            mLocked.orientedSurfaceWidth = mLocked.surfaceHeight;
-            mLocked.orientedSurfaceHeight = mLocked.surfaceWidth;
-            mLocked.orientedXPrecision = mLocked.yPrecision;
-            mLocked.orientedYPrecision = mLocked.xPrecision;
-            orientedXScale = mLocked.yScale;
-            orientedYScale = mLocked.xScale;
-            break;
-        default:
-            mLocked.orientedSurfaceWidth = mLocked.surfaceWidth;
-            mLocked.orientedSurfaceHeight = mLocked.surfaceHeight;
-            mLocked.orientedXPrecision = mLocked.xPrecision;
-            mLocked.orientedYPrecision = mLocked.yPrecision;
-            orientedXScale = mLocked.xScale;
-            orientedYScale = mLocked.yScale;
-            break;
-        }
-
-        // Configure position ranges.
-        mLocked.orientedRanges.x.min = 0;
-        mLocked.orientedRanges.x.max = mLocked.orientedSurfaceWidth;
-        mLocked.orientedRanges.x.flat = 0;
-        mLocked.orientedRanges.x.fuzz = orientedXScale;
-
-        mLocked.orientedRanges.y.min = 0;
-        mLocked.orientedRanges.y.max = mLocked.orientedSurfaceHeight;
-        mLocked.orientedRanges.y.flat = 0;
-        mLocked.orientedRanges.y.fuzz = orientedYScale;
-    }
-
-    return true;
-}
-
-void TouchInputMapper::dumpSurfaceLocked(String8& dump) {
-    dump.appendFormat(INDENT3 "SurfaceWidth: %dpx\n", mLocked.surfaceWidth);
-    dump.appendFormat(INDENT3 "SurfaceHeight: %dpx\n", mLocked.surfaceHeight);
-    dump.appendFormat(INDENT3 "SurfaceOrientation: %d\n", mLocked.surfaceOrientation);
-}
-
-void TouchInputMapper::configureVirtualKeysLocked() {
-    assert(mRawAxes.x.valid && mRawAxes.y.valid);
-
-    Vector<VirtualKeyDefinition> virtualKeyDefinitions;
-    getEventHub()->getVirtualKeyDefinitions(getDeviceId(), virtualKeyDefinitions);
-
-    mLocked.virtualKeys.clear();
-
-    if (virtualKeyDefinitions.size() == 0) {
-        return;
-    }
-
-    mLocked.virtualKeys.setCapacity(virtualKeyDefinitions.size());
-
-    int32_t touchScreenLeft = mRawAxes.x.minValue;
-    int32_t touchScreenTop = mRawAxes.y.minValue;
-    int32_t touchScreenWidth = mRawAxes.x.getRange();
-    int32_t touchScreenHeight = mRawAxes.y.getRange();
-
-    for (size_t i = 0; i < virtualKeyDefinitions.size(); i++) {
-        const VirtualKeyDefinition& virtualKeyDefinition =
-                virtualKeyDefinitions[i];
-
-        mLocked.virtualKeys.add();
-        VirtualKey& virtualKey = mLocked.virtualKeys.editTop();
-
-        virtualKey.scanCode = virtualKeyDefinition.scanCode;
-        int32_t keyCode;
-        uint32_t flags;
-        if (getEventHub()->scancodeToKeycode(getDeviceId(), virtualKey.scanCode,
-                & keyCode, & flags)) {
-            LOGW(INDENT "VirtualKey %d: could not obtain key code, ignoring",
-                    virtualKey.scanCode);
-            mLocked.virtualKeys.pop(); // drop the key
-            continue;
-        }
-
-        virtualKey.keyCode = keyCode;
-        virtualKey.flags = flags;
-
-        // convert the key definition's display coordinates into touch coordinates for a hit box
-        int32_t halfWidth = virtualKeyDefinition.width / 2;
-        int32_t halfHeight = virtualKeyDefinition.height / 2;
-
-        virtualKey.hitLeft = (virtualKeyDefinition.centerX - halfWidth)
-                * touchScreenWidth / mLocked.surfaceWidth + touchScreenLeft;
-        virtualKey.hitRight= (virtualKeyDefinition.centerX + halfWidth)
-                * touchScreenWidth / mLocked.surfaceWidth + touchScreenLeft;
-        virtualKey.hitTop = (virtualKeyDefinition.centerY - halfHeight)
-                * touchScreenHeight / mLocked.surfaceHeight + touchScreenTop;
-        virtualKey.hitBottom = (virtualKeyDefinition.centerY + halfHeight)
-                * touchScreenHeight / mLocked.surfaceHeight + touchScreenTop;
-
-    }
-}
-
-void TouchInputMapper::dumpVirtualKeysLocked(String8& dump) {
-    if (!mLocked.virtualKeys.isEmpty()) {
-        dump.append(INDENT3 "Virtual Keys:\n");
-
-        for (size_t i = 0; i < mLocked.virtualKeys.size(); i++) {
-            const VirtualKey& virtualKey = mLocked.virtualKeys.itemAt(i);
-            dump.appendFormat(INDENT4 "%d: scanCode=%d, keyCode=%d, "
-                    "hitLeft=%d, hitRight=%d, hitTop=%d, hitBottom=%d\n",
-                    i, virtualKey.scanCode, virtualKey.keyCode,
-                    virtualKey.hitLeft, virtualKey.hitRight,
-                    virtualKey.hitTop, virtualKey.hitBottom);
-        }
-    }
-}
-
-void TouchInputMapper::parseCalibration() {
-    const PropertyMap& in = getDevice()->getConfiguration();
-    Calibration& out = mCalibration;
-
-    // Position
-    out.haveXOrigin = in.tryGetProperty(String8("touch.position.xOrigin"), out.xOrigin);
-    out.haveYOrigin = in.tryGetProperty(String8("touch.position.yOrigin"), out.yOrigin);
-    out.haveXScale = in.tryGetProperty(String8("touch.position.xScale"), out.xScale);
-    out.haveYScale = in.tryGetProperty(String8("touch.position.yScale"), out.yScale);
-
-    // Touch Size
-    out.touchSizeCalibration = Calibration::TOUCH_SIZE_CALIBRATION_DEFAULT;
-    String8 touchSizeCalibrationString;
-    if (in.tryGetProperty(String8("touch.touchSize.calibration"), touchSizeCalibrationString)) {
-        if (touchSizeCalibrationString == "none") {
-            out.touchSizeCalibration = Calibration::TOUCH_SIZE_CALIBRATION_NONE;
-        } else if (touchSizeCalibrationString == "geometric") {
-            out.touchSizeCalibration = Calibration::TOUCH_SIZE_CALIBRATION_GEOMETRIC;
-        } else if (touchSizeCalibrationString == "pressure") {
-            out.touchSizeCalibration = Calibration::TOUCH_SIZE_CALIBRATION_PRESSURE;
-        } else if (touchSizeCalibrationString != "default") {
-            LOGW("Invalid value for touch.touchSize.calibration: '%s'",
-                    touchSizeCalibrationString.string());
-        }
-    }
-
-    // Tool Size
-    out.toolSizeCalibration = Calibration::TOOL_SIZE_CALIBRATION_DEFAULT;
-    String8 toolSizeCalibrationString;
-    if (in.tryGetProperty(String8("touch.toolSize.calibration"), toolSizeCalibrationString)) {
-        if (toolSizeCalibrationString == "none") {
-            out.toolSizeCalibration = Calibration::TOOL_SIZE_CALIBRATION_NONE;
-        } else if (toolSizeCalibrationString == "geometric") {
-            out.toolSizeCalibration = Calibration::TOOL_SIZE_CALIBRATION_GEOMETRIC;
-        } else if (toolSizeCalibrationString == "linear") {
-            out.toolSizeCalibration = Calibration::TOOL_SIZE_CALIBRATION_LINEAR;
-        } else if (toolSizeCalibrationString == "area") {
-            out.toolSizeCalibration = Calibration::TOOL_SIZE_CALIBRATION_AREA;
-        } else if (toolSizeCalibrationString != "default") {
-            LOGW("Invalid value for touch.toolSize.calibration: '%s'",
-                    toolSizeCalibrationString.string());
-        }
-    }
-
-    out.haveToolSizeLinearScale = in.tryGetProperty(String8("touch.toolSize.linearScale"),
-            out.toolSizeLinearScale);
-    out.haveToolSizeLinearBias = in.tryGetProperty(String8("touch.toolSize.linearBias"),
-            out.toolSizeLinearBias);
-    out.haveToolSizeAreaScale = in.tryGetProperty(String8("touch.toolSize.areaScale"),
-            out.toolSizeAreaScale);
-    out.haveToolSizeAreaBias = in.tryGetProperty(String8("touch.toolSize.areaBias"),
-            out.toolSizeAreaBias);
-    out.haveToolSizeIsSummed = in.tryGetProperty(String8("touch.toolSize.isSummed"),
-            out.toolSizeIsSummed);
-
-    // Pressure
-    out.pressureCalibration = Calibration::PRESSURE_CALIBRATION_DEFAULT;
-    String8 pressureCalibrationString;
-    if (in.tryGetProperty(String8("touch.pressure.calibration"), pressureCalibrationString)) {
-        if (pressureCalibrationString == "none") {
-            out.pressureCalibration = Calibration::PRESSURE_CALIBRATION_NONE;
-        } else if (pressureCalibrationString == "physical") {
-            out.pressureCalibration = Calibration::PRESSURE_CALIBRATION_PHYSICAL;
-        } else if (pressureCalibrationString == "amplitude") {
-            out.pressureCalibration = Calibration::PRESSURE_CALIBRATION_AMPLITUDE;
-        } else if (pressureCalibrationString != "default") {
-            LOGW("Invalid value for touch.pressure.calibration: '%s'",
-                    pressureCalibrationString.string());
-        }
-    }
-
-    out.pressureSource = Calibration::PRESSURE_SOURCE_DEFAULT;
-    String8 pressureSourceString;
-    if (in.tryGetProperty(String8("touch.pressure.source"), pressureSourceString)) {
-        if (pressureSourceString == "pressure") {
-            out.pressureSource = Calibration::PRESSURE_SOURCE_PRESSURE;
-        } else if (pressureSourceString == "touch") {
-            out.pressureSource = Calibration::PRESSURE_SOURCE_TOUCH;
-        } else if (pressureSourceString != "default") {
-            LOGW("Invalid value for touch.pressure.source: '%s'",
-                    pressureSourceString.string());
-        }
-    }
-
-    out.havePressureScale = in.tryGetProperty(String8("touch.pressure.scale"),
-            out.pressureScale);
-
-    // Size
-    out.sizeCalibration = Calibration::SIZE_CALIBRATION_DEFAULT;
-    String8 sizeCalibrationString;
-    if (in.tryGetProperty(String8("touch.size.calibration"), sizeCalibrationString)) {
-        if (sizeCalibrationString == "none") {
-            out.sizeCalibration = Calibration::SIZE_CALIBRATION_NONE;
-        } else if (sizeCalibrationString == "normalized") {
-            out.sizeCalibration = Calibration::SIZE_CALIBRATION_NORMALIZED;
-        } else if (sizeCalibrationString != "default") {
-            LOGW("Invalid value for touch.size.calibration: '%s'",
-                    sizeCalibrationString.string());
-        }
-    }
-
-    // Orientation
-    out.orientationCalibration = Calibration::ORIENTATION_CALIBRATION_DEFAULT;
-    String8 orientationCalibrationString;
-    if (in.tryGetProperty(String8("touch.orientation.calibration"), orientationCalibrationString)) {
-        if (orientationCalibrationString == "none") {
-            out.orientationCalibration = Calibration::ORIENTATION_CALIBRATION_NONE;
-        } else if (orientationCalibrationString == "interpolated") {
-            out.orientationCalibration = Calibration::ORIENTATION_CALIBRATION_INTERPOLATED;
-        } else if (orientationCalibrationString != "default") {
-            LOGW("Invalid value for touch.orientation.calibration: '%s'",
-                    orientationCalibrationString.string());
-        }
-    }
-}
-
-void TouchInputMapper::resolveCalibration() {
-    // Pressure
-    switch (mCalibration.pressureSource) {
-    case Calibration::PRESSURE_SOURCE_DEFAULT:
-        if (mRawAxes.pressure.valid) {
-            mCalibration.pressureSource = Calibration::PRESSURE_SOURCE_PRESSURE;
-        } else if (mRawAxes.touchMajor.valid) {
-            mCalibration.pressureSource = Calibration::PRESSURE_SOURCE_TOUCH;
-        }
-        break;
-
-    case Calibration::PRESSURE_SOURCE_PRESSURE:
-        if (! mRawAxes.pressure.valid) {
-            LOGW("Calibration property touch.pressure.source is 'pressure' but "
-                    "the pressure axis is not available.");
-        }
-        break;
-
-    case Calibration::PRESSURE_SOURCE_TOUCH:
-        if (! mRawAxes.touchMajor.valid) {
-            LOGW("Calibration property touch.pressure.source is 'touch' but "
-                    "the touchMajor axis is not available.");
-        }
-        break;
-
-    default:
-        break;
-    }
-
-    switch (mCalibration.pressureCalibration) {
-    case Calibration::PRESSURE_CALIBRATION_DEFAULT:
-        if (mCalibration.pressureSource != Calibration::PRESSURE_SOURCE_DEFAULT) {
-            mCalibration.pressureCalibration = Calibration::PRESSURE_CALIBRATION_AMPLITUDE;
-        } else {
-            mCalibration.pressureCalibration = Calibration::PRESSURE_CALIBRATION_NONE;
-        }
-        break;
-
-    default:
-        break;
-    }
-
-    // Tool Size
-    switch (mCalibration.toolSizeCalibration) {
-    case Calibration::TOOL_SIZE_CALIBRATION_DEFAULT:
-        if (mRawAxes.toolMajor.valid) {
-            mCalibration.toolSizeCalibration = Calibration::TOOL_SIZE_CALIBRATION_LINEAR;
-        } else {
-            mCalibration.toolSizeCalibration = Calibration::TOOL_SIZE_CALIBRATION_NONE;
-        }
-        break;
-
-    default:
-        break;
-    }
-
-    // Touch Size
-    switch (mCalibration.touchSizeCalibration) {
-    case Calibration::TOUCH_SIZE_CALIBRATION_DEFAULT:
-        if (mCalibration.pressureCalibration != Calibration::PRESSURE_CALIBRATION_NONE
-                && mCalibration.toolSizeCalibration != Calibration::TOOL_SIZE_CALIBRATION_NONE) {
-            mCalibration.touchSizeCalibration = Calibration::TOUCH_SIZE_CALIBRATION_PRESSURE;
-        } else {
-            mCalibration.touchSizeCalibration = Calibration::TOUCH_SIZE_CALIBRATION_NONE;
-        }
-        break;
-
-    default:
-        break;
-    }
-
-    // Size
-    switch (mCalibration.sizeCalibration) {
-    case Calibration::SIZE_CALIBRATION_DEFAULT:
-        if (mRawAxes.toolMajor.valid) {
-            mCalibration.sizeCalibration = Calibration::SIZE_CALIBRATION_NORMALIZED;
-        } else {
-            mCalibration.sizeCalibration = Calibration::SIZE_CALIBRATION_NONE;
-        }
-        break;
-
-    default:
-        break;
-    }
-
-    // Orientation
-    switch (mCalibration.orientationCalibration) {
-    case Calibration::ORIENTATION_CALIBRATION_DEFAULT:
-        if (mRawAxes.orientation.valid) {
-            mCalibration.orientationCalibration = Calibration::ORIENTATION_CALIBRATION_INTERPOLATED;
-        } else {
-            mCalibration.orientationCalibration = Calibration::ORIENTATION_CALIBRATION_NONE;
-        }
-        break;
-
-    default:
-        break;
-    }
-}
-
-void TouchInputMapper::dumpCalibration(String8& dump) {
-    dump.append(INDENT3 "Calibration:\n");
-
-    // Position
-    if (mCalibration.haveXOrigin) {
-        dump.appendFormat(INDENT4 "touch.position.xOrigin: %d\n", mCalibration.xOrigin);
-    }
-    if (mCalibration.haveYOrigin) {
-        dump.appendFormat(INDENT4 "touch.position.yOrigin: %d\n", mCalibration.yOrigin);
-    }
-    if (mCalibration.haveXScale) {
-        dump.appendFormat(INDENT4 "touch.position.xScale: %0.3f\n", mCalibration.xScale);
-    }
-    if (mCalibration.haveYScale) {
-        dump.appendFormat(INDENT4 "touch.position.yScale: %0.3f\n", mCalibration.yScale);
-    }
-
-    // Touch Size
-    switch (mCalibration.touchSizeCalibration) {
-    case Calibration::TOUCH_SIZE_CALIBRATION_NONE:
-        dump.append(INDENT4 "touch.touchSize.calibration: none\n");
-        break;
-    case Calibration::TOUCH_SIZE_CALIBRATION_GEOMETRIC:
-        dump.append(INDENT4 "touch.touchSize.calibration: geometric\n");
-        break;
-    case Calibration::TOUCH_SIZE_CALIBRATION_PRESSURE:
-        dump.append(INDENT4 "touch.touchSize.calibration: pressure\n");
-        break;
-    default:
-        assert(false);
-    }
-
-    // Tool Size
-    switch (mCalibration.toolSizeCalibration) {
-    case Calibration::TOOL_SIZE_CALIBRATION_NONE:
-        dump.append(INDENT4 "touch.toolSize.calibration: none\n");
-        break;
-    case Calibration::TOOL_SIZE_CALIBRATION_GEOMETRIC:
-        dump.append(INDENT4 "touch.toolSize.calibration: geometric\n");
-        break;
-    case Calibration::TOOL_SIZE_CALIBRATION_LINEAR:
-        dump.append(INDENT4 "touch.toolSize.calibration: linear\n");
-        break;
-    case Calibration::TOOL_SIZE_CALIBRATION_AREA:
-        dump.append(INDENT4 "touch.toolSize.calibration: area\n");
-        break;
-    default:
-        assert(false);
-    }
-
-    if (mCalibration.haveToolSizeLinearScale) {
-        dump.appendFormat(INDENT4 "touch.toolSize.linearScale: %0.3f\n",
-                mCalibration.toolSizeLinearScale);
-    }
-
-    if (mCalibration.haveToolSizeLinearBias) {
-        dump.appendFormat(INDENT4 "touch.toolSize.linearBias: %0.3f\n",
-                mCalibration.toolSizeLinearBias);
-    }
-
-    if (mCalibration.haveToolSizeAreaScale) {
-        dump.appendFormat(INDENT4 "touch.toolSize.areaScale: %0.3f\n",
-                mCalibration.toolSizeAreaScale);
-    }
-
-    if (mCalibration.haveToolSizeAreaBias) {
-        dump.appendFormat(INDENT4 "touch.toolSize.areaBias: %0.3f\n",
-                mCalibration.toolSizeAreaBias);
-    }
-
-    if (mCalibration.haveToolSizeIsSummed) {
-        dump.appendFormat(INDENT4 "touch.toolSize.isSummed: %s\n",
-                toString(mCalibration.toolSizeIsSummed));
-    }
-
-    // Pressure
-    switch (mCalibration.pressureCalibration) {
-    case Calibration::PRESSURE_CALIBRATION_NONE:
-        dump.append(INDENT4 "touch.pressure.calibration: none\n");
-        break;
-    case Calibration::PRESSURE_CALIBRATION_PHYSICAL:
-        dump.append(INDENT4 "touch.pressure.calibration: physical\n");
-        break;
-    case Calibration::PRESSURE_CALIBRATION_AMPLITUDE:
-        dump.append(INDENT4 "touch.pressure.calibration: amplitude\n");
-        break;
-    default:
-        assert(false);
-    }
-
-    switch (mCalibration.pressureSource) {
-    case Calibration::PRESSURE_SOURCE_PRESSURE:
-        dump.append(INDENT4 "touch.pressure.source: pressure\n");
-        break;
-    case Calibration::PRESSURE_SOURCE_TOUCH:
-        dump.append(INDENT4 "touch.pressure.source: touch\n");
-        break;
-    case Calibration::PRESSURE_SOURCE_DEFAULT:
-        break;
-    default:
-        assert(false);
-    }
-
-    if (mCalibration.havePressureScale) {
-        dump.appendFormat(INDENT4 "touch.pressure.scale: %0.3f\n",
-                mCalibration.pressureScale);
-    }
-
-    // Size
-    switch (mCalibration.sizeCalibration) {
-    case Calibration::SIZE_CALIBRATION_NONE:
-        dump.append(INDENT4 "touch.size.calibration: none\n");
-        break;
-    case Calibration::SIZE_CALIBRATION_NORMALIZED:
-        dump.append(INDENT4 "touch.size.calibration: normalized\n");
-        break;
-    default:
-        assert(false);
-    }
-
-    // Orientation
-    switch (mCalibration.orientationCalibration) {
-    case Calibration::ORIENTATION_CALIBRATION_NONE:
-        dump.append(INDENT4 "touch.orientation.calibration: none\n");
-        break;
-    case Calibration::ORIENTATION_CALIBRATION_INTERPOLATED:
-        dump.append(INDENT4 "touch.orientation.calibration: interpolated\n");
-        break;
-    default:
-        assert(false);
-    }
-}
-
-void TouchInputMapper::reset() {
-    // Synthesize touch up event if touch is currently down.
-    // This will also take care of finishing virtual key processing if needed.
-    if (mLastTouch.pointerCount != 0) {
-        nsecs_t when = systemTime(SYSTEM_TIME_MONOTONIC);
-        mCurrentTouch.clear();
-        syncTouch(when, true);
-    }
-
-    { // acquire lock
-        AutoMutex _l(mLock);
-        initializeLocked();
-    } // release lock
-
-    InputMapper::reset();
-}
-
-void TouchInputMapper::syncTouch(nsecs_t when, bool havePointerIds) {
-    uint32_t policyFlags = 0;
-
-    // Preprocess pointer data.
-
-    if (mParameters.useBadTouchFilter) {
-        if (applyBadTouchFilter()) {
-            havePointerIds = false;
-        }
-    }
-
-    if (mParameters.useJumpyTouchFilter) {
-        if (applyJumpyTouchFilter()) {
-            havePointerIds = false;
-        }
-    }
-
-    if (! havePointerIds) {
-        calculatePointerIds();
-    }
-
-    TouchData temp;
-    TouchData* savedTouch;
-    if (mParameters.useAveragingTouchFilter) {
-        temp.copyFrom(mCurrentTouch);
-        savedTouch = & temp;
-
-        applyAveragingTouchFilter();
-    } else {
-        savedTouch = & mCurrentTouch;
-    }
-
-    // Process touches and virtual keys.
-
-    TouchResult touchResult = consumeOffScreenTouches(when, policyFlags);
-    if (touchResult == DISPATCH_TOUCH) {
-        dispatchTouches(when, policyFlags);
-    }
-
-    // Copy current touch to last touch in preparation for the next cycle.
-
-    if (touchResult == DROP_STROKE) {
-        mLastTouch.clear();
-    } else {
-        mLastTouch.copyFrom(*savedTouch);
-    }
-}
-
-TouchInputMapper::TouchResult TouchInputMapper::consumeOffScreenTouches(
-        nsecs_t when, uint32_t policyFlags) {
-    int32_t keyEventAction, keyEventFlags;
-    int32_t keyCode, scanCode, downTime;
-    TouchResult touchResult;
-
-    { // acquire lock
-        AutoMutex _l(mLock);
-
-        // Update surface size and orientation, including virtual key positions.
-        if (! configureSurfaceLocked()) {
-            return DROP_STROKE;
-        }
-
-        // Check for virtual key press.
-        if (mLocked.currentVirtualKey.down) {
-            if (mCurrentTouch.pointerCount == 0) {
-                // Pointer went up while virtual key was down.
-                mLocked.currentVirtualKey.down = false;
-#if DEBUG_VIRTUAL_KEYS
-                LOGD("VirtualKeys: Generating key up: keyCode=%d, scanCode=%d",
-                        mLocked.currentVirtualKey.keyCode, mLocked.currentVirtualKey.scanCode);
-#endif
-                keyEventAction = AKEY_EVENT_ACTION_UP;
-                keyEventFlags = AKEY_EVENT_FLAG_FROM_SYSTEM | AKEY_EVENT_FLAG_VIRTUAL_HARD_KEY;
-                touchResult = SKIP_TOUCH;
-                goto DispatchVirtualKey;
-            }
-
-            if (mCurrentTouch.pointerCount == 1) {
-                int32_t x = mCurrentTouch.pointers[0].x;
-                int32_t y = mCurrentTouch.pointers[0].y;
-                const VirtualKey* virtualKey = findVirtualKeyHitLocked(x, y);
-                if (virtualKey && virtualKey->keyCode == mLocked.currentVirtualKey.keyCode) {
-                    // Pointer is still within the space of the virtual key.
-                    return SKIP_TOUCH;
-                }
-            }
-
-            // Pointer left virtual key area or another pointer also went down.
-            // Send key cancellation and drop the stroke so subsequent motions will be
-            // considered fresh downs.  This is useful when the user swipes away from the
-            // virtual key area into the main display surface.
-            mLocked.currentVirtualKey.down = false;
-#if DEBUG_VIRTUAL_KEYS
-            LOGD("VirtualKeys: Canceling key: keyCode=%d, scanCode=%d",
-                    mLocked.currentVirtualKey.keyCode, mLocked.currentVirtualKey.scanCode);
-#endif
-            keyEventAction = AKEY_EVENT_ACTION_UP;
-            keyEventFlags = AKEY_EVENT_FLAG_FROM_SYSTEM | AKEY_EVENT_FLAG_VIRTUAL_HARD_KEY
-                    | AKEY_EVENT_FLAG_CANCELED;
-
-            // Check whether the pointer moved inside the display area where we should
-            // start a new stroke.
-            int32_t x = mCurrentTouch.pointers[0].x;
-            int32_t y = mCurrentTouch.pointers[0].y;
-            if (isPointInsideSurfaceLocked(x, y)) {
-                mLastTouch.clear();
-                touchResult = DISPATCH_TOUCH;
-            } else {
-                touchResult = DROP_STROKE;
-            }
-        } else {
-            if (mCurrentTouch.pointerCount >= 1 && mLastTouch.pointerCount == 0) {
-                // Pointer just went down.  Handle off-screen touches, if needed.
-                int32_t x = mCurrentTouch.pointers[0].x;
-                int32_t y = mCurrentTouch.pointers[0].y;
-                if (! isPointInsideSurfaceLocked(x, y)) {
-                    // If exactly one pointer went down, check for virtual key hit.
-                    // Otherwise we will drop the entire stroke.
-                    if (mCurrentTouch.pointerCount == 1) {
-                        const VirtualKey* virtualKey = findVirtualKeyHitLocked(x, y);
-                        if (virtualKey) {
-                            mLocked.currentVirtualKey.down = true;
-                            mLocked.currentVirtualKey.downTime = when;
-                            mLocked.currentVirtualKey.keyCode = virtualKey->keyCode;
-                            mLocked.currentVirtualKey.scanCode = virtualKey->scanCode;
-#if DEBUG_VIRTUAL_KEYS
-                            LOGD("VirtualKeys: Generating key down: keyCode=%d, scanCode=%d",
-                                    mLocked.currentVirtualKey.keyCode,
-                                    mLocked.currentVirtualKey.scanCode);
-#endif
-                            keyEventAction = AKEY_EVENT_ACTION_DOWN;
-                            keyEventFlags = AKEY_EVENT_FLAG_FROM_SYSTEM
-                                    | AKEY_EVENT_FLAG_VIRTUAL_HARD_KEY;
-                            touchResult = SKIP_TOUCH;
-                            goto DispatchVirtualKey;
-                        }
-                    }
-                    return DROP_STROKE;
-                }
-            }
-            return DISPATCH_TOUCH;
-        }
-
-    DispatchVirtualKey:
-        // Collect remaining state needed to dispatch virtual key.
-        keyCode = mLocked.currentVirtualKey.keyCode;
-        scanCode = mLocked.currentVirtualKey.scanCode;
-        downTime = mLocked.currentVirtualKey.downTime;
-    } // release lock
-
-    // Dispatch virtual key.
-    int32_t metaState = mContext->getGlobalMetaState();
-    policyFlags |= POLICY_FLAG_VIRTUAL;
-    getDispatcher()->notifyKey(when, getDeviceId(), AINPUT_SOURCE_KEYBOARD, policyFlags,
-            keyEventAction, keyEventFlags, keyCode, scanCode, metaState, downTime);
-    return touchResult;
-}
-
-void TouchInputMapper::dispatchTouches(nsecs_t when, uint32_t policyFlags) {
-    uint32_t currentPointerCount = mCurrentTouch.pointerCount;
-    uint32_t lastPointerCount = mLastTouch.pointerCount;
-    if (currentPointerCount == 0 && lastPointerCount == 0) {
-        return; // nothing to do!
-    }
-
-    BitSet32 currentIdBits = mCurrentTouch.idBits;
-    BitSet32 lastIdBits = mLastTouch.idBits;
-
-    if (currentIdBits == lastIdBits) {
-        // No pointer id changes so this is a move event.
-        // The dispatcher takes care of batching moves so we don't have to deal with that here.
-        int32_t motionEventAction = AMOTION_EVENT_ACTION_MOVE;
-        dispatchTouch(when, policyFlags, & mCurrentTouch,
-                currentIdBits, -1, currentPointerCount, motionEventAction);
-    } else {
-        // There may be pointers going up and pointers going down and pointers moving
-        // all at the same time.
-        BitSet32 upIdBits(lastIdBits.value & ~ currentIdBits.value);
-        BitSet32 downIdBits(currentIdBits.value & ~ lastIdBits.value);
-        BitSet32 activeIdBits(lastIdBits.value);
-        uint32_t pointerCount = lastPointerCount;
-
-        // Produce an intermediate representation of the touch data that consists of the
-        // old location of pointers that have just gone up and the new location of pointers that
-        // have just moved but omits the location of pointers that have just gone down.
-        TouchData interimTouch;
-        interimTouch.copyFrom(mLastTouch);
-
-        BitSet32 moveIdBits(lastIdBits.value & currentIdBits.value);
-        bool moveNeeded = false;
-        while (!moveIdBits.isEmpty()) {
-            uint32_t moveId = moveIdBits.firstMarkedBit();
-            moveIdBits.clearBit(moveId);
-
-            int32_t oldIndex = mLastTouch.idToIndex[moveId];
-            int32_t newIndex = mCurrentTouch.idToIndex[moveId];
-            if (mLastTouch.pointers[oldIndex] != mCurrentTouch.pointers[newIndex]) {
-                interimTouch.pointers[oldIndex] = mCurrentTouch.pointers[newIndex];
-                moveNeeded = true;
-            }
-        }
-
-        // Dispatch pointer up events using the interim pointer locations.
-        while (!upIdBits.isEmpty()) {
-            uint32_t upId = upIdBits.firstMarkedBit();
-            upIdBits.clearBit(upId);
-            BitSet32 oldActiveIdBits = activeIdBits;
-            activeIdBits.clearBit(upId);
-
-            int32_t motionEventAction;
-            if (activeIdBits.isEmpty()) {
-                motionEventAction = AMOTION_EVENT_ACTION_UP;
-            } else {
-                motionEventAction = AMOTION_EVENT_ACTION_POINTER_UP;
-            }
-
-            dispatchTouch(when, policyFlags, &interimTouch,
-                    oldActiveIdBits, upId, pointerCount, motionEventAction);
-            pointerCount -= 1;
-        }
-
-        // Dispatch move events if any of the remaining pointers moved from their old locations.
-        // Although applications receive new locations as part of individual pointer up
-        // events, they do not generally handle them except when presented in a move event.
-        if (moveNeeded) {
-            dispatchTouch(when, policyFlags, &mCurrentTouch,
-                    activeIdBits, -1, pointerCount, AMOTION_EVENT_ACTION_MOVE);
-        }
-
-        // Dispatch pointer down events using the new pointer locations.
-        while (!downIdBits.isEmpty()) {
-            uint32_t downId = downIdBits.firstMarkedBit();
-            downIdBits.clearBit(downId);
-            BitSet32 oldActiveIdBits = activeIdBits;
-            activeIdBits.markBit(downId);
-
-            int32_t motionEventAction;
-            if (oldActiveIdBits.isEmpty()) {
-                motionEventAction = AMOTION_EVENT_ACTION_DOWN;
-                mDownTime = when;
-            } else {
-                motionEventAction = AMOTION_EVENT_ACTION_POINTER_DOWN;
-            }
-
-            pointerCount += 1;
-            dispatchTouch(when, policyFlags, &mCurrentTouch,
-                    activeIdBits, downId, pointerCount, motionEventAction);
-        }
-    }
-}
-
-void TouchInputMapper::dispatchTouch(nsecs_t when, uint32_t policyFlags,
-        TouchData* touch, BitSet32 idBits, uint32_t changedId, uint32_t pointerCount,
-        int32_t motionEventAction) {
-    int32_t pointerIds[MAX_POINTERS];
-    PointerCoords pointerCoords[MAX_POINTERS];
-    int32_t motionEventEdgeFlags = 0;
-    float xPrecision, yPrecision;
-
-    { // acquire lock
-        AutoMutex _l(mLock);
-
-        // Walk through the the active pointers and map touch screen coordinates (TouchData) into
-        // display coordinates (PointerCoords) and adjust for display orientation.
-        for (uint32_t outIndex = 0; ! idBits.isEmpty(); outIndex++) {
-            uint32_t id = idBits.firstMarkedBit();
-            idBits.clearBit(id);
-            uint32_t inIndex = touch->idToIndex[id];
-
-            const PointerData& in = touch->pointers[inIndex];
-
-            // X and Y
-            float x = float(in.x - mLocked.xOrigin) * mLocked.xScale;
-            float y = float(in.y - mLocked.yOrigin) * mLocked.yScale;
-
-            // ToolMajor and ToolMinor
-            float toolMajor, toolMinor;
-            switch (mCalibration.toolSizeCalibration) {
-            case Calibration::TOOL_SIZE_CALIBRATION_GEOMETRIC:
-                toolMajor = in.toolMajor * mLocked.geometricScale;
-                if (mRawAxes.toolMinor.valid) {
-                    toolMinor = in.toolMinor * mLocked.geometricScale;
-                } else {
-                    toolMinor = toolMajor;
-                }
-                break;
-            case Calibration::TOOL_SIZE_CALIBRATION_LINEAR:
-                toolMajor = in.toolMajor != 0
-                        ? in.toolMajor * mLocked.toolSizeLinearScale + mLocked.toolSizeLinearBias
-                        : 0;
-                if (mRawAxes.toolMinor.valid) {
-                    toolMinor = in.toolMinor != 0
-                            ? in.toolMinor * mLocked.toolSizeLinearScale
-                                    + mLocked.toolSizeLinearBias
-                            : 0;
-                } else {
-                    toolMinor = toolMajor;
-                }
-                break;
-            case Calibration::TOOL_SIZE_CALIBRATION_AREA:
-                if (in.toolMajor != 0) {
-                    float diameter = sqrtf(in.toolMajor
-                            * mLocked.toolSizeAreaScale + mLocked.toolSizeAreaBias);
-                    toolMajor = diameter * mLocked.toolSizeLinearScale + mLocked.toolSizeLinearBias;
-                } else {
-                    toolMajor = 0;
-                }
-                toolMinor = toolMajor;
-                break;
-            default:
-                toolMajor = 0;
-                toolMinor = 0;
-                break;
-            }
-
-            if (mCalibration.haveToolSizeIsSummed && mCalibration.toolSizeIsSummed) {
-                toolMajor /= pointerCount;
-                toolMinor /= pointerCount;
-            }
-
-            // Pressure
-            float rawPressure;
-            switch (mCalibration.pressureSource) {
-            case Calibration::PRESSURE_SOURCE_PRESSURE:
-                rawPressure = in.pressure;
-                break;
-            case Calibration::PRESSURE_SOURCE_TOUCH:
-                rawPressure = in.touchMajor;
-                break;
-            default:
-                rawPressure = 0;
-            }
-
-            float pressure;
-            switch (mCalibration.pressureCalibration) {
-            case Calibration::PRESSURE_CALIBRATION_PHYSICAL:
-            case Calibration::PRESSURE_CALIBRATION_AMPLITUDE:
-                pressure = rawPressure * mLocked.pressureScale;
-                break;
-            default:
-                pressure = 1;
-                break;
-            }
-
-            // TouchMajor and TouchMinor
-            float touchMajor, touchMinor;
-            switch (mCalibration.touchSizeCalibration) {
-            case Calibration::TOUCH_SIZE_CALIBRATION_GEOMETRIC:
-                touchMajor = in.touchMajor * mLocked.geometricScale;
-                if (mRawAxes.touchMinor.valid) {
-                    touchMinor = in.touchMinor * mLocked.geometricScale;
-                } else {
-                    touchMinor = touchMajor;
-                }
-                break;
-            case Calibration::TOUCH_SIZE_CALIBRATION_PRESSURE:
-                touchMajor = toolMajor * pressure;
-                touchMinor = toolMinor * pressure;
-                break;
-            default:
-                touchMajor = 0;
-                touchMinor = 0;
-                break;
-            }
-
-            if (touchMajor > toolMajor) {
-                touchMajor = toolMajor;
-            }
-            if (touchMinor > toolMinor) {
-                touchMinor = toolMinor;
-            }
-
-            // Size
-            float size;
-            switch (mCalibration.sizeCalibration) {
-            case Calibration::SIZE_CALIBRATION_NORMALIZED: {
-                float rawSize = mRawAxes.toolMinor.valid
-                        ? avg(in.toolMajor, in.toolMinor)
-                        : in.toolMajor;
-                size = rawSize * mLocked.sizeScale;
-                break;
-            }
-            default:
-                size = 0;
-                break;
-            }
-
-            // Orientation
-            float orientation;
-            switch (mCalibration.orientationCalibration) {
-            case Calibration::ORIENTATION_CALIBRATION_INTERPOLATED:
-                orientation = in.orientation * mLocked.orientationScale;
-                break;
-            default:
-                orientation = 0;
-            }
-
-            // Adjust coords for orientation.
-            switch (mLocked.surfaceOrientation) {
-            case InputReaderPolicyInterface::ROTATION_90: {
-                float xTemp = x;
-                x = y;
-                y = mLocked.surfaceWidth - xTemp;
-                orientation -= M_PI_2;
-                if (orientation < - M_PI_2) {
-                    orientation += M_PI;
-                }
-                break;
-            }
-            case InputReaderPolicyInterface::ROTATION_180: {
-                x = mLocked.surfaceWidth - x;
-                y = mLocked.surfaceHeight - y;
-                orientation = - orientation;
-                break;
-            }
-            case InputReaderPolicyInterface::ROTATION_270: {
-                float xTemp = x;
-                x = mLocked.surfaceHeight - y;
-                y = xTemp;
-                orientation += M_PI_2;
-                if (orientation > M_PI_2) {
-                    orientation -= M_PI;
-                }
-                break;
-            }
-            }
-
-            // Write output coords.
-            PointerCoords& out = pointerCoords[outIndex];
-            out.x = x;
-            out.y = y;
-            out.pressure = pressure;
-            out.size = size;
-            out.touchMajor = touchMajor;
-            out.touchMinor = touchMinor;
-            out.toolMajor = toolMajor;
-            out.toolMinor = toolMinor;
-            out.orientation = orientation;
-
-            pointerIds[outIndex] = int32_t(id);
-
-            if (id == changedId) {
-                motionEventAction |= outIndex << AMOTION_EVENT_ACTION_POINTER_INDEX_SHIFT;
-            }
-        }
-
-        // Check edge flags by looking only at the first pointer since the flags are
-        // global to the event.
-        if (motionEventAction == AMOTION_EVENT_ACTION_DOWN) {
-            if (pointerCoords[0].x <= 0) {
-                motionEventEdgeFlags |= AMOTION_EVENT_EDGE_FLAG_LEFT;
-            } else if (pointerCoords[0].x >= mLocked.orientedSurfaceWidth) {
-                motionEventEdgeFlags |= AMOTION_EVENT_EDGE_FLAG_RIGHT;
-            }
-            if (pointerCoords[0].y <= 0) {
-                motionEventEdgeFlags |= AMOTION_EVENT_EDGE_FLAG_TOP;
-            } else if (pointerCoords[0].y >= mLocked.orientedSurfaceHeight) {
-                motionEventEdgeFlags |= AMOTION_EVENT_EDGE_FLAG_BOTTOM;
-            }
-        }
-
-        xPrecision = mLocked.orientedXPrecision;
-        yPrecision = mLocked.orientedYPrecision;
-    } // release lock
-
-    getDispatcher()->notifyMotion(when, getDeviceId(), getSources(), policyFlags,
-            motionEventAction, 0, getContext()->getGlobalMetaState(), motionEventEdgeFlags,
-            pointerCount, pointerIds, pointerCoords,
-            xPrecision, yPrecision, mDownTime);
-}
-
-bool TouchInputMapper::isPointInsideSurfaceLocked(int32_t x, int32_t y) {
-    if (mRawAxes.x.valid && mRawAxes.y.valid) {
-        return x >= mRawAxes.x.minValue && x <= mRawAxes.x.maxValue
-                && y >= mRawAxes.y.minValue && y <= mRawAxes.y.maxValue;
-    }
-    return true;
-}
-
-const TouchInputMapper::VirtualKey* TouchInputMapper::findVirtualKeyHitLocked(
-        int32_t x, int32_t y) {
-    size_t numVirtualKeys = mLocked.virtualKeys.size();
-    for (size_t i = 0; i < numVirtualKeys; i++) {
-        const VirtualKey& virtualKey = mLocked.virtualKeys[i];
-
-#if DEBUG_VIRTUAL_KEYS
-        LOGD("VirtualKeys: Hit test (%d, %d): keyCode=%d, scanCode=%d, "
-                "left=%d, top=%d, right=%d, bottom=%d",
-                x, y,
-                virtualKey.keyCode, virtualKey.scanCode,
-                virtualKey.hitLeft, virtualKey.hitTop,
-                virtualKey.hitRight, virtualKey.hitBottom);
-#endif
-
-        if (virtualKey.isHit(x, y)) {
-            return & virtualKey;
-        }
-    }
-
-    return NULL;
-}
-
-void TouchInputMapper::calculatePointerIds() {
-    uint32_t currentPointerCount = mCurrentTouch.pointerCount;
-    uint32_t lastPointerCount = mLastTouch.pointerCount;
-
-    if (currentPointerCount == 0) {
-        // No pointers to assign.
-        mCurrentTouch.idBits.clear();
-    } else if (lastPointerCount == 0) {
-        // All pointers are new.
-        mCurrentTouch.idBits.clear();
-        for (uint32_t i = 0; i < currentPointerCount; i++) {
-            mCurrentTouch.pointers[i].id = i;
-            mCurrentTouch.idToIndex[i] = i;
-            mCurrentTouch.idBits.markBit(i);
-        }
-    } else if (currentPointerCount == 1 && lastPointerCount == 1) {
-        // Only one pointer and no change in count so it must have the same id as before.
-        uint32_t id = mLastTouch.pointers[0].id;
-        mCurrentTouch.pointers[0].id = id;
-        mCurrentTouch.idToIndex[id] = 0;
-        mCurrentTouch.idBits.value = BitSet32::valueForBit(id);
-    } else {
-        // General case.
-        // We build a heap of squared euclidean distances between current and last pointers
-        // associated with the current and last pointer indices.  Then, we find the best
-        // match (by distance) for each current pointer.
-        PointerDistanceHeapElement heap[MAX_POINTERS * MAX_POINTERS];
-
-        uint32_t heapSize = 0;
-        for (uint32_t currentPointerIndex = 0; currentPointerIndex < currentPointerCount;
-                currentPointerIndex++) {
-            for (uint32_t lastPointerIndex = 0; lastPointerIndex < lastPointerCount;
-                    lastPointerIndex++) {
-                int64_t deltaX = mCurrentTouch.pointers[currentPointerIndex].x
-                        - mLastTouch.pointers[lastPointerIndex].x;
-                int64_t deltaY = mCurrentTouch.pointers[currentPointerIndex].y
-                        - mLastTouch.pointers[lastPointerIndex].y;
-
-                uint64_t distance = uint64_t(deltaX * deltaX + deltaY * deltaY);
-
-                // Insert new element into the heap (sift up).
-                heap[heapSize].currentPointerIndex = currentPointerIndex;
-                heap[heapSize].lastPointerIndex = lastPointerIndex;
-                heap[heapSize].distance = distance;
-                heapSize += 1;
-            }
-        }
-
-        // Heapify
-        for (uint32_t startIndex = heapSize / 2; startIndex != 0; ) {
-            startIndex -= 1;
-            for (uint32_t parentIndex = startIndex; ;) {
-                uint32_t childIndex = parentIndex * 2 + 1;
-                if (childIndex >= heapSize) {
-                    break;
-                }
-
-                if (childIndex + 1 < heapSize
-                        && heap[childIndex + 1].distance < heap[childIndex].distance) {
-                    childIndex += 1;
-                }
-
-                if (heap[parentIndex].distance <= heap[childIndex].distance) {
-                    break;
-                }
-
-                swap(heap[parentIndex], heap[childIndex]);
-                parentIndex = childIndex;
-            }
-        }
-
-#if DEBUG_POINTER_ASSIGNMENT
-        LOGD("calculatePointerIds - initial distance min-heap: size=%d", heapSize);
-        for (size_t i = 0; i < heapSize; i++) {
-            LOGD("  heap[%d]: cur=%d, last=%d, distance=%lld",
-                    i, heap[i].currentPointerIndex, heap[i].lastPointerIndex,
-                    heap[i].distance);
-        }
-#endif
-
-        // Pull matches out by increasing order of distance.
-        // To avoid reassigning pointers that have already been matched, the loop keeps track
-        // of which last and current pointers have been matched using the matchedXXXBits variables.
-        // It also tracks the used pointer id bits.
-        BitSet32 matchedLastBits(0);
-        BitSet32 matchedCurrentBits(0);
-        BitSet32 usedIdBits(0);
-        bool first = true;
-        for (uint32_t i = min(currentPointerCount, lastPointerCount); i > 0; i--) {
-            for (;;) {
-                if (first) {
-                    // The first time through the loop, we just consume the root element of
-                    // the heap (the one with smallest distance).
-                    first = false;
-                } else {
-                    // Previous iterations consumed the root element of the heap.
-                    // Pop root element off of the heap (sift down).
-                    heapSize -= 1;
-                    assert(heapSize > 0);
-
-                    // Sift down.
-                    heap[0] = heap[heapSize];
-                    for (uint32_t parentIndex = 0; ;) {
-                        uint32_t childIndex = parentIndex * 2 + 1;
-                        if (childIndex >= heapSize) {
-                            break;
-                        }
-
-                        if (childIndex + 1 < heapSize
-                                && heap[childIndex + 1].distance < heap[childIndex].distance) {
-                            childIndex += 1;
-                        }
-
-                        if (heap[parentIndex].distance <= heap[childIndex].distance) {
-                            break;
-                        }
-
-                        swap(heap[parentIndex], heap[childIndex]);
-                        parentIndex = childIndex;
-                    }
-
-#if DEBUG_POINTER_ASSIGNMENT
-                    LOGD("calculatePointerIds - reduced distance min-heap: size=%d", heapSize);
-                    for (size_t i = 0; i < heapSize; i++) {
-                        LOGD("  heap[%d]: cur=%d, last=%d, distance=%lld",
-                                i, heap[i].currentPointerIndex, heap[i].lastPointerIndex,
-                                heap[i].distance);
-                    }
-#endif
-                }
-
-                uint32_t currentPointerIndex = heap[0].currentPointerIndex;
-                if (matchedCurrentBits.hasBit(currentPointerIndex)) continue; // already matched
-
-                uint32_t lastPointerIndex = heap[0].lastPointerIndex;
-                if (matchedLastBits.hasBit(lastPointerIndex)) continue; // already matched
-
-                matchedCurrentBits.markBit(currentPointerIndex);
-                matchedLastBits.markBit(lastPointerIndex);
-
-                uint32_t id = mLastTouch.pointers[lastPointerIndex].id;
-                mCurrentTouch.pointers[currentPointerIndex].id = id;
-                mCurrentTouch.idToIndex[id] = currentPointerIndex;
-                usedIdBits.markBit(id);
-
-#if DEBUG_POINTER_ASSIGNMENT
-                LOGD("calculatePointerIds - matched: cur=%d, last=%d, id=%d, distance=%lld",
-                        lastPointerIndex, currentPointerIndex, id, heap[0].distance);
-#endif
-                break;
-            }
-        }
-
-        // Assign fresh ids to new pointers.
-        if (currentPointerCount > lastPointerCount) {
-            for (uint32_t i = currentPointerCount - lastPointerCount; ;) {
-                uint32_t currentPointerIndex = matchedCurrentBits.firstUnmarkedBit();
-                uint32_t id = usedIdBits.firstUnmarkedBit();
-
-                mCurrentTouch.pointers[currentPointerIndex].id = id;
-                mCurrentTouch.idToIndex[id] = currentPointerIndex;
-                usedIdBits.markBit(id);
-
-#if DEBUG_POINTER_ASSIGNMENT
-                LOGD("calculatePointerIds - assigned: cur=%d, id=%d",
-                        currentPointerIndex, id);
-#endif
-
-                if (--i == 0) break; // done
-                matchedCurrentBits.markBit(currentPointerIndex);
-            }
-        }
-
-        // Fix id bits.
-        mCurrentTouch.idBits = usedIdBits;
-    }
-}
-
-/* Special hack for devices that have bad screen data: if one of the
- * points has moved more than a screen height from the last position,
- * then drop it. */
-bool TouchInputMapper::applyBadTouchFilter() {
-    // This hack requires valid axis parameters.
-    if (! mRawAxes.y.valid) {
-        return false;
-    }
-
-    uint32_t pointerCount = mCurrentTouch.pointerCount;
-
-    // Nothing to do if there are no points.
-    if (pointerCount == 0) {
-        return false;
-    }
-
-    // Don't do anything if a finger is going down or up.  We run
-    // here before assigning pointer IDs, so there isn't a good
-    // way to do per-finger matching.
-    if (pointerCount != mLastTouch.pointerCount) {
-        return false;
-    }
-
-    // We consider a single movement across more than a 7/16 of
-    // the long size of the screen to be bad.  This was a magic value
-    // determined by looking at the maximum distance it is feasible
-    // to actually move in one sample.
-    int32_t maxDeltaY = mRawAxes.y.getRange() * 7 / 16;
-
-    // XXX The original code in InputDevice.java included commented out
-    //     code for testing the X axis.  Note that when we drop a point
-    //     we don't actually restore the old X either.  Strange.
-    //     The old code also tries to track when bad points were previously
-    //     detected but it turns out that due to the placement of a "break"
-    //     at the end of the loop, we never set mDroppedBadPoint to true
-    //     so it is effectively dead code.
-    // Need to figure out if the old code is busted or just overcomplicated
-    // but working as intended.
-
-    // Look through all new points and see if any are farther than
-    // acceptable from all previous points.
-    for (uint32_t i = pointerCount; i-- > 0; ) {
-        int32_t y = mCurrentTouch.pointers[i].y;
-        int32_t closestY = INT_MAX;
-        int32_t closestDeltaY = 0;
-
-#if DEBUG_HACKS
-        LOGD("BadTouchFilter: Looking at next point #%d: y=%d", i, y);
-#endif
-
-        for (uint32_t j = pointerCount; j-- > 0; ) {
-            int32_t lastY = mLastTouch.pointers[j].y;
-            int32_t deltaY = abs(y - lastY);
-
-#if DEBUG_HACKS
-            LOGD("BadTouchFilter: Comparing with last point #%d: y=%d deltaY=%d",
-                    j, lastY, deltaY);
-#endif
-
-            if (deltaY < maxDeltaY) {
-                goto SkipSufficientlyClosePoint;
-            }
-            if (deltaY < closestDeltaY) {
-                closestDeltaY = deltaY;
-                closestY = lastY;
-            }
-        }
-
-        // Must not have found a close enough match.
-#if DEBUG_HACKS
-        LOGD("BadTouchFilter: Dropping bad point #%d: newY=%d oldY=%d deltaY=%d maxDeltaY=%d",
-                i, y, closestY, closestDeltaY, maxDeltaY);
-#endif
-
-        mCurrentTouch.pointers[i].y = closestY;
-        return true; // XXX original code only corrects one point
-
-    SkipSufficientlyClosePoint: ;
-    }
-
-    // No change.
-    return false;
-}
-
-/* Special hack for devices that have bad screen data: drop points where
- * the coordinate value for one axis has jumped to the other pointer's location.
- */
-bool TouchInputMapper::applyJumpyTouchFilter() {
-    // This hack requires valid axis parameters.
-    if (! mRawAxes.y.valid) {
-        return false;
-    }
-
-    uint32_t pointerCount = mCurrentTouch.pointerCount;
-    if (mLastTouch.pointerCount != pointerCount) {
-#if DEBUG_HACKS
-        LOGD("JumpyTouchFilter: Different pointer count %d -> %d",
-                mLastTouch.pointerCount, pointerCount);
-        for (uint32_t i = 0; i < pointerCount; i++) {
-            LOGD("  Pointer %d (%d, %d)", i,
-                    mCurrentTouch.pointers[i].x, mCurrentTouch.pointers[i].y);
-        }
-#endif
-
-        if (mJumpyTouchFilter.jumpyPointsDropped < JUMPY_TRANSITION_DROPS) {
-            if (mLastTouch.pointerCount == 1 && pointerCount == 2) {
-                // Just drop the first few events going from 1 to 2 pointers.
-                // They're bad often enough that they're not worth considering.
-                mCurrentTouch.pointerCount = 1;
-                mJumpyTouchFilter.jumpyPointsDropped += 1;
-
-#if DEBUG_HACKS
-                LOGD("JumpyTouchFilter: Pointer 2 dropped");
-#endif
-                return true;
-            } else if (mLastTouch.pointerCount == 2 && pointerCount == 1) {
-                // The event when we go from 2 -> 1 tends to be messed up too
-                mCurrentTouch.pointerCount = 2;
-                mCurrentTouch.pointers[0] = mLastTouch.pointers[0];
-                mCurrentTouch.pointers[1] = mLastTouch.pointers[1];
-                mJumpyTouchFilter.jumpyPointsDropped += 1;
-
-#if DEBUG_HACKS
-                for (int32_t i = 0; i < 2; i++) {
-                    LOGD("JumpyTouchFilter: Pointer %d replaced (%d, %d)", i,
-                            mCurrentTouch.pointers[i].x, mCurrentTouch.pointers[i].y);
-                }
-#endif
-                return true;
-            }
-        }
-        // Reset jumpy points dropped on other transitions or if limit exceeded.
-        mJumpyTouchFilter.jumpyPointsDropped = 0;
-
-#if DEBUG_HACKS
-        LOGD("JumpyTouchFilter: Transition - drop limit reset");
-#endif
-        return false;
-    }
-
-    // We have the same number of pointers as last time.
-    // A 'jumpy' point is one where the coordinate value for one axis
-    // has jumped to the other pointer's location. No need to do anything
-    // else if we only have one pointer.
-    if (pointerCount < 2) {
-        return false;
-    }
-
-    if (mJumpyTouchFilter.jumpyPointsDropped < JUMPY_DROP_LIMIT) {
-        int jumpyEpsilon = mRawAxes.y.getRange() / JUMPY_EPSILON_DIVISOR;
-
-        // We only replace the single worst jumpy point as characterized by pointer distance
-        // in a single axis.
-        int32_t badPointerIndex = -1;
-        int32_t badPointerReplacementIndex = -1;
-        int32_t badPointerDistance = INT_MIN; // distance to be corrected
-
-        for (uint32_t i = pointerCount; i-- > 0; ) {
-            int32_t x = mCurrentTouch.pointers[i].x;
-            int32_t y = mCurrentTouch.pointers[i].y;
-
-#if DEBUG_HACKS
-            LOGD("JumpyTouchFilter: Point %d (%d, %d)", i, x, y);
-#endif
-
-            // Check if a touch point is too close to another's coordinates
-            bool dropX = false, dropY = false;
-            for (uint32_t j = 0; j < pointerCount; j++) {
-                if (i == j) {
-                    continue;
-                }
-
-                if (abs(x - mCurrentTouch.pointers[j].x) <= jumpyEpsilon) {
-                    dropX = true;
-                    break;
-                }
-
-                if (abs(y - mCurrentTouch.pointers[j].y) <= jumpyEpsilon) {
-                    dropY = true;
-                    break;
-                }
-            }
-            if (! dropX && ! dropY) {
-                continue; // not jumpy
-            }
-
-            // Find a replacement candidate by comparing with older points on the
-            // complementary (non-jumpy) axis.
-            int32_t distance = INT_MIN; // distance to be corrected
-            int32_t replacementIndex = -1;
-
-            if (dropX) {
-                // X looks too close.  Find an older replacement point with a close Y.
-                int32_t smallestDeltaY = INT_MAX;
-                for (uint32_t j = 0; j < pointerCount; j++) {
-                    int32_t deltaY = abs(y - mLastTouch.pointers[j].y);
-                    if (deltaY < smallestDeltaY) {
-                        smallestDeltaY = deltaY;
-                        replacementIndex = j;
-                    }
-                }
-                distance = abs(x - mLastTouch.pointers[replacementIndex].x);
-            } else {
-                // Y looks too close.  Find an older replacement point with a close X.
-                int32_t smallestDeltaX = INT_MAX;
-                for (uint32_t j = 0; j < pointerCount; j++) {
-                    int32_t deltaX = abs(x - mLastTouch.pointers[j].x);
-                    if (deltaX < smallestDeltaX) {
-                        smallestDeltaX = deltaX;
-                        replacementIndex = j;
-                    }
-                }
-                distance = abs(y - mLastTouch.pointers[replacementIndex].y);
-            }
-
-            // If replacing this pointer would correct a worse error than the previous ones
-            // considered, then use this replacement instead.
-            if (distance > badPointerDistance) {
-                badPointerIndex = i;
-                badPointerReplacementIndex = replacementIndex;
-                badPointerDistance = distance;
-            }
-        }
-
-        // Correct the jumpy pointer if one was found.
-        if (badPointerIndex >= 0) {
-#if DEBUG_HACKS
-            LOGD("JumpyTouchFilter: Replacing bad pointer %d with (%d, %d)",
-                    badPointerIndex,
-                    mLastTouch.pointers[badPointerReplacementIndex].x,
-                    mLastTouch.pointers[badPointerReplacementIndex].y);
-#endif
-
-            mCurrentTouch.pointers[badPointerIndex].x =
-                    mLastTouch.pointers[badPointerReplacementIndex].x;
-            mCurrentTouch.pointers[badPointerIndex].y =
-                    mLastTouch.pointers[badPointerReplacementIndex].y;
-            mJumpyTouchFilter.jumpyPointsDropped += 1;
-            return true;
-        }
-    }
-
-    mJumpyTouchFilter.jumpyPointsDropped = 0;
-    return false;
-}
-
-/* Special hack for devices that have bad screen data: aggregate and
- * compute averages of the coordinate data, to reduce the amount of
- * jitter seen by applications. */
-void TouchInputMapper::applyAveragingTouchFilter() {
-    for (uint32_t currentIndex = 0; currentIndex < mCurrentTouch.pointerCount; currentIndex++) {
-        uint32_t id = mCurrentTouch.pointers[currentIndex].id;
-        int32_t x = mCurrentTouch.pointers[currentIndex].x;
-        int32_t y = mCurrentTouch.pointers[currentIndex].y;
-        int32_t pressure;
-        switch (mCalibration.pressureSource) {
-        case Calibration::PRESSURE_SOURCE_PRESSURE:
-            pressure = mCurrentTouch.pointers[currentIndex].pressure;
-            break;
-        case Calibration::PRESSURE_SOURCE_TOUCH:
-            pressure = mCurrentTouch.pointers[currentIndex].touchMajor;
-            break;
-        default:
-            pressure = 1;
-            break;
-        }
-
-        if (mLastTouch.idBits.hasBit(id)) {
-            // Pointer was down before and is still down now.
-            // Compute average over history trace.
-            uint32_t start = mAveragingTouchFilter.historyStart[id];
-            uint32_t end = mAveragingTouchFilter.historyEnd[id];
-
-            int64_t deltaX = x - mAveragingTouchFilter.historyData[end].pointers[id].x;
-            int64_t deltaY = y - mAveragingTouchFilter.historyData[end].pointers[id].y;
-            uint64_t distance = uint64_t(deltaX * deltaX + deltaY * deltaY);
-
-#if DEBUG_HACKS
-            LOGD("AveragingTouchFilter: Pointer id %d - Distance from last sample: %lld",
-                    id, distance);
-#endif
-
-            if (distance < AVERAGING_DISTANCE_LIMIT) {
-                // Increment end index in preparation for recording new historical data.
-                end += 1;
-                if (end > AVERAGING_HISTORY_SIZE) {
-                    end = 0;
-                }
-
-                // If the end index has looped back to the start index then we have filled
-                // the historical trace up to the desired size so we drop the historical
-                // data at the start of the trace.
-                if (end == start) {
-                    start += 1;
-                    if (start > AVERAGING_HISTORY_SIZE) {
-                        start = 0;
-                    }
-                }
-
-                // Add the raw data to the historical trace.
-                mAveragingTouchFilter.historyStart[id] = start;
-                mAveragingTouchFilter.historyEnd[id] = end;
-                mAveragingTouchFilter.historyData[end].pointers[id].x = x;
-                mAveragingTouchFilter.historyData[end].pointers[id].y = y;
-                mAveragingTouchFilter.historyData[end].pointers[id].pressure = pressure;
-
-                // Average over all historical positions in the trace by total pressure.
-                int32_t averagedX = 0;
-                int32_t averagedY = 0;
-                int32_t totalPressure = 0;
-                for (;;) {
-                    int32_t historicalX = mAveragingTouchFilter.historyData[start].pointers[id].x;
-                    int32_t historicalY = mAveragingTouchFilter.historyData[start].pointers[id].y;
-                    int32_t historicalPressure = mAveragingTouchFilter.historyData[start]
-                            .pointers[id].pressure;
-
-                    averagedX += historicalX * historicalPressure;
-                    averagedY += historicalY * historicalPressure;
-                    totalPressure += historicalPressure;
-
-                    if (start == end) {
-                        break;
-                    }
-
-                    start += 1;
-                    if (start > AVERAGING_HISTORY_SIZE) {
-                        start = 0;
-                    }
-                }
-
-                if (totalPressure != 0) {
-                    averagedX /= totalPressure;
-                    averagedY /= totalPressure;
-
-#if DEBUG_HACKS
-                    LOGD("AveragingTouchFilter: Pointer id %d - "
-                            "totalPressure=%d, averagedX=%d, averagedY=%d", id, totalPressure,
-                            averagedX, averagedY);
-#endif
-
-                    mCurrentTouch.pointers[currentIndex].x = averagedX;
-                    mCurrentTouch.pointers[currentIndex].y = averagedY;
-                }
-            } else {
-#if DEBUG_HACKS
-                LOGD("AveragingTouchFilter: Pointer id %d - Exceeded max distance", id);
-#endif
-            }
-        } else {
-#if DEBUG_HACKS
-            LOGD("AveragingTouchFilter: Pointer id %d - Pointer went up", id);
-#endif
-        }
-
-        // Reset pointer history.
-        mAveragingTouchFilter.historyStart[id] = 0;
-        mAveragingTouchFilter.historyEnd[id] = 0;
-        mAveragingTouchFilter.historyData[0].pointers[id].x = x;
-        mAveragingTouchFilter.historyData[0].pointers[id].y = y;
-        mAveragingTouchFilter.historyData[0].pointers[id].pressure = pressure;
-    }
-}
-
-int32_t TouchInputMapper::getKeyCodeState(uint32_t sourceMask, int32_t keyCode) {
-    { // acquire lock
-        AutoMutex _l(mLock);
-
-        if (mLocked.currentVirtualKey.down && mLocked.currentVirtualKey.keyCode == keyCode) {
-            return AKEY_STATE_VIRTUAL;
-        }
-
-        size_t numVirtualKeys = mLocked.virtualKeys.size();
-        for (size_t i = 0; i < numVirtualKeys; i++) {
-            const VirtualKey& virtualKey = mLocked.virtualKeys[i];
-            if (virtualKey.keyCode == keyCode) {
-                return AKEY_STATE_UP;
-            }
-        }
-    } // release lock
-
-    return AKEY_STATE_UNKNOWN;
-}
-
-int32_t TouchInputMapper::getScanCodeState(uint32_t sourceMask, int32_t scanCode) {
-    { // acquire lock
-        AutoMutex _l(mLock);
-
-        if (mLocked.currentVirtualKey.down && mLocked.currentVirtualKey.scanCode == scanCode) {
-            return AKEY_STATE_VIRTUAL;
-        }
-
-        size_t numVirtualKeys = mLocked.virtualKeys.size();
-        for (size_t i = 0; i < numVirtualKeys; i++) {
-            const VirtualKey& virtualKey = mLocked.virtualKeys[i];
-            if (virtualKey.scanCode == scanCode) {
-                return AKEY_STATE_UP;
-            }
-        }
-    } // release lock
-
-    return AKEY_STATE_UNKNOWN;
-}
-
-bool TouchInputMapper::markSupportedKeyCodes(uint32_t sourceMask, size_t numCodes,
-        const int32_t* keyCodes, uint8_t* outFlags) {
-    { // acquire lock
-        AutoMutex _l(mLock);
-
-        size_t numVirtualKeys = mLocked.virtualKeys.size();
-        for (size_t i = 0; i < numVirtualKeys; i++) {
-            const VirtualKey& virtualKey = mLocked.virtualKeys[i];
-
-            for (size_t i = 0; i < numCodes; i++) {
-                if (virtualKey.keyCode == keyCodes[i]) {
-                    outFlags[i] = 1;
-                }
-            }
-        }
-    } // release lock
-
-    return true;
-}
-
-
-// --- SingleTouchInputMapper ---
-
-SingleTouchInputMapper::SingleTouchInputMapper(InputDevice* device) :
-        TouchInputMapper(device) {
-    initialize();
-}
-
-SingleTouchInputMapper::~SingleTouchInputMapper() {
-}
-
-void SingleTouchInputMapper::initialize() {
-    mAccumulator.clear();
-
-    mDown = false;
-    mX = 0;
-    mY = 0;
-    mPressure = 0; // default to 0 for devices that don't report pressure
-    mToolWidth = 0; // default to 0 for devices that don't report tool width
-}
-
-void SingleTouchInputMapper::reset() {
-    TouchInputMapper::reset();
-
-    initialize();
- }
-
-void SingleTouchInputMapper::process(const RawEvent* rawEvent) {
-    switch (rawEvent->type) {
-    case EV_KEY:
-        switch (rawEvent->scanCode) {
-        case BTN_TOUCH:
-            mAccumulator.fields |= Accumulator::FIELD_BTN_TOUCH;
-            mAccumulator.btnTouch = rawEvent->value != 0;
-            // Don't sync immediately.  Wait until the next SYN_REPORT since we might
-            // not have received valid position information yet.  This logic assumes that
-            // BTN_TOUCH is always followed by SYN_REPORT as part of a complete packet.
-            break;
-        }
-        break;
-
-    case EV_ABS:
-        switch (rawEvent->scanCode) {
-        case ABS_X:
-            mAccumulator.fields |= Accumulator::FIELD_ABS_X;
-            mAccumulator.absX = rawEvent->value;
-            break;
-        case ABS_Y:
-            mAccumulator.fields |= Accumulator::FIELD_ABS_Y;
-            mAccumulator.absY = rawEvent->value;
-            break;
-        case ABS_PRESSURE:
-            mAccumulator.fields |= Accumulator::FIELD_ABS_PRESSURE;
-            mAccumulator.absPressure = rawEvent->value;
-            break;
-        case ABS_TOOL_WIDTH:
-            mAccumulator.fields |= Accumulator::FIELD_ABS_TOOL_WIDTH;
-            mAccumulator.absToolWidth = rawEvent->value;
-            break;
-        }
-        break;
-
-    case EV_SYN:
-        switch (rawEvent->scanCode) {
-        case SYN_REPORT:
-            sync(rawEvent->when);
-            break;
-        }
-        break;
-    }
-}
-
-void SingleTouchInputMapper::sync(nsecs_t when) {
-    uint32_t fields = mAccumulator.fields;
-    if (fields == 0) {
-        return; // no new state changes, so nothing to do
-    }
-
-    if (fields & Accumulator::FIELD_BTN_TOUCH) {
-        mDown = mAccumulator.btnTouch;
-    }
-
-    if (fields & Accumulator::FIELD_ABS_X) {
-        mX = mAccumulator.absX;
-    }
-
-    if (fields & Accumulator::FIELD_ABS_Y) {
-        mY = mAccumulator.absY;
-    }
-
-    if (fields & Accumulator::FIELD_ABS_PRESSURE) {
-        mPressure = mAccumulator.absPressure;
-    }
-
-    if (fields & Accumulator::FIELD_ABS_TOOL_WIDTH) {
-        mToolWidth = mAccumulator.absToolWidth;
-    }
-
-    mCurrentTouch.clear();
-
-    if (mDown) {
-        mCurrentTouch.pointerCount = 1;
-        mCurrentTouch.pointers[0].id = 0;
-        mCurrentTouch.pointers[0].x = mX;
-        mCurrentTouch.pointers[0].y = mY;
-        mCurrentTouch.pointers[0].pressure = mPressure;
-        mCurrentTouch.pointers[0].touchMajor = 0;
-        mCurrentTouch.pointers[0].touchMinor = 0;
-        mCurrentTouch.pointers[0].toolMajor = mToolWidth;
-        mCurrentTouch.pointers[0].toolMinor = mToolWidth;
-        mCurrentTouch.pointers[0].orientation = 0;
-        mCurrentTouch.idToIndex[0] = 0;
-        mCurrentTouch.idBits.markBit(0);
-    }
-
-    syncTouch(when, true);
-
-    mAccumulator.clear();
-}
-
-void SingleTouchInputMapper::configureRawAxes() {
-    TouchInputMapper::configureRawAxes();
-
-    getEventHub()->getAbsoluteAxisInfo(getDeviceId(), ABS_X, & mRawAxes.x);
-    getEventHub()->getAbsoluteAxisInfo(getDeviceId(), ABS_Y, & mRawAxes.y);
-    getEventHub()->getAbsoluteAxisInfo(getDeviceId(), ABS_PRESSURE, & mRawAxes.pressure);
-    getEventHub()->getAbsoluteAxisInfo(getDeviceId(), ABS_TOOL_WIDTH, & mRawAxes.toolMajor);
-}
-
-
-// --- MultiTouchInputMapper ---
-
-MultiTouchInputMapper::MultiTouchInputMapper(InputDevice* device) :
-        TouchInputMapper(device) {
-    initialize();
-}
-
-MultiTouchInputMapper::~MultiTouchInputMapper() {
-}
-
-void MultiTouchInputMapper::initialize() {
-    mAccumulator.clear();
-}
-
-void MultiTouchInputMapper::reset() {
-    TouchInputMapper::reset();
-
-    initialize();
-}
-
-void MultiTouchInputMapper::process(const RawEvent* rawEvent) {
-    switch (rawEvent->type) {
-    case EV_ABS: {
-        uint32_t pointerIndex = mAccumulator.pointerCount;
-        Accumulator::Pointer* pointer = & mAccumulator.pointers[pointerIndex];
-
-        switch (rawEvent->scanCode) {
-        case ABS_MT_POSITION_X:
-            pointer->fields |= Accumulator::FIELD_ABS_MT_POSITION_X;
-            pointer->absMTPositionX = rawEvent->value;
-            break;
-        case ABS_MT_POSITION_Y:
-            pointer->fields |= Accumulator::FIELD_ABS_MT_POSITION_Y;
-            pointer->absMTPositionY = rawEvent->value;
-            break;
-        case ABS_MT_TOUCH_MAJOR:
-            pointer->fields |= Accumulator::FIELD_ABS_MT_TOUCH_MAJOR;
-            pointer->absMTTouchMajor = rawEvent->value;
-            break;
-        case ABS_MT_TOUCH_MINOR:
-            pointer->fields |= Accumulator::FIELD_ABS_MT_TOUCH_MINOR;
-            pointer->absMTTouchMinor = rawEvent->value;
-            break;
-        case ABS_MT_WIDTH_MAJOR:
-            pointer->fields |= Accumulator::FIELD_ABS_MT_WIDTH_MAJOR;
-            pointer->absMTWidthMajor = rawEvent->value;
-            break;
-        case ABS_MT_WIDTH_MINOR:
-            pointer->fields |= Accumulator::FIELD_ABS_MT_WIDTH_MINOR;
-            pointer->absMTWidthMinor = rawEvent->value;
-            break;
-        case ABS_MT_ORIENTATION:
-            pointer->fields |= Accumulator::FIELD_ABS_MT_ORIENTATION;
-            pointer->absMTOrientation = rawEvent->value;
-            break;
-        case ABS_MT_TRACKING_ID:
-            pointer->fields |= Accumulator::FIELD_ABS_MT_TRACKING_ID;
-            pointer->absMTTrackingId = rawEvent->value;
-            break;
-        case ABS_MT_PRESSURE:
-            pointer->fields |= Accumulator::FIELD_ABS_MT_PRESSURE;
-            pointer->absMTPressure = rawEvent->value;
-            break;
-        }
-        break;
-    }
-
-    case EV_SYN:
-        switch (rawEvent->scanCode) {
-        case SYN_MT_REPORT: {
-            // MultiTouch Sync: The driver has returned all data for *one* of the pointers.
-            uint32_t pointerIndex = mAccumulator.pointerCount;
-
-            if (mAccumulator.pointers[pointerIndex].fields) {
-                if (pointerIndex == MAX_POINTERS) {
-                    LOGW("MultiTouch device driver returned more than maximum of %d pointers.",
-                            MAX_POINTERS);
-                } else {
-                    pointerIndex += 1;
-                    mAccumulator.pointerCount = pointerIndex;
-                }
-            }
-
-            mAccumulator.pointers[pointerIndex].clear();
-            break;
-        }
-
-        case SYN_REPORT:
-            sync(rawEvent->when);
-            break;
-        }
-        break;
-    }
-}
-
-void MultiTouchInputMapper::sync(nsecs_t when) {
-    static const uint32_t REQUIRED_FIELDS =
-            Accumulator::FIELD_ABS_MT_POSITION_X | Accumulator::FIELD_ABS_MT_POSITION_Y;
-
-    uint32_t inCount = mAccumulator.pointerCount;
-    uint32_t outCount = 0;
-    bool havePointerIds = true;
-
-    mCurrentTouch.clear();
-
-    for (uint32_t inIndex = 0; inIndex < inCount; inIndex++) {
-        const Accumulator::Pointer& inPointer = mAccumulator.pointers[inIndex];
-        uint32_t fields = inPointer.fields;
-
-        if ((fields & REQUIRED_FIELDS) != REQUIRED_FIELDS) {
-            // Some drivers send empty MT sync packets without X / Y to indicate a pointer up.
-            // Drop this finger.
-            continue;
-        }
-
-        PointerData& outPointer = mCurrentTouch.pointers[outCount];
-        outPointer.x = inPointer.absMTPositionX;
-        outPointer.y = inPointer.absMTPositionY;
-
-        if (fields & Accumulator::FIELD_ABS_MT_PRESSURE) {
-            if (inPointer.absMTPressure <= 0) {
-                // Some devices send sync packets with X / Y but with a 0 pressure to indicate
-                // a pointer going up.  Drop this finger.
-                continue;
-            }
-            outPointer.pressure = inPointer.absMTPressure;
-        } else {
-            // Default pressure to 0 if absent.
-            outPointer.pressure = 0;
-        }
-
-        if (fields & Accumulator::FIELD_ABS_MT_TOUCH_MAJOR) {
-            if (inPointer.absMTTouchMajor <= 0) {
-                // Some devices send sync packets with X / Y but with a 0 touch major to indicate
-                // a pointer going up.  Drop this finger.
-                continue;
-            }
-            outPointer.touchMajor = inPointer.absMTTouchMajor;
-        } else {
-            // Default touch area to 0 if absent.
-            outPointer.touchMajor = 0;
-        }
-
-        if (fields & Accumulator::FIELD_ABS_MT_TOUCH_MINOR) {
-            outPointer.touchMinor = inPointer.absMTTouchMinor;
-        } else {
-            // Assume touch area is circular.
-            outPointer.touchMinor = outPointer.touchMajor;
-        }
-
-        if (fields & Accumulator::FIELD_ABS_MT_WIDTH_MAJOR) {
-            outPointer.toolMajor = inPointer.absMTWidthMajor;
-        } else {
-            // Default tool area to 0 if absent.
-            outPointer.toolMajor = 0;
-        }
-
-        if (fields & Accumulator::FIELD_ABS_MT_WIDTH_MINOR) {
-            outPointer.toolMinor = inPointer.absMTWidthMinor;
-        } else {
-            // Assume tool area is circular.
-            outPointer.toolMinor = outPointer.toolMajor;
-        }
-
-        if (fields & Accumulator::FIELD_ABS_MT_ORIENTATION) {
-            outPointer.orientation = inPointer.absMTOrientation;
-        } else {
-            // Default orientation to vertical if absent.
-            outPointer.orientation = 0;
-        }
-
-        // Assign pointer id using tracking id if available.
-        if (havePointerIds) {
-            if (fields & Accumulator::FIELD_ABS_MT_TRACKING_ID) {
-                uint32_t id = uint32_t(inPointer.absMTTrackingId);
-
-                if (id > MAX_POINTER_ID) {
-#if DEBUG_POINTERS
-                    LOGD("Pointers: Ignoring driver provided pointer id %d because "
-                            "it is larger than max supported id %d",
-                            id, MAX_POINTER_ID);
-#endif
-                    havePointerIds = false;
-                }
-                else {
-                    outPointer.id = id;
-                    mCurrentTouch.idToIndex[id] = outCount;
-                    mCurrentTouch.idBits.markBit(id);
-                }
-            } else {
-                havePointerIds = false;
-            }
-        }
-
-        outCount += 1;
-    }
-
-    mCurrentTouch.pointerCount = outCount;
-
-    syncTouch(when, havePointerIds);
-
-    mAccumulator.clear();
-}
-
-void MultiTouchInputMapper::configureRawAxes() {
-    TouchInputMapper::configureRawAxes();
-
-    getEventHub()->getAbsoluteAxisInfo(getDeviceId(), ABS_MT_POSITION_X, & mRawAxes.x);
-    getEventHub()->getAbsoluteAxisInfo(getDeviceId(), ABS_MT_POSITION_Y, & mRawAxes.y);
-    getEventHub()->getAbsoluteAxisInfo(getDeviceId(), ABS_MT_TOUCH_MAJOR, & mRawAxes.touchMajor);
-    getEventHub()->getAbsoluteAxisInfo(getDeviceId(), ABS_MT_TOUCH_MINOR, & mRawAxes.touchMinor);
-    getEventHub()->getAbsoluteAxisInfo(getDeviceId(), ABS_MT_WIDTH_MAJOR, & mRawAxes.toolMajor);
-    getEventHub()->getAbsoluteAxisInfo(getDeviceId(), ABS_MT_WIDTH_MINOR, & mRawAxes.toolMinor);
-    getEventHub()->getAbsoluteAxisInfo(getDeviceId(), ABS_MT_ORIENTATION, & mRawAxes.orientation);
-    getEventHub()->getAbsoluteAxisInfo(getDeviceId(), ABS_MT_PRESSURE, & mRawAxes.pressure);
-}
-
-
-} // namespace android
diff --git a/libs/ui/KeyCharacterMap.cpp b/libs/ui/KeyCharacterMap.cpp
index 9bfa8f6..2decfe9 100644
--- a/libs/ui/KeyCharacterMap.cpp
+++ b/libs/ui/KeyCharacterMap.cpp
@@ -185,9 +185,11 @@
     const Key* key;
     const Behavior* behavior;
     if (getKeyBehavior(keyCode, metaState, &key, &behavior)) {
-        outFallbackAction->keyCode = behavior->fallbackKeyCode;
-        outFallbackAction->metaState = metaState & ~behavior->metaState;
-        result = true;
+        if (behavior->fallbackKeyCode) {
+            outFallbackAction->keyCode = behavior->fallbackKeyCode;
+            outFallbackAction->metaState = metaState & ~behavior->metaState;
+            result = true;
+        }
     }
 #if DEBUG_MAPPING
     LOGD("getFallbackKeyCode: keyCode=%d, metaState=0x%08x ~ Result %s, "
diff --git a/libs/ui/tests/Android.mk b/libs/ui/tests/Android.mk
index aa017b9..580d73c 100644
--- a/libs/ui/tests/Android.mk
+++ b/libs/ui/tests/Android.mk
@@ -7,8 +7,6 @@
 # Build the unit tests.
 test_src_files := \
     InputChannel_test.cpp \
-    InputReader_test.cpp \
-    InputDispatcher_test.cpp \
     InputPublisherAndConsumer_test.cpp
 
 shared_libraries := \
diff --git a/libs/ui/tests/InputDispatcher_test.cpp b/libs/ui/tests/InputDispatcher_test.cpp
deleted file mode 100644
index 7e17c57..0000000
--- a/libs/ui/tests/InputDispatcher_test.cpp
+++ /dev/null
@@ -1,229 +0,0 @@
-//
-// Copyright 2010 The Android Open Source Project
-//
-
-#include <ui/InputDispatcher.h>
-#include <gtest/gtest.h>
-#include <linux/input.h>
-
-namespace android {
-
-// An arbitrary time value.
-static const nsecs_t ARBITRARY_TIME = 1234;
-
-// An arbitrary device id.
-static const int32_t DEVICE_ID = 1;
-
-// An arbitrary injector pid / uid pair that has permission to inject events.
-static const int32_t INJECTOR_PID = 999;
-static const int32_t INJECTOR_UID = 1001;
-
-
-// --- FakeInputDispatcherPolicy ---
-
-class FakeInputDispatcherPolicy : public InputDispatcherPolicyInterface {
-protected:
-    virtual ~FakeInputDispatcherPolicy() {
-    }
-
-public:
-    FakeInputDispatcherPolicy() {
-    }
-
-private:
-    virtual void notifyConfigurationChanged(nsecs_t when) {
-    }
-
-    virtual nsecs_t notifyANR(const sp<InputApplicationHandle>& inputApplicationHandle,
-            const sp<InputChannel>& inputChannel) {
-        return 0;
-    }
-
-    virtual void notifyInputChannelBroken(const sp<InputChannel>& inputChannel) {
-    }
-
-    virtual nsecs_t getKeyRepeatTimeout() {
-        return 500 * 1000000LL;
-    }
-
-    virtual nsecs_t getKeyRepeatDelay() {
-        return 50 * 1000000LL;
-    }
-
-    virtual int32_t getMaxEventsPerSecond() {
-        return 60;
-    }
-
-    virtual void interceptKeyBeforeQueueing(const KeyEvent* keyEvent, uint32_t& policyFlags) {
-    }
-
-    virtual void interceptGenericBeforeQueueing(nsecs_t when, uint32_t& policyFlags) {
-    }
-
-    virtual bool interceptKeyBeforeDispatching(const sp<InputChannel>& inputChannel,
-            const KeyEvent* keyEvent, uint32_t policyFlags) {
-        return false;
-    }
-
-    virtual bool dispatchUnhandledKey(const sp<InputChannel>& inputChannel,
-            const KeyEvent* keyEvent, uint32_t policyFlags, KeyEvent* outFallbackKeyEvent) {
-        return false;
-    }
-
-    virtual void notifySwitch(nsecs_t when,
-            int32_t switchCode, int32_t switchValue, uint32_t policyFlags) {
-    }
-
-    virtual void pokeUserActivity(nsecs_t eventTime, int32_t eventType) {
-    }
-
-    virtual bool checkInjectEventsPermissionNonReentrant(
-            int32_t injectorPid, int32_t injectorUid) {
-        return false;
-    }
-};
-
-
-// --- InputDispatcherTest ---
-
-class InputDispatcherTest : public testing::Test {
-protected:
-    sp<FakeInputDispatcherPolicy> mFakePolicy;
-    sp<InputDispatcher> mDispatcher;
-
-    virtual void SetUp() {
-        mFakePolicy = new FakeInputDispatcherPolicy();
-        mDispatcher = new InputDispatcher(mFakePolicy);
-    }
-
-    virtual void TearDown() {
-        mFakePolicy.clear();
-        mDispatcher.clear();
-    }
-};
-
-
-TEST_F(InputDispatcherTest, InjectInputEvent_ValidatesKeyEvents) {
-    KeyEvent event;
-
-    // Rejects undefined key actions.
-    event.initialize(DEVICE_ID, AINPUT_SOURCE_KEYBOARD,
-            /*action*/ -1, 0,
-            AKEYCODE_A, KEY_A, AMETA_NONE, 0, ARBITRARY_TIME, ARBITRARY_TIME);
-    ASSERT_EQ(INPUT_EVENT_INJECTION_FAILED, mDispatcher->injectInputEvent(&event,
-            INJECTOR_PID, INJECTOR_UID, INPUT_EVENT_INJECTION_SYNC_NONE, 0))
-            << "Should reject key events with undefined action.";
-
-    // Rejects ACTION_MULTIPLE since it is not supported despite being defined in the API.
-    event.initialize(DEVICE_ID, AINPUT_SOURCE_KEYBOARD,
-            AKEY_EVENT_ACTION_MULTIPLE, 0,
-            AKEYCODE_A, KEY_A, AMETA_NONE, 0, ARBITRARY_TIME, ARBITRARY_TIME);
-    ASSERT_EQ(INPUT_EVENT_INJECTION_FAILED, mDispatcher->injectInputEvent(&event,
-            INJECTOR_PID, INJECTOR_UID, INPUT_EVENT_INJECTION_SYNC_NONE, 0))
-            << "Should reject key events with ACTION_MULTIPLE.";
-}
-
-TEST_F(InputDispatcherTest, InjectInputEvent_ValidatesMotionEvents) {
-    MotionEvent event;
-    int32_t pointerIds[MAX_POINTERS + 1];
-    PointerCoords pointerCoords[MAX_POINTERS + 1];
-    for (int i = 0; i <= MAX_POINTERS; i++) {
-        pointerIds[i] = i;
-    }
-
-    // Rejects undefined motion actions.
-    event.initialize(DEVICE_ID, AINPUT_SOURCE_TOUCHSCREEN,
-            /*action*/ -1, 0, 0, AMETA_NONE, 0, 0, 0, 0,
-            ARBITRARY_TIME, ARBITRARY_TIME,
-            /*pointerCount*/ 1, pointerIds, pointerCoords);
-    ASSERT_EQ(INPUT_EVENT_INJECTION_FAILED, mDispatcher->injectInputEvent(&event,
-            INJECTOR_PID, INJECTOR_UID, INPUT_EVENT_INJECTION_SYNC_NONE, 0))
-            << "Should reject motion events with undefined action.";
-
-    // Rejects pointer down with invalid index.
-    event.initialize(DEVICE_ID, AINPUT_SOURCE_TOUCHSCREEN,
-            AMOTION_EVENT_ACTION_POINTER_DOWN | (1 << AMOTION_EVENT_ACTION_POINTER_INDEX_SHIFT),
-            0, 0, AMETA_NONE, 0, 0, 0, 0,
-            ARBITRARY_TIME, ARBITRARY_TIME,
-            /*pointerCount*/ 1, pointerIds, pointerCoords);
-    ASSERT_EQ(INPUT_EVENT_INJECTION_FAILED, mDispatcher->injectInputEvent(&event,
-            INJECTOR_PID, INJECTOR_UID, INPUT_EVENT_INJECTION_SYNC_NONE, 0))
-            << "Should reject motion events with pointer down index too large.";
-
-    event.initialize(DEVICE_ID, AINPUT_SOURCE_TOUCHSCREEN,
-            AMOTION_EVENT_ACTION_POINTER_DOWN | (-1 << AMOTION_EVENT_ACTION_POINTER_INDEX_SHIFT),
-            0, 0, AMETA_NONE, 0, 0, 0, 0,
-            ARBITRARY_TIME, ARBITRARY_TIME,
-            /*pointerCount*/ 1, pointerIds, pointerCoords);
-    ASSERT_EQ(INPUT_EVENT_INJECTION_FAILED, mDispatcher->injectInputEvent(&event,
-            INJECTOR_PID, INJECTOR_UID, INPUT_EVENT_INJECTION_SYNC_NONE, 0))
-            << "Should reject motion events with pointer down index too small.";
-
-    // Rejects pointer up with invalid index.
-    event.initialize(DEVICE_ID, AINPUT_SOURCE_TOUCHSCREEN,
-            AMOTION_EVENT_ACTION_POINTER_UP | (1 << AMOTION_EVENT_ACTION_POINTER_INDEX_SHIFT),
-            0, 0, AMETA_NONE, 0, 0, 0, 0,
-            ARBITRARY_TIME, ARBITRARY_TIME,
-            /*pointerCount*/ 1, pointerIds, pointerCoords);
-    ASSERT_EQ(INPUT_EVENT_INJECTION_FAILED, mDispatcher->injectInputEvent(&event,
-            INJECTOR_PID, INJECTOR_UID, INPUT_EVENT_INJECTION_SYNC_NONE, 0))
-            << "Should reject motion events with pointer up index too large.";
-
-    event.initialize(DEVICE_ID, AINPUT_SOURCE_TOUCHSCREEN,
-            AMOTION_EVENT_ACTION_POINTER_UP | (-1 << AMOTION_EVENT_ACTION_POINTER_INDEX_SHIFT),
-            0, 0, AMETA_NONE, 0, 0, 0, 0,
-            ARBITRARY_TIME, ARBITRARY_TIME,
-            /*pointerCount*/ 1, pointerIds, pointerCoords);
-    ASSERT_EQ(INPUT_EVENT_INJECTION_FAILED, mDispatcher->injectInputEvent(&event,
-            INJECTOR_PID, INJECTOR_UID, INPUT_EVENT_INJECTION_SYNC_NONE, 0))
-            << "Should reject motion events with pointer up index too small.";
-
-    // Rejects motion events with invalid number of pointers.
-    event.initialize(DEVICE_ID, AINPUT_SOURCE_TOUCHSCREEN,
-            AMOTION_EVENT_ACTION_DOWN, 0, 0, AMETA_NONE, 0, 0, 0, 0,
-            ARBITRARY_TIME, ARBITRARY_TIME,
-            /*pointerCount*/ 0, pointerIds, pointerCoords);
-    ASSERT_EQ(INPUT_EVENT_INJECTION_FAILED, mDispatcher->injectInputEvent(&event,
-            INJECTOR_PID, INJECTOR_UID, INPUT_EVENT_INJECTION_SYNC_NONE, 0))
-            << "Should reject motion events with 0 pointers.";
-
-    event.initialize(DEVICE_ID, AINPUT_SOURCE_TOUCHSCREEN,
-            AMOTION_EVENT_ACTION_DOWN, 0, 0, AMETA_NONE, 0, 0, 0, 0,
-            ARBITRARY_TIME, ARBITRARY_TIME,
-            /*pointerCount*/ MAX_POINTERS + 1, pointerIds, pointerCoords);
-    ASSERT_EQ(INPUT_EVENT_INJECTION_FAILED, mDispatcher->injectInputEvent(&event,
-            INJECTOR_PID, INJECTOR_UID, INPUT_EVENT_INJECTION_SYNC_NONE, 0))
-            << "Should reject motion events with more than MAX_POINTERS pointers.";
-
-    // Rejects motion events with invalid pointer ids.
-    pointerIds[0] = -1;
-    event.initialize(DEVICE_ID, AINPUT_SOURCE_TOUCHSCREEN,
-            AMOTION_EVENT_ACTION_DOWN, 0, 0, AMETA_NONE, 0, 0, 0, 0,
-            ARBITRARY_TIME, ARBITRARY_TIME,
-            /*pointerCount*/ 1, pointerIds, pointerCoords);
-    ASSERT_EQ(INPUT_EVENT_INJECTION_FAILED, mDispatcher->injectInputEvent(&event,
-            INJECTOR_PID, INJECTOR_UID, INPUT_EVENT_INJECTION_SYNC_NONE, 0))
-            << "Should reject motion events with pointer ids less than 0.";
-
-    pointerIds[0] = MAX_POINTER_ID + 1;
-    event.initialize(DEVICE_ID, AINPUT_SOURCE_TOUCHSCREEN,
-            AMOTION_EVENT_ACTION_DOWN, 0, 0, AMETA_NONE, 0, 0, 0, 0,
-            ARBITRARY_TIME, ARBITRARY_TIME,
-            /*pointerCount*/ 1, pointerIds, pointerCoords);
-    ASSERT_EQ(INPUT_EVENT_INJECTION_FAILED, mDispatcher->injectInputEvent(&event,
-            INJECTOR_PID, INJECTOR_UID, INPUT_EVENT_INJECTION_SYNC_NONE, 0))
-            << "Should reject motion events with pointer ids greater than MAX_POINTER_ID.";
-
-    // Rejects motion events with duplicate pointer ids.
-    pointerIds[0] = 1;
-    pointerIds[1] = 1;
-    event.initialize(DEVICE_ID, AINPUT_SOURCE_TOUCHSCREEN,
-            AMOTION_EVENT_ACTION_DOWN, 0, 0, AMETA_NONE, 0, 0, 0, 0,
-            ARBITRARY_TIME, ARBITRARY_TIME,
-            /*pointerCount*/ 2, pointerIds, pointerCoords);
-    ASSERT_EQ(INPUT_EVENT_INJECTION_FAILED, mDispatcher->injectInputEvent(&event,
-            INJECTOR_PID, INJECTOR_UID, INPUT_EVENT_INJECTION_SYNC_NONE, 0))
-            << "Should reject motion events with duplicate pointer ids.";
-}
-
-} // namespace android
diff --git a/libs/ui/tests/InputReader_test.cpp b/libs/ui/tests/InputReader_test.cpp
deleted file mode 100644
index 97cbc25..0000000
--- a/libs/ui/tests/InputReader_test.cpp
+++ /dev/null
@@ -1,3497 +0,0 @@
-//
-// Copyright 2010 The Android Open Source Project
-//
-
-#include <ui/InputReader.h>
-#include <utils/List.h>
-#include <gtest/gtest.h>
-#include <math.h>
-
-namespace android {
-
-// An arbitrary time value.
-static const nsecs_t ARBITRARY_TIME = 1234;
-
-// Arbitrary display properties.
-static const int32_t DISPLAY_ID = 0;
-static const int32_t DISPLAY_WIDTH = 480;
-static const int32_t DISPLAY_HEIGHT = 800;
-
-// Error tolerance for floating point assertions.
-static const float EPSILON = 0.001f;
-
-template<typename T>
-static inline T min(T a, T b) {
-    return a < b ? a : b;
-}
-
-static inline float avg(float x, float y) {
-    return (x + y) / 2;
-}
-
-
-// --- FakeInputReaderPolicy ---
-
-class FakeInputReaderPolicy : public InputReaderPolicyInterface {
-    struct DisplayInfo {
-        int32_t width;
-        int32_t height;
-        int32_t orientation;
-    };
-
-    KeyedVector<int32_t, DisplayInfo> mDisplayInfos;
-    bool mFilterTouchEvents;
-    bool mFilterJumpyTouchEvents;
-    Vector<String8> mExcludedDeviceNames;
-
-protected:
-    virtual ~FakeInputReaderPolicy() { }
-
-public:
-    FakeInputReaderPolicy() :
-            mFilterTouchEvents(false), mFilterJumpyTouchEvents(false) {
-    }
-
-    void removeDisplayInfo(int32_t displayId) {
-        mDisplayInfos.removeItem(displayId);
-    }
-
-    void setDisplayInfo(int32_t displayId, int32_t width, int32_t height, int32_t orientation) {
-        removeDisplayInfo(displayId);
-
-        DisplayInfo info;
-        info.width = width;
-        info.height = height;
-        info.orientation = orientation;
-        mDisplayInfos.add(displayId, info);
-    }
-
-    void setFilterTouchEvents(bool enabled) {
-        mFilterTouchEvents = enabled;
-    }
-
-    void setFilterJumpyTouchEvents(bool enabled) {
-        mFilterJumpyTouchEvents = enabled;
-    }
-
-    void addExcludedDeviceName(const String8& deviceName) {
-        mExcludedDeviceNames.push(deviceName);
-    }
-
-private:
-    virtual bool getDisplayInfo(int32_t displayId,
-            int32_t* width, int32_t* height, int32_t* orientation) {
-        ssize_t index = mDisplayInfos.indexOfKey(displayId);
-        if (index >= 0) {
-            const DisplayInfo& info = mDisplayInfos.valueAt(index);
-            if (width) {
-                *width = info.width;
-            }
-            if (height) {
-                *height = info.height;
-            }
-            if (orientation) {
-                *orientation = info.orientation;
-            }
-            return true;
-        }
-        return false;
-    }
-
-    virtual bool filterTouchEvents() {
-        return mFilterTouchEvents;
-    }
-
-    virtual bool filterJumpyTouchEvents() {
-        return mFilterJumpyTouchEvents;
-    }
-
-    virtual void getExcludedDeviceNames(Vector<String8>& outExcludedDeviceNames) {
-        outExcludedDeviceNames.appendVector(mExcludedDeviceNames);
-    }
-};
-
-
-// --- FakeInputDispatcher ---
-
-class FakeInputDispatcher : public InputDispatcherInterface {
-public:
-    struct NotifyConfigurationChangedArgs {
-        nsecs_t eventTime;
-    };
-
-    struct NotifyKeyArgs {
-        nsecs_t eventTime;
-        int32_t deviceId;
-        int32_t source;
-        uint32_t policyFlags;
-        int32_t action;
-        int32_t flags;
-        int32_t keyCode;
-        int32_t scanCode;
-        int32_t metaState;
-        nsecs_t downTime;
-    };
-
-    struct NotifyMotionArgs {
-        nsecs_t eventTime;
-        int32_t deviceId;
-        int32_t source;
-        uint32_t policyFlags;
-        int32_t action;
-        int32_t flags;
-        int32_t metaState;
-        int32_t edgeFlags;
-        uint32_t pointerCount;
-        Vector<int32_t> pointerIds;
-        Vector<PointerCoords> pointerCoords;
-        float xPrecision;
-        float yPrecision;
-        nsecs_t downTime;
-    };
-
-    struct NotifySwitchArgs {
-        nsecs_t when;
-        int32_t switchCode;
-        int32_t switchValue;
-        uint32_t policyFlags;
-    };
-
-private:
-    List<NotifyConfigurationChangedArgs> mNotifyConfigurationChangedArgs;
-    List<NotifyKeyArgs> mNotifyKeyArgs;
-    List<NotifyMotionArgs> mNotifyMotionArgs;
-    List<NotifySwitchArgs> mNotifySwitchArgs;
-
-protected:
-    virtual ~FakeInputDispatcher() { }
-
-public:
-    FakeInputDispatcher() {
-    }
-
-    void assertNotifyConfigurationChangedWasCalled(NotifyConfigurationChangedArgs* outArgs = NULL) {
-        ASSERT_FALSE(mNotifyConfigurationChangedArgs.empty())
-                << "Expected notifyConfigurationChanged() to have been called.";
-        if (outArgs) {
-            *outArgs = *mNotifyConfigurationChangedArgs.begin();
-        }
-        mNotifyConfigurationChangedArgs.erase(mNotifyConfigurationChangedArgs.begin());
-    }
-
-    void assertNotifyKeyWasCalled(NotifyKeyArgs* outArgs = NULL) {
-        ASSERT_FALSE(mNotifyKeyArgs.empty())
-                << "Expected notifyKey() to have been called.";
-        if (outArgs) {
-            *outArgs = *mNotifyKeyArgs.begin();
-        }
-        mNotifyKeyArgs.erase(mNotifyKeyArgs.begin());
-    }
-
-    void assertNotifyKeyWasNotCalled() {
-        ASSERT_TRUE(mNotifyKeyArgs.empty())
-                << "Expected notifyKey() to not have been called.";
-    }
-
-    void assertNotifyMotionWasCalled(NotifyMotionArgs* outArgs = NULL) {
-        ASSERT_FALSE(mNotifyMotionArgs.empty())
-                << "Expected notifyMotion() to have been called.";
-        if (outArgs) {
-            *outArgs = *mNotifyMotionArgs.begin();
-        }
-        mNotifyMotionArgs.erase(mNotifyMotionArgs.begin());
-    }
-
-    void assertNotifyMotionWasNotCalled() {
-        ASSERT_TRUE(mNotifyMotionArgs.empty())
-                << "Expected notifyMotion() to not have been called.";
-    }
-
-    void assertNotifySwitchWasCalled(NotifySwitchArgs* outArgs = NULL) {
-        ASSERT_FALSE(mNotifySwitchArgs.empty())
-                << "Expected notifySwitch() to have been called.";
-        if (outArgs) {
-            *outArgs = *mNotifySwitchArgs.begin();
-        }
-        mNotifySwitchArgs.erase(mNotifySwitchArgs.begin());
-    }
-
-private:
-    virtual void notifyConfigurationChanged(nsecs_t eventTime) {
-        NotifyConfigurationChangedArgs args;
-        args.eventTime = eventTime;
-        mNotifyConfigurationChangedArgs.push_back(args);
-    }
-
-    virtual void notifyKey(nsecs_t eventTime, int32_t deviceId, int32_t source,
-            uint32_t policyFlags, int32_t action, int32_t flags, int32_t keyCode,
-            int32_t scanCode, int32_t metaState, nsecs_t downTime) {
-        NotifyKeyArgs args;
-        args.eventTime = eventTime;
-        args.deviceId = deviceId;
-        args.source = source;
-        args.policyFlags = policyFlags;
-        args.action = action;
-        args.flags = flags;
-        args.keyCode = keyCode;
-        args.scanCode = scanCode;
-        args.metaState = metaState;
-        args.downTime = downTime;
-        mNotifyKeyArgs.push_back(args);
-    }
-
-    virtual void notifyMotion(nsecs_t eventTime, int32_t deviceId, int32_t source,
-            uint32_t policyFlags, int32_t action, int32_t flags,
-            int32_t metaState, int32_t edgeFlags,
-            uint32_t pointerCount, const int32_t* pointerIds, const PointerCoords* pointerCoords,
-            float xPrecision, float yPrecision, nsecs_t downTime) {
-        NotifyMotionArgs args;
-        args.eventTime = eventTime;
-        args.deviceId = deviceId;
-        args.source = source;
-        args.policyFlags = policyFlags;
-        args.action = action;
-        args.flags = flags;
-        args.metaState = metaState;
-        args.edgeFlags = edgeFlags;
-        args.pointerCount = pointerCount;
-        args.pointerIds.clear();
-        args.pointerIds.appendArray(pointerIds, pointerCount);
-        args.pointerCoords.clear();
-        args.pointerCoords.appendArray(pointerCoords, pointerCount);
-        args.xPrecision = xPrecision;
-        args.yPrecision = yPrecision;
-        args.downTime = downTime;
-        mNotifyMotionArgs.push_back(args);
-    }
-
-    virtual void notifySwitch(nsecs_t when,
-            int32_t switchCode, int32_t switchValue, uint32_t policyFlags) {
-        NotifySwitchArgs args;
-        args.when = when;
-        args.switchCode = switchCode;
-        args.switchValue = switchValue;
-        args.policyFlags = policyFlags;
-        mNotifySwitchArgs.push_back(args);
-    }
-
-    virtual void dump(String8& dump) {
-        ADD_FAILURE() << "Should never be called by input reader.";
-    }
-
-    virtual void dispatchOnce() {
-        ADD_FAILURE() << "Should never be called by input reader.";
-    }
-
-    virtual int32_t injectInputEvent(const InputEvent* event,
-            int32_t injectorPid, int32_t injectorUid, int32_t syncMode, int32_t timeoutMillis) {
-        ADD_FAILURE() << "Should never be called by input reader.";
-        return INPUT_EVENT_INJECTION_FAILED;
-    }
-
-    virtual void setInputWindows(const Vector<InputWindow>& inputWindows) {
-        ADD_FAILURE() << "Should never be called by input reader.";
-    }
-
-    virtual void setFocusedApplication(const InputApplication* inputApplication) {
-        ADD_FAILURE() << "Should never be called by input reader.";
-    }
-
-    virtual void setInputDispatchMode(bool enabled, bool frozen) {
-        ADD_FAILURE() << "Should never be called by input reader.";
-    }
-
-    virtual bool transferTouchFocus(const sp<InputChannel>& fromChannel,
-            const sp<InputChannel>& toChannel) {
-        ADD_FAILURE() << "Should never be called by input reader.";
-        return 0;
-    }
-
-    virtual status_t registerInputChannel(const sp<InputChannel>& inputChannel, bool monitor) {
-        ADD_FAILURE() << "Should never be called by input reader.";
-        return 0;
-    }
-
-    virtual status_t unregisterInputChannel(const sp<InputChannel>& inputChannel) {
-        ADD_FAILURE() << "Should never be called by input reader.";
-        return 0;
-    }
-};
-
-
-// --- FakeEventHub ---
-
-class FakeEventHub : public EventHubInterface {
-    struct KeyInfo {
-        int32_t keyCode;
-        uint32_t flags;
-    };
-
-    struct Device {
-        String8 name;
-        uint32_t classes;
-        PropertyMap configuration;
-        KeyedVector<int, RawAbsoluteAxisInfo> axes;
-        KeyedVector<int32_t, int32_t> keyCodeStates;
-        KeyedVector<int32_t, int32_t> scanCodeStates;
-        KeyedVector<int32_t, int32_t> switchStates;
-        KeyedVector<int32_t, KeyInfo> keys;
-        KeyedVector<int32_t, bool> leds;
-        Vector<VirtualKeyDefinition> virtualKeys;
-
-        Device(const String8& name, uint32_t classes) :
-                name(name), classes(classes) {
-        }
-    };
-
-    KeyedVector<int32_t, Device*> mDevices;
-    Vector<String8> mExcludedDevices;
-    List<RawEvent> mEvents;
-
-protected:
-    virtual ~FakeEventHub() {
-        for (size_t i = 0; i < mDevices.size(); i++) {
-            delete mDevices.valueAt(i);
-        }
-    }
-
-public:
-    FakeEventHub() { }
-
-    void addDevice(int32_t deviceId, const String8& name, uint32_t classes) {
-        Device* device = new Device(name, classes);
-        mDevices.add(deviceId, device);
-
-        enqueueEvent(ARBITRARY_TIME, deviceId, EventHubInterface::DEVICE_ADDED, 0, 0, 0, 0);
-    }
-
-    void removeDevice(int32_t deviceId) {
-        delete mDevices.valueFor(deviceId);
-        mDevices.removeItem(deviceId);
-
-        enqueueEvent(ARBITRARY_TIME, deviceId, EventHubInterface::DEVICE_REMOVED, 0, 0, 0, 0);
-    }
-
-    void finishDeviceScan() {
-        enqueueEvent(ARBITRARY_TIME, 0, EventHubInterface::FINISHED_DEVICE_SCAN, 0, 0, 0, 0);
-    }
-
-    void addConfigurationProperty(int32_t deviceId, const String8& key, const String8& value) {
-        Device* device = getDevice(deviceId);
-        device->configuration.addProperty(key, value);
-    }
-
-    void addAxis(int32_t deviceId, int axis,
-            int32_t minValue, int32_t maxValue, int flat, int fuzz) {
-        Device* device = getDevice(deviceId);
-
-        RawAbsoluteAxisInfo info;
-        info.valid = true;
-        info.minValue = minValue;
-        info.maxValue = maxValue;
-        info.flat = flat;
-        info.fuzz = fuzz;
-        device->axes.add(axis, info);
-    }
-
-    void setKeyCodeState(int32_t deviceId, int32_t keyCode, int32_t state) {
-        Device* device = getDevice(deviceId);
-        device->keyCodeStates.replaceValueFor(keyCode, state);
-    }
-
-    void setScanCodeState(int32_t deviceId, int32_t scanCode, int32_t state) {
-        Device* device = getDevice(deviceId);
-        device->scanCodeStates.replaceValueFor(scanCode, state);
-    }
-
-    void setSwitchState(int32_t deviceId, int32_t switchCode, int32_t state) {
-        Device* device = getDevice(deviceId);
-        device->switchStates.replaceValueFor(switchCode, state);
-    }
-
-    void addKey(int32_t deviceId, int32_t scanCode, int32_t keyCode, uint32_t flags) {
-        Device* device = getDevice(deviceId);
-        KeyInfo info;
-        info.keyCode = keyCode;
-        info.flags = flags;
-        device->keys.add(scanCode, info);
-    }
-
-    void addLed(int32_t deviceId, int32_t led, bool initialState) {
-        Device* device = getDevice(deviceId);
-        device->leds.add(led, initialState);
-    }
-
-    bool getLedState(int32_t deviceId, int32_t led) {
-        Device* device = getDevice(deviceId);
-        return device->leds.valueFor(led);
-    }
-
-    Vector<String8>& getExcludedDevices() {
-        return mExcludedDevices;
-    }
-
-    void addVirtualKeyDefinition(int32_t deviceId, const VirtualKeyDefinition& definition) {
-        Device* device = getDevice(deviceId);
-        device->virtualKeys.push(definition);
-    }
-
-    void enqueueEvent(nsecs_t when, int32_t deviceId, int32_t type,
-            int32_t scanCode, int32_t keyCode, int32_t value, uint32_t flags) {
-        RawEvent event;
-        event.when = when;
-        event.deviceId = deviceId;
-        event.type = type;
-        event.scanCode = scanCode;
-        event.keyCode = keyCode;
-        event.value = value;
-        event.flags = flags;
-        mEvents.push_back(event);
-    }
-
-    void assertQueueIsEmpty() {
-        ASSERT_EQ(size_t(0), mEvents.size())
-                << "Expected the event queue to be empty (fully consumed).";
-    }
-
-private:
-    Device* getDevice(int32_t deviceId) const {
-        ssize_t index = mDevices.indexOfKey(deviceId);
-        return index >= 0 ? mDevices.valueAt(index) : NULL;
-    }
-
-    virtual uint32_t getDeviceClasses(int32_t deviceId) const {
-        Device* device = getDevice(deviceId);
-        return device ? device->classes : 0;
-    }
-
-    virtual String8 getDeviceName(int32_t deviceId) const {
-        Device* device = getDevice(deviceId);
-        return device ? device->name : String8("unknown");
-    }
-
-    virtual void getConfiguration(int32_t deviceId, PropertyMap* outConfiguration) const {
-        Device* device = getDevice(deviceId);
-        if (device) {
-            *outConfiguration = device->configuration;
-        }
-    }
-
-    virtual status_t getAbsoluteAxisInfo(int32_t deviceId, int axis,
-            RawAbsoluteAxisInfo* outAxisInfo) const {
-        Device* device = getDevice(deviceId);
-        if (device) {
-            ssize_t index = device->axes.indexOfKey(axis);
-            if (index >= 0) {
-                *outAxisInfo = device->axes.valueAt(index);
-                return OK;
-            }
-        }
-        return -1;
-    }
-
-    virtual status_t scancodeToKeycode(int32_t deviceId, int scancode,
-            int32_t* outKeycode, uint32_t* outFlags) const {
-        Device* device = getDevice(deviceId);
-        if (device) {
-            ssize_t index = device->keys.indexOfKey(scancode);
-            if (index >= 0) {
-                if (outKeycode) {
-                    *outKeycode = device->keys.valueAt(index).keyCode;
-                }
-                if (outFlags) {
-                    *outFlags = device->keys.valueAt(index).flags;
-                }
-                return OK;
-            }
-        }
-        return NAME_NOT_FOUND;
-    }
-
-    virtual void addExcludedDevice(const char* deviceName) {
-        mExcludedDevices.add(String8(deviceName));
-    }
-
-    virtual bool getEvent(RawEvent* outEvent) {
-        if (mEvents.empty()) {
-            return false;
-        }
-
-        *outEvent = *mEvents.begin();
-        mEvents.erase(mEvents.begin());
-        return true;
-    }
-
-    virtual int32_t getScanCodeState(int32_t deviceId, int32_t scanCode) const {
-        Device* device = getDevice(deviceId);
-        if (device) {
-            ssize_t index = device->scanCodeStates.indexOfKey(scanCode);
-            if (index >= 0) {
-                return device->scanCodeStates.valueAt(index);
-            }
-        }
-        return AKEY_STATE_UNKNOWN;
-    }
-
-    virtual int32_t getKeyCodeState(int32_t deviceId, int32_t keyCode) const {
-        Device* device = getDevice(deviceId);
-        if (device) {
-            ssize_t index = device->keyCodeStates.indexOfKey(keyCode);
-            if (index >= 0) {
-                return device->keyCodeStates.valueAt(index);
-            }
-        }
-        return AKEY_STATE_UNKNOWN;
-    }
-
-    virtual int32_t getSwitchState(int32_t deviceId, int32_t sw) const {
-        Device* device = getDevice(deviceId);
-        if (device) {
-            ssize_t index = device->switchStates.indexOfKey(sw);
-            if (index >= 0) {
-                return device->switchStates.valueAt(index);
-            }
-        }
-        return AKEY_STATE_UNKNOWN;
-    }
-
-    virtual bool markSupportedKeyCodes(int32_t deviceId, size_t numCodes, const int32_t* keyCodes,
-            uint8_t* outFlags) const {
-        bool result = false;
-        Device* device = getDevice(deviceId);
-        if (device) {
-            for (size_t i = 0; i < numCodes; i++) {
-                for (size_t j = 0; j < device->keys.size(); j++) {
-                    if (keyCodes[i] == device->keys.valueAt(j).keyCode) {
-                        outFlags[i] = 1;
-                        result = true;
-                    }
-                }
-            }
-        }
-        return result;
-    }
-
-    virtual bool hasLed(int32_t deviceId, int32_t led) const {
-        Device* device = getDevice(deviceId);
-        return device && device->leds.indexOfKey(led) >= 0;
-    }
-
-    virtual void setLedState(int32_t deviceId, int32_t led, bool on) {
-        Device* device = getDevice(deviceId);
-        if (device) {
-            ssize_t index = device->leds.indexOfKey(led);
-            if (index >= 0) {
-                device->leds.replaceValueAt(led, on);
-            } else {
-                ADD_FAILURE()
-                        << "Attempted to set the state of an LED that the EventHub declared "
-                        "was not present.  led=" << led;
-            }
-        }
-    }
-
-    virtual void getVirtualKeyDefinitions(int32_t deviceId,
-            Vector<VirtualKeyDefinition>& outVirtualKeys) const {
-        outVirtualKeys.clear();
-
-        Device* device = getDevice(deviceId);
-        if (device) {
-            outVirtualKeys.appendVector(device->virtualKeys);
-        }
-    }
-
-    virtual void dump(String8& dump) {
-    }
-};
-
-
-// --- FakeInputReaderContext ---
-
-class FakeInputReaderContext : public InputReaderContext {
-    sp<EventHubInterface> mEventHub;
-    sp<InputReaderPolicyInterface> mPolicy;
-    sp<InputDispatcherInterface> mDispatcher;
-    int32_t mGlobalMetaState;
-    bool mUpdateGlobalMetaStateWasCalled;
-
-public:
-    FakeInputReaderContext(const sp<EventHubInterface>& eventHub,
-            const sp<InputReaderPolicyInterface>& policy,
-            const sp<InputDispatcherInterface>& dispatcher) :
-            mEventHub(eventHub), mPolicy(policy), mDispatcher(dispatcher),
-            mGlobalMetaState(0) {
-    }
-
-    virtual ~FakeInputReaderContext() { }
-
-    void assertUpdateGlobalMetaStateWasCalled() {
-        ASSERT_TRUE(mUpdateGlobalMetaStateWasCalled)
-                << "Expected updateGlobalMetaState() to have been called.";
-        mUpdateGlobalMetaStateWasCalled = false;
-    }
-
-    void setGlobalMetaState(int32_t state) {
-        mGlobalMetaState = state;
-    }
-
-private:
-    virtual void updateGlobalMetaState() {
-        mUpdateGlobalMetaStateWasCalled = true;
-    }
-
-    virtual int32_t getGlobalMetaState() {
-        return mGlobalMetaState;
-    }
-
-    virtual EventHubInterface* getEventHub() {
-        return mEventHub.get();
-    }
-
-    virtual InputReaderPolicyInterface* getPolicy() {
-        return mPolicy.get();
-    }
-
-    virtual InputDispatcherInterface* getDispatcher() {
-        return mDispatcher.get();
-    }
-};
-
-
-// --- FakeInputMapper ---
-
-class FakeInputMapper : public InputMapper {
-    uint32_t mSources;
-    int32_t mKeyboardType;
-    int32_t mMetaState;
-    KeyedVector<int32_t, int32_t> mKeyCodeStates;
-    KeyedVector<int32_t, int32_t> mScanCodeStates;
-    KeyedVector<int32_t, int32_t> mSwitchStates;
-    Vector<int32_t> mSupportedKeyCodes;
-    RawEvent mLastEvent;
-
-    bool mConfigureWasCalled;
-    bool mResetWasCalled;
-    bool mProcessWasCalled;
-
-public:
-    FakeInputMapper(InputDevice* device, uint32_t sources) :
-            InputMapper(device),
-            mSources(sources), mKeyboardType(AINPUT_KEYBOARD_TYPE_NONE),
-            mMetaState(0),
-            mConfigureWasCalled(false), mResetWasCalled(false), mProcessWasCalled(false) {
-    }
-
-    virtual ~FakeInputMapper() { }
-
-    void setKeyboardType(int32_t keyboardType) {
-        mKeyboardType = keyboardType;
-    }
-
-    void setMetaState(int32_t metaState) {
-        mMetaState = metaState;
-    }
-
-    void assertConfigureWasCalled() {
-        ASSERT_TRUE(mConfigureWasCalled)
-                << "Expected configure() to have been called.";
-        mConfigureWasCalled = false;
-    }
-
-    void assertResetWasCalled() {
-        ASSERT_TRUE(mResetWasCalled)
-                << "Expected reset() to have been called.";
-        mResetWasCalled = false;
-    }
-
-    void assertProcessWasCalled(RawEvent* outLastEvent = NULL) {
-        ASSERT_TRUE(mProcessWasCalled)
-                << "Expected process() to have been called.";
-        if (outLastEvent) {
-            *outLastEvent = mLastEvent;
-        }
-        mProcessWasCalled = false;
-    }
-
-    void setKeyCodeState(int32_t keyCode, int32_t state) {
-        mKeyCodeStates.replaceValueFor(keyCode, state);
-    }
-
-    void setScanCodeState(int32_t scanCode, int32_t state) {
-        mScanCodeStates.replaceValueFor(scanCode, state);
-    }
-
-    void setSwitchState(int32_t switchCode, int32_t state) {
-        mSwitchStates.replaceValueFor(switchCode, state);
-    }
-
-    void addSupportedKeyCode(int32_t keyCode) {
-        mSupportedKeyCodes.add(keyCode);
-    }
-
-private:
-    virtual uint32_t getSources() {
-        return mSources;
-    }
-
-    virtual void populateDeviceInfo(InputDeviceInfo* deviceInfo) {
-        InputMapper::populateDeviceInfo(deviceInfo);
-
-        if (mKeyboardType != AINPUT_KEYBOARD_TYPE_NONE) {
-            deviceInfo->setKeyboardType(mKeyboardType);
-        }
-    }
-
-    virtual void configure() {
-        mConfigureWasCalled = true;
-    }
-
-    virtual void reset() {
-        mResetWasCalled = true;
-    }
-
-    virtual void process(const RawEvent* rawEvent) {
-        mLastEvent = *rawEvent;
-        mProcessWasCalled = true;
-    }
-
-    virtual int32_t getKeyCodeState(uint32_t sourceMask, int32_t keyCode) {
-        ssize_t index = mKeyCodeStates.indexOfKey(keyCode);
-        return index >= 0 ? mKeyCodeStates.valueAt(index) : AKEY_STATE_UNKNOWN;
-    }
-
-    virtual int32_t getScanCodeState(uint32_t sourceMask, int32_t scanCode) {
-        ssize_t index = mScanCodeStates.indexOfKey(scanCode);
-        return index >= 0 ? mScanCodeStates.valueAt(index) : AKEY_STATE_UNKNOWN;
-    }
-
-    virtual int32_t getSwitchState(uint32_t sourceMask, int32_t switchCode) {
-        ssize_t index = mSwitchStates.indexOfKey(switchCode);
-        return index >= 0 ? mSwitchStates.valueAt(index) : AKEY_STATE_UNKNOWN;
-    }
-
-    virtual bool markSupportedKeyCodes(uint32_t sourceMask, size_t numCodes,
-            const int32_t* keyCodes, uint8_t* outFlags) {
-        bool result = false;
-        for (size_t i = 0; i < numCodes; i++) {
-            for (size_t j = 0; j < mSupportedKeyCodes.size(); j++) {
-                if (keyCodes[i] == mSupportedKeyCodes[j]) {
-                    outFlags[i] = 1;
-                    result = true;
-                }
-            }
-        }
-        return result;
-    }
-
-    virtual int32_t getMetaState() {
-        return mMetaState;
-    }
-};
-
-
-// --- InstrumentedInputReader ---
-
-class InstrumentedInputReader : public InputReader {
-    InputDevice* mNextDevice;
-
-public:
-    InstrumentedInputReader(const sp<EventHubInterface>& eventHub,
-            const sp<InputReaderPolicyInterface>& policy,
-            const sp<InputDispatcherInterface>& dispatcher) :
-            InputReader(eventHub, policy, dispatcher) {
-    }
-
-    virtual ~InstrumentedInputReader() {
-        if (mNextDevice) {
-            delete mNextDevice;
-        }
-    }
-
-    void setNextDevice(InputDevice* device) {
-        mNextDevice = device;
-    }
-
-protected:
-    virtual InputDevice* createDevice(int32_t deviceId, const String8& name, uint32_t classes) {
-        if (mNextDevice) {
-            InputDevice* device = mNextDevice;
-            mNextDevice = NULL;
-            return device;
-        }
-        return InputReader::createDevice(deviceId, name, classes);
-    }
-
-    friend class InputReaderTest;
-};
-
-
-// --- InputReaderTest ---
-
-class InputReaderTest : public testing::Test {
-protected:
-    sp<FakeInputDispatcher> mFakeDispatcher;
-    sp<FakeInputReaderPolicy> mFakePolicy;
-    sp<FakeEventHub> mFakeEventHub;
-    sp<InstrumentedInputReader> mReader;
-
-    virtual void SetUp() {
-        mFakeEventHub = new FakeEventHub();
-        mFakePolicy = new FakeInputReaderPolicy();
-        mFakeDispatcher = new FakeInputDispatcher();
-
-        mReader = new InstrumentedInputReader(mFakeEventHub, mFakePolicy, mFakeDispatcher);
-    }
-
-    virtual void TearDown() {
-        mReader.clear();
-
-        mFakeDispatcher.clear();
-        mFakePolicy.clear();
-        mFakeEventHub.clear();
-    }
-
-    void addDevice(int32_t deviceId, const String8& name, uint32_t classes) {
-        mFakeEventHub->addDevice(deviceId, name, classes);
-        mFakeEventHub->finishDeviceScan();
-        mReader->loopOnce();
-        mReader->loopOnce();
-        mFakeEventHub->assertQueueIsEmpty();
-    }
-
-    FakeInputMapper* addDeviceWithFakeInputMapper(int32_t deviceId,
-            const String8& name, uint32_t classes, uint32_t sources) {
-        InputDevice* device = new InputDevice(mReader.get(), deviceId, name);
-        FakeInputMapper* mapper = new FakeInputMapper(device, sources);
-        device->addMapper(mapper);
-        mReader->setNextDevice(device);
-        addDevice(deviceId, name, classes);
-        return mapper;
-    }
-};
-
-TEST_F(InputReaderTest, GetInputConfiguration_WhenNoDevices_ReturnsDefaults) {
-    InputConfiguration config;
-    mReader->getInputConfiguration(&config);
-
-    ASSERT_EQ(InputConfiguration::KEYBOARD_NOKEYS, config.keyboard);
-    ASSERT_EQ(InputConfiguration::NAVIGATION_NONAV, config.navigation);
-    ASSERT_EQ(InputConfiguration::TOUCHSCREEN_NOTOUCH, config.touchScreen);
-}
-
-TEST_F(InputReaderTest, GetInputConfiguration_WhenAlphabeticKeyboardPresent_ReturnsQwertyKeyboard) {
-    ASSERT_NO_FATAL_FAILURE(addDevice(0, String8("keyboard"),
-            INPUT_DEVICE_CLASS_KEYBOARD | INPUT_DEVICE_CLASS_ALPHAKEY));
-
-    InputConfiguration config;
-    mReader->getInputConfiguration(&config);
-
-    ASSERT_EQ(InputConfiguration::KEYBOARD_QWERTY, config.keyboard);
-    ASSERT_EQ(InputConfiguration::NAVIGATION_NONAV, config.navigation);
-    ASSERT_EQ(InputConfiguration::TOUCHSCREEN_NOTOUCH, config.touchScreen);
-}
-
-TEST_F(InputReaderTest, GetInputConfiguration_WhenTouchScreenPresent_ReturnsFingerTouchScreen) {
-    ASSERT_NO_FATAL_FAILURE(addDevice(0, String8("touchscreen"),
-            INPUT_DEVICE_CLASS_TOUCHSCREEN));
-
-    InputConfiguration config;
-    mReader->getInputConfiguration(&config);
-
-    ASSERT_EQ(InputConfiguration::KEYBOARD_NOKEYS, config.keyboard);
-    ASSERT_EQ(InputConfiguration::NAVIGATION_NONAV, config.navigation);
-    ASSERT_EQ(InputConfiguration::TOUCHSCREEN_FINGER, config.touchScreen);
-}
-
-TEST_F(InputReaderTest, GetInputConfiguration_WhenTrackballPresent_ReturnsTrackballNavigation) {
-    ASSERT_NO_FATAL_FAILURE(addDevice(0, String8("trackball"),
-            INPUT_DEVICE_CLASS_TRACKBALL));
-
-    InputConfiguration config;
-    mReader->getInputConfiguration(&config);
-
-    ASSERT_EQ(InputConfiguration::KEYBOARD_NOKEYS, config.keyboard);
-    ASSERT_EQ(InputConfiguration::NAVIGATION_TRACKBALL, config.navigation);
-    ASSERT_EQ(InputConfiguration::TOUCHSCREEN_NOTOUCH, config.touchScreen);
-}
-
-TEST_F(InputReaderTest, GetInputConfiguration_WhenDPadPresent_ReturnsDPadNavigation) {
-    ASSERT_NO_FATAL_FAILURE(addDevice(0, String8("dpad"),
-            INPUT_DEVICE_CLASS_DPAD));
-
-    InputConfiguration config;
-    mReader->getInputConfiguration(&config);
-
-    ASSERT_EQ(InputConfiguration::KEYBOARD_NOKEYS, config.keyboard);
-    ASSERT_EQ(InputConfiguration::NAVIGATION_DPAD, config.navigation);
-    ASSERT_EQ(InputConfiguration::TOUCHSCREEN_NOTOUCH, config.touchScreen);
-}
-
-TEST_F(InputReaderTest, GetInputDeviceInfo_WhenDeviceIdIsValid) {
-    ASSERT_NO_FATAL_FAILURE(addDevice(1, String8("keyboard"),
-            INPUT_DEVICE_CLASS_KEYBOARD));
-
-    InputDeviceInfo info;
-    status_t result = mReader->getInputDeviceInfo(1, &info);
-
-    ASSERT_EQ(OK, result);
-    ASSERT_EQ(1, info.getId());
-    ASSERT_STREQ("keyboard", info.getName().string());
-    ASSERT_EQ(AINPUT_KEYBOARD_TYPE_NON_ALPHABETIC, info.getKeyboardType());
-    ASSERT_EQ(AINPUT_SOURCE_KEYBOARD, info.getSources());
-    ASSERT_EQ(size_t(0), info.getMotionRanges().size());
-}
-
-TEST_F(InputReaderTest, GetInputDeviceInfo_WhenDeviceIdIsInvalid) {
-    InputDeviceInfo info;
-    status_t result = mReader->getInputDeviceInfo(-1, &info);
-
-    ASSERT_EQ(NAME_NOT_FOUND, result);
-}
-
-TEST_F(InputReaderTest, GetInputDeviceInfo_WhenDeviceIdIsIgnored) {
-    addDevice(1, String8("ignored"), 0); // no classes so device will be ignored
-
-    InputDeviceInfo info;
-    status_t result = mReader->getInputDeviceInfo(1, &info);
-
-    ASSERT_EQ(NAME_NOT_FOUND, result);
-}
-
-TEST_F(InputReaderTest, GetInputDeviceIds) {
-    ASSERT_NO_FATAL_FAILURE(addDevice(1, String8("keyboard"),
-            INPUT_DEVICE_CLASS_KEYBOARD | INPUT_DEVICE_CLASS_ALPHAKEY));
-    ASSERT_NO_FATAL_FAILURE(addDevice(2, String8("trackball"),
-            INPUT_DEVICE_CLASS_TRACKBALL));
-
-    Vector<int32_t> ids;
-    mReader->getInputDeviceIds(ids);
-
-    ASSERT_EQ(size_t(2), ids.size());
-    ASSERT_EQ(1, ids[0]);
-    ASSERT_EQ(2, ids[1]);
-}
-
-TEST_F(InputReaderTest, GetKeyCodeState_ForwardsRequestsToMappers) {
-    FakeInputMapper* mapper = NULL;
-    ASSERT_NO_FATAL_FAILURE(mapper = addDeviceWithFakeInputMapper(1, String8("fake"),
-            INPUT_DEVICE_CLASS_KEYBOARD, AINPUT_SOURCE_KEYBOARD));
-    mapper->setKeyCodeState(AKEYCODE_A, AKEY_STATE_DOWN);
-
-    ASSERT_EQ(AKEY_STATE_UNKNOWN, mReader->getKeyCodeState(0,
-            AINPUT_SOURCE_ANY, AKEYCODE_A))
-            << "Should return unknown when the device id is >= 0 but unknown.";
-
-    ASSERT_EQ(AKEY_STATE_UNKNOWN, mReader->getKeyCodeState(1,
-            AINPUT_SOURCE_TRACKBALL, AKEYCODE_A))
-            << "Should return unknown when the device id is valid but the sources are not supported by the device.";
-
-    ASSERT_EQ(AKEY_STATE_DOWN, mReader->getKeyCodeState(1,
-            AINPUT_SOURCE_KEYBOARD | AINPUT_SOURCE_TRACKBALL, AKEYCODE_A))
-            << "Should return value provided by mapper when device id is valid and the device supports some of the sources.";
-
-    ASSERT_EQ(AKEY_STATE_UNKNOWN, mReader->getKeyCodeState(-1,
-            AINPUT_SOURCE_TRACKBALL, AKEYCODE_A))
-            << "Should return unknown when the device id is < 0 but the sources are not supported by any device.";
-
-    ASSERT_EQ(AKEY_STATE_DOWN, mReader->getKeyCodeState(-1,
-            AINPUT_SOURCE_KEYBOARD | AINPUT_SOURCE_TRACKBALL, AKEYCODE_A))
-            << "Should return value provided by mapper when device id is < 0 and one of the devices supports some of the sources.";
-}
-
-TEST_F(InputReaderTest, GetScanCodeState_ForwardsRequestsToMappers) {
-    FakeInputMapper* mapper = NULL;
-    ASSERT_NO_FATAL_FAILURE(mapper = addDeviceWithFakeInputMapper(1, String8("fake"),
-            INPUT_DEVICE_CLASS_KEYBOARD, AINPUT_SOURCE_KEYBOARD));
-    mapper->setScanCodeState(KEY_A, AKEY_STATE_DOWN);
-
-    ASSERT_EQ(AKEY_STATE_UNKNOWN, mReader->getScanCodeState(0,
-            AINPUT_SOURCE_ANY, KEY_A))
-            << "Should return unknown when the device id is >= 0 but unknown.";
-
-    ASSERT_EQ(AKEY_STATE_UNKNOWN, mReader->getScanCodeState(1,
-            AINPUT_SOURCE_TRACKBALL, KEY_A))
-            << "Should return unknown when the device id is valid but the sources are not supported by the device.";
-
-    ASSERT_EQ(AKEY_STATE_DOWN, mReader->getScanCodeState(1,
-            AINPUT_SOURCE_KEYBOARD | AINPUT_SOURCE_TRACKBALL, KEY_A))
-            << "Should return value provided by mapper when device id is valid and the device supports some of the sources.";
-
-    ASSERT_EQ(AKEY_STATE_UNKNOWN, mReader->getScanCodeState(-1,
-            AINPUT_SOURCE_TRACKBALL, KEY_A))
-            << "Should return unknown when the device id is < 0 but the sources are not supported by any device.";
-
-    ASSERT_EQ(AKEY_STATE_DOWN, mReader->getScanCodeState(-1,
-            AINPUT_SOURCE_KEYBOARD | AINPUT_SOURCE_TRACKBALL, KEY_A))
-            << "Should return value provided by mapper when device id is < 0 and one of the devices supports some of the sources.";
-}
-
-TEST_F(InputReaderTest, GetSwitchState_ForwardsRequestsToMappers) {
-    FakeInputMapper* mapper = NULL;
-    ASSERT_NO_FATAL_FAILURE(mapper = addDeviceWithFakeInputMapper(1, String8("fake"),
-            INPUT_DEVICE_CLASS_KEYBOARD, AINPUT_SOURCE_KEYBOARD));
-    mapper->setSwitchState(SW_LID, AKEY_STATE_DOWN);
-
-    ASSERT_EQ(AKEY_STATE_UNKNOWN, mReader->getSwitchState(0,
-            AINPUT_SOURCE_ANY, SW_LID))
-            << "Should return unknown when the device id is >= 0 but unknown.";
-
-    ASSERT_EQ(AKEY_STATE_UNKNOWN, mReader->getSwitchState(1,
-            AINPUT_SOURCE_TRACKBALL, SW_LID))
-            << "Should return unknown when the device id is valid but the sources are not supported by the device.";
-
-    ASSERT_EQ(AKEY_STATE_DOWN, mReader->getSwitchState(1,
-            AINPUT_SOURCE_KEYBOARD | AINPUT_SOURCE_TRACKBALL, SW_LID))
-            << "Should return value provided by mapper when device id is valid and the device supports some of the sources.";
-
-    ASSERT_EQ(AKEY_STATE_UNKNOWN, mReader->getSwitchState(-1,
-            AINPUT_SOURCE_TRACKBALL, SW_LID))
-            << "Should return unknown when the device id is < 0 but the sources are not supported by any device.";
-
-    ASSERT_EQ(AKEY_STATE_DOWN, mReader->getSwitchState(-1,
-            AINPUT_SOURCE_KEYBOARD | AINPUT_SOURCE_TRACKBALL, SW_LID))
-            << "Should return value provided by mapper when device id is < 0 and one of the devices supports some of the sources.";
-}
-
-TEST_F(InputReaderTest, MarkSupportedKeyCodes_ForwardsRequestsToMappers) {
-    FakeInputMapper* mapper = NULL;
-    ASSERT_NO_FATAL_FAILURE(mapper = addDeviceWithFakeInputMapper(1, String8("fake"),
-            INPUT_DEVICE_CLASS_KEYBOARD, AINPUT_SOURCE_KEYBOARD));
-    mapper->addSupportedKeyCode(AKEYCODE_A);
-    mapper->addSupportedKeyCode(AKEYCODE_B);
-
-    const int32_t keyCodes[4] = { AKEYCODE_A, AKEYCODE_B, AKEYCODE_1, AKEYCODE_2 };
-    uint8_t flags[4] = { 0, 0, 0, 1 };
-
-    ASSERT_FALSE(mReader->hasKeys(0, AINPUT_SOURCE_ANY, 4, keyCodes, flags))
-            << "Should return false when device id is >= 0 but unknown.";
-    ASSERT_TRUE(!flags[0] && !flags[1] && !flags[2] && !flags[3]);
-
-    flags[3] = 1;
-    ASSERT_FALSE(mReader->hasKeys(1, AINPUT_SOURCE_TRACKBALL, 4, keyCodes, flags))
-            << "Should return false when device id is valid but the sources are not supported by the device.";
-    ASSERT_TRUE(!flags[0] && !flags[1] && !flags[2] && !flags[3]);
-
-    flags[3] = 1;
-    ASSERT_TRUE(mReader->hasKeys(1, AINPUT_SOURCE_KEYBOARD | AINPUT_SOURCE_TRACKBALL, 4, keyCodes, flags))
-            << "Should return value provided by mapper when device id is valid and the device supports some of the sources.";
-    ASSERT_TRUE(flags[0] && flags[1] && !flags[2] && !flags[3]);
-
-    flags[3] = 1;
-    ASSERT_FALSE(mReader->hasKeys(-1, AINPUT_SOURCE_TRACKBALL, 4, keyCodes, flags))
-            << "Should return false when the device id is < 0 but the sources are not supported by any device.";
-    ASSERT_TRUE(!flags[0] && !flags[1] && !flags[2] && !flags[3]);
-
-    flags[3] = 1;
-    ASSERT_TRUE(mReader->hasKeys(-1, AINPUT_SOURCE_KEYBOARD | AINPUT_SOURCE_TRACKBALL, 4, keyCodes, flags))
-            << "Should return value provided by mapper when device id is < 0 and one of the devices supports some of the sources.";
-    ASSERT_TRUE(flags[0] && flags[1] && !flags[2] && !flags[3]);
-}
-
-TEST_F(InputReaderTest, LoopOnce_WhenDeviceScanFinished_SendsConfigurationChanged) {
-    addDevice(1, String8("ignored"), INPUT_DEVICE_CLASS_KEYBOARD);
-
-    FakeInputDispatcher::NotifyConfigurationChangedArgs args;
-    ASSERT_NO_FATAL_FAILURE(mFakeDispatcher->assertNotifyConfigurationChangedWasCalled(&args));
-    ASSERT_EQ(ARBITRARY_TIME, args.eventTime);
-}
-
-TEST_F(InputReaderTest, LoopOnce_ForwardsRawEventsToMappers) {
-    FakeInputMapper* mapper = NULL;
-    ASSERT_NO_FATAL_FAILURE(mapper = addDeviceWithFakeInputMapper(1, String8("fake"),
-            INPUT_DEVICE_CLASS_KEYBOARD, AINPUT_SOURCE_KEYBOARD));
-
-    mFakeEventHub->enqueueEvent(0, 1, EV_KEY, KEY_A, AKEYCODE_A, 1, POLICY_FLAG_WAKE);
-    mReader->loopOnce();
-    ASSERT_NO_FATAL_FAILURE(mFakeEventHub->assertQueueIsEmpty());
-
-    RawEvent event;
-    ASSERT_NO_FATAL_FAILURE(mapper->assertProcessWasCalled(&event));
-    ASSERT_EQ(0, event.when);
-    ASSERT_EQ(1, event.deviceId);
-    ASSERT_EQ(EV_KEY, event.type);
-    ASSERT_EQ(KEY_A, event.scanCode);
-    ASSERT_EQ(AKEYCODE_A, event.keyCode);
-    ASSERT_EQ(1, event.value);
-    ASSERT_EQ(POLICY_FLAG_WAKE, event.flags);
-}
-
-
-// --- InputDeviceTest ---
-
-class InputDeviceTest : public testing::Test {
-protected:
-    static const char* DEVICE_NAME;
-    static const int32_t DEVICE_ID;
-
-    sp<FakeEventHub> mFakeEventHub;
-    sp<FakeInputReaderPolicy> mFakePolicy;
-    sp<FakeInputDispatcher> mFakeDispatcher;
-    FakeInputReaderContext* mFakeContext;
-
-    InputDevice* mDevice;
-
-    virtual void SetUp() {
-        mFakeEventHub = new FakeEventHub();
-        mFakePolicy = new FakeInputReaderPolicy();
-        mFakeDispatcher = new FakeInputDispatcher();
-        mFakeContext = new FakeInputReaderContext(mFakeEventHub, mFakePolicy, mFakeDispatcher);
-
-        mFakeEventHub->addDevice(DEVICE_ID, String8(DEVICE_NAME), 0);
-        mDevice = new InputDevice(mFakeContext, DEVICE_ID, String8(DEVICE_NAME));
-    }
-
-    virtual void TearDown() {
-        delete mDevice;
-
-        delete mFakeContext;
-        mFakeDispatcher.clear();
-        mFakePolicy.clear();
-        mFakeEventHub.clear();
-    }
-};
-
-const char* InputDeviceTest::DEVICE_NAME = "device";
-const int32_t InputDeviceTest::DEVICE_ID = 1;
-
-TEST_F(InputDeviceTest, ImmutableProperties) {
-    ASSERT_EQ(DEVICE_ID, mDevice->getId());
-    ASSERT_STREQ(DEVICE_NAME, mDevice->getName());
-}
-
-TEST_F(InputDeviceTest, WhenNoMappersAreRegistered_DeviceIsIgnored) {
-    // Configuration.
-    mDevice->configure();
-
-    // Metadata.
-    ASSERT_TRUE(mDevice->isIgnored());
-    ASSERT_EQ(AINPUT_SOURCE_UNKNOWN, mDevice->getSources());
-
-    InputDeviceInfo info;
-    mDevice->getDeviceInfo(&info);
-    ASSERT_EQ(DEVICE_ID, info.getId());
-    ASSERT_STREQ(DEVICE_NAME, info.getName().string());
-    ASSERT_EQ(AINPUT_KEYBOARD_TYPE_NONE, info.getKeyboardType());
-    ASSERT_EQ(AINPUT_SOURCE_UNKNOWN, info.getSources());
-
-    // State queries.
-    ASSERT_EQ(0, mDevice->getMetaState());
-
-    ASSERT_EQ(AKEY_STATE_UNKNOWN, mDevice->getKeyCodeState(AINPUT_SOURCE_KEYBOARD, 0))
-            << "Ignored device should return unknown key code state.";
-    ASSERT_EQ(AKEY_STATE_UNKNOWN, mDevice->getScanCodeState(AINPUT_SOURCE_KEYBOARD, 0))
-            << "Ignored device should return unknown scan code state.";
-    ASSERT_EQ(AKEY_STATE_UNKNOWN, mDevice->getSwitchState(AINPUT_SOURCE_KEYBOARD, 0))
-            << "Ignored device should return unknown switch state.";
-
-    const int32_t keyCodes[2] = { AKEYCODE_A, AKEYCODE_B };
-    uint8_t flags[2] = { 0, 1 };
-    ASSERT_FALSE(mDevice->markSupportedKeyCodes(AINPUT_SOURCE_KEYBOARD, 2, keyCodes, flags))
-            << "Ignored device should never mark any key codes.";
-    ASSERT_EQ(0, flags[0]) << "Flag for unsupported key should be unchanged.";
-    ASSERT_EQ(1, flags[1]) << "Flag for unsupported key should be unchanged.";
-
-    // Reset.
-    mDevice->reset();
-}
-
-TEST_F(InputDeviceTest, WhenMappersAreRegistered_DeviceIsNotIgnoredAndForwardsRequestsToMappers) {
-    // Configuration.
-    mFakeEventHub->addConfigurationProperty(DEVICE_ID, String8("key"), String8("value"));
-
-    FakeInputMapper* mapper1 = new FakeInputMapper(mDevice, AINPUT_SOURCE_KEYBOARD);
-    mapper1->setKeyboardType(AINPUT_KEYBOARD_TYPE_ALPHABETIC);
-    mapper1->setMetaState(AMETA_ALT_ON);
-    mapper1->addSupportedKeyCode(AKEYCODE_A);
-    mapper1->addSupportedKeyCode(AKEYCODE_B);
-    mapper1->setKeyCodeState(AKEYCODE_A, AKEY_STATE_DOWN);
-    mapper1->setKeyCodeState(AKEYCODE_B, AKEY_STATE_UP);
-    mapper1->setScanCodeState(2, AKEY_STATE_DOWN);
-    mapper1->setScanCodeState(3, AKEY_STATE_UP);
-    mapper1->setSwitchState(4, AKEY_STATE_DOWN);
-    mDevice->addMapper(mapper1);
-
-    FakeInputMapper* mapper2 = new FakeInputMapper(mDevice, AINPUT_SOURCE_TOUCHSCREEN);
-    mapper2->setMetaState(AMETA_SHIFT_ON);
-    mDevice->addMapper(mapper2);
-
-    mDevice->configure();
-
-    String8 propertyValue;
-    ASSERT_TRUE(mDevice->getConfiguration().tryGetProperty(String8("key"), propertyValue))
-            << "Device should have read configuration during configuration phase.";
-    ASSERT_STREQ("value", propertyValue.string());
-
-    ASSERT_NO_FATAL_FAILURE(mapper1->assertConfigureWasCalled());
-    ASSERT_NO_FATAL_FAILURE(mapper2->assertConfigureWasCalled());
-
-    // Metadata.
-    ASSERT_FALSE(mDevice->isIgnored());
-    ASSERT_EQ(uint32_t(AINPUT_SOURCE_KEYBOARD | AINPUT_SOURCE_TOUCHSCREEN), mDevice->getSources());
-
-    InputDeviceInfo info;
-    mDevice->getDeviceInfo(&info);
-    ASSERT_EQ(DEVICE_ID, info.getId());
-    ASSERT_STREQ(DEVICE_NAME, info.getName().string());
-    ASSERT_EQ(AINPUT_KEYBOARD_TYPE_ALPHABETIC, info.getKeyboardType());
-    ASSERT_EQ(uint32_t(AINPUT_SOURCE_KEYBOARD | AINPUT_SOURCE_TOUCHSCREEN), info.getSources());
-
-    // State queries.
-    ASSERT_EQ(AMETA_ALT_ON | AMETA_SHIFT_ON, mDevice->getMetaState())
-            << "Should query mappers and combine meta states.";
-
-    ASSERT_EQ(AKEY_STATE_UNKNOWN, mDevice->getKeyCodeState(AINPUT_SOURCE_TRACKBALL, AKEYCODE_A))
-            << "Should return unknown key code state when source not supported.";
-    ASSERT_EQ(AKEY_STATE_UNKNOWN, mDevice->getScanCodeState(AINPUT_SOURCE_TRACKBALL, AKEYCODE_A))
-            << "Should return unknown scan code state when source not supported.";
-    ASSERT_EQ(AKEY_STATE_UNKNOWN, mDevice->getSwitchState(AINPUT_SOURCE_TRACKBALL, AKEYCODE_A))
-            << "Should return unknown switch state when source not supported.";
-
-    ASSERT_EQ(AKEY_STATE_DOWN, mDevice->getKeyCodeState(AINPUT_SOURCE_KEYBOARD, AKEYCODE_A))
-            << "Should query mapper when source is supported.";
-    ASSERT_EQ(AKEY_STATE_UP, mDevice->getScanCodeState(AINPUT_SOURCE_KEYBOARD, 3))
-            << "Should query mapper when source is supported.";
-    ASSERT_EQ(AKEY_STATE_DOWN, mDevice->getSwitchState(AINPUT_SOURCE_KEYBOARD, 4))
-            << "Should query mapper when source is supported.";
-
-    const int32_t keyCodes[4] = { AKEYCODE_A, AKEYCODE_B, AKEYCODE_1, AKEYCODE_2 };
-    uint8_t flags[4] = { 0, 0, 0, 1 };
-    ASSERT_FALSE(mDevice->markSupportedKeyCodes(AINPUT_SOURCE_TRACKBALL, 4, keyCodes, flags))
-            << "Should do nothing when source is unsupported.";
-    ASSERT_EQ(0, flags[0]) << "Flag should be unchanged when source is unsupported.";
-    ASSERT_EQ(0, flags[1]) << "Flag should be unchanged when source is unsupported.";
-    ASSERT_EQ(0, flags[2]) << "Flag should be unchanged when source is unsupported.";
-    ASSERT_EQ(1, flags[3]) << "Flag should be unchanged when source is unsupported.";
-
-    ASSERT_TRUE(mDevice->markSupportedKeyCodes(AINPUT_SOURCE_KEYBOARD, 4, keyCodes, flags))
-            << "Should query mapper when source is supported.";
-    ASSERT_EQ(1, flags[0]) << "Flag for supported key should be set.";
-    ASSERT_EQ(1, flags[1]) << "Flag for supported key should be set.";
-    ASSERT_EQ(0, flags[2]) << "Flag for unsupported key should be unchanged.";
-    ASSERT_EQ(1, flags[3]) << "Flag for unsupported key should be unchanged.";
-
-    // Event handling.
-    RawEvent event;
-    mDevice->process(&event);
-
-    ASSERT_NO_FATAL_FAILURE(mapper1->assertProcessWasCalled());
-    ASSERT_NO_FATAL_FAILURE(mapper2->assertProcessWasCalled());
-
-    // Reset.
-    mDevice->reset();
-
-    ASSERT_NO_FATAL_FAILURE(mapper1->assertResetWasCalled());
-    ASSERT_NO_FATAL_FAILURE(mapper2->assertResetWasCalled());
-}
-
-
-// --- InputMapperTest ---
-
-class InputMapperTest : public testing::Test {
-protected:
-    static const char* DEVICE_NAME;
-    static const int32_t DEVICE_ID;
-
-    sp<FakeEventHub> mFakeEventHub;
-    sp<FakeInputReaderPolicy> mFakePolicy;
-    sp<FakeInputDispatcher> mFakeDispatcher;
-    FakeInputReaderContext* mFakeContext;
-    InputDevice* mDevice;
-
-    virtual void SetUp() {
-        mFakeEventHub = new FakeEventHub();
-        mFakePolicy = new FakeInputReaderPolicy();
-        mFakeDispatcher = new FakeInputDispatcher();
-        mFakeContext = new FakeInputReaderContext(mFakeEventHub, mFakePolicy, mFakeDispatcher);
-        mDevice = new InputDevice(mFakeContext, DEVICE_ID, String8(DEVICE_NAME));
-
-        mFakeEventHub->addDevice(DEVICE_ID, String8(DEVICE_NAME), 0);
-    }
-
-    virtual void TearDown() {
-        delete mDevice;
-        delete mFakeContext;
-        mFakeDispatcher.clear();
-        mFakePolicy.clear();
-        mFakeEventHub.clear();
-    }
-
-    void addConfigurationProperty(const char* key, const char* value) {
-        mFakeEventHub->addConfigurationProperty(DEVICE_ID, String8(key), String8(value));
-    }
-
-    void addMapperAndConfigure(InputMapper* mapper) {
-        mDevice->addMapper(mapper);
-        mDevice->configure();
-    }
-
-    static void process(InputMapper* mapper, nsecs_t when, int32_t deviceId, int32_t type,
-            int32_t scanCode, int32_t keyCode, int32_t value, uint32_t flags) {
-        RawEvent event;
-        event.when = when;
-        event.deviceId = deviceId;
-        event.type = type;
-        event.scanCode = scanCode;
-        event.keyCode = keyCode;
-        event.value = value;
-        event.flags = flags;
-        mapper->process(&event);
-    }
-
-    static void assertMotionRange(const InputDeviceInfo& info,
-            int32_t rangeType, float min, float max, float flat, float fuzz) {
-        const InputDeviceInfo::MotionRange* range = info.getMotionRange(rangeType);
-        ASSERT_TRUE(range != NULL) << "Range: " << rangeType;
-        ASSERT_NEAR(min, range->min, EPSILON) << "Range: " << rangeType;
-        ASSERT_NEAR(max, range->max, EPSILON) << "Range: " << rangeType;
-        ASSERT_NEAR(flat, range->flat, EPSILON) << "Range: " << rangeType;
-        ASSERT_NEAR(fuzz, range->fuzz, EPSILON) << "Range: " << rangeType;
-    }
-
-    static void assertPointerCoords(const PointerCoords& coords,
-            float x, float y, float pressure, float size,
-            float touchMajor, float touchMinor, float toolMajor, float toolMinor,
-            float orientation) {
-        ASSERT_NEAR(x, coords.x, 1);
-        ASSERT_NEAR(y, coords.y, 1);
-        ASSERT_NEAR(pressure, coords.pressure, EPSILON);
-        ASSERT_NEAR(size, coords.size, EPSILON);
-        ASSERT_NEAR(touchMajor, coords.touchMajor, 1);
-        ASSERT_NEAR(touchMinor, coords.touchMinor, 1);
-        ASSERT_NEAR(toolMajor, coords.toolMajor, 1);
-        ASSERT_NEAR(toolMinor, coords.toolMinor, 1);
-        ASSERT_NEAR(orientation, coords.orientation, EPSILON);
-    }
-};
-
-const char* InputMapperTest::DEVICE_NAME = "device";
-const int32_t InputMapperTest::DEVICE_ID = 1;
-
-
-// --- SwitchInputMapperTest ---
-
-class SwitchInputMapperTest : public InputMapperTest {
-protected:
-};
-
-TEST_F(SwitchInputMapperTest, GetSources) {
-    SwitchInputMapper* mapper = new SwitchInputMapper(mDevice);
-    addMapperAndConfigure(mapper);
-
-    ASSERT_EQ(uint32_t(0), mapper->getSources());
-}
-
-TEST_F(SwitchInputMapperTest, GetSwitchState) {
-    SwitchInputMapper* mapper = new SwitchInputMapper(mDevice);
-    addMapperAndConfigure(mapper);
-
-    mFakeEventHub->setSwitchState(DEVICE_ID, SW_LID, 1);
-    ASSERT_EQ(1, mapper->getSwitchState(AINPUT_SOURCE_ANY, SW_LID));
-
-    mFakeEventHub->setSwitchState(DEVICE_ID, SW_LID, 0);
-    ASSERT_EQ(0, mapper->getSwitchState(AINPUT_SOURCE_ANY, SW_LID));
-}
-
-TEST_F(SwitchInputMapperTest, Process) {
-    SwitchInputMapper* mapper = new SwitchInputMapper(mDevice);
-    addMapperAndConfigure(mapper);
-
-    process(mapper, ARBITRARY_TIME, DEVICE_ID, EV_SW, SW_LID, 0, 1, 0);
-
-    FakeInputDispatcher::NotifySwitchArgs args;
-    ASSERT_NO_FATAL_FAILURE(mFakeDispatcher->assertNotifySwitchWasCalled(&args));
-    ASSERT_EQ(ARBITRARY_TIME, args.when);
-    ASSERT_EQ(SW_LID, args.switchCode);
-    ASSERT_EQ(1, args.switchValue);
-    ASSERT_EQ(uint32_t(0), args.policyFlags);
-}
-
-
-// --- KeyboardInputMapperTest ---
-
-class KeyboardInputMapperTest : public InputMapperTest {
-protected:
-    void testDPadKeyRotation(KeyboardInputMapper* mapper,
-            int32_t originalScanCode, int32_t originalKeyCode, int32_t rotatedKeyCode);
-};
-
-void KeyboardInputMapperTest::testDPadKeyRotation(KeyboardInputMapper* mapper,
-        int32_t originalScanCode, int32_t originalKeyCode, int32_t rotatedKeyCode) {
-    FakeInputDispatcher::NotifyKeyArgs args;
-
-    process(mapper, ARBITRARY_TIME, DEVICE_ID, EV_KEY, originalScanCode, originalKeyCode, 1, 0);
-    ASSERT_NO_FATAL_FAILURE(mFakeDispatcher->assertNotifyKeyWasCalled(&args));
-    ASSERT_EQ(AKEY_EVENT_ACTION_DOWN, args.action);
-    ASSERT_EQ(originalScanCode, args.scanCode);
-    ASSERT_EQ(rotatedKeyCode, args.keyCode);
-
-    process(mapper, ARBITRARY_TIME, DEVICE_ID, EV_KEY, originalScanCode, originalKeyCode, 0, 0);
-    ASSERT_NO_FATAL_FAILURE(mFakeDispatcher->assertNotifyKeyWasCalled(&args));
-    ASSERT_EQ(AKEY_EVENT_ACTION_UP, args.action);
-    ASSERT_EQ(originalScanCode, args.scanCode);
-    ASSERT_EQ(rotatedKeyCode, args.keyCode);
-}
-
-
-TEST_F(KeyboardInputMapperTest, GetSources) {
-    KeyboardInputMapper* mapper = new KeyboardInputMapper(mDevice,
-            AINPUT_SOURCE_KEYBOARD, AINPUT_KEYBOARD_TYPE_ALPHABETIC);
-    addMapperAndConfigure(mapper);
-
-    ASSERT_EQ(AINPUT_SOURCE_KEYBOARD, mapper->getSources());
-}
-
-TEST_F(KeyboardInputMapperTest, Process_SimpleKeyPress) {
-    KeyboardInputMapper* mapper = new KeyboardInputMapper(mDevice,
-            AINPUT_SOURCE_KEYBOARD, AINPUT_KEYBOARD_TYPE_ALPHABETIC);
-    addMapperAndConfigure(mapper);
-
-    // Key down.
-    process(mapper, ARBITRARY_TIME, DEVICE_ID,
-            EV_KEY, KEY_HOME, AKEYCODE_HOME, 1, POLICY_FLAG_WAKE);
-    FakeInputDispatcher::NotifyKeyArgs args;
-    ASSERT_NO_FATAL_FAILURE(mFakeDispatcher->assertNotifyKeyWasCalled(&args));
-    ASSERT_EQ(DEVICE_ID, args.deviceId);
-    ASSERT_EQ(AINPUT_SOURCE_KEYBOARD, args.source);
-    ASSERT_EQ(ARBITRARY_TIME, args.eventTime);
-    ASSERT_EQ(AKEY_EVENT_ACTION_DOWN, args.action);
-    ASSERT_EQ(AKEYCODE_HOME, args.keyCode);
-    ASSERT_EQ(KEY_HOME, args.scanCode);
-    ASSERT_EQ(AMETA_NONE, args.metaState);
-    ASSERT_EQ(AKEY_EVENT_FLAG_FROM_SYSTEM, args.flags);
-    ASSERT_EQ(POLICY_FLAG_WAKE, args.policyFlags);
-    ASSERT_EQ(ARBITRARY_TIME, args.downTime);
-
-    // Key up.
-    process(mapper, ARBITRARY_TIME + 1, DEVICE_ID,
-            EV_KEY, KEY_HOME, AKEYCODE_HOME, 0, POLICY_FLAG_WAKE);
-    ASSERT_NO_FATAL_FAILURE(mFakeDispatcher->assertNotifyKeyWasCalled(&args));
-    ASSERT_EQ(DEVICE_ID, args.deviceId);
-    ASSERT_EQ(AINPUT_SOURCE_KEYBOARD, args.source);
-    ASSERT_EQ(ARBITRARY_TIME + 1, args.eventTime);
-    ASSERT_EQ(AKEY_EVENT_ACTION_UP, args.action);
-    ASSERT_EQ(AKEYCODE_HOME, args.keyCode);
-    ASSERT_EQ(KEY_HOME, args.scanCode);
-    ASSERT_EQ(AMETA_NONE, args.metaState);
-    ASSERT_EQ(AKEY_EVENT_FLAG_FROM_SYSTEM, args.flags);
-    ASSERT_EQ(POLICY_FLAG_WAKE, args.policyFlags);
-    ASSERT_EQ(ARBITRARY_TIME, args.downTime);
-}
-
-TEST_F(KeyboardInputMapperTest, Reset_WhenKeysAreNotDown_DoesNotSynthesizeKeyUp) {
-    KeyboardInputMapper* mapper = new KeyboardInputMapper(mDevice,
-            AINPUT_SOURCE_KEYBOARD, AINPUT_KEYBOARD_TYPE_ALPHABETIC);
-    addMapperAndConfigure(mapper);
-
-    // Key down.
-    process(mapper, ARBITRARY_TIME, DEVICE_ID,
-            EV_KEY, KEY_HOME, AKEYCODE_HOME, 1, POLICY_FLAG_WAKE);
-    ASSERT_NO_FATAL_FAILURE(mFakeDispatcher->assertNotifyKeyWasCalled());
-
-    // Key up.
-    process(mapper, ARBITRARY_TIME, DEVICE_ID,
-            EV_KEY, KEY_HOME, AKEYCODE_HOME, 0, POLICY_FLAG_WAKE);
-    ASSERT_NO_FATAL_FAILURE(mFakeDispatcher->assertNotifyKeyWasCalled());
-
-    // Reset.  Since no keys still down, should not synthesize any key ups.
-    mapper->reset();
-    ASSERT_NO_FATAL_FAILURE(mFakeDispatcher->assertNotifyKeyWasNotCalled());
-}
-
-TEST_F(KeyboardInputMapperTest, Reset_WhenKeysAreDown_SynthesizesKeyUps) {
-    KeyboardInputMapper* mapper = new KeyboardInputMapper(mDevice,
-            AINPUT_SOURCE_KEYBOARD, AINPUT_KEYBOARD_TYPE_ALPHABETIC);
-    addMapperAndConfigure(mapper);
-
-    // Metakey down.
-    process(mapper, ARBITRARY_TIME, DEVICE_ID,
-            EV_KEY, KEY_LEFTSHIFT, AKEYCODE_SHIFT_LEFT, 1, 0);
-    ASSERT_NO_FATAL_FAILURE(mFakeDispatcher->assertNotifyKeyWasCalled());
-
-    // Key down.
-    process(mapper, ARBITRARY_TIME + 1, DEVICE_ID,
-            EV_KEY, KEY_A, AKEYCODE_A, 1, 0);
-    ASSERT_NO_FATAL_FAILURE(mFakeDispatcher->assertNotifyKeyWasCalled());
-
-    // Reset.  Since two keys are still down, should synthesize two key ups in reverse order.
-    mapper->reset();
-
-    FakeInputDispatcher::NotifyKeyArgs args;
-    ASSERT_NO_FATAL_FAILURE(mFakeDispatcher->assertNotifyKeyWasCalled(&args));
-    ASSERT_EQ(DEVICE_ID, args.deviceId);
-    ASSERT_EQ(AINPUT_SOURCE_KEYBOARD, args.source);
-    ASSERT_EQ(AKEY_EVENT_ACTION_UP, args.action);
-    ASSERT_EQ(AKEYCODE_A, args.keyCode);
-    ASSERT_EQ(KEY_A, args.scanCode);
-    ASSERT_EQ(AMETA_SHIFT_LEFT_ON | AMETA_SHIFT_ON, args.metaState);
-    ASSERT_EQ(AKEY_EVENT_FLAG_FROM_SYSTEM, args.flags);
-    ASSERT_EQ(uint32_t(0), args.policyFlags);
-    ASSERT_EQ(ARBITRARY_TIME + 1, args.downTime);
-
-    ASSERT_NO_FATAL_FAILURE(mFakeDispatcher->assertNotifyKeyWasCalled(&args));
-    ASSERT_EQ(DEVICE_ID, args.deviceId);
-    ASSERT_EQ(AINPUT_SOURCE_KEYBOARD, args.source);
-    ASSERT_EQ(AKEY_EVENT_ACTION_UP, args.action);
-    ASSERT_EQ(AKEYCODE_SHIFT_LEFT, args.keyCode);
-    ASSERT_EQ(KEY_LEFTSHIFT, args.scanCode);
-    ASSERT_EQ(AMETA_NONE, args.metaState);
-    ASSERT_EQ(AKEY_EVENT_FLAG_FROM_SYSTEM, args.flags);
-    ASSERT_EQ(uint32_t(0), args.policyFlags);
-    ASSERT_EQ(ARBITRARY_TIME + 1, args.downTime);
-
-    // And that's it.
-    ASSERT_NO_FATAL_FAILURE(mFakeDispatcher->assertNotifyKeyWasNotCalled());
-}
-
-TEST_F(KeyboardInputMapperTest, Process_ShouldUpdateMetaState) {
-    KeyboardInputMapper* mapper = new KeyboardInputMapper(mDevice,
-            AINPUT_SOURCE_KEYBOARD, AINPUT_KEYBOARD_TYPE_ALPHABETIC);
-    addMapperAndConfigure(mapper);
-
-    // Initial metastate.
-    ASSERT_EQ(AMETA_NONE, mapper->getMetaState());
-
-    // Metakey down.
-    process(mapper, ARBITRARY_TIME, DEVICE_ID,
-            EV_KEY, KEY_LEFTSHIFT, AKEYCODE_SHIFT_LEFT, 1, 0);
-    FakeInputDispatcher::NotifyKeyArgs args;
-    ASSERT_NO_FATAL_FAILURE(mFakeDispatcher->assertNotifyKeyWasCalled(&args));
-    ASSERT_EQ(AMETA_SHIFT_LEFT_ON | AMETA_SHIFT_ON, args.metaState);
-    ASSERT_EQ(AMETA_SHIFT_LEFT_ON | AMETA_SHIFT_ON, mapper->getMetaState());
-    ASSERT_NO_FATAL_FAILURE(mFakeContext->assertUpdateGlobalMetaStateWasCalled());
-
-    // Key down.
-    process(mapper, ARBITRARY_TIME + 1, DEVICE_ID,
-            EV_KEY, KEY_A, AKEYCODE_A, 1, 0);
-    ASSERT_NO_FATAL_FAILURE(mFakeDispatcher->assertNotifyKeyWasCalled(&args));
-    ASSERT_EQ(AMETA_SHIFT_LEFT_ON | AMETA_SHIFT_ON, args.metaState);
-    ASSERT_EQ(AMETA_SHIFT_LEFT_ON | AMETA_SHIFT_ON, mapper->getMetaState());
-
-    // Key up.
-    process(mapper, ARBITRARY_TIME + 2, DEVICE_ID,
-            EV_KEY, KEY_A, AKEYCODE_A, 0, 0);
-    ASSERT_NO_FATAL_FAILURE(mFakeDispatcher->assertNotifyKeyWasCalled(&args));
-    ASSERT_EQ(AMETA_SHIFT_LEFT_ON | AMETA_SHIFT_ON, args.metaState);
-    ASSERT_EQ(AMETA_SHIFT_LEFT_ON | AMETA_SHIFT_ON, mapper->getMetaState());
-
-    // Metakey up.
-    process(mapper, ARBITRARY_TIME + 3, DEVICE_ID,
-            EV_KEY, KEY_LEFTSHIFT, AKEYCODE_SHIFT_LEFT, 0, 0);
-    ASSERT_NO_FATAL_FAILURE(mFakeDispatcher->assertNotifyKeyWasCalled(&args));
-    ASSERT_EQ(AMETA_NONE, args.metaState);
-    ASSERT_EQ(AMETA_NONE, mapper->getMetaState());
-    ASSERT_NO_FATAL_FAILURE(mFakeContext->assertUpdateGlobalMetaStateWasCalled());
-}
-
-TEST_F(KeyboardInputMapperTest, Process_WhenNotOrientationAware_ShouldNotRotateDPad) {
-    KeyboardInputMapper* mapper = new KeyboardInputMapper(mDevice,
-            AINPUT_SOURCE_KEYBOARD, AINPUT_KEYBOARD_TYPE_ALPHABETIC);
-    addMapperAndConfigure(mapper);
-
-    mFakePolicy->setDisplayInfo(DISPLAY_ID,
-            DISPLAY_WIDTH, DISPLAY_HEIGHT,
-            InputReaderPolicyInterface::ROTATION_90);
-    ASSERT_NO_FATAL_FAILURE(testDPadKeyRotation(mapper,
-            KEY_UP, AKEYCODE_DPAD_UP, AKEYCODE_DPAD_UP));
-    ASSERT_NO_FATAL_FAILURE(testDPadKeyRotation(mapper,
-            KEY_RIGHT, AKEYCODE_DPAD_RIGHT, AKEYCODE_DPAD_RIGHT));
-    ASSERT_NO_FATAL_FAILURE(testDPadKeyRotation(mapper,
-            KEY_DOWN, AKEYCODE_DPAD_DOWN, AKEYCODE_DPAD_DOWN));
-    ASSERT_NO_FATAL_FAILURE(testDPadKeyRotation(mapper,
-            KEY_LEFT, AKEYCODE_DPAD_LEFT, AKEYCODE_DPAD_LEFT));
-}
-
-TEST_F(KeyboardInputMapperTest, Process_WhenOrientationAware_ShouldRotateDPad) {
-    KeyboardInputMapper* mapper = new KeyboardInputMapper(mDevice,
-            AINPUT_SOURCE_KEYBOARD, AINPUT_KEYBOARD_TYPE_ALPHABETIC);
-    addConfigurationProperty("keyboard.orientationAware", "1");
-    addMapperAndConfigure(mapper);
-
-    mFakePolicy->setDisplayInfo(DISPLAY_ID,
-            DISPLAY_WIDTH, DISPLAY_HEIGHT,
-            InputReaderPolicyInterface::ROTATION_0);
-    ASSERT_NO_FATAL_FAILURE(testDPadKeyRotation(mapper,
-            KEY_UP, AKEYCODE_DPAD_UP, AKEYCODE_DPAD_UP));
-    ASSERT_NO_FATAL_FAILURE(testDPadKeyRotation(mapper,
-            KEY_RIGHT, AKEYCODE_DPAD_RIGHT, AKEYCODE_DPAD_RIGHT));
-    ASSERT_NO_FATAL_FAILURE(testDPadKeyRotation(mapper,
-            KEY_DOWN, AKEYCODE_DPAD_DOWN, AKEYCODE_DPAD_DOWN));
-    ASSERT_NO_FATAL_FAILURE(testDPadKeyRotation(mapper,
-            KEY_LEFT, AKEYCODE_DPAD_LEFT, AKEYCODE_DPAD_LEFT));
-
-    mFakePolicy->setDisplayInfo(DISPLAY_ID,
-            DISPLAY_WIDTH, DISPLAY_HEIGHT,
-            InputReaderPolicyInterface::ROTATION_90);
-    ASSERT_NO_FATAL_FAILURE(testDPadKeyRotation(mapper,
-            KEY_UP, AKEYCODE_DPAD_UP, AKEYCODE_DPAD_LEFT));
-    ASSERT_NO_FATAL_FAILURE(testDPadKeyRotation(mapper,
-            KEY_RIGHT, AKEYCODE_DPAD_RIGHT, AKEYCODE_DPAD_UP));
-    ASSERT_NO_FATAL_FAILURE(testDPadKeyRotation(mapper,
-            KEY_DOWN, AKEYCODE_DPAD_DOWN, AKEYCODE_DPAD_RIGHT));
-    ASSERT_NO_FATAL_FAILURE(testDPadKeyRotation(mapper,
-            KEY_LEFT, AKEYCODE_DPAD_LEFT, AKEYCODE_DPAD_DOWN));
-
-    mFakePolicy->setDisplayInfo(DISPLAY_ID,
-            DISPLAY_WIDTH, DISPLAY_HEIGHT,
-            InputReaderPolicyInterface::ROTATION_180);
-    ASSERT_NO_FATAL_FAILURE(testDPadKeyRotation(mapper,
-            KEY_UP, AKEYCODE_DPAD_UP, AKEYCODE_DPAD_DOWN));
-    ASSERT_NO_FATAL_FAILURE(testDPadKeyRotation(mapper,
-            KEY_RIGHT, AKEYCODE_DPAD_RIGHT, AKEYCODE_DPAD_LEFT));
-    ASSERT_NO_FATAL_FAILURE(testDPadKeyRotation(mapper,
-            KEY_DOWN, AKEYCODE_DPAD_DOWN, AKEYCODE_DPAD_UP));
-    ASSERT_NO_FATAL_FAILURE(testDPadKeyRotation(mapper,
-            KEY_LEFT, AKEYCODE_DPAD_LEFT, AKEYCODE_DPAD_RIGHT));
-
-    mFakePolicy->setDisplayInfo(DISPLAY_ID,
-            DISPLAY_WIDTH, DISPLAY_HEIGHT,
-            InputReaderPolicyInterface::ROTATION_270);
-    ASSERT_NO_FATAL_FAILURE(testDPadKeyRotation(mapper,
-            KEY_UP, AKEYCODE_DPAD_UP, AKEYCODE_DPAD_RIGHT));
-    ASSERT_NO_FATAL_FAILURE(testDPadKeyRotation(mapper,
-            KEY_RIGHT, AKEYCODE_DPAD_RIGHT, AKEYCODE_DPAD_DOWN));
-    ASSERT_NO_FATAL_FAILURE(testDPadKeyRotation(mapper,
-            KEY_DOWN, AKEYCODE_DPAD_DOWN, AKEYCODE_DPAD_LEFT));
-    ASSERT_NO_FATAL_FAILURE(testDPadKeyRotation(mapper,
-            KEY_LEFT, AKEYCODE_DPAD_LEFT, AKEYCODE_DPAD_UP));
-
-    // Special case: if orientation changes while key is down, we still emit the same keycode
-    // in the key up as we did in the key down.
-    FakeInputDispatcher::NotifyKeyArgs args;
-
-    mFakePolicy->setDisplayInfo(DISPLAY_ID,
-            DISPLAY_WIDTH, DISPLAY_HEIGHT,
-            InputReaderPolicyInterface::ROTATION_270);
-    process(mapper, ARBITRARY_TIME, DEVICE_ID, EV_KEY, KEY_UP, AKEYCODE_DPAD_UP, 1, 0);
-    ASSERT_NO_FATAL_FAILURE(mFakeDispatcher->assertNotifyKeyWasCalled(&args));
-    ASSERT_EQ(AKEY_EVENT_ACTION_DOWN, args.action);
-    ASSERT_EQ(KEY_UP, args.scanCode);
-    ASSERT_EQ(AKEYCODE_DPAD_RIGHT, args.keyCode);
-
-    mFakePolicy->setDisplayInfo(DISPLAY_ID,
-            DISPLAY_WIDTH, DISPLAY_HEIGHT,
-            InputReaderPolicyInterface::ROTATION_180);
-    process(mapper, ARBITRARY_TIME, DEVICE_ID, EV_KEY, KEY_UP, AKEYCODE_DPAD_UP, 0, 0);
-    ASSERT_NO_FATAL_FAILURE(mFakeDispatcher->assertNotifyKeyWasCalled(&args));
-    ASSERT_EQ(AKEY_EVENT_ACTION_UP, args.action);
-    ASSERT_EQ(KEY_UP, args.scanCode);
-    ASSERT_EQ(AKEYCODE_DPAD_RIGHT, args.keyCode);
-}
-
-TEST_F(KeyboardInputMapperTest, GetKeyCodeState) {
-    KeyboardInputMapper* mapper = new KeyboardInputMapper(mDevice,
-            AINPUT_SOURCE_KEYBOARD, AINPUT_KEYBOARD_TYPE_ALPHABETIC);
-    addMapperAndConfigure(mapper);
-
-    mFakeEventHub->setKeyCodeState(DEVICE_ID, AKEYCODE_A, 1);
-    ASSERT_EQ(1, mapper->getKeyCodeState(AINPUT_SOURCE_ANY, AKEYCODE_A));
-
-    mFakeEventHub->setKeyCodeState(DEVICE_ID, AKEYCODE_A, 0);
-    ASSERT_EQ(0, mapper->getKeyCodeState(AINPUT_SOURCE_ANY, AKEYCODE_A));
-}
-
-TEST_F(KeyboardInputMapperTest, GetScanCodeState) {
-    KeyboardInputMapper* mapper = new KeyboardInputMapper(mDevice,
-            AINPUT_SOURCE_KEYBOARD, AINPUT_KEYBOARD_TYPE_ALPHABETIC);
-    addMapperAndConfigure(mapper);
-
-    mFakeEventHub->setScanCodeState(DEVICE_ID, KEY_A, 1);
-    ASSERT_EQ(1, mapper->getScanCodeState(AINPUT_SOURCE_ANY, KEY_A));
-
-    mFakeEventHub->setScanCodeState(DEVICE_ID, KEY_A, 0);
-    ASSERT_EQ(0, mapper->getScanCodeState(AINPUT_SOURCE_ANY, KEY_A));
-}
-
-TEST_F(KeyboardInputMapperTest, MarkSupportedKeyCodes) {
-    KeyboardInputMapper* mapper = new KeyboardInputMapper(mDevice,
-            AINPUT_SOURCE_KEYBOARD, AINPUT_KEYBOARD_TYPE_ALPHABETIC);
-    addMapperAndConfigure(mapper);
-
-    mFakeEventHub->addKey(DEVICE_ID, KEY_A, AKEYCODE_A, 0);
-
-    const int32_t keyCodes[2] = { AKEYCODE_A, AKEYCODE_B };
-    uint8_t flags[2] = { 0, 0 };
-    ASSERT_TRUE(mapper->markSupportedKeyCodes(AINPUT_SOURCE_ANY, 1, keyCodes, flags));
-    ASSERT_TRUE(flags[0]);
-    ASSERT_FALSE(flags[1]);
-}
-
-TEST_F(KeyboardInputMapperTest, Process_LockedKeysShouldToggleMetaStateAndLeds) {
-    mFakeEventHub->addLed(DEVICE_ID, LED_CAPSL, true /*initially on*/);
-    mFakeEventHub->addLed(DEVICE_ID, LED_NUML, false /*initially off*/);
-    mFakeEventHub->addLed(DEVICE_ID, LED_SCROLLL, false /*initially off*/);
-
-    KeyboardInputMapper* mapper = new KeyboardInputMapper(mDevice,
-            AINPUT_SOURCE_KEYBOARD, AINPUT_KEYBOARD_TYPE_ALPHABETIC);
-    addMapperAndConfigure(mapper);
-
-    // Initialization should have turned all of the lights off.
-    ASSERT_FALSE(mFakeEventHub->getLedState(DEVICE_ID, LED_CAPSL));
-    ASSERT_FALSE(mFakeEventHub->getLedState(DEVICE_ID, LED_NUML));
-    ASSERT_FALSE(mFakeEventHub->getLedState(DEVICE_ID, LED_SCROLLL));
-
-    // Toggle caps lock on.
-    process(mapper, ARBITRARY_TIME, DEVICE_ID,
-            EV_KEY, KEY_CAPSLOCK, AKEYCODE_CAPS_LOCK, 1, 0);
-    process(mapper, ARBITRARY_TIME, DEVICE_ID,
-            EV_KEY, KEY_CAPSLOCK, AKEYCODE_CAPS_LOCK, 0, 0);
-    ASSERT_TRUE(mFakeEventHub->getLedState(DEVICE_ID, LED_CAPSL));
-    ASSERT_FALSE(mFakeEventHub->getLedState(DEVICE_ID, LED_NUML));
-    ASSERT_FALSE(mFakeEventHub->getLedState(DEVICE_ID, LED_SCROLLL));
-    ASSERT_EQ(AMETA_CAPS_LOCK_ON, mapper->getMetaState());
-
-    // Toggle num lock on.
-    process(mapper, ARBITRARY_TIME, DEVICE_ID,
-            EV_KEY, KEY_NUMLOCK, AKEYCODE_NUM_LOCK, 1, 0);
-    process(mapper, ARBITRARY_TIME, DEVICE_ID,
-            EV_KEY, KEY_NUMLOCK, AKEYCODE_NUM_LOCK, 0, 0);
-    ASSERT_TRUE(mFakeEventHub->getLedState(DEVICE_ID, LED_CAPSL));
-    ASSERT_TRUE(mFakeEventHub->getLedState(DEVICE_ID, LED_NUML));
-    ASSERT_FALSE(mFakeEventHub->getLedState(DEVICE_ID, LED_SCROLLL));
-    ASSERT_EQ(AMETA_CAPS_LOCK_ON | AMETA_NUM_LOCK_ON, mapper->getMetaState());
-
-    // Toggle caps lock off.
-    process(mapper, ARBITRARY_TIME, DEVICE_ID,
-            EV_KEY, KEY_CAPSLOCK, AKEYCODE_CAPS_LOCK, 1, 0);
-    process(mapper, ARBITRARY_TIME, DEVICE_ID,
-            EV_KEY, KEY_CAPSLOCK, AKEYCODE_CAPS_LOCK, 0, 0);
-    ASSERT_FALSE(mFakeEventHub->getLedState(DEVICE_ID, LED_CAPSL));
-    ASSERT_TRUE(mFakeEventHub->getLedState(DEVICE_ID, LED_NUML));
-    ASSERT_FALSE(mFakeEventHub->getLedState(DEVICE_ID, LED_SCROLLL));
-    ASSERT_EQ(AMETA_NUM_LOCK_ON, mapper->getMetaState());
-
-    // Toggle scroll lock on.
-    process(mapper, ARBITRARY_TIME, DEVICE_ID,
-            EV_KEY, KEY_SCROLLLOCK, AKEYCODE_SCROLL_LOCK, 1, 0);
-    process(mapper, ARBITRARY_TIME, DEVICE_ID,
-            EV_KEY, KEY_SCROLLLOCK, AKEYCODE_SCROLL_LOCK, 0, 0);
-    ASSERT_FALSE(mFakeEventHub->getLedState(DEVICE_ID, LED_CAPSL));
-    ASSERT_TRUE(mFakeEventHub->getLedState(DEVICE_ID, LED_NUML));
-    ASSERT_TRUE(mFakeEventHub->getLedState(DEVICE_ID, LED_SCROLLL));
-    ASSERT_EQ(AMETA_NUM_LOCK_ON | AMETA_SCROLL_LOCK_ON, mapper->getMetaState());
-
-    // Toggle num lock off.
-    process(mapper, ARBITRARY_TIME, DEVICE_ID,
-            EV_KEY, KEY_NUMLOCK, AKEYCODE_NUM_LOCK, 1, 0);
-    process(mapper, ARBITRARY_TIME, DEVICE_ID,
-            EV_KEY, KEY_NUMLOCK, AKEYCODE_NUM_LOCK, 0, 0);
-    ASSERT_FALSE(mFakeEventHub->getLedState(DEVICE_ID, LED_CAPSL));
-    ASSERT_FALSE(mFakeEventHub->getLedState(DEVICE_ID, LED_NUML));
-    ASSERT_TRUE(mFakeEventHub->getLedState(DEVICE_ID, LED_SCROLLL));
-    ASSERT_EQ(AMETA_SCROLL_LOCK_ON, mapper->getMetaState());
-
-    // Toggle scroll lock off.
-    process(mapper, ARBITRARY_TIME, DEVICE_ID,
-            EV_KEY, KEY_SCROLLLOCK, AKEYCODE_SCROLL_LOCK, 1, 0);
-    process(mapper, ARBITRARY_TIME, DEVICE_ID,
-            EV_KEY, KEY_SCROLLLOCK, AKEYCODE_SCROLL_LOCK, 0, 0);
-    ASSERT_FALSE(mFakeEventHub->getLedState(DEVICE_ID, LED_CAPSL));
-    ASSERT_FALSE(mFakeEventHub->getLedState(DEVICE_ID, LED_NUML));
-    ASSERT_FALSE(mFakeEventHub->getLedState(DEVICE_ID, LED_SCROLLL));
-    ASSERT_EQ(AMETA_NONE, mapper->getMetaState());
-}
-
-
-// --- TrackballInputMapperTest ---
-
-class TrackballInputMapperTest : public InputMapperTest {
-protected:
-    static const int32_t TRACKBALL_MOVEMENT_THRESHOLD;
-
-    void testMotionRotation(TrackballInputMapper* mapper,
-            int32_t originalX, int32_t originalY, int32_t rotatedX, int32_t rotatedY);
-};
-
-const int32_t TrackballInputMapperTest::TRACKBALL_MOVEMENT_THRESHOLD = 6;
-
-void TrackballInputMapperTest::testMotionRotation(TrackballInputMapper* mapper,
-        int32_t originalX, int32_t originalY, int32_t rotatedX, int32_t rotatedY) {
-    FakeInputDispatcher::NotifyMotionArgs args;
-
-    process(mapper, ARBITRARY_TIME, DEVICE_ID, EV_REL, REL_X, 0, originalX, 0);
-    process(mapper, ARBITRARY_TIME, DEVICE_ID, EV_REL, REL_Y, 0, originalY, 0);
-    process(mapper, ARBITRARY_TIME, DEVICE_ID, EV_SYN, SYN_REPORT, 0, 0, 0);
-    ASSERT_NO_FATAL_FAILURE(mFakeDispatcher->assertNotifyMotionWasCalled(&args));
-    ASSERT_EQ(AMOTION_EVENT_ACTION_MOVE, args.action);
-    ASSERT_NO_FATAL_FAILURE(assertPointerCoords(args.pointerCoords[0],
-            float(rotatedX) / TRACKBALL_MOVEMENT_THRESHOLD,
-            float(rotatedY) / TRACKBALL_MOVEMENT_THRESHOLD,
-            0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f));
-}
-
-TEST_F(TrackballInputMapperTest, GetSources) {
-    TrackballInputMapper* mapper = new TrackballInputMapper(mDevice);
-    addMapperAndConfigure(mapper);
-
-    ASSERT_EQ(AINPUT_SOURCE_TRACKBALL, mapper->getSources());
-}
-
-TEST_F(TrackballInputMapperTest, PopulateDeviceInfo) {
-    TrackballInputMapper* mapper = new TrackballInputMapper(mDevice);
-    addMapperAndConfigure(mapper);
-
-    InputDeviceInfo info;
-    mapper->populateDeviceInfo(&info);
-
-    ASSERT_NO_FATAL_FAILURE(assertMotionRange(info, AINPUT_MOTION_RANGE_X,
-            -1.0f, 1.0f, 0.0f, 1.0f / TRACKBALL_MOVEMENT_THRESHOLD));
-    ASSERT_NO_FATAL_FAILURE(assertMotionRange(info, AINPUT_MOTION_RANGE_Y,
-            -1.0f, 1.0f, 0.0f, 1.0f / TRACKBALL_MOVEMENT_THRESHOLD));
-}
-
-TEST_F(TrackballInputMapperTest, Process_ShouldSetAllFieldsAndIncludeGlobalMetaState) {
-    TrackballInputMapper* mapper = new TrackballInputMapper(mDevice);
-    addMapperAndConfigure(mapper);
-
-    mFakeContext->setGlobalMetaState(AMETA_SHIFT_LEFT_ON | AMETA_SHIFT_ON);
-
-    FakeInputDispatcher::NotifyMotionArgs args;
-
-    // Button press.
-    // Mostly testing non x/y behavior here so we don't need to check again elsewhere.
-    process(mapper, ARBITRARY_TIME, DEVICE_ID, EV_KEY, BTN_MOUSE, 0, 1, 0);
-    ASSERT_NO_FATAL_FAILURE(mFakeDispatcher->assertNotifyMotionWasCalled(&args));
-    ASSERT_EQ(ARBITRARY_TIME, args.eventTime);
-    ASSERT_EQ(DEVICE_ID, args.deviceId);
-    ASSERT_EQ(AINPUT_SOURCE_TRACKBALL, args.source);
-    ASSERT_EQ(uint32_t(0), args.policyFlags);
-    ASSERT_EQ(AMOTION_EVENT_ACTION_DOWN, args.action);
-    ASSERT_EQ(0, args.flags);
-    ASSERT_EQ(AMETA_SHIFT_LEFT_ON | AMETA_SHIFT_ON, args.metaState);
-    ASSERT_EQ(0, args.edgeFlags);
-    ASSERT_EQ(uint32_t(1), args.pointerCount);
-    ASSERT_EQ(0, args.pointerIds[0]);
-    ASSERT_NO_FATAL_FAILURE(assertPointerCoords(args.pointerCoords[0],
-            0.0f, 0.0f, 1.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f));
-    ASSERT_EQ(TRACKBALL_MOVEMENT_THRESHOLD, args.xPrecision);
-    ASSERT_EQ(TRACKBALL_MOVEMENT_THRESHOLD, args.yPrecision);
-    ASSERT_EQ(ARBITRARY_TIME, args.downTime);
-
-    // Button release.  Should have same down time.
-    process(mapper, ARBITRARY_TIME + 1, DEVICE_ID, EV_KEY, BTN_MOUSE, 0, 0, 0);
-    ASSERT_NO_FATAL_FAILURE(mFakeDispatcher->assertNotifyMotionWasCalled(&args));
-    ASSERT_EQ(ARBITRARY_TIME + 1, args.eventTime);
-    ASSERT_EQ(DEVICE_ID, args.deviceId);
-    ASSERT_EQ(AINPUT_SOURCE_TRACKBALL, args.source);
-    ASSERT_EQ(uint32_t(0), args.policyFlags);
-    ASSERT_EQ(AMOTION_EVENT_ACTION_UP, args.action);
-    ASSERT_EQ(0, args.flags);
-    ASSERT_EQ(AMETA_SHIFT_LEFT_ON | AMETA_SHIFT_ON, args.metaState);
-    ASSERT_EQ(0, args.edgeFlags);
-    ASSERT_EQ(uint32_t(1), args.pointerCount);
-    ASSERT_EQ(0, args.pointerIds[0]);
-    ASSERT_NO_FATAL_FAILURE(assertPointerCoords(args.pointerCoords[0],
-            0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f));
-    ASSERT_EQ(TRACKBALL_MOVEMENT_THRESHOLD, args.xPrecision);
-    ASSERT_EQ(TRACKBALL_MOVEMENT_THRESHOLD, args.yPrecision);
-    ASSERT_EQ(ARBITRARY_TIME, args.downTime);
-}
-
-TEST_F(TrackballInputMapperTest, Process_ShouldHandleIndependentXYUpdates) {
-    TrackballInputMapper* mapper = new TrackballInputMapper(mDevice);
-    addMapperAndConfigure(mapper);
-
-    FakeInputDispatcher::NotifyMotionArgs args;
-
-    // Motion in X but not Y.
-    process(mapper, ARBITRARY_TIME, DEVICE_ID, EV_REL, REL_X, 0, 1, 0);
-    process(mapper, ARBITRARY_TIME, DEVICE_ID, EV_SYN, SYN_REPORT, 0, 0, 0);
-    ASSERT_NO_FATAL_FAILURE(mFakeDispatcher->assertNotifyMotionWasCalled(&args));
-    ASSERT_EQ(AMOTION_EVENT_ACTION_MOVE, args.action);
-    ASSERT_NO_FATAL_FAILURE(assertPointerCoords(args.pointerCoords[0],
-            1.0f / TRACKBALL_MOVEMENT_THRESHOLD, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f));
-
-    // Motion in Y but not X.
-    process(mapper, ARBITRARY_TIME, DEVICE_ID, EV_REL, REL_Y, 0, -2, 0);
-    process(mapper, ARBITRARY_TIME, DEVICE_ID, EV_SYN, SYN_REPORT, 0, 0, 0);
-    ASSERT_NO_FATAL_FAILURE(mFakeDispatcher->assertNotifyMotionWasCalled(&args));
-    ASSERT_EQ(AMOTION_EVENT_ACTION_MOVE, args.action);
-    ASSERT_NEAR(0.0f, args.pointerCoords[0].x, EPSILON);
-    ASSERT_NO_FATAL_FAILURE(assertPointerCoords(args.pointerCoords[0],
-            0.0f, -2.0f / TRACKBALL_MOVEMENT_THRESHOLD, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f));
-}
-
-TEST_F(TrackballInputMapperTest, Process_ShouldHandleIndependentButtonUpdates) {
-    TrackballInputMapper* mapper = new TrackballInputMapper(mDevice);
-    addMapperAndConfigure(mapper);
-
-    FakeInputDispatcher::NotifyMotionArgs args;
-
-    // Button press without following sync.
-    process(mapper, ARBITRARY_TIME, DEVICE_ID, EV_KEY, BTN_MOUSE, 0, 1, 0);
-    ASSERT_NO_FATAL_FAILURE(mFakeDispatcher->assertNotifyMotionWasCalled(&args));
-    ASSERT_EQ(AMOTION_EVENT_ACTION_DOWN, args.action);
-    ASSERT_NO_FATAL_FAILURE(assertPointerCoords(args.pointerCoords[0],
-            0.0f, 0.0f, 1.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f));
-
-    // Button release without following sync.
-    process(mapper, ARBITRARY_TIME, DEVICE_ID, EV_KEY, BTN_MOUSE, 0, 0, 0);
-    ASSERT_NO_FATAL_FAILURE(mFakeDispatcher->assertNotifyMotionWasCalled(&args));
-    ASSERT_EQ(AMOTION_EVENT_ACTION_UP, args.action);
-    ASSERT_NO_FATAL_FAILURE(assertPointerCoords(args.pointerCoords[0],
-            0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f));
-}
-
-TEST_F(TrackballInputMapperTest, Process_ShouldHandleCombinedXYAndButtonUpdates) {
-    TrackballInputMapper* mapper = new TrackballInputMapper(mDevice);
-    addMapperAndConfigure(mapper);
-
-    FakeInputDispatcher::NotifyMotionArgs args;
-
-    // Combined X, Y and Button.
-    process(mapper, ARBITRARY_TIME, DEVICE_ID, EV_REL, REL_X, 0, 1, 0);
-    process(mapper, ARBITRARY_TIME, DEVICE_ID, EV_REL, REL_Y, 0, -2, 0);
-    process(mapper, ARBITRARY_TIME, DEVICE_ID, EV_KEY, BTN_MOUSE, 0, 1, 0);
-    process(mapper, ARBITRARY_TIME, DEVICE_ID, EV_SYN, SYN_REPORT, 0, 0, 0);
-    ASSERT_NO_FATAL_FAILURE(mFakeDispatcher->assertNotifyMotionWasCalled(&args));
-    ASSERT_EQ(AMOTION_EVENT_ACTION_DOWN, args.action);
-    ASSERT_NO_FATAL_FAILURE(assertPointerCoords(args.pointerCoords[0],
-            1.0f / TRACKBALL_MOVEMENT_THRESHOLD, -2.0f / TRACKBALL_MOVEMENT_THRESHOLD,
-            1.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f));
-
-    // Move X, Y a bit while pressed.
-    process(mapper, ARBITRARY_TIME, DEVICE_ID, EV_REL, REL_X, 0, 2, 0);
-    process(mapper, ARBITRARY_TIME, DEVICE_ID, EV_REL, REL_Y, 0, 1, 0);
-    process(mapper, ARBITRARY_TIME, DEVICE_ID, EV_SYN, SYN_REPORT, 0, 0, 0);
-    ASSERT_NO_FATAL_FAILURE(mFakeDispatcher->assertNotifyMotionWasCalled(&args));
-    ASSERT_EQ(AMOTION_EVENT_ACTION_MOVE, args.action);
-    ASSERT_NO_FATAL_FAILURE(assertPointerCoords(args.pointerCoords[0],
-            2.0f / TRACKBALL_MOVEMENT_THRESHOLD, 1.0f / TRACKBALL_MOVEMENT_THRESHOLD,
-            1.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f));
-
-    // Release Button.
-    process(mapper, ARBITRARY_TIME, DEVICE_ID, EV_KEY, BTN_MOUSE, 0, 0, 0);
-    ASSERT_NO_FATAL_FAILURE(mFakeDispatcher->assertNotifyMotionWasCalled(&args));
-    ASSERT_EQ(AMOTION_EVENT_ACTION_UP, args.action);
-    ASSERT_NO_FATAL_FAILURE(assertPointerCoords(args.pointerCoords[0],
-            0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f));
-}
-
-TEST_F(TrackballInputMapperTest, Reset_WhenButtonIsNotDown_ShouldNotSynthesizeButtonUp) {
-    TrackballInputMapper* mapper = new TrackballInputMapper(mDevice);
-    addMapperAndConfigure(mapper);
-
-    FakeInputDispatcher::NotifyMotionArgs args;
-
-    // Button press.
-    process(mapper, ARBITRARY_TIME, DEVICE_ID, EV_KEY, BTN_MOUSE, 0, 1, 0);
-    ASSERT_NO_FATAL_FAILURE(mFakeDispatcher->assertNotifyMotionWasCalled(&args));
-
-    // Button release.
-    process(mapper, ARBITRARY_TIME, DEVICE_ID, EV_KEY, BTN_MOUSE, 0, 0, 0);
-    ASSERT_NO_FATAL_FAILURE(mFakeDispatcher->assertNotifyMotionWasCalled(&args));
-
-    // Reset.  Should not synthesize button up since button is not pressed.
-    mapper->reset();
-
-    ASSERT_NO_FATAL_FAILURE(mFakeDispatcher->assertNotifyMotionWasNotCalled());
-}
-
-TEST_F(TrackballInputMapperTest, Reset_WhenButtonIsDown_ShouldSynthesizeButtonUp) {
-    TrackballInputMapper* mapper = new TrackballInputMapper(mDevice);
-    addMapperAndConfigure(mapper);
-
-    FakeInputDispatcher::NotifyMotionArgs args;
-
-    // Button press.
-    process(mapper, ARBITRARY_TIME, DEVICE_ID, EV_KEY, BTN_MOUSE, 0, 1, 0);
-    ASSERT_NO_FATAL_FAILURE(mFakeDispatcher->assertNotifyMotionWasCalled(&args));
-
-    // Reset.  Should synthesize button up.
-    mapper->reset();
-
-    ASSERT_NO_FATAL_FAILURE(mFakeDispatcher->assertNotifyMotionWasCalled(&args));
-    ASSERT_EQ(AMOTION_EVENT_ACTION_UP, args.action);
-    ASSERT_NO_FATAL_FAILURE(assertPointerCoords(args.pointerCoords[0],
-            0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f));
-}
-
-TEST_F(TrackballInputMapperTest, Process_WhenNotOrientationAware_ShouldNotRotateMotions) {
-    TrackballInputMapper* mapper = new TrackballInputMapper(mDevice);
-    addMapperAndConfigure(mapper);
-
-    mFakePolicy->setDisplayInfo(DISPLAY_ID,
-            DISPLAY_WIDTH, DISPLAY_HEIGHT,
-            InputReaderPolicyInterface::ROTATION_90);
-    ASSERT_NO_FATAL_FAILURE(testMotionRotation(mapper,  0,  1,  0,  1));
-    ASSERT_NO_FATAL_FAILURE(testMotionRotation(mapper,  1,  1,  1,  1));
-    ASSERT_NO_FATAL_FAILURE(testMotionRotation(mapper,  1,  0,  1,  0));
-    ASSERT_NO_FATAL_FAILURE(testMotionRotation(mapper,  1, -1,  1, -1));
-    ASSERT_NO_FATAL_FAILURE(testMotionRotation(mapper,  0, -1,  0, -1));
-    ASSERT_NO_FATAL_FAILURE(testMotionRotation(mapper, -1, -1, -1, -1));
-    ASSERT_NO_FATAL_FAILURE(testMotionRotation(mapper, -1,  0, -1,  0));
-    ASSERT_NO_FATAL_FAILURE(testMotionRotation(mapper, -1,  1, -1,  1));
-}
-
-TEST_F(TrackballInputMapperTest, Process_WhenOrientationAware_ShouldRotateMotions) {
-    TrackballInputMapper* mapper = new TrackballInputMapper(mDevice);
-    addConfigurationProperty("trackball.orientationAware", "1");
-    addMapperAndConfigure(mapper);
-
-    mFakePolicy->setDisplayInfo(DISPLAY_ID,
-            DISPLAY_WIDTH, DISPLAY_HEIGHT,
-            InputReaderPolicyInterface::ROTATION_0);
-    ASSERT_NO_FATAL_FAILURE(testMotionRotation(mapper,  0,  1,  0,  1));
-    ASSERT_NO_FATAL_FAILURE(testMotionRotation(mapper,  1,  1,  1,  1));
-    ASSERT_NO_FATAL_FAILURE(testMotionRotation(mapper,  1,  0,  1,  0));
-    ASSERT_NO_FATAL_FAILURE(testMotionRotation(mapper,  1, -1,  1, -1));
-    ASSERT_NO_FATAL_FAILURE(testMotionRotation(mapper,  0, -1,  0, -1));
-    ASSERT_NO_FATAL_FAILURE(testMotionRotation(mapper, -1, -1, -1, -1));
-    ASSERT_NO_FATAL_FAILURE(testMotionRotation(mapper, -1,  0, -1,  0));
-    ASSERT_NO_FATAL_FAILURE(testMotionRotation(mapper, -1,  1, -1,  1));
-
-    mFakePolicy->setDisplayInfo(DISPLAY_ID,
-            DISPLAY_WIDTH, DISPLAY_HEIGHT,
-            InputReaderPolicyInterface::ROTATION_90);
-    ASSERT_NO_FATAL_FAILURE(testMotionRotation(mapper,  0,  1,  1,  0));
-    ASSERT_NO_FATAL_FAILURE(testMotionRotation(mapper,  1,  1,  1, -1));
-    ASSERT_NO_FATAL_FAILURE(testMotionRotation(mapper,  1,  0,  0, -1));
-    ASSERT_NO_FATAL_FAILURE(testMotionRotation(mapper,  1, -1, -1, -1));
-    ASSERT_NO_FATAL_FAILURE(testMotionRotation(mapper,  0, -1, -1,  0));
-    ASSERT_NO_FATAL_FAILURE(testMotionRotation(mapper, -1, -1, -1,  1));
-    ASSERT_NO_FATAL_FAILURE(testMotionRotation(mapper, -1,  0,  0,  1));
-    ASSERT_NO_FATAL_FAILURE(testMotionRotation(mapper, -1,  1,  1,  1));
-
-    mFakePolicy->setDisplayInfo(DISPLAY_ID,
-            DISPLAY_WIDTH, DISPLAY_HEIGHT,
-            InputReaderPolicyInterface::ROTATION_180);
-    ASSERT_NO_FATAL_FAILURE(testMotionRotation(mapper,  0,  1,  0, -1));
-    ASSERT_NO_FATAL_FAILURE(testMotionRotation(mapper,  1,  1, -1, -1));
-    ASSERT_NO_FATAL_FAILURE(testMotionRotation(mapper,  1,  0, -1,  0));
-    ASSERT_NO_FATAL_FAILURE(testMotionRotation(mapper,  1, -1, -1,  1));
-    ASSERT_NO_FATAL_FAILURE(testMotionRotation(mapper,  0, -1,  0,  1));
-    ASSERT_NO_FATAL_FAILURE(testMotionRotation(mapper, -1, -1,  1,  1));
-    ASSERT_NO_FATAL_FAILURE(testMotionRotation(mapper, -1,  0,  1,  0));
-    ASSERT_NO_FATAL_FAILURE(testMotionRotation(mapper, -1,  1,  1, -1));
-
-    mFakePolicy->setDisplayInfo(DISPLAY_ID,
-            DISPLAY_WIDTH, DISPLAY_HEIGHT,
-            InputReaderPolicyInterface::ROTATION_270);
-    ASSERT_NO_FATAL_FAILURE(testMotionRotation(mapper,  0,  1, -1,  0));
-    ASSERT_NO_FATAL_FAILURE(testMotionRotation(mapper,  1,  1, -1,  1));
-    ASSERT_NO_FATAL_FAILURE(testMotionRotation(mapper,  1,  0,  0,  1));
-    ASSERT_NO_FATAL_FAILURE(testMotionRotation(mapper,  1, -1,  1,  1));
-    ASSERT_NO_FATAL_FAILURE(testMotionRotation(mapper,  0, -1,  1,  0));
-    ASSERT_NO_FATAL_FAILURE(testMotionRotation(mapper, -1, -1,  1, -1));
-    ASSERT_NO_FATAL_FAILURE(testMotionRotation(mapper, -1,  0,  0, -1));
-    ASSERT_NO_FATAL_FAILURE(testMotionRotation(mapper, -1,  1, -1, -1));
-}
-
-
-// --- TouchInputMapperTest ---
-
-class TouchInputMapperTest : public InputMapperTest {
-protected:
-    static const int32_t RAW_X_MIN;
-    static const int32_t RAW_X_MAX;
-    static const int32_t RAW_Y_MIN;
-    static const int32_t RAW_Y_MAX;
-    static const int32_t RAW_TOUCH_MIN;
-    static const int32_t RAW_TOUCH_MAX;
-    static const int32_t RAW_TOOL_MIN;
-    static const int32_t RAW_TOOL_MAX;
-    static const int32_t RAW_PRESSURE_MIN;
-    static const int32_t RAW_PRESSURE_MAX;
-    static const int32_t RAW_ORIENTATION_MIN;
-    static const int32_t RAW_ORIENTATION_MAX;
-    static const int32_t RAW_ID_MIN;
-    static const int32_t RAW_ID_MAX;
-    static const float X_PRECISION;
-    static const float Y_PRECISION;
-
-    static const VirtualKeyDefinition VIRTUAL_KEYS[2];
-
-    enum Axes {
-        POSITION = 1 << 0,
-        TOUCH = 1 << 1,
-        TOOL = 1 << 2,
-        PRESSURE = 1 << 3,
-        ORIENTATION = 1 << 4,
-        MINOR = 1 << 5,
-        ID = 1 << 6,
-    };
-
-    void prepareDisplay(int32_t orientation);
-    void prepareVirtualKeys();
-    int32_t toRawX(float displayX);
-    int32_t toRawY(float displayY);
-    float toDisplayX(int32_t rawX);
-    float toDisplayY(int32_t rawY);
-};
-
-const int32_t TouchInputMapperTest::RAW_X_MIN = 25;
-const int32_t TouchInputMapperTest::RAW_X_MAX = 1020;
-const int32_t TouchInputMapperTest::RAW_Y_MIN = 30;
-const int32_t TouchInputMapperTest::RAW_Y_MAX = 1010;
-const int32_t TouchInputMapperTest::RAW_TOUCH_MIN = 0;
-const int32_t TouchInputMapperTest::RAW_TOUCH_MAX = 31;
-const int32_t TouchInputMapperTest::RAW_TOOL_MIN = 0;
-const int32_t TouchInputMapperTest::RAW_TOOL_MAX = 15;
-const int32_t TouchInputMapperTest::RAW_PRESSURE_MIN = RAW_TOUCH_MIN;
-const int32_t TouchInputMapperTest::RAW_PRESSURE_MAX = RAW_TOUCH_MAX;
-const int32_t TouchInputMapperTest::RAW_ORIENTATION_MIN = -7;
-const int32_t TouchInputMapperTest::RAW_ORIENTATION_MAX = 7;
-const int32_t TouchInputMapperTest::RAW_ID_MIN = 0;
-const int32_t TouchInputMapperTest::RAW_ID_MAX = 9;
-const float TouchInputMapperTest::X_PRECISION = float(RAW_X_MAX - RAW_X_MIN) / DISPLAY_WIDTH;
-const float TouchInputMapperTest::Y_PRECISION = float(RAW_Y_MAX - RAW_Y_MIN) / DISPLAY_HEIGHT;
-
-const VirtualKeyDefinition TouchInputMapperTest::VIRTUAL_KEYS[2] = {
-        { KEY_HOME, 60, DISPLAY_HEIGHT + 15, 20, 20 },
-        { KEY_MENU, DISPLAY_HEIGHT - 60, DISPLAY_WIDTH + 15, 20, 20 },
-};
-
-void TouchInputMapperTest::prepareDisplay(int32_t orientation) {
-    mFakePolicy->setDisplayInfo(DISPLAY_ID, DISPLAY_WIDTH, DISPLAY_HEIGHT, orientation);
-}
-
-void TouchInputMapperTest::prepareVirtualKeys() {
-    mFakeEventHub->addVirtualKeyDefinition(DEVICE_ID, VIRTUAL_KEYS[0]);
-    mFakeEventHub->addVirtualKeyDefinition(DEVICE_ID, VIRTUAL_KEYS[1]);
-    mFakeEventHub->addKey(DEVICE_ID, KEY_HOME, AKEYCODE_HOME, POLICY_FLAG_WAKE);
-    mFakeEventHub->addKey(DEVICE_ID, KEY_MENU, AKEYCODE_MENU, POLICY_FLAG_WAKE);
-}
-
-int32_t TouchInputMapperTest::toRawX(float displayX) {
-    return int32_t(displayX * (RAW_X_MAX - RAW_X_MIN) / DISPLAY_WIDTH + RAW_X_MIN);
-}
-
-int32_t TouchInputMapperTest::toRawY(float displayY) {
-    return int32_t(displayY * (RAW_Y_MAX - RAW_Y_MIN) / DISPLAY_HEIGHT + RAW_Y_MIN);
-}
-
-float TouchInputMapperTest::toDisplayX(int32_t rawX) {
-    return float(rawX - RAW_X_MIN) * DISPLAY_WIDTH / (RAW_X_MAX - RAW_X_MIN);
-}
-
-float TouchInputMapperTest::toDisplayY(int32_t rawY) {
-    return float(rawY - RAW_Y_MIN) * DISPLAY_HEIGHT / (RAW_Y_MAX - RAW_Y_MIN);
-}
-
-
-// --- SingleTouchInputMapperTest ---
-
-class SingleTouchInputMapperTest : public TouchInputMapperTest {
-protected:
-    void prepareAxes(int axes);
-
-    void processDown(SingleTouchInputMapper* mapper, int32_t x, int32_t y);
-    void processMove(SingleTouchInputMapper* mapper, int32_t x, int32_t y);
-    void processUp(SingleTouchInputMapper* mappery);
-    void processPressure(SingleTouchInputMapper* mapper, int32_t pressure);
-    void processToolMajor(SingleTouchInputMapper* mapper, int32_t toolMajor);
-    void processSync(SingleTouchInputMapper* mapper);
-};
-
-void SingleTouchInputMapperTest::prepareAxes(int axes) {
-    if (axes & POSITION) {
-        mFakeEventHub->addAxis(DEVICE_ID, ABS_X, RAW_X_MIN, RAW_X_MAX, 0, 0);
-        mFakeEventHub->addAxis(DEVICE_ID, ABS_Y, RAW_Y_MIN, RAW_Y_MAX, 0, 0);
-    }
-    if (axes & PRESSURE) {
-        mFakeEventHub->addAxis(DEVICE_ID, ABS_PRESSURE, RAW_PRESSURE_MIN, RAW_PRESSURE_MAX, 0, 0);
-    }
-    if (axes & TOOL) {
-        mFakeEventHub->addAxis(DEVICE_ID, ABS_TOOL_WIDTH, RAW_TOOL_MIN, RAW_TOOL_MAX, 0, 0);
-    }
-}
-
-void SingleTouchInputMapperTest::processDown(SingleTouchInputMapper* mapper, int32_t x, int32_t y) {
-    process(mapper, ARBITRARY_TIME, DEVICE_ID, EV_KEY, BTN_TOUCH, 0, 1, 0);
-    process(mapper, ARBITRARY_TIME, DEVICE_ID, EV_ABS, ABS_X, 0, x, 0);
-    process(mapper, ARBITRARY_TIME, DEVICE_ID, EV_ABS, ABS_Y, 0, y, 0);
-}
-
-void SingleTouchInputMapperTest::processMove(SingleTouchInputMapper* mapper, int32_t x, int32_t y) {
-    process(mapper, ARBITRARY_TIME, DEVICE_ID, EV_ABS, ABS_X, 0, x, 0);
-    process(mapper, ARBITRARY_TIME, DEVICE_ID, EV_ABS, ABS_Y, 0, y, 0);
-}
-
-void SingleTouchInputMapperTest::processUp(SingleTouchInputMapper* mapper) {
-    process(mapper, ARBITRARY_TIME, DEVICE_ID, EV_KEY, BTN_TOUCH, 0, 0, 0);
-}
-
-void SingleTouchInputMapperTest::processPressure(
-        SingleTouchInputMapper* mapper, int32_t pressure) {
-    process(mapper, ARBITRARY_TIME, DEVICE_ID, EV_ABS, ABS_PRESSURE, 0, pressure, 0);
-}
-
-void SingleTouchInputMapperTest::processToolMajor(
-        SingleTouchInputMapper* mapper, int32_t toolMajor) {
-    process(mapper, ARBITRARY_TIME, DEVICE_ID, EV_ABS, ABS_TOOL_WIDTH, 0, toolMajor, 0);
-}
-
-void SingleTouchInputMapperTest::processSync(SingleTouchInputMapper* mapper) {
-    process(mapper, ARBITRARY_TIME, DEVICE_ID, EV_SYN, SYN_REPORT, 0, 0, 0);
-}
-
-
-TEST_F(SingleTouchInputMapperTest, GetSources_WhenDeviceTypeIsTouchPad_ReturnsTouchPad) {
-    SingleTouchInputMapper* mapper = new SingleTouchInputMapper(mDevice);
-    prepareAxes(POSITION);
-    addConfigurationProperty("touch.deviceType", "touchPad");
-    addMapperAndConfigure(mapper);
-
-    ASSERT_EQ(AINPUT_SOURCE_TOUCHPAD, mapper->getSources());
-}
-
-TEST_F(SingleTouchInputMapperTest, GetSources_WhenDeviceTypeIsTouchScreen_ReturnsTouchScreen) {
-    SingleTouchInputMapper* mapper = new SingleTouchInputMapper(mDevice);
-    prepareAxes(POSITION);
-    addConfigurationProperty("touch.deviceType", "touchScreen");
-    addMapperAndConfigure(mapper);
-
-    ASSERT_EQ(AINPUT_SOURCE_TOUCHSCREEN, mapper->getSources());
-}
-
-TEST_F(SingleTouchInputMapperTest, GetKeyCodeState) {
-    SingleTouchInputMapper* mapper = new SingleTouchInputMapper(mDevice);
-    prepareDisplay(InputReaderPolicyInterface::ROTATION_0);
-    prepareAxes(POSITION);
-    prepareVirtualKeys();
-    addMapperAndConfigure(mapper);
-
-    // Unknown key.
-    ASSERT_EQ(AKEY_STATE_UNKNOWN, mapper->getKeyCodeState(AINPUT_SOURCE_ANY, AKEYCODE_A));
-
-    // Virtual key is down.
-    int32_t x = toRawX(VIRTUAL_KEYS[0].centerX);
-    int32_t y = toRawY(VIRTUAL_KEYS[0].centerY);
-    processDown(mapper, x, y);
-    processSync(mapper);
-    ASSERT_NO_FATAL_FAILURE(mFakeDispatcher->assertNotifyKeyWasCalled());
-
-    ASSERT_EQ(AKEY_STATE_VIRTUAL, mapper->getKeyCodeState(AINPUT_SOURCE_ANY, AKEYCODE_HOME));
-
-    // Virtual key is up.
-    processUp(mapper);
-    processSync(mapper);
-    ASSERT_NO_FATAL_FAILURE(mFakeDispatcher->assertNotifyKeyWasCalled());
-
-    ASSERT_EQ(AKEY_STATE_UP, mapper->getKeyCodeState(AINPUT_SOURCE_ANY, AKEYCODE_HOME));
-}
-
-TEST_F(SingleTouchInputMapperTest, GetScanCodeState) {
-    SingleTouchInputMapper* mapper = new SingleTouchInputMapper(mDevice);
-    prepareDisplay(InputReaderPolicyInterface::ROTATION_0);
-    prepareAxes(POSITION);
-    prepareVirtualKeys();
-    addMapperAndConfigure(mapper);
-
-    // Unknown key.
-    ASSERT_EQ(AKEY_STATE_UNKNOWN, mapper->getScanCodeState(AINPUT_SOURCE_ANY, KEY_A));
-
-    // Virtual key is down.
-    int32_t x = toRawX(VIRTUAL_KEYS[0].centerX);
-    int32_t y = toRawY(VIRTUAL_KEYS[0].centerY);
-    processDown(mapper, x, y);
-    processSync(mapper);
-    ASSERT_NO_FATAL_FAILURE(mFakeDispatcher->assertNotifyKeyWasCalled());
-
-    ASSERT_EQ(AKEY_STATE_VIRTUAL, mapper->getScanCodeState(AINPUT_SOURCE_ANY, KEY_HOME));
-
-    // Virtual key is up.
-    processUp(mapper);
-    processSync(mapper);
-    ASSERT_NO_FATAL_FAILURE(mFakeDispatcher->assertNotifyKeyWasCalled());
-
-    ASSERT_EQ(AKEY_STATE_UP, mapper->getScanCodeState(AINPUT_SOURCE_ANY, KEY_HOME));
-}
-
-TEST_F(SingleTouchInputMapperTest, MarkSupportedKeyCodes) {
-    SingleTouchInputMapper* mapper = new SingleTouchInputMapper(mDevice);
-    prepareDisplay(InputReaderPolicyInterface::ROTATION_0);
-    prepareAxes(POSITION);
-    prepareVirtualKeys();
-    addMapperAndConfigure(mapper);
-
-    const int32_t keys[2] = { AKEYCODE_HOME, AKEYCODE_A };
-    uint8_t flags[2] = { 0, 0 };
-    ASSERT_TRUE(mapper->markSupportedKeyCodes(AINPUT_SOURCE_ANY, 2, keys, flags));
-    ASSERT_TRUE(flags[0]);
-    ASSERT_FALSE(flags[1]);
-}
-
-TEST_F(SingleTouchInputMapperTest, Reset_WhenVirtualKeysAreDown_SendsUp) {
-    // Note: Ideally we should send cancels but the implementation is more straightforward
-    // with up and this will only happen if a device is forcibly removed.
-    SingleTouchInputMapper* mapper = new SingleTouchInputMapper(mDevice);
-    prepareDisplay(InputReaderPolicyInterface::ROTATION_0);
-    prepareAxes(POSITION);
-    prepareVirtualKeys();
-    addMapperAndConfigure(mapper);
-
-    mFakeContext->setGlobalMetaState(AMETA_SHIFT_LEFT_ON | AMETA_SHIFT_ON);
-
-    // Press virtual key.
-    int32_t x = toRawX(VIRTUAL_KEYS[0].centerX);
-    int32_t y = toRawY(VIRTUAL_KEYS[0].centerY);
-    processDown(mapper, x, y);
-    processSync(mapper);
-    ASSERT_NO_FATAL_FAILURE(mFakeDispatcher->assertNotifyKeyWasCalled());
-
-    // Reset.  Since key is down, synthesize key up.
-    mapper->reset();
-
-    FakeInputDispatcher::NotifyKeyArgs args;
-    ASSERT_NO_FATAL_FAILURE(mFakeDispatcher->assertNotifyKeyWasCalled(&args));
-    //ASSERT_EQ(ARBITRARY_TIME, args.eventTime);
-    ASSERT_EQ(DEVICE_ID, args.deviceId);
-    ASSERT_EQ(AINPUT_SOURCE_KEYBOARD, args.source);
-    ASSERT_EQ(POLICY_FLAG_VIRTUAL, args.policyFlags);
-    ASSERT_EQ(AKEY_EVENT_ACTION_UP, args.action);
-    ASSERT_EQ(AKEY_EVENT_FLAG_FROM_SYSTEM | AKEY_EVENT_FLAG_VIRTUAL_HARD_KEY, args.flags);
-    ASSERT_EQ(AKEYCODE_HOME, args.keyCode);
-    ASSERT_EQ(KEY_HOME, args.scanCode);
-    ASSERT_EQ(AMETA_SHIFT_LEFT_ON | AMETA_SHIFT_ON, args.metaState);
-    ASSERT_EQ(ARBITRARY_TIME, args.downTime);
-}
-
-TEST_F(SingleTouchInputMapperTest, Reset_WhenNothingIsPressed_NothingMuchHappens) {
-    SingleTouchInputMapper* mapper = new SingleTouchInputMapper(mDevice);
-    prepareDisplay(InputReaderPolicyInterface::ROTATION_0);
-    prepareAxes(POSITION);
-    prepareVirtualKeys();
-    addMapperAndConfigure(mapper);
-
-    // Press virtual key.
-    int32_t x = toRawX(VIRTUAL_KEYS[0].centerX);
-    int32_t y = toRawY(VIRTUAL_KEYS[0].centerY);
-    processDown(mapper, x, y);
-    processSync(mapper);
-    ASSERT_NO_FATAL_FAILURE(mFakeDispatcher->assertNotifyKeyWasCalled());
-
-    // Release virtual key.
-    processUp(mapper);
-    processSync(mapper);
-    ASSERT_NO_FATAL_FAILURE(mFakeDispatcher->assertNotifyKeyWasCalled());
-
-    // Reset.  Since no key is down, nothing happens.
-    mapper->reset();
-
-    ASSERT_NO_FATAL_FAILURE(mFakeDispatcher->assertNotifyKeyWasNotCalled());
-    ASSERT_NO_FATAL_FAILURE(mFakeDispatcher->assertNotifyMotionWasNotCalled());
-}
-
-TEST_F(SingleTouchInputMapperTest, Process_WhenVirtualKeyIsPressedAndReleasedNormally_SendsKeyDownAndKeyUp) {
-    SingleTouchInputMapper* mapper = new SingleTouchInputMapper(mDevice);
-    prepareDisplay(InputReaderPolicyInterface::ROTATION_0);
-    prepareAxes(POSITION);
-    prepareVirtualKeys();
-    addMapperAndConfigure(mapper);
-
-    mFakeContext->setGlobalMetaState(AMETA_SHIFT_LEFT_ON | AMETA_SHIFT_ON);
-
-    FakeInputDispatcher::NotifyKeyArgs args;
-
-    // Press virtual key.
-    int32_t x = toRawX(VIRTUAL_KEYS[0].centerX);
-    int32_t y = toRawY(VIRTUAL_KEYS[0].centerY);
-    processDown(mapper, x, y);
-    processSync(mapper);
-
-    ASSERT_NO_FATAL_FAILURE(mFakeDispatcher->assertNotifyKeyWasCalled(&args));
-    ASSERT_EQ(ARBITRARY_TIME, args.eventTime);
-    ASSERT_EQ(DEVICE_ID, args.deviceId);
-    ASSERT_EQ(AINPUT_SOURCE_KEYBOARD, args.source);
-    ASSERT_EQ(POLICY_FLAG_VIRTUAL, args.policyFlags);
-    ASSERT_EQ(AKEY_EVENT_ACTION_DOWN, args.action);
-    ASSERT_EQ(AKEY_EVENT_FLAG_FROM_SYSTEM | AKEY_EVENT_FLAG_VIRTUAL_HARD_KEY, args.flags);
-    ASSERT_EQ(AKEYCODE_HOME, args.keyCode);
-    ASSERT_EQ(KEY_HOME, args.scanCode);
-    ASSERT_EQ(AMETA_SHIFT_LEFT_ON | AMETA_SHIFT_ON, args.metaState);
-    ASSERT_EQ(ARBITRARY_TIME, args.downTime);
-
-    // Release virtual key.
-    processUp(mapper);
-    processSync(mapper);
-
-    ASSERT_NO_FATAL_FAILURE(mFakeDispatcher->assertNotifyKeyWasCalled(&args));
-    ASSERT_EQ(ARBITRARY_TIME, args.eventTime);
-    ASSERT_EQ(DEVICE_ID, args.deviceId);
-    ASSERT_EQ(AINPUT_SOURCE_KEYBOARD, args.source);
-    ASSERT_EQ(POLICY_FLAG_VIRTUAL, args.policyFlags);
-    ASSERT_EQ(AKEY_EVENT_ACTION_UP, args.action);
-    ASSERT_EQ(AKEY_EVENT_FLAG_FROM_SYSTEM | AKEY_EVENT_FLAG_VIRTUAL_HARD_KEY, args.flags);
-    ASSERT_EQ(AKEYCODE_HOME, args.keyCode);
-    ASSERT_EQ(KEY_HOME, args.scanCode);
-    ASSERT_EQ(AMETA_SHIFT_LEFT_ON | AMETA_SHIFT_ON, args.metaState);
-    ASSERT_EQ(ARBITRARY_TIME, args.downTime);
-
-    // Should not have sent any motions.
-    ASSERT_NO_FATAL_FAILURE(mFakeDispatcher->assertNotifyKeyWasNotCalled());
-}
-
-TEST_F(SingleTouchInputMapperTest, Process_WhenVirtualKeyIsPressedAndMovedOutOfBounds_SendsKeyDownAndKeyCancel) {
-    SingleTouchInputMapper* mapper = new SingleTouchInputMapper(mDevice);
-    prepareDisplay(InputReaderPolicyInterface::ROTATION_0);
-    prepareAxes(POSITION);
-    prepareVirtualKeys();
-    addMapperAndConfigure(mapper);
-
-    mFakeContext->setGlobalMetaState(AMETA_SHIFT_LEFT_ON | AMETA_SHIFT_ON);
-
-    FakeInputDispatcher::NotifyKeyArgs keyArgs;
-
-    // Press virtual key.
-    int32_t x = toRawX(VIRTUAL_KEYS[0].centerX);
-    int32_t y = toRawY(VIRTUAL_KEYS[0].centerY);
-    processDown(mapper, x, y);
-    processSync(mapper);
-
-    ASSERT_NO_FATAL_FAILURE(mFakeDispatcher->assertNotifyKeyWasCalled(&keyArgs));
-    ASSERT_EQ(ARBITRARY_TIME, keyArgs.eventTime);
-    ASSERT_EQ(DEVICE_ID, keyArgs.deviceId);
-    ASSERT_EQ(AINPUT_SOURCE_KEYBOARD, keyArgs.source);
-    ASSERT_EQ(POLICY_FLAG_VIRTUAL, keyArgs.policyFlags);
-    ASSERT_EQ(AKEY_EVENT_ACTION_DOWN, keyArgs.action);
-    ASSERT_EQ(AKEY_EVENT_FLAG_FROM_SYSTEM | AKEY_EVENT_FLAG_VIRTUAL_HARD_KEY, keyArgs.flags);
-    ASSERT_EQ(AKEYCODE_HOME, keyArgs.keyCode);
-    ASSERT_EQ(KEY_HOME, keyArgs.scanCode);
-    ASSERT_EQ(AMETA_SHIFT_LEFT_ON | AMETA_SHIFT_ON, keyArgs.metaState);
-    ASSERT_EQ(ARBITRARY_TIME, keyArgs.downTime);
-
-    // Move out of bounds.  This should generate a cancel and a pointer down since we moved
-    // into the display area.
-    y -= 100;
-    processMove(mapper, x, y);
-    processSync(mapper);
-
-    ASSERT_NO_FATAL_FAILURE(mFakeDispatcher->assertNotifyKeyWasCalled(&keyArgs));
-    ASSERT_EQ(ARBITRARY_TIME, keyArgs.eventTime);
-    ASSERT_EQ(DEVICE_ID, keyArgs.deviceId);
-    ASSERT_EQ(AINPUT_SOURCE_KEYBOARD, keyArgs.source);
-    ASSERT_EQ(POLICY_FLAG_VIRTUAL, keyArgs.policyFlags);
-    ASSERT_EQ(AKEY_EVENT_ACTION_UP, keyArgs.action);
-    ASSERT_EQ(AKEY_EVENT_FLAG_FROM_SYSTEM | AKEY_EVENT_FLAG_VIRTUAL_HARD_KEY
-            | AKEY_EVENT_FLAG_CANCELED, keyArgs.flags);
-    ASSERT_EQ(AKEYCODE_HOME, keyArgs.keyCode);
-    ASSERT_EQ(KEY_HOME, keyArgs.scanCode);
-    ASSERT_EQ(AMETA_SHIFT_LEFT_ON | AMETA_SHIFT_ON, keyArgs.metaState);
-    ASSERT_EQ(ARBITRARY_TIME, keyArgs.downTime);
-
-    FakeInputDispatcher::NotifyMotionArgs motionArgs;
-    ASSERT_NO_FATAL_FAILURE(mFakeDispatcher->assertNotifyMotionWasCalled(&motionArgs));
-    ASSERT_EQ(ARBITRARY_TIME, motionArgs.eventTime);
-    ASSERT_EQ(DEVICE_ID, motionArgs.deviceId);
-    ASSERT_EQ(AINPUT_SOURCE_TOUCHSCREEN, motionArgs.source);
-    ASSERT_EQ(uint32_t(0), motionArgs.policyFlags);
-    ASSERT_EQ(AMOTION_EVENT_ACTION_DOWN, motionArgs.action);
-    ASSERT_EQ(0, motionArgs.flags);
-    ASSERT_EQ(AMETA_SHIFT_LEFT_ON | AMETA_SHIFT_ON, motionArgs.metaState);
-    ASSERT_EQ(0, motionArgs.edgeFlags);
-    ASSERT_EQ(size_t(1), motionArgs.pointerCount);
-    ASSERT_EQ(0, motionArgs.pointerIds[0]);
-    ASSERT_NO_FATAL_FAILURE(assertPointerCoords(motionArgs.pointerCoords[0],
-            toDisplayX(x), toDisplayY(y), 1, 0, 0, 0, 0, 0, 0));
-    ASSERT_NEAR(X_PRECISION, motionArgs.xPrecision, EPSILON);
-    ASSERT_NEAR(Y_PRECISION, motionArgs.yPrecision, EPSILON);
-    ASSERT_EQ(ARBITRARY_TIME, motionArgs.downTime);
-
-    // Keep moving out of bounds.  Should generate a pointer move.
-    y -= 50;
-    processMove(mapper, x, y);
-    processSync(mapper);
-
-    ASSERT_NO_FATAL_FAILURE(mFakeDispatcher->assertNotifyMotionWasCalled(&motionArgs));
-    ASSERT_EQ(ARBITRARY_TIME, motionArgs.eventTime);
-    ASSERT_EQ(DEVICE_ID, motionArgs.deviceId);
-    ASSERT_EQ(AINPUT_SOURCE_TOUCHSCREEN, motionArgs.source);
-    ASSERT_EQ(uint32_t(0), motionArgs.policyFlags);
-    ASSERT_EQ(AMOTION_EVENT_ACTION_MOVE, motionArgs.action);
-    ASSERT_EQ(0, motionArgs.flags);
-    ASSERT_EQ(AMETA_SHIFT_LEFT_ON | AMETA_SHIFT_ON, motionArgs.metaState);
-    ASSERT_EQ(0, motionArgs.edgeFlags);
-    ASSERT_EQ(size_t(1), motionArgs.pointerCount);
-    ASSERT_EQ(0, motionArgs.pointerIds[0]);
-    ASSERT_NO_FATAL_FAILURE(assertPointerCoords(motionArgs.pointerCoords[0],
-            toDisplayX(x), toDisplayY(y), 1, 0, 0, 0, 0, 0, 0));
-    ASSERT_NEAR(X_PRECISION, motionArgs.xPrecision, EPSILON);
-    ASSERT_NEAR(Y_PRECISION, motionArgs.yPrecision, EPSILON);
-    ASSERT_EQ(ARBITRARY_TIME, motionArgs.downTime);
-
-    // Release out of bounds.  Should generate a pointer up.
-    processUp(mapper);
-    processSync(mapper);
-
-    ASSERT_NO_FATAL_FAILURE(mFakeDispatcher->assertNotifyMotionWasCalled(&motionArgs));
-    ASSERT_EQ(ARBITRARY_TIME, motionArgs.eventTime);
-    ASSERT_EQ(DEVICE_ID, motionArgs.deviceId);
-    ASSERT_EQ(AINPUT_SOURCE_TOUCHSCREEN, motionArgs.source);
-    ASSERT_EQ(uint32_t(0), motionArgs.policyFlags);
-    ASSERT_EQ(AMOTION_EVENT_ACTION_UP, motionArgs.action);
-    ASSERT_EQ(0, motionArgs.flags);
-    ASSERT_EQ(AMETA_SHIFT_LEFT_ON | AMETA_SHIFT_ON, motionArgs.metaState);
-    ASSERT_EQ(0, motionArgs.edgeFlags);
-    ASSERT_EQ(size_t(1), motionArgs.pointerCount);
-    ASSERT_EQ(0, motionArgs.pointerIds[0]);
-    ASSERT_NO_FATAL_FAILURE(assertPointerCoords(motionArgs.pointerCoords[0],
-            toDisplayX(x), toDisplayY(y), 1, 0, 0, 0, 0, 0, 0));
-    ASSERT_NEAR(X_PRECISION, motionArgs.xPrecision, EPSILON);
-    ASSERT_NEAR(Y_PRECISION, motionArgs.yPrecision, EPSILON);
-    ASSERT_EQ(ARBITRARY_TIME, motionArgs.downTime);
-
-    // Should not have sent any more keys or motions.
-    ASSERT_NO_FATAL_FAILURE(mFakeDispatcher->assertNotifyKeyWasNotCalled());
-    ASSERT_NO_FATAL_FAILURE(mFakeDispatcher->assertNotifyMotionWasNotCalled());
-}
-
-TEST_F(SingleTouchInputMapperTest, Process_WhenTouchStartsOutsideDisplayAndMovesIn_SendsDownAsTouchEntersDisplay) {
-    SingleTouchInputMapper* mapper = new SingleTouchInputMapper(mDevice);
-    prepareDisplay(InputReaderPolicyInterface::ROTATION_0);
-    prepareAxes(POSITION);
-    prepareVirtualKeys();
-    addMapperAndConfigure(mapper);
-
-    mFakeContext->setGlobalMetaState(AMETA_SHIFT_LEFT_ON | AMETA_SHIFT_ON);
-
-    FakeInputDispatcher::NotifyMotionArgs motionArgs;
-
-    // Initially go down out of bounds.
-    int32_t x = -10;
-    int32_t y = -10;
-    processDown(mapper, x, y);
-    processSync(mapper);
-
-    ASSERT_NO_FATAL_FAILURE(mFakeDispatcher->assertNotifyMotionWasNotCalled());
-
-    // Move into the display area.  Should generate a pointer down.
-    x = 50;
-    y = 75;
-    processMove(mapper, x, y);
-    processSync(mapper);
-
-    ASSERT_NO_FATAL_FAILURE(mFakeDispatcher->assertNotifyMotionWasCalled(&motionArgs));
-    ASSERT_EQ(ARBITRARY_TIME, motionArgs.eventTime);
-    ASSERT_EQ(DEVICE_ID, motionArgs.deviceId);
-    ASSERT_EQ(AINPUT_SOURCE_TOUCHSCREEN, motionArgs.source);
-    ASSERT_EQ(uint32_t(0), motionArgs.policyFlags);
-    ASSERT_EQ(AMOTION_EVENT_ACTION_DOWN, motionArgs.action);
-    ASSERT_EQ(0, motionArgs.flags);
-    ASSERT_EQ(AMETA_SHIFT_LEFT_ON | AMETA_SHIFT_ON, motionArgs.metaState);
-    ASSERT_EQ(0, motionArgs.edgeFlags);
-    ASSERT_EQ(size_t(1), motionArgs.pointerCount);
-    ASSERT_EQ(0, motionArgs.pointerIds[0]);
-    ASSERT_NO_FATAL_FAILURE(assertPointerCoords(motionArgs.pointerCoords[0],
-            toDisplayX(x), toDisplayY(y), 1, 0, 0, 0, 0, 0, 0));
-    ASSERT_NEAR(X_PRECISION, motionArgs.xPrecision, EPSILON);
-    ASSERT_NEAR(Y_PRECISION, motionArgs.yPrecision, EPSILON);
-    ASSERT_EQ(ARBITRARY_TIME, motionArgs.downTime);
-
-    // Release.  Should generate a pointer up.
-    processUp(mapper);
-    processSync(mapper);
-
-    ASSERT_NO_FATAL_FAILURE(mFakeDispatcher->assertNotifyMotionWasCalled(&motionArgs));
-    ASSERT_EQ(ARBITRARY_TIME, motionArgs.eventTime);
-    ASSERT_EQ(DEVICE_ID, motionArgs.deviceId);
-    ASSERT_EQ(AINPUT_SOURCE_TOUCHSCREEN, motionArgs.source);
-    ASSERT_EQ(uint32_t(0), motionArgs.policyFlags);
-    ASSERT_EQ(AMOTION_EVENT_ACTION_UP, motionArgs.action);
-    ASSERT_EQ(0, motionArgs.flags);
-    ASSERT_EQ(AMETA_SHIFT_LEFT_ON | AMETA_SHIFT_ON, motionArgs.metaState);
-    ASSERT_EQ(0, motionArgs.edgeFlags);
-    ASSERT_EQ(size_t(1), motionArgs.pointerCount);
-    ASSERT_EQ(0, motionArgs.pointerIds[0]);
-    ASSERT_NO_FATAL_FAILURE(assertPointerCoords(motionArgs.pointerCoords[0],
-            toDisplayX(x), toDisplayY(y), 1, 0, 0, 0, 0, 0, 0));
-    ASSERT_NEAR(X_PRECISION, motionArgs.xPrecision, EPSILON);
-    ASSERT_NEAR(Y_PRECISION, motionArgs.yPrecision, EPSILON);
-    ASSERT_EQ(ARBITRARY_TIME, motionArgs.downTime);
-
-    // Should not have sent any more keys or motions.
-    ASSERT_NO_FATAL_FAILURE(mFakeDispatcher->assertNotifyKeyWasNotCalled());
-    ASSERT_NO_FATAL_FAILURE(mFakeDispatcher->assertNotifyMotionWasNotCalled());
-}
-
-TEST_F(SingleTouchInputMapperTest, Process_NormalSingleTouchGesture) {
-    SingleTouchInputMapper* mapper = new SingleTouchInputMapper(mDevice);
-    prepareDisplay(InputReaderPolicyInterface::ROTATION_0);
-    prepareAxes(POSITION);
-    prepareVirtualKeys();
-    addMapperAndConfigure(mapper);
-
-    mFakeContext->setGlobalMetaState(AMETA_SHIFT_LEFT_ON | AMETA_SHIFT_ON);
-
-    FakeInputDispatcher::NotifyMotionArgs motionArgs;
-
-    // Down.
-    int32_t x = 100;
-    int32_t y = 125;
-    processDown(mapper, x, y);
-    processSync(mapper);
-
-    ASSERT_NO_FATAL_FAILURE(mFakeDispatcher->assertNotifyMotionWasCalled(&motionArgs));
-    ASSERT_EQ(ARBITRARY_TIME, motionArgs.eventTime);
-    ASSERT_EQ(DEVICE_ID, motionArgs.deviceId);
-    ASSERT_EQ(AINPUT_SOURCE_TOUCHSCREEN, motionArgs.source);
-    ASSERT_EQ(uint32_t(0), motionArgs.policyFlags);
-    ASSERT_EQ(AMOTION_EVENT_ACTION_DOWN, motionArgs.action);
-    ASSERT_EQ(0, motionArgs.flags);
-    ASSERT_EQ(AMETA_SHIFT_LEFT_ON | AMETA_SHIFT_ON, motionArgs.metaState);
-    ASSERT_EQ(0, motionArgs.edgeFlags);
-    ASSERT_EQ(size_t(1), motionArgs.pointerCount);
-    ASSERT_EQ(0, motionArgs.pointerIds[0]);
-    ASSERT_NO_FATAL_FAILURE(assertPointerCoords(motionArgs.pointerCoords[0],
-            toDisplayX(x), toDisplayY(y), 1, 0, 0, 0, 0, 0, 0));
-    ASSERT_NEAR(X_PRECISION, motionArgs.xPrecision, EPSILON);
-    ASSERT_NEAR(Y_PRECISION, motionArgs.yPrecision, EPSILON);
-    ASSERT_EQ(ARBITRARY_TIME, motionArgs.downTime);
-
-    // Move.
-    x += 50;
-    y += 75;
-    processMove(mapper, x, y);
-    processSync(mapper);
-
-    ASSERT_NO_FATAL_FAILURE(mFakeDispatcher->assertNotifyMotionWasCalled(&motionArgs));
-    ASSERT_EQ(ARBITRARY_TIME, motionArgs.eventTime);
-    ASSERT_EQ(DEVICE_ID, motionArgs.deviceId);
-    ASSERT_EQ(AINPUT_SOURCE_TOUCHSCREEN, motionArgs.source);
-    ASSERT_EQ(uint32_t(0), motionArgs.policyFlags);
-    ASSERT_EQ(AMOTION_EVENT_ACTION_MOVE, motionArgs.action);
-    ASSERT_EQ(0, motionArgs.flags);
-    ASSERT_EQ(AMETA_SHIFT_LEFT_ON | AMETA_SHIFT_ON, motionArgs.metaState);
-    ASSERT_EQ(0, motionArgs.edgeFlags);
-    ASSERT_EQ(size_t(1), motionArgs.pointerCount);
-    ASSERT_EQ(0, motionArgs.pointerIds[0]);
-    ASSERT_NO_FATAL_FAILURE(assertPointerCoords(motionArgs.pointerCoords[0],
-            toDisplayX(x), toDisplayY(y), 1, 0, 0, 0, 0, 0, 0));
-    ASSERT_NEAR(X_PRECISION, motionArgs.xPrecision, EPSILON);
-    ASSERT_NEAR(Y_PRECISION, motionArgs.yPrecision, EPSILON);
-    ASSERT_EQ(ARBITRARY_TIME, motionArgs.downTime);
-
-    // Up.
-    processUp(mapper);
-    processSync(mapper);
-
-    ASSERT_NO_FATAL_FAILURE(mFakeDispatcher->assertNotifyMotionWasCalled(&motionArgs));
-    ASSERT_EQ(ARBITRARY_TIME, motionArgs.eventTime);
-    ASSERT_EQ(DEVICE_ID, motionArgs.deviceId);
-    ASSERT_EQ(AINPUT_SOURCE_TOUCHSCREEN, motionArgs.source);
-    ASSERT_EQ(uint32_t(0), motionArgs.policyFlags);
-    ASSERT_EQ(AMOTION_EVENT_ACTION_UP, motionArgs.action);
-    ASSERT_EQ(0, motionArgs.flags);
-    ASSERT_EQ(AMETA_SHIFT_LEFT_ON | AMETA_SHIFT_ON, motionArgs.metaState);
-    ASSERT_EQ(0, motionArgs.edgeFlags);
-    ASSERT_EQ(size_t(1), motionArgs.pointerCount);
-    ASSERT_EQ(0, motionArgs.pointerIds[0]);
-    ASSERT_NO_FATAL_FAILURE(assertPointerCoords(motionArgs.pointerCoords[0],
-            toDisplayX(x), toDisplayY(y), 1, 0, 0, 0, 0, 0, 0));
-    ASSERT_NEAR(X_PRECISION, motionArgs.xPrecision, EPSILON);
-    ASSERT_NEAR(Y_PRECISION, motionArgs.yPrecision, EPSILON);
-    ASSERT_EQ(ARBITRARY_TIME, motionArgs.downTime);
-
-    // Should not have sent any more keys or motions.
-    ASSERT_NO_FATAL_FAILURE(mFakeDispatcher->assertNotifyKeyWasNotCalled());
-    ASSERT_NO_FATAL_FAILURE(mFakeDispatcher->assertNotifyMotionWasNotCalled());
-}
-
-TEST_F(SingleTouchInputMapperTest, Process_WhenNotOrientationAware_DoesNotRotateMotions) {
-    SingleTouchInputMapper* mapper = new SingleTouchInputMapper(mDevice);
-    prepareAxes(POSITION);
-    addConfigurationProperty("touch.orientationAware", "0");
-    addMapperAndConfigure(mapper);
-
-    FakeInputDispatcher::NotifyMotionArgs args;
-
-    // Rotation 90.
-    prepareDisplay(InputReaderPolicyInterface::ROTATION_90);
-    processDown(mapper, toRawX(50), toRawY(75));
-    processSync(mapper);
-
-    ASSERT_NO_FATAL_FAILURE(mFakeDispatcher->assertNotifyMotionWasCalled(&args));
-    ASSERT_NEAR(50, args.pointerCoords[0].x, 1);
-    ASSERT_NEAR(75, args.pointerCoords[0].y, 1);
-
-    processUp(mapper);
-    processSync(mapper);
-    ASSERT_NO_FATAL_FAILURE(mFakeDispatcher->assertNotifyMotionWasCalled());
-}
-
-TEST_F(SingleTouchInputMapperTest, Process_WhenOrientationAware_RotatesMotions) {
-    SingleTouchInputMapper* mapper = new SingleTouchInputMapper(mDevice);
-    prepareAxes(POSITION);
-    addMapperAndConfigure(mapper);
-
-    FakeInputDispatcher::NotifyMotionArgs args;
-
-    // Rotation 0.
-    prepareDisplay(InputReaderPolicyInterface::ROTATION_0);
-    processDown(mapper, toRawX(50), toRawY(75));
-    processSync(mapper);
-
-    ASSERT_NO_FATAL_FAILURE(mFakeDispatcher->assertNotifyMotionWasCalled(&args));
-    ASSERT_NEAR(50, args.pointerCoords[0].x, 1);
-    ASSERT_NEAR(75, args.pointerCoords[0].y, 1);
-
-    processUp(mapper);
-    processSync(mapper);
-    ASSERT_NO_FATAL_FAILURE(mFakeDispatcher->assertNotifyMotionWasCalled());
-
-    // Rotation 90.
-    prepareDisplay(InputReaderPolicyInterface::ROTATION_90);
-    processDown(mapper, toRawX(50), toRawY(75));
-    processSync(mapper);
-
-    ASSERT_NO_FATAL_FAILURE(mFakeDispatcher->assertNotifyMotionWasCalled(&args));
-    ASSERT_NEAR(75, args.pointerCoords[0].x, 1);
-    ASSERT_NEAR(DISPLAY_WIDTH - 50, args.pointerCoords[0].y, 1);
-
-    processUp(mapper);
-    processSync(mapper);
-    ASSERT_NO_FATAL_FAILURE(mFakeDispatcher->assertNotifyMotionWasCalled());
-
-    // Rotation 180.
-    prepareDisplay(InputReaderPolicyInterface::ROTATION_180);
-    processDown(mapper, toRawX(50), toRawY(75));
-    processSync(mapper);
-
-    ASSERT_NO_FATAL_FAILURE(mFakeDispatcher->assertNotifyMotionWasCalled(&args));
-    ASSERT_NEAR(DISPLAY_WIDTH - 50, args.pointerCoords[0].x, 1);
-    ASSERT_NEAR(DISPLAY_HEIGHT - 75, args.pointerCoords[0].y, 1);
-
-    processUp(mapper);
-    processSync(mapper);
-    ASSERT_NO_FATAL_FAILURE(mFakeDispatcher->assertNotifyMotionWasCalled());
-
-    // Rotation 270.
-    prepareDisplay(InputReaderPolicyInterface::ROTATION_270);
-    processDown(mapper, toRawX(50), toRawY(75));
-    processSync(mapper);
-
-    ASSERT_NO_FATAL_FAILURE(mFakeDispatcher->assertNotifyMotionWasCalled(&args));
-    ASSERT_NEAR(DISPLAY_HEIGHT - 75, args.pointerCoords[0].x, 1);
-    ASSERT_NEAR(50, args.pointerCoords[0].y, 1);
-
-    processUp(mapper);
-    processSync(mapper);
-    ASSERT_NO_FATAL_FAILURE(mFakeDispatcher->assertNotifyMotionWasCalled());
-}
-
-TEST_F(SingleTouchInputMapperTest, Process_AllAxes_DefaultCalibration) {
-    SingleTouchInputMapper* mapper = new SingleTouchInputMapper(mDevice);
-    prepareDisplay(InputReaderPolicyInterface::ROTATION_0);
-    prepareAxes(POSITION | PRESSURE | TOOL);
-    addMapperAndConfigure(mapper);
-
-    // These calculations are based on the input device calibration documentation.
-    int32_t rawX = 100;
-    int32_t rawY = 200;
-    int32_t rawPressure = 10;
-    int32_t rawToolMajor = 12;
-
-    float x = toDisplayX(rawX);
-    float y = toDisplayY(rawY);
-    float pressure = float(rawPressure) / RAW_PRESSURE_MAX;
-    float size = float(rawToolMajor) / RAW_TOOL_MAX;
-    float tool = min(DISPLAY_WIDTH, DISPLAY_HEIGHT) * size;
-    float touch = min(tool * pressure, tool);
-
-    processDown(mapper, rawX, rawY);
-    processPressure(mapper, rawPressure);
-    processToolMajor(mapper, rawToolMajor);
-    processSync(mapper);
-
-    FakeInputDispatcher::NotifyMotionArgs args;
-    ASSERT_NO_FATAL_FAILURE(mFakeDispatcher->assertNotifyMotionWasCalled(&args));
-    ASSERT_NO_FATAL_FAILURE(assertPointerCoords(args.pointerCoords[0],
-            x, y, pressure, size, touch, touch, tool, tool, 0));
-}
-
-
-// --- MultiTouchInputMapperTest ---
-
-class MultiTouchInputMapperTest : public TouchInputMapperTest {
-protected:
-    void prepareAxes(int axes);
-
-    void processPosition(MultiTouchInputMapper* mapper, int32_t x, int32_t y);
-    void processTouchMajor(MultiTouchInputMapper* mapper, int32_t touchMajor);
-    void processTouchMinor(MultiTouchInputMapper* mapper, int32_t touchMinor);
-    void processToolMajor(MultiTouchInputMapper* mapper, int32_t toolMajor);
-    void processToolMinor(MultiTouchInputMapper* mapper, int32_t toolMinor);
-    void processOrientation(MultiTouchInputMapper* mapper, int32_t orientation);
-    void processPressure(MultiTouchInputMapper* mapper, int32_t pressure);
-    void processId(MultiTouchInputMapper* mapper, int32_t id);
-    void processMTSync(MultiTouchInputMapper* mapper);
-    void processSync(MultiTouchInputMapper* mapper);
-};
-
-void MultiTouchInputMapperTest::prepareAxes(int axes) {
-    if (axes & POSITION) {
-        mFakeEventHub->addAxis(DEVICE_ID, ABS_MT_POSITION_X, RAW_X_MIN, RAW_X_MAX, 0, 0);
-        mFakeEventHub->addAxis(DEVICE_ID, ABS_MT_POSITION_Y, RAW_Y_MIN, RAW_Y_MAX, 0, 0);
-    }
-    if (axes & TOUCH) {
-        mFakeEventHub->addAxis(DEVICE_ID, ABS_MT_TOUCH_MAJOR, RAW_TOUCH_MIN, RAW_TOUCH_MAX, 0, 0);
-        if (axes & MINOR) {
-            mFakeEventHub->addAxis(DEVICE_ID, ABS_MT_TOUCH_MINOR,
-                    RAW_TOUCH_MIN, RAW_TOUCH_MAX, 0, 0);
-        }
-    }
-    if (axes & TOOL) {
-        mFakeEventHub->addAxis(DEVICE_ID, ABS_MT_WIDTH_MAJOR, RAW_TOOL_MIN, RAW_TOOL_MAX, 0, 0);
-        if (axes & MINOR) {
-            mFakeEventHub->addAxis(DEVICE_ID, ABS_MT_WIDTH_MINOR,
-                    RAW_TOOL_MAX, RAW_TOOL_MAX, 0, 0);
-        }
-    }
-    if (axes & ORIENTATION) {
-        mFakeEventHub->addAxis(DEVICE_ID, ABS_MT_ORIENTATION,
-                RAW_ORIENTATION_MIN, RAW_ORIENTATION_MAX, 0, 0);
-    }
-    if (axes & PRESSURE) {
-        mFakeEventHub->addAxis(DEVICE_ID, ABS_MT_PRESSURE,
-                RAW_PRESSURE_MIN, RAW_PRESSURE_MAX, 0, 0);
-    }
-    if (axes & ID) {
-        mFakeEventHub->addAxis(DEVICE_ID, ABS_MT_TRACKING_ID,
-                RAW_ID_MIN, RAW_ID_MAX, 0, 0);
-    }
-}
-
-void MultiTouchInputMapperTest::processPosition(
-        MultiTouchInputMapper* mapper, int32_t x, int32_t y) {
-    process(mapper, ARBITRARY_TIME, DEVICE_ID, EV_ABS, ABS_MT_POSITION_X, 0, x, 0);
-    process(mapper, ARBITRARY_TIME, DEVICE_ID, EV_ABS, ABS_MT_POSITION_Y, 0, y, 0);
-}
-
-void MultiTouchInputMapperTest::processTouchMajor(
-        MultiTouchInputMapper* mapper, int32_t touchMajor) {
-    process(mapper, ARBITRARY_TIME, DEVICE_ID, EV_ABS, ABS_MT_TOUCH_MAJOR, 0, touchMajor, 0);
-}
-
-void MultiTouchInputMapperTest::processTouchMinor(
-        MultiTouchInputMapper* mapper, int32_t touchMinor) {
-    process(mapper, ARBITRARY_TIME, DEVICE_ID, EV_ABS, ABS_MT_TOUCH_MINOR, 0, touchMinor, 0);
-}
-
-void MultiTouchInputMapperTest::processToolMajor(
-        MultiTouchInputMapper* mapper, int32_t toolMajor) {
-    process(mapper, ARBITRARY_TIME, DEVICE_ID, EV_ABS, ABS_MT_WIDTH_MAJOR, 0, toolMajor, 0);
-}
-
-void MultiTouchInputMapperTest::processToolMinor(
-        MultiTouchInputMapper* mapper, int32_t toolMinor) {
-    process(mapper, ARBITRARY_TIME, DEVICE_ID, EV_ABS, ABS_MT_WIDTH_MINOR, 0, toolMinor, 0);
-}
-
-void MultiTouchInputMapperTest::processOrientation(
-        MultiTouchInputMapper* mapper, int32_t orientation) {
-    process(mapper, ARBITRARY_TIME, DEVICE_ID, EV_ABS, ABS_MT_ORIENTATION, 0, orientation, 0);
-}
-
-void MultiTouchInputMapperTest::processPressure(
-        MultiTouchInputMapper* mapper, int32_t pressure) {
-    process(mapper, ARBITRARY_TIME, DEVICE_ID, EV_ABS, ABS_MT_PRESSURE, 0, pressure, 0);
-}
-
-void MultiTouchInputMapperTest::processId(
-        MultiTouchInputMapper* mapper, int32_t id) {
-    process(mapper, ARBITRARY_TIME, DEVICE_ID, EV_ABS, ABS_MT_TRACKING_ID, 0, id, 0);
-}
-
-void MultiTouchInputMapperTest::processMTSync(MultiTouchInputMapper* mapper) {
-    process(mapper, ARBITRARY_TIME, DEVICE_ID, EV_SYN, SYN_MT_REPORT, 0, 0, 0);
-}
-
-void MultiTouchInputMapperTest::processSync(MultiTouchInputMapper* mapper) {
-    process(mapper, ARBITRARY_TIME, DEVICE_ID, EV_SYN, SYN_REPORT, 0, 0, 0);
-}
-
-
-TEST_F(MultiTouchInputMapperTest, Process_NormalMultiTouchGesture_WithoutTrackingIds) {
-    MultiTouchInputMapper* mapper = new MultiTouchInputMapper(mDevice);
-    prepareDisplay(InputReaderPolicyInterface::ROTATION_0);
-    prepareAxes(POSITION);
-    prepareVirtualKeys();
-    addMapperAndConfigure(mapper);
-
-    mFakeContext->setGlobalMetaState(AMETA_SHIFT_LEFT_ON | AMETA_SHIFT_ON);
-
-    FakeInputDispatcher::NotifyMotionArgs motionArgs;
-
-    // Two fingers down at once.
-    int32_t x1 = 100, y1 = 125, x2 = 300, y2 = 500;
-    processPosition(mapper, x1, y1);
-    processMTSync(mapper);
-    processPosition(mapper, x2, y2);
-    processMTSync(mapper);
-    processSync(mapper);
-
-    ASSERT_NO_FATAL_FAILURE(mFakeDispatcher->assertNotifyMotionWasCalled(&motionArgs));
-    ASSERT_EQ(ARBITRARY_TIME, motionArgs.eventTime);
-    ASSERT_EQ(DEVICE_ID, motionArgs.deviceId);
-    ASSERT_EQ(AINPUT_SOURCE_TOUCHSCREEN, motionArgs.source);
-    ASSERT_EQ(uint32_t(0), motionArgs.policyFlags);
-    ASSERT_EQ(AMOTION_EVENT_ACTION_DOWN, motionArgs.action);
-    ASSERT_EQ(0, motionArgs.flags);
-    ASSERT_EQ(AMETA_SHIFT_LEFT_ON | AMETA_SHIFT_ON, motionArgs.metaState);
-    ASSERT_EQ(0, motionArgs.edgeFlags);
-    ASSERT_EQ(size_t(1), motionArgs.pointerCount);
-    ASSERT_EQ(0, motionArgs.pointerIds[0]);
-    ASSERT_NO_FATAL_FAILURE(assertPointerCoords(motionArgs.pointerCoords[0],
-            toDisplayX(x1), toDisplayY(y1), 1, 0, 0, 0, 0, 0, 0));
-    ASSERT_NEAR(X_PRECISION, motionArgs.xPrecision, EPSILON);
-    ASSERT_NEAR(Y_PRECISION, motionArgs.yPrecision, EPSILON);
-    ASSERT_EQ(ARBITRARY_TIME, motionArgs.downTime);
-
-    ASSERT_NO_FATAL_FAILURE(mFakeDispatcher->assertNotifyMotionWasCalled(&motionArgs));
-    ASSERT_EQ(ARBITRARY_TIME, motionArgs.eventTime);
-    ASSERT_EQ(DEVICE_ID, motionArgs.deviceId);
-    ASSERT_EQ(AINPUT_SOURCE_TOUCHSCREEN, motionArgs.source);
-    ASSERT_EQ(uint32_t(0), motionArgs.policyFlags);
-    ASSERT_EQ(AMOTION_EVENT_ACTION_POINTER_DOWN | (1 << AMOTION_EVENT_ACTION_POINTER_INDEX_SHIFT),
-            motionArgs.action);
-    ASSERT_EQ(0, motionArgs.flags);
-    ASSERT_EQ(AMETA_SHIFT_LEFT_ON | AMETA_SHIFT_ON, motionArgs.metaState);
-    ASSERT_EQ(0, motionArgs.edgeFlags);
-    ASSERT_EQ(size_t(2), motionArgs.pointerCount);
-    ASSERT_EQ(0, motionArgs.pointerIds[0]);
-    ASSERT_EQ(1, motionArgs.pointerIds[1]);
-    ASSERT_NO_FATAL_FAILURE(assertPointerCoords(motionArgs.pointerCoords[0],
-            toDisplayX(x1), toDisplayY(y1), 1, 0, 0, 0, 0, 0, 0));
-    ASSERT_NO_FATAL_FAILURE(assertPointerCoords(motionArgs.pointerCoords[1],
-            toDisplayX(x2), toDisplayY(y2), 1, 0, 0, 0, 0, 0, 0));
-    ASSERT_NEAR(X_PRECISION, motionArgs.xPrecision, EPSILON);
-    ASSERT_NEAR(Y_PRECISION, motionArgs.yPrecision, EPSILON);
-    ASSERT_EQ(ARBITRARY_TIME, motionArgs.downTime);
-
-    // Move.
-    x1 += 10; y1 += 15; x2 += 5; y2 -= 10;
-    processPosition(mapper, x1, y1);
-    processMTSync(mapper);
-    processPosition(mapper, x2, y2);
-    processMTSync(mapper);
-    processSync(mapper);
-
-    ASSERT_NO_FATAL_FAILURE(mFakeDispatcher->assertNotifyMotionWasCalled(&motionArgs));
-    ASSERT_EQ(ARBITRARY_TIME, motionArgs.eventTime);
-    ASSERT_EQ(DEVICE_ID, motionArgs.deviceId);
-    ASSERT_EQ(AINPUT_SOURCE_TOUCHSCREEN, motionArgs.source);
-    ASSERT_EQ(uint32_t(0), motionArgs.policyFlags);
-    ASSERT_EQ(AMOTION_EVENT_ACTION_MOVE, motionArgs.action);
-    ASSERT_EQ(0, motionArgs.flags);
-    ASSERT_EQ(AMETA_SHIFT_LEFT_ON | AMETA_SHIFT_ON, motionArgs.metaState);
-    ASSERT_EQ(0, motionArgs.edgeFlags);
-    ASSERT_EQ(size_t(2), motionArgs.pointerCount);
-    ASSERT_EQ(0, motionArgs.pointerIds[0]);
-    ASSERT_EQ(1, motionArgs.pointerIds[1]);
-    ASSERT_NO_FATAL_FAILURE(assertPointerCoords(motionArgs.pointerCoords[0],
-            toDisplayX(x1), toDisplayY(y1), 1, 0, 0, 0, 0, 0, 0));
-    ASSERT_NO_FATAL_FAILURE(assertPointerCoords(motionArgs.pointerCoords[1],
-            toDisplayX(x2), toDisplayY(y2), 1, 0, 0, 0, 0, 0, 0));
-    ASSERT_NEAR(X_PRECISION, motionArgs.xPrecision, EPSILON);
-    ASSERT_NEAR(Y_PRECISION, motionArgs.yPrecision, EPSILON);
-    ASSERT_EQ(ARBITRARY_TIME, motionArgs.downTime);
-
-    // First finger up.
-    x2 += 15; y2 -= 20;
-    processPosition(mapper, x2, y2);
-    processMTSync(mapper);
-    processSync(mapper);
-
-    ASSERT_NO_FATAL_FAILURE(mFakeDispatcher->assertNotifyMotionWasCalled(&motionArgs));
-    ASSERT_EQ(ARBITRARY_TIME, motionArgs.eventTime);
-    ASSERT_EQ(DEVICE_ID, motionArgs.deviceId);
-    ASSERT_EQ(AINPUT_SOURCE_TOUCHSCREEN, motionArgs.source);
-    ASSERT_EQ(uint32_t(0), motionArgs.policyFlags);
-    ASSERT_EQ(AMOTION_EVENT_ACTION_POINTER_UP | (0 << AMOTION_EVENT_ACTION_POINTER_INDEX_SHIFT),
-            motionArgs.action);
-    ASSERT_EQ(0, motionArgs.flags);
-    ASSERT_EQ(AMETA_SHIFT_LEFT_ON | AMETA_SHIFT_ON, motionArgs.metaState);
-    ASSERT_EQ(0, motionArgs.edgeFlags);
-    ASSERT_EQ(size_t(2), motionArgs.pointerCount);
-    ASSERT_EQ(0, motionArgs.pointerIds[0]);
-    ASSERT_EQ(1, motionArgs.pointerIds[1]);
-    ASSERT_NO_FATAL_FAILURE(assertPointerCoords(motionArgs.pointerCoords[0],
-            toDisplayX(x1), toDisplayY(y1), 1, 0, 0, 0, 0, 0, 0));
-    ASSERT_NO_FATAL_FAILURE(assertPointerCoords(motionArgs.pointerCoords[1],
-            toDisplayX(x2), toDisplayY(y2), 1, 0, 0, 0, 0, 0, 0));
-    ASSERT_NEAR(X_PRECISION, motionArgs.xPrecision, EPSILON);
-    ASSERT_NEAR(Y_PRECISION, motionArgs.yPrecision, EPSILON);
-    ASSERT_EQ(ARBITRARY_TIME, motionArgs.downTime);
-
-    ASSERT_NO_FATAL_FAILURE(mFakeDispatcher->assertNotifyMotionWasCalled(&motionArgs));
-    ASSERT_EQ(ARBITRARY_TIME, motionArgs.eventTime);
-    ASSERT_EQ(DEVICE_ID, motionArgs.deviceId);
-    ASSERT_EQ(AINPUT_SOURCE_TOUCHSCREEN, motionArgs.source);
-    ASSERT_EQ(uint32_t(0), motionArgs.policyFlags);
-    ASSERT_EQ(AMOTION_EVENT_ACTION_MOVE, motionArgs.action);
-    ASSERT_EQ(0, motionArgs.flags);
-    ASSERT_EQ(AMETA_SHIFT_LEFT_ON | AMETA_SHIFT_ON, motionArgs.metaState);
-    ASSERT_EQ(0, motionArgs.edgeFlags);
-    ASSERT_EQ(size_t(1), motionArgs.pointerCount);
-    ASSERT_EQ(1, motionArgs.pointerIds[0]);
-    ASSERT_NO_FATAL_FAILURE(assertPointerCoords(motionArgs.pointerCoords[0],
-            toDisplayX(x2), toDisplayY(y2), 1, 0, 0, 0, 0, 0, 0));
-    ASSERT_NEAR(X_PRECISION, motionArgs.xPrecision, EPSILON);
-    ASSERT_NEAR(Y_PRECISION, motionArgs.yPrecision, EPSILON);
-    ASSERT_EQ(ARBITRARY_TIME, motionArgs.downTime);
-
-    // Move.
-    x2 += 20; y2 -= 25;
-    processPosition(mapper, x2, y2);
-    processMTSync(mapper);
-    processSync(mapper);
-
-    ASSERT_NO_FATAL_FAILURE(mFakeDispatcher->assertNotifyMotionWasCalled(&motionArgs));
-    ASSERT_EQ(ARBITRARY_TIME, motionArgs.eventTime);
-    ASSERT_EQ(DEVICE_ID, motionArgs.deviceId);
-    ASSERT_EQ(AINPUT_SOURCE_TOUCHSCREEN, motionArgs.source);
-    ASSERT_EQ(uint32_t(0), motionArgs.policyFlags);
-    ASSERT_EQ(AMOTION_EVENT_ACTION_MOVE, motionArgs.action);
-    ASSERT_EQ(0, motionArgs.flags);
-    ASSERT_EQ(AMETA_SHIFT_LEFT_ON | AMETA_SHIFT_ON, motionArgs.metaState);
-    ASSERT_EQ(0, motionArgs.edgeFlags);
-    ASSERT_EQ(size_t(1), motionArgs.pointerCount);
-    ASSERT_EQ(1, motionArgs.pointerIds[0]);
-    ASSERT_NO_FATAL_FAILURE(assertPointerCoords(motionArgs.pointerCoords[0],
-            toDisplayX(x2), toDisplayY(y2), 1, 0, 0, 0, 0, 0, 0));
-    ASSERT_NEAR(X_PRECISION, motionArgs.xPrecision, EPSILON);
-    ASSERT_NEAR(Y_PRECISION, motionArgs.yPrecision, EPSILON);
-    ASSERT_EQ(ARBITRARY_TIME, motionArgs.downTime);
-
-    // New finger down.
-    int32_t x3 = 700, y3 = 300;
-    processPosition(mapper, x2, y2);
-    processMTSync(mapper);
-    processPosition(mapper, x3, y3);
-    processMTSync(mapper);
-    processSync(mapper);
-
-    ASSERT_NO_FATAL_FAILURE(mFakeDispatcher->assertNotifyMotionWasCalled(&motionArgs));
-    ASSERT_EQ(ARBITRARY_TIME, motionArgs.eventTime);
-    ASSERT_EQ(DEVICE_ID, motionArgs.deviceId);
-    ASSERT_EQ(AINPUT_SOURCE_TOUCHSCREEN, motionArgs.source);
-    ASSERT_EQ(uint32_t(0), motionArgs.policyFlags);
-    ASSERT_EQ(AMOTION_EVENT_ACTION_POINTER_DOWN | (0 << AMOTION_EVENT_ACTION_POINTER_INDEX_SHIFT),
-            motionArgs.action);
-    ASSERT_EQ(0, motionArgs.flags);
-    ASSERT_EQ(AMETA_SHIFT_LEFT_ON | AMETA_SHIFT_ON, motionArgs.metaState);
-    ASSERT_EQ(0, motionArgs.edgeFlags);
-    ASSERT_EQ(size_t(2), motionArgs.pointerCount);
-    ASSERT_EQ(0, motionArgs.pointerIds[0]);
-    ASSERT_EQ(1, motionArgs.pointerIds[1]);
-    ASSERT_NO_FATAL_FAILURE(assertPointerCoords(motionArgs.pointerCoords[0],
-            toDisplayX(x3), toDisplayY(y3), 1, 0, 0, 0, 0, 0, 0));
-    ASSERT_NO_FATAL_FAILURE(assertPointerCoords(motionArgs.pointerCoords[1],
-            toDisplayX(x2), toDisplayY(y2), 1, 0, 0, 0, 0, 0, 0));
-    ASSERT_NEAR(X_PRECISION, motionArgs.xPrecision, EPSILON);
-    ASSERT_NEAR(Y_PRECISION, motionArgs.yPrecision, EPSILON);
-    ASSERT_EQ(ARBITRARY_TIME, motionArgs.downTime);
-
-    // Second finger up.
-    x3 += 30; y3 -= 20;
-    processPosition(mapper, x3, y3);
-    processMTSync(mapper);
-    processSync(mapper);
-
-    ASSERT_NO_FATAL_FAILURE(mFakeDispatcher->assertNotifyMotionWasCalled(&motionArgs));
-    ASSERT_EQ(ARBITRARY_TIME, motionArgs.eventTime);
-    ASSERT_EQ(DEVICE_ID, motionArgs.deviceId);
-    ASSERT_EQ(AINPUT_SOURCE_TOUCHSCREEN, motionArgs.source);
-    ASSERT_EQ(uint32_t(0), motionArgs.policyFlags);
-    ASSERT_EQ(AMOTION_EVENT_ACTION_POINTER_UP | (1 << AMOTION_EVENT_ACTION_POINTER_INDEX_SHIFT),
-            motionArgs.action);
-    ASSERT_EQ(0, motionArgs.flags);
-    ASSERT_EQ(AMETA_SHIFT_LEFT_ON | AMETA_SHIFT_ON, motionArgs.metaState);
-    ASSERT_EQ(0, motionArgs.edgeFlags);
-    ASSERT_EQ(size_t(2), motionArgs.pointerCount);
-    ASSERT_EQ(0, motionArgs.pointerIds[0]);
-    ASSERT_EQ(1, motionArgs.pointerIds[1]);
-    ASSERT_NO_FATAL_FAILURE(assertPointerCoords(motionArgs.pointerCoords[0],
-            toDisplayX(x3), toDisplayY(y3), 1, 0, 0, 0, 0, 0, 0));
-    ASSERT_NO_FATAL_FAILURE(assertPointerCoords(motionArgs.pointerCoords[1],
-            toDisplayX(x2), toDisplayY(y2), 1, 0, 0, 0, 0, 0, 0));
-    ASSERT_NEAR(X_PRECISION, motionArgs.xPrecision, EPSILON);
-    ASSERT_NEAR(Y_PRECISION, motionArgs.yPrecision, EPSILON);
-    ASSERT_EQ(ARBITRARY_TIME, motionArgs.downTime);
-
-    ASSERT_NO_FATAL_FAILURE(mFakeDispatcher->assertNotifyMotionWasCalled(&motionArgs));
-    ASSERT_EQ(ARBITRARY_TIME, motionArgs.eventTime);
-    ASSERT_EQ(DEVICE_ID, motionArgs.deviceId);
-    ASSERT_EQ(AINPUT_SOURCE_TOUCHSCREEN, motionArgs.source);
-    ASSERT_EQ(uint32_t(0), motionArgs.policyFlags);
-    ASSERT_EQ(AMOTION_EVENT_ACTION_MOVE, motionArgs.action);
-    ASSERT_EQ(0, motionArgs.flags);
-    ASSERT_EQ(AMETA_SHIFT_LEFT_ON | AMETA_SHIFT_ON, motionArgs.metaState);
-    ASSERT_EQ(0, motionArgs.edgeFlags);
-    ASSERT_EQ(size_t(1), motionArgs.pointerCount);
-    ASSERT_EQ(0, motionArgs.pointerIds[0]);
-    ASSERT_NO_FATAL_FAILURE(assertPointerCoords(motionArgs.pointerCoords[0],
-            toDisplayX(x3), toDisplayY(y3), 1, 0, 0, 0, 0, 0, 0));
-    ASSERT_NEAR(X_PRECISION, motionArgs.xPrecision, EPSILON);
-    ASSERT_NEAR(Y_PRECISION, motionArgs.yPrecision, EPSILON);
-    ASSERT_EQ(ARBITRARY_TIME, motionArgs.downTime);
-
-    // Last finger up.
-    processMTSync(mapper);
-    processSync(mapper);
-
-    ASSERT_NO_FATAL_FAILURE(mFakeDispatcher->assertNotifyMotionWasCalled(&motionArgs));
-    ASSERT_EQ(ARBITRARY_TIME, motionArgs.eventTime);
-    ASSERT_EQ(DEVICE_ID, motionArgs.deviceId);
-    ASSERT_EQ(AINPUT_SOURCE_TOUCHSCREEN, motionArgs.source);
-    ASSERT_EQ(uint32_t(0), motionArgs.policyFlags);
-    ASSERT_EQ(AMOTION_EVENT_ACTION_UP, motionArgs.action);
-    ASSERT_EQ(0, motionArgs.flags);
-    ASSERT_EQ(AMETA_SHIFT_LEFT_ON | AMETA_SHIFT_ON, motionArgs.metaState);
-    ASSERT_EQ(0, motionArgs.edgeFlags);
-    ASSERT_EQ(size_t(1), motionArgs.pointerCount);
-    ASSERT_EQ(0, motionArgs.pointerIds[0]);
-    ASSERT_NO_FATAL_FAILURE(assertPointerCoords(motionArgs.pointerCoords[0],
-            toDisplayX(x3), toDisplayY(y3), 1, 0, 0, 0, 0, 0, 0));
-    ASSERT_NEAR(X_PRECISION, motionArgs.xPrecision, EPSILON);
-    ASSERT_NEAR(Y_PRECISION, motionArgs.yPrecision, EPSILON);
-    ASSERT_EQ(ARBITRARY_TIME, motionArgs.downTime);
-
-    // Should not have sent any more keys or motions.
-    ASSERT_NO_FATAL_FAILURE(mFakeDispatcher->assertNotifyKeyWasNotCalled());
-    ASSERT_NO_FATAL_FAILURE(mFakeDispatcher->assertNotifyMotionWasNotCalled());
-}
-
-TEST_F(MultiTouchInputMapperTest, Process_NormalMultiTouchGesture_WithTrackingIds) {
-    MultiTouchInputMapper* mapper = new MultiTouchInputMapper(mDevice);
-    prepareDisplay(InputReaderPolicyInterface::ROTATION_0);
-    prepareAxes(POSITION | ID);
-    prepareVirtualKeys();
-    addMapperAndConfigure(mapper);
-
-    mFakeContext->setGlobalMetaState(AMETA_SHIFT_LEFT_ON | AMETA_SHIFT_ON);
-
-    FakeInputDispatcher::NotifyMotionArgs motionArgs;
-
-    // Two fingers down at once.
-    int32_t x1 = 100, y1 = 125, x2 = 300, y2 = 500;
-    processPosition(mapper, x1, y1);
-    processId(mapper, 1);
-    processMTSync(mapper);
-    processPosition(mapper, x2, y2);
-    processId(mapper, 2);
-    processMTSync(mapper);
-    processSync(mapper);
-
-    ASSERT_NO_FATAL_FAILURE(mFakeDispatcher->assertNotifyMotionWasCalled(&motionArgs));
-    ASSERT_EQ(AMOTION_EVENT_ACTION_DOWN, motionArgs.action);
-    ASSERT_EQ(size_t(1), motionArgs.pointerCount);
-    ASSERT_EQ(1, motionArgs.pointerIds[0]);
-    ASSERT_NO_FATAL_FAILURE(assertPointerCoords(motionArgs.pointerCoords[0],
-            toDisplayX(x1), toDisplayY(y1), 1, 0, 0, 0, 0, 0, 0));
-
-    ASSERT_NO_FATAL_FAILURE(mFakeDispatcher->assertNotifyMotionWasCalled(&motionArgs));
-    ASSERT_EQ(AMOTION_EVENT_ACTION_POINTER_DOWN | (1 << AMOTION_EVENT_ACTION_POINTER_INDEX_SHIFT),
-            motionArgs.action);
-    ASSERT_EQ(size_t(2), motionArgs.pointerCount);
-    ASSERT_EQ(1, motionArgs.pointerIds[0]);
-    ASSERT_EQ(2, motionArgs.pointerIds[1]);
-    ASSERT_NO_FATAL_FAILURE(assertPointerCoords(motionArgs.pointerCoords[0],
-            toDisplayX(x1), toDisplayY(y1), 1, 0, 0, 0, 0, 0, 0));
-    ASSERT_NO_FATAL_FAILURE(assertPointerCoords(motionArgs.pointerCoords[1],
-            toDisplayX(x2), toDisplayY(y2), 1, 0, 0, 0, 0, 0, 0));
-
-    // Move.
-    x1 += 10; y1 += 15; x2 += 5; y2 -= 10;
-    processPosition(mapper, x1, y1);
-    processId(mapper, 1);
-    processMTSync(mapper);
-    processPosition(mapper, x2, y2);
-    processId(mapper, 2);
-    processMTSync(mapper);
-    processSync(mapper);
-
-    ASSERT_NO_FATAL_FAILURE(mFakeDispatcher->assertNotifyMotionWasCalled(&motionArgs));
-    ASSERT_EQ(AMOTION_EVENT_ACTION_MOVE, motionArgs.action);
-    ASSERT_EQ(size_t(2), motionArgs.pointerCount);
-    ASSERT_EQ(1, motionArgs.pointerIds[0]);
-    ASSERT_EQ(2, motionArgs.pointerIds[1]);
-    ASSERT_NO_FATAL_FAILURE(assertPointerCoords(motionArgs.pointerCoords[0],
-            toDisplayX(x1), toDisplayY(y1), 1, 0, 0, 0, 0, 0, 0));
-    ASSERT_NO_FATAL_FAILURE(assertPointerCoords(motionArgs.pointerCoords[1],
-            toDisplayX(x2), toDisplayY(y2), 1, 0, 0, 0, 0, 0, 0));
-
-    // First finger up.
-    x2 += 15; y2 -= 20;
-    processPosition(mapper, x2, y2);
-    processId(mapper, 2);
-    processMTSync(mapper);
-    processSync(mapper);
-
-    ASSERT_NO_FATAL_FAILURE(mFakeDispatcher->assertNotifyMotionWasCalled(&motionArgs));
-    ASSERT_EQ(AMOTION_EVENT_ACTION_POINTER_UP | (0 << AMOTION_EVENT_ACTION_POINTER_INDEX_SHIFT),
-            motionArgs.action);
-    ASSERT_EQ(size_t(2), motionArgs.pointerCount);
-    ASSERT_EQ(1, motionArgs.pointerIds[0]);
-    ASSERT_EQ(2, motionArgs.pointerIds[1]);
-    ASSERT_NO_FATAL_FAILURE(assertPointerCoords(motionArgs.pointerCoords[0],
-            toDisplayX(x1), toDisplayY(y1), 1, 0, 0, 0, 0, 0, 0));
-    ASSERT_NO_FATAL_FAILURE(assertPointerCoords(motionArgs.pointerCoords[1],
-            toDisplayX(x2), toDisplayY(y2), 1, 0, 0, 0, 0, 0, 0));
-
-    ASSERT_NO_FATAL_FAILURE(mFakeDispatcher->assertNotifyMotionWasCalled(&motionArgs));
-    ASSERT_EQ(AMOTION_EVENT_ACTION_MOVE, motionArgs.action);
-    ASSERT_EQ(size_t(1), motionArgs.pointerCount);
-    ASSERT_EQ(2, motionArgs.pointerIds[0]);
-    ASSERT_NO_FATAL_FAILURE(assertPointerCoords(motionArgs.pointerCoords[0],
-            toDisplayX(x2), toDisplayY(y2), 1, 0, 0, 0, 0, 0, 0));
-
-    // Move.
-    x2 += 20; y2 -= 25;
-    processPosition(mapper, x2, y2);
-    processId(mapper, 2);
-    processMTSync(mapper);
-    processSync(mapper);
-
-    ASSERT_NO_FATAL_FAILURE(mFakeDispatcher->assertNotifyMotionWasCalled(&motionArgs));
-    ASSERT_EQ(AMOTION_EVENT_ACTION_MOVE, motionArgs.action);
-    ASSERT_EQ(size_t(1), motionArgs.pointerCount);
-    ASSERT_EQ(2, motionArgs.pointerIds[0]);
-    ASSERT_NO_FATAL_FAILURE(assertPointerCoords(motionArgs.pointerCoords[0],
-            toDisplayX(x2), toDisplayY(y2), 1, 0, 0, 0, 0, 0, 0));
-
-    // New finger down.
-    int32_t x3 = 700, y3 = 300;
-    processPosition(mapper, x2, y2);
-    processId(mapper, 2);
-    processMTSync(mapper);
-    processPosition(mapper, x3, y3);
-    processId(mapper, 3);
-    processMTSync(mapper);
-    processSync(mapper);
-
-    ASSERT_NO_FATAL_FAILURE(mFakeDispatcher->assertNotifyMotionWasCalled(&motionArgs));
-    ASSERT_EQ(AMOTION_EVENT_ACTION_POINTER_DOWN | (1 << AMOTION_EVENT_ACTION_POINTER_INDEX_SHIFT),
-            motionArgs.action);
-    ASSERT_EQ(size_t(2), motionArgs.pointerCount);
-    ASSERT_EQ(2, motionArgs.pointerIds[0]);
-    ASSERT_EQ(3, motionArgs.pointerIds[1]);
-    ASSERT_NO_FATAL_FAILURE(assertPointerCoords(motionArgs.pointerCoords[0],
-            toDisplayX(x2), toDisplayY(y2), 1, 0, 0, 0, 0, 0, 0));
-    ASSERT_NO_FATAL_FAILURE(assertPointerCoords(motionArgs.pointerCoords[1],
-            toDisplayX(x3), toDisplayY(y3), 1, 0, 0, 0, 0, 0, 0));
-
-    // Second finger up.
-    x3 += 30; y3 -= 20;
-    processPosition(mapper, x3, y3);
-    processId(mapper, 3);
-    processMTSync(mapper);
-    processSync(mapper);
-
-    ASSERT_NO_FATAL_FAILURE(mFakeDispatcher->assertNotifyMotionWasCalled(&motionArgs));
-    ASSERT_EQ(AMOTION_EVENT_ACTION_POINTER_UP | (0 << AMOTION_EVENT_ACTION_POINTER_INDEX_SHIFT),
-            motionArgs.action);
-    ASSERT_EQ(size_t(2), motionArgs.pointerCount);
-    ASSERT_EQ(2, motionArgs.pointerIds[0]);
-    ASSERT_EQ(3, motionArgs.pointerIds[1]);
-    ASSERT_NO_FATAL_FAILURE(assertPointerCoords(motionArgs.pointerCoords[0],
-            toDisplayX(x2), toDisplayY(y2), 1, 0, 0, 0, 0, 0, 0));
-    ASSERT_NO_FATAL_FAILURE(assertPointerCoords(motionArgs.pointerCoords[1],
-            toDisplayX(x3), toDisplayY(y3), 1, 0, 0, 0, 0, 0, 0));
-
-    ASSERT_NO_FATAL_FAILURE(mFakeDispatcher->assertNotifyMotionWasCalled(&motionArgs));
-    ASSERT_EQ(AMOTION_EVENT_ACTION_MOVE, motionArgs.action);
-    ASSERT_EQ(size_t(1), motionArgs.pointerCount);
-    ASSERT_EQ(3, motionArgs.pointerIds[0]);
-    ASSERT_NO_FATAL_FAILURE(assertPointerCoords(motionArgs.pointerCoords[0],
-            toDisplayX(x3), toDisplayY(y3), 1, 0, 0, 0, 0, 0, 0));
-
-    // Last finger up.
-    processMTSync(mapper);
-    processSync(mapper);
-
-    ASSERT_NO_FATAL_FAILURE(mFakeDispatcher->assertNotifyMotionWasCalled(&motionArgs));
-    ASSERT_EQ(AMOTION_EVENT_ACTION_UP, motionArgs.action);
-    ASSERT_EQ(size_t(1), motionArgs.pointerCount);
-    ASSERT_EQ(3, motionArgs.pointerIds[0]);
-    ASSERT_NO_FATAL_FAILURE(assertPointerCoords(motionArgs.pointerCoords[0],
-            toDisplayX(x3), toDisplayY(y3), 1, 0, 0, 0, 0, 0, 0));
-
-    // Should not have sent any more keys or motions.
-    ASSERT_NO_FATAL_FAILURE(mFakeDispatcher->assertNotifyKeyWasNotCalled());
-    ASSERT_NO_FATAL_FAILURE(mFakeDispatcher->assertNotifyMotionWasNotCalled());
-}
-
-TEST_F(MultiTouchInputMapperTest, Process_AllAxes_WithDefaultCalibration) {
-    MultiTouchInputMapper* mapper = new MultiTouchInputMapper(mDevice);
-    prepareDisplay(InputReaderPolicyInterface::ROTATION_0);
-    prepareAxes(POSITION | TOUCH | TOOL | PRESSURE | ORIENTATION | ID | MINOR);
-    addMapperAndConfigure(mapper);
-
-    // These calculations are based on the input device calibration documentation.
-    int32_t rawX = 100;
-    int32_t rawY = 200;
-    int32_t rawTouchMajor = 7;
-    int32_t rawTouchMinor = 6;
-    int32_t rawToolMajor = 9;
-    int32_t rawToolMinor = 8;
-    int32_t rawPressure = 11;
-    int32_t rawOrientation = 3;
-    int32_t id = 5;
-
-    float x = toDisplayX(rawX);
-    float y = toDisplayY(rawY);
-    float pressure = float(rawPressure) / RAW_PRESSURE_MAX;
-    float size = avg(rawToolMajor, rawToolMinor) / RAW_TOOL_MAX;
-    float toolMajor = float(min(DISPLAY_WIDTH, DISPLAY_HEIGHT)) * rawToolMajor / RAW_TOOL_MAX;
-    float toolMinor = float(min(DISPLAY_WIDTH, DISPLAY_HEIGHT)) * rawToolMinor / RAW_TOOL_MAX;
-    float touchMajor = min(toolMajor * pressure, toolMajor);
-    float touchMinor = min(toolMinor * pressure, toolMinor);
-    float orientation = float(rawOrientation) / RAW_ORIENTATION_MAX * M_PI_2;
-
-    processPosition(mapper, rawX, rawY);
-    processTouchMajor(mapper, rawTouchMajor);
-    processTouchMinor(mapper, rawTouchMinor);
-    processToolMajor(mapper, rawToolMajor);
-    processToolMinor(mapper, rawToolMinor);
-    processPressure(mapper, rawPressure);
-    processOrientation(mapper, rawOrientation);
-    processId(mapper, id);
-    processMTSync(mapper);
-    processSync(mapper);
-
-    FakeInputDispatcher::NotifyMotionArgs args;
-    ASSERT_NO_FATAL_FAILURE(mFakeDispatcher->assertNotifyMotionWasCalled(&args));
-    ASSERT_EQ(id, args.pointerIds[0]);
-    ASSERT_NO_FATAL_FAILURE(assertPointerCoords(args.pointerCoords[0],
-            x, y, pressure, size, touchMajor, touchMinor, toolMajor, toolMinor, orientation));
-}
-
-TEST_F(MultiTouchInputMapperTest, Process_TouchAndToolAxes_GeometricCalibration) {
-    MultiTouchInputMapper* mapper = new MultiTouchInputMapper(mDevice);
-    prepareDisplay(InputReaderPolicyInterface::ROTATION_0);
-    prepareAxes(POSITION | TOUCH | TOOL | MINOR);
-    addConfigurationProperty("touch.touchSize.calibration", "geometric");
-    addConfigurationProperty("touch.toolSize.calibration", "geometric");
-    addMapperAndConfigure(mapper);
-
-    // These calculations are based on the input device calibration documentation.
-    int32_t rawX = 100;
-    int32_t rawY = 200;
-    int32_t rawTouchMajor = 140;
-    int32_t rawTouchMinor = 120;
-    int32_t rawToolMajor = 180;
-    int32_t rawToolMinor = 160;
-
-    float x = toDisplayX(rawX);
-    float y = toDisplayY(rawY);
-    float pressure = float(rawTouchMajor) / RAW_TOUCH_MAX;
-    float size = avg(rawToolMajor, rawToolMinor) / RAW_TOOL_MAX;
-    float scale = avg(float(DISPLAY_WIDTH) / (RAW_X_MAX - RAW_X_MIN),
-            float(DISPLAY_HEIGHT) / (RAW_Y_MAX - RAW_Y_MIN));
-    float toolMajor = float(rawToolMajor) * scale;
-    float toolMinor = float(rawToolMinor) * scale;
-    float touchMajor = min(float(rawTouchMajor) * scale, toolMajor);
-    float touchMinor = min(float(rawTouchMinor) * scale, toolMinor);
-
-    processPosition(mapper, rawX, rawY);
-    processTouchMajor(mapper, rawTouchMajor);
-    processTouchMinor(mapper, rawTouchMinor);
-    processToolMajor(mapper, rawToolMajor);
-    processToolMinor(mapper, rawToolMinor);
-    processMTSync(mapper);
-    processSync(mapper);
-
-    FakeInputDispatcher::NotifyMotionArgs args;
-    ASSERT_NO_FATAL_FAILURE(mFakeDispatcher->assertNotifyMotionWasCalled(&args));
-    ASSERT_NO_FATAL_FAILURE(assertPointerCoords(args.pointerCoords[0],
-            x, y, pressure, size, touchMajor, touchMinor, toolMajor, toolMinor, 0));
-}
-
-TEST_F(MultiTouchInputMapperTest, Process_TouchToolPressureSizeAxes_SummedLinearCalibration) {
-    MultiTouchInputMapper* mapper = new MultiTouchInputMapper(mDevice);
-    prepareDisplay(InputReaderPolicyInterface::ROTATION_0);
-    prepareAxes(POSITION | TOUCH | TOOL);
-    addConfigurationProperty("touch.touchSize.calibration", "pressure");
-    addConfigurationProperty("touch.toolSize.calibration", "linear");
-    addConfigurationProperty("touch.toolSize.linearScale", "10");
-    addConfigurationProperty("touch.toolSize.linearBias", "160");
-    addConfigurationProperty("touch.toolSize.isSummed", "1");
-    addConfigurationProperty("touch.pressure.calibration", "amplitude");
-    addConfigurationProperty("touch.pressure.source", "touch");
-    addConfigurationProperty("touch.pressure.scale", "0.01");
-    addMapperAndConfigure(mapper);
-
-    // These calculations are based on the input device calibration documentation.
-    // Note: We only provide a single common touch/tool value because the device is assumed
-    //       not to emit separate values for each pointer (isSummed = 1).
-    int32_t rawX = 100;
-    int32_t rawY = 200;
-    int32_t rawX2 = 150;
-    int32_t rawY2 = 250;
-    int32_t rawTouchMajor = 60;
-    int32_t rawToolMajor = 5;
-
-    float x = toDisplayX(rawX);
-    float y = toDisplayY(rawY);
-    float x2 = toDisplayX(rawX2);
-    float y2 = toDisplayY(rawY2);
-    float pressure = float(rawTouchMajor) * 0.01f;
-    float size = float(rawToolMajor) / RAW_TOOL_MAX;
-    float tool = (float(rawToolMajor) * 10.0f + 160.0f) / 2;
-    float touch = min(tool * pressure, tool);
-
-    processPosition(mapper, rawX, rawY);
-    processTouchMajor(mapper, rawTouchMajor);
-    processToolMajor(mapper, rawToolMajor);
-    processMTSync(mapper);
-    processPosition(mapper, rawX2, rawY2);
-    processTouchMajor(mapper, rawTouchMajor);
-    processToolMajor(mapper, rawToolMajor);
-    processMTSync(mapper);
-    processSync(mapper);
-
-    FakeInputDispatcher::NotifyMotionArgs args;
-    ASSERT_NO_FATAL_FAILURE(mFakeDispatcher->assertNotifyMotionWasCalled(&args));
-    ASSERT_EQ(AMOTION_EVENT_ACTION_DOWN, args.action);
-    ASSERT_NO_FATAL_FAILURE(mFakeDispatcher->assertNotifyMotionWasCalled(&args));
-    ASSERT_EQ(AMOTION_EVENT_ACTION_POINTER_DOWN | (1 << AMOTION_EVENT_ACTION_POINTER_INDEX_SHIFT),
-            args.action);
-    ASSERT_EQ(size_t(2), args.pointerCount);
-    ASSERT_NO_FATAL_FAILURE(assertPointerCoords(args.pointerCoords[0],
-            x, y, pressure, size, touch, touch, tool, tool, 0));
-    ASSERT_NO_FATAL_FAILURE(assertPointerCoords(args.pointerCoords[1],
-            x2, y2, pressure, size, touch, touch, tool, tool, 0));
-}
-
-TEST_F(MultiTouchInputMapperTest, Process_TouchToolPressureSizeAxes_AreaCalibration) {
-    MultiTouchInputMapper* mapper = new MultiTouchInputMapper(mDevice);
-    prepareDisplay(InputReaderPolicyInterface::ROTATION_0);
-    prepareAxes(POSITION | TOUCH | TOOL);
-    addConfigurationProperty("touch.touchSize.calibration", "pressure");
-    addConfigurationProperty("touch.toolSize.calibration", "area");
-    addConfigurationProperty("touch.toolSize.areaScale", "22");
-    addConfigurationProperty("touch.toolSize.areaBias", "1");
-    addConfigurationProperty("touch.toolSize.linearScale", "9.2");
-    addConfigurationProperty("touch.toolSize.linearBias", "3");
-    addConfigurationProperty("touch.pressure.calibration", "amplitude");
-    addConfigurationProperty("touch.pressure.source", "touch");
-    addConfigurationProperty("touch.pressure.scale", "0.01");
-    addMapperAndConfigure(mapper);
-
-    // These calculations are based on the input device calibration documentation.
-    int32_t rawX = 100;
-    int32_t rawY = 200;
-    int32_t rawTouchMajor = 60;
-    int32_t rawToolMajor = 5;
-
-    float x = toDisplayX(rawX);
-    float y = toDisplayY(rawY);
-    float pressure = float(rawTouchMajor) * 0.01f;
-    float size = float(rawToolMajor) / RAW_TOOL_MAX;
-    float tool = sqrtf(float(rawToolMajor) * 22.0f + 1.0f) * 9.2f + 3.0f;
-    float touch = min(tool * pressure, tool);
-
-    processPosition(mapper, rawX, rawY);
-    processTouchMajor(mapper, rawTouchMajor);
-    processToolMajor(mapper, rawToolMajor);
-    processMTSync(mapper);
-    processSync(mapper);
-
-    FakeInputDispatcher::NotifyMotionArgs args;
-    ASSERT_NO_FATAL_FAILURE(mFakeDispatcher->assertNotifyMotionWasCalled(&args));
-    ASSERT_NO_FATAL_FAILURE(assertPointerCoords(args.pointerCoords[0],
-            x, y, pressure, size, touch, touch, tool, tool, 0));
-}
-
-} // namespace android
diff --git a/libs/utils/PropertyMap.cpp b/libs/utils/PropertyMap.cpp
index fd7edec..d472d45 100644
--- a/libs/utils/PropertyMap.cpp
+++ b/libs/utils/PropertyMap.cpp
@@ -109,6 +109,12 @@
     return true;
 }
 
+void PropertyMap::addAll(const PropertyMap* map) {
+    for (size_t i = 0; i < map->mProperties.size(); i++) {
+        mProperties.add(map->mProperties.keyAt(i), map->mProperties.valueAt(i));
+    }
+}
+
 status_t PropertyMap::load(const String8& filename, PropertyMap** outMap) {
     *outMap = NULL;
 
diff --git a/libs/utils/Threads.cpp b/libs/utils/Threads.cpp
index f6c55e4..ad9a94f 100644
--- a/libs/utils/Threads.cpp
+++ b/libs/utils/Threads.cpp
@@ -774,6 +774,9 @@
             self->mExitPending = true;
             self->mLock.lock();
             self->mRunning = false;
+            // clear thread ID so that requestExitAndWait() does not exit if
+            // called by a new thread using the same thread ID as this one.
+            self->mThread = thread_id_t(-1);
             self->mThreadExitedCondition.broadcast();
             self->mLock.unlock();
             break;
diff --git a/opengl/libs/EGL/egl.cpp b/opengl/libs/EGL/egl.cpp
index 7acce02..386cc5d 100644
--- a/opengl/libs/EGL/egl.cpp
+++ b/opengl/libs/EGL/egl.cpp
@@ -895,7 +895,7 @@
     dp->refs--;
     dp->numTotalConfigs = 0;
     delete [] dp->configs;
-    clearTLS();
+
     return res;
 }
 
@@ -1231,6 +1231,27 @@
     return result;
 }
 
+static void loseCurrent(egl_context_t * cur_c)
+{
+    if (cur_c) {
+        egl_surface_t * cur_r = get_surface(cur_c->read);
+        egl_surface_t * cur_d = get_surface(cur_c->draw);
+
+        // by construction, these are either 0 or valid (possibly terminated)
+        // it should be impossible for these to be invalid
+        ContextRef _cur_c(cur_c);
+        SurfaceRef _cur_r(cur_r);
+        SurfaceRef _cur_d(cur_d);
+
+        cur_c->read = NULL;
+        cur_c->draw = NULL;
+
+        _cur_c.release();
+        _cur_r.release();
+        _cur_d.release();
+    }
+}
+
 EGLBoolean eglMakeCurrent(  EGLDisplay dpy, EGLSurface draw,
                             EGLSurface read, EGLContext ctx)
 {
@@ -1259,13 +1280,9 @@
 
     // these are the current objects structs
     egl_context_t * cur_c = get_context(getContext());
-    egl_surface_t * cur_r = NULL;
-    egl_surface_t * cur_d = NULL;
     
     if (ctx != EGL_NO_CONTEXT) {
         c = get_context(ctx);
-        cur_r = get_surface(c->read);
-        cur_d = get_surface(c->draw);
         impl_ctx = c->context;
     } else {
         // no context given, use the implementation of the current context
@@ -1311,30 +1328,21 @@
     }
 
     if (result == EGL_TRUE) {
-        // by construction, these are either 0 or valid (possibly terminated)
-        // it should be impossible for these to be invalid
-        ContextRef _cur_c(cur_c);
-        SurfaceRef _cur_r(cur_r);
-        SurfaceRef _cur_d(cur_d);
 
-        // cur_c has to be valid here (but could be terminated)
+        loseCurrent(cur_c);
+
         if (ctx != EGL_NO_CONTEXT) {
             setGLHooksThreadSpecific(c->cnx->hooks[c->version]);
             setContext(ctx);
             _c.acquire();
+            _r.acquire();
+            _d.acquire();
+            c->read = read;
+            c->draw = draw;
         } else {
             setGLHooksThreadSpecific(&gHooksNoContext);
             setContext(EGL_NO_CONTEXT);
         }
-        _cur_c.release();
-
-        _r.acquire();
-        _cur_r.release();
-        if (c) c->read = read;
-
-        _d.acquire();
-        _cur_d.release();
-        if (c) c->draw = draw;
     }
     return result;
 }
@@ -1721,6 +1729,9 @@
 
 EGLBoolean eglReleaseThread(void)
 {
+    // If there is context bound to the thread, release it
+    loseCurrent(get_context(getContext()));
+
     for (int i=0 ; i<IMPL_NUM_IMPLEMENTATIONS ; i++) {
         egl_connection_t* const cnx = &gEGLImpl[i];
         if (cnx->dso) {
diff --git a/opengl/tests/hwc/Android.mk b/opengl/tests/hwc/Android.mk
index 743dbf1..6312970 100644
--- a/opengl/tests/hwc/Android.mk
+++ b/opengl/tests/hwc/Android.mk
@@ -1,7 +1,40 @@
+# Copyright (C) 2010 The Android Open Source Project
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+#      http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+
 LOCAL_PATH:= $(call my-dir)
 
 include $(CLEAR_VARS)
-LOCAL_SRC_FILES:= hwc_stress.cpp
+LOCAL_MODULE_TAGS := tests
+LOCAL_MODULE:= libhwcTest
+LOCAL_SRC_FILES:= hwcTestLib.cpp
+LOCAL_C_INCLUDES += system/extras/tests/include \
+    bionic \
+    bionic/libstdc++/include \
+    external/stlport/stlport \
+    frameworks/base/opengl/tests \
+    frameworks/base/opengl/tests/include \
+
+LOCAL_CFLAGS := -DGL_GLEXT_PROTOTYPES -DEGL_EGLEXT_PROTOTYPES
+
+LOCAL_SHARED_LIBRARIES += libcutils libutils libstlport
+LOCAL_STATIC_LIBRARIES += libglTest
+LOCAL_PRELINK_MODULE := false
+
+include $(BUILD_STATIC_LIBRARY)
+
+include $(CLEAR_VARS)
+LOCAL_SRC_FILES:= hwcStress.cpp
 
 LOCAL_SHARED_LIBRARIES := \
     libcutils \
@@ -12,12 +45,18 @@
 
 LOCAL_STATIC_LIBRARIES := \
     libtestUtil \
+    libglTest \
+    libhwcTest \
 
 LOCAL_C_INCLUDES += \
     system/extras/tests/include \
     hardware/libhardware/include \
+    frameworks/base/opengl/tests \
+    frameworks/base/opengl/tests/include \
 
-LOCAL_MODULE:= hwc_stress
+LOCAL_CFLAGS := -DGL_GLEXT_PROTOTYPES -DEGL_EGLEXT_PROTOTYPES
+
+LOCAL_MODULE:= hwcStress
 LOCAL_MODULE_PATH := $(TARGET_OUT_DATA)/nativestresstest
 
 LOCAL_MODULE_TAGS := tests
@@ -25,3 +64,93 @@
 LOCAL_CFLAGS := -DGL_GLEXT_PROTOTYPES -DEGL_EGLEXT_PROTOTYPES
 
 include $(BUILD_NATIVE_TEST)
+
+include $(CLEAR_VARS)
+LOCAL_SRC_FILES:= hwcRects.cpp
+
+LOCAL_SHARED_LIBRARIES := \
+    libcutils \
+    libEGL \
+    libGLESv2 \
+    libui \
+    libhardware \
+
+LOCAL_STATIC_LIBRARIES := \
+    libtestUtil \
+    libglTest \
+    libhwcTest \
+
+LOCAL_C_INCLUDES += \
+    system/extras/tests/include \
+    hardware/libhardware/include \
+    frameworks/base/opengl/tests \
+    frameworks/base/opengl/tests/include \
+
+LOCAL_MODULE:= hwcRects
+LOCAL_MODULE_PATH := $(TARGET_OUT_DATA)/nativeutil
+
+LOCAL_MODULE_TAGS := tests
+
+LOCAL_CFLAGS := -DGL_GLEXT_PROTOTYPES -DEGL_EGLEXT_PROTOTYPES
+
+include $(BUILD_NATIVE_TEST)
+
+include $(CLEAR_VARS)
+LOCAL_SRC_FILES:= hwcColorEquiv.cpp
+
+LOCAL_SHARED_LIBRARIES := \
+    libcutils \
+    libEGL \
+    libGLESv2 \
+    libui \
+    libhardware \
+
+LOCAL_STATIC_LIBRARIES := \
+    libtestUtil \
+    libglTest \
+    libhwcTest \
+
+LOCAL_C_INCLUDES += \
+    system/extras/tests/include \
+    hardware/libhardware/include \
+    frameworks/base/opengl/tests \
+    frameworks/base/opengl/tests/include \
+
+LOCAL_MODULE:= hwcColorEquiv
+LOCAL_MODULE_PATH := $(TARGET_OUT_DATA)/nativeutil
+
+LOCAL_MODULE_TAGS := tests
+
+LOCAL_CFLAGS := -DGL_GLEXT_PROTOTYPES -DEGL_EGLEXT_PROTOTYPES
+
+include $(BUILD_NATIVE_TEST)
+
+include $(CLEAR_VARS)
+LOCAL_SRC_FILES:= hwcCommit.cpp
+
+LOCAL_SHARED_LIBRARIES := \
+    libcutils \
+    libEGL \
+    libGLESv2 \
+    libui \
+    libhardware \
+
+LOCAL_STATIC_LIBRARIES := \
+    libtestUtil \
+    libglTest \
+    libhwcTest \
+
+LOCAL_C_INCLUDES += \
+    system/extras/tests/include \
+    hardware/libhardware/include \
+    frameworks/base/opengl/tests \
+    frameworks/base/opengl/tests/include \
+
+LOCAL_MODULE:= hwcCommit
+LOCAL_MODULE_PATH := $(TARGET_OUT_DATA)/nativebenchmark
+
+LOCAL_MODULE_TAGS := tests
+
+LOCAL_CFLAGS := -DGL_GLEXT_PROTOTYPES -DEGL_EGLEXT_PROTOTYPES
+
+include $(BUILD_NATIVE_TEST)
diff --git a/opengl/tests/hwc/hwcColorEquiv.cpp b/opengl/tests/hwc/hwcColorEquiv.cpp
new file mode 100644
index 0000000..1d03948
--- /dev/null
+++ b/opengl/tests/hwc/hwcColorEquiv.cpp
@@ -0,0 +1,438 @@
+/*
+ * Copyright (C) 2011 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+/*
+ * Hardware Composer Color Equivalence
+ *
+ * Synopsis
+ *   hwc_colorequiv [options] eFmt
+ *
+ *     options:
+         -v - verbose
+ *       -s <0.##, 0.##, 0.##> - Start color (default: <0.0, 0.0, 0.0>
+ *       -e <0.##, 0.##, 0.##> - Ending color (default: <1.0, 1.0, 1.0>
+ *       -r fmt - reference graphic format
+ *       -D #.## - End of test delay
+ *
+ *     graphic formats:
+ *       RGBA8888 (reference frame default)
+ *       RGBX8888
+ *       RGB888
+ *       RGB565
+ *       BGRA8888
+ *       RGBA5551
+ *       RGBA4444
+ *       YV12
+ *
+ * Description
+ *   Renders a horizontal blend in two frames.  The first frame is rendered
+ *   in the upper third of the display and is called the reference frame.
+ *   The second frame is displayed in the middle third and is called the
+ *   equivalence frame.  The primary purpose of this utility is to verify
+ *   that the colors produced in the reference and equivalence frames are
+ *   the same.  The colors are the same when the colors are the same
+ *   vertically between the reference and equivalence frames.
+ *
+ *   By default the reference frame is rendered through the use of the
+ *   RGBA8888 graphic format.  The -r option can be used to specify a
+ *   non-default reference frame graphic format.  The graphic format of
+ *   the equivalence frame is determined by a single required positional
+ *   parameter.  Intentionally there is no default for the graphic format
+ *   of the equivalence frame.
+ *
+ *   The horizontal blend in the reference frame is produced from a linear
+ *   interpolation from a start color (default: <0.0, 0.0, 0.0> on the left
+ *   side to an end color (default <1.0, 1.0, 1.0> on the right side.  Where
+ *   possible the equivalence frame is rendered with the equivalent color
+ *   from the reference frame.  A color of black is used in the equivalence
+ *   frame for cases where an equivalent color does not exist.
+ */
+
+#include <algorithm>
+#include <assert.h>
+#include <cerrno>
+#include <cmath>
+#include <cstdlib>
+#include <ctime>
+#include <libgen.h>
+#include <sched.h>
+#include <sstream>
+#include <stdint.h>
+#include <string.h>
+#include <unistd.h>
+#include <vector>
+
+#include <sys/syscall.h>
+#include <sys/types.h>
+#include <sys/wait.h>
+
+#include <EGL/egl.h>
+#include <EGL/eglext.h>
+#include <GLES2/gl2.h>
+#include <GLES2/gl2ext.h>
+
+#include <ui/FramebufferNativeWindow.h>
+#include <ui/GraphicBuffer.h>
+#include <ui/EGLUtils.h>
+
+#define LOG_TAG "hwcColorEquivTest"
+#include <utils/Log.h>
+#include <testUtil.h>
+
+#include <hardware/hwcomposer.h>
+
+#include "hwcTestLib.h"
+
+using namespace std;
+using namespace android;
+
+// Defaults for command-line options
+const bool defaultVerbose = false;
+const ColorFract defaultStartColor(0.0, 0.0, 0.0);
+const ColorFract defaultEndColor(1.0, 1.0, 1.0);
+const char *defaultRefFormat = "RGBA8888";
+const float defaultEndDelay = 2.0; // Default delay after rendering graphics
+
+// Defines
+#define MAXSTR               100
+#define MAXCMD               200
+#define BITSPERBYTE            8 // TODO: Obtain from <values.h>, once
+                                 // it has been added
+
+#define CMD_STOP_FRAMEWORK   "stop 2>&1"
+#define CMD_START_FRAMEWORK  "start 2>&1"
+
+// Macros
+#define NUMA(a) (sizeof(a) / sizeof(a [0])) // Num elements in an array
+#define MEMCLR(addr, size) do { \
+        memset((addr), 0, (size)); \
+    } while (0)
+
+// Globals
+static const int texUsage = GraphicBuffer::USAGE_HW_TEXTURE |
+        GraphicBuffer::USAGE_SW_WRITE_RARELY;
+static hwc_composer_device_t *hwcDevice;
+static EGLDisplay dpy;
+static EGLSurface surface;
+static EGLint width, height;
+
+// Functions prototypes
+void init(void);
+void printSyntax(const char *cmd);
+
+// Command-line option settings
+static bool verbose = defaultVerbose;
+static ColorFract startRefColor = defaultStartColor;
+static ColorFract endRefColor = defaultEndColor;
+static float endDelay = defaultEndDelay;
+static const struct hwcTestGraphicFormat *refFormat
+    = hwcTestGraphicFormatLookup(defaultRefFormat);
+static const struct hwcTestGraphicFormat *equivFormat;
+
+/*
+ * Main
+ *
+ * Performs the following high-level sequence of operations:
+ *
+ *   1. Command-line parsing
+ *
+ *   2. Stop framework
+ *
+ *   3. Initialization
+ *
+ *   4. Create Hardware Composer description of reference and equivalence frames
+ *
+ *   5. Have Hardware Composer render the reference and equivalence frames
+ *
+ *   6. Delay for amount of time given by endDelay
+ *
+ *   7. Start framework
+ */
+int
+main(int argc, char *argv[])
+{
+    int rv, opt;
+    bool error;
+    char *chptr;
+    unsigned int pass;
+    char cmd[MAXCMD];
+    string str;
+
+    testSetLogCatTag(LOG_TAG);
+
+    assert(refFormat != NULL);
+
+    testSetLogCatTag(LOG_TAG);
+
+    // Parse command line arguments
+    while ((opt = getopt(argc, argv, "vs:e:r:D:?h")) != -1) {
+        switch (opt) {
+          case 'D': // End of test delay
+                    // Delay between completion of final pass and restart
+                    // of framework
+            endDelay = strtod(optarg, &chptr);
+            if ((*chptr != '\0') || (endDelay < 0.0)) {
+                testPrintE("Invalid command-line specified end of test delay "
+                           "of: %s", optarg);
+                exit(1);
+            }
+            break;
+
+          case 's': // Starting reference color
+            str = optarg;
+            while (optind < argc) {
+                if (*argv[optind] == '-') { break; }
+                char endChar = (str.length() > 1) ? str[str.length() - 1] : 0;
+                if ((endChar == '>') || (endChar == ']')) { break; }
+                str += " " + string(argv[optind++]);
+            }
+            {
+                istringstream in(str);
+                startRefColor = hwcTestParseColor(in, error);
+                // Any parse error or characters not used by parser
+                if (error
+                    || (((unsigned int) in.tellg() != in.str().length())
+                        && (in.tellg() != (streampos) -1))) {
+                    testPrintE("Invalid command-line specified start "
+                               "reference color of: %s", str.c_str());
+                    exit(2);
+                }
+            }
+            break;
+
+          case 'e': // Ending reference color
+            str = optarg;
+            while (optind < argc) {
+                if (*argv[optind] == '-') { break; }
+                char endChar = (str.length() > 1) ? str[str.length() - 1] : 0;
+                if ((endChar == '>') || (endChar == ']')) { break; }
+                str += " " + string(argv[optind++]);
+            }
+            {
+                istringstream in(str);
+                endRefColor = hwcTestParseColor(in, error);
+                // Any parse error or characters not used by parser
+                if (error
+                    || (((unsigned int) in.tellg() != in.str().length())
+                        && (in.tellg() != (streampos) -1))) {
+                    testPrintE("Invalid command-line specified end "
+                               "reference color of: %s", str.c_str());
+                    exit(3);
+                }
+            }
+            break;
+
+          case 'r': // Reference graphic format
+            refFormat = hwcTestGraphicFormatLookup(optarg);
+            if (refFormat == NULL) {
+                testPrintE("Unkown command-line specified reference graphic "
+                           "format of: %s", optarg);
+                printSyntax(basename(argv[0]));
+                exit(4);
+            }
+            break;
+
+          case 'v': // Verbose
+            verbose = true;
+            break;
+
+          case 'h': // Help
+          case '?':
+          default:
+            printSyntax(basename(argv[0]));
+            exit(((optopt == 0) || (optopt == '?')) ? 0 : 5);
+        }
+    }
+
+    // Expect a single positional parameter, which specifies the
+    // equivalence graphic format.
+    if (argc != (optind + 1)) {
+        testPrintE("Expected a single command-line postional parameter");
+        printSyntax(basename(argv[0]));
+        exit(6);
+    }
+    equivFormat = hwcTestGraphicFormatLookup(argv[optind]);
+    if (equivFormat == NULL) {
+        testPrintE("Unkown command-line specified equivalence graphic "
+                   "format of: %s", argv[optind]);
+        printSyntax(basename(argv[0]));
+        exit(7);
+    }
+
+    testPrintI("refFormat: %u %s", refFormat->format, refFormat->desc);
+    testPrintI("equivFormat: %u %s", equivFormat->format, equivFormat->desc);
+    testPrintI("startRefColor: %s", ((string) startRefColor).c_str());
+    testPrintI("endRefColor: %s", ((string) endRefColor).c_str());
+    testPrintI("endDelay: %f", endDelay);
+
+    // Stop framework
+    rv = snprintf(cmd, sizeof(cmd), "%s", CMD_STOP_FRAMEWORK);
+    if (rv >= (signed) sizeof(cmd) - 1) {
+        testPrintE("Command too long for: %s", CMD_STOP_FRAMEWORK);
+        exit(8);
+    }
+    testExecCmd(cmd);
+    testDelay(1.0); // TODO - needs means to query whether asynchronous stop
+                    // framework operation has completed.  For now, just wait
+                    // a long time.
+
+    init();
+
+    // Use the upper third of the display for the reference frame and
+    // the middle third for the equivalence frame.
+    unsigned int refHeight = height / 3;
+    unsigned int refPosY = 0; // Reference frame Y position
+    unsigned int refPosX = 0; // Reference frame X position
+    unsigned int refWidth = width - refPosX;
+    if ((refWidth & refFormat->wMod) != 0) {
+        refWidth += refFormat->wMod - (refWidth % refFormat->wMod);
+    }
+    unsigned int equivHeight = height / 3;
+    unsigned int equivPosY = refHeight; // Equivalence frame Y position
+    unsigned int equivPosX = 0;         // Equivalence frame X position
+    unsigned int equivWidth = width - equivPosX;
+    if ((equivWidth & equivFormat->wMod) != 0) {
+        equivWidth += equivFormat->wMod - (equivWidth % equivFormat->wMod);
+    }
+
+    // Create reference and equivalence graphic buffers
+    const unsigned int numFrames = 2;
+    sp<GraphicBuffer> refFrame;
+    refFrame = new GraphicBuffer(refWidth, refHeight,
+                                 refFormat->format, texUsage);
+    if ((rv = refFrame->initCheck()) != NO_ERROR) {
+        testPrintE("refFrame initCheck failed, rv: %i", rv);
+        testPrintE("  width %u height: %u format: %u %s", refWidth, refHeight,
+                   refFormat->format,
+                   hwcTestGraphicFormat2str(refFormat->format));
+        exit(9);
+    }
+    testPrintI("refFrame width: %u height: %u format: %u %s",
+               refWidth, refHeight, refFormat->format,
+               hwcTestGraphicFormat2str(refFormat->format));
+
+    sp<GraphicBuffer> equivFrame;
+    equivFrame = new GraphicBuffer(equivWidth, equivHeight,
+                                   equivFormat->format, texUsage);
+    if ((rv = refFrame->initCheck()) != NO_ERROR) {
+        testPrintE("refFrame initCheck failed, rv: %i", rv);
+        testPrintE("  width %u height: %u format: %u %s", refWidth, refHeight,
+                   refFormat->format,
+                   hwcTestGraphicFormat2str(refFormat->format));
+        exit(10);
+    }
+    testPrintI("equivFrame width: %u height: %u format: %u %s",
+               equivWidth, equivHeight, equivFormat->format,
+               hwcTestGraphicFormat2str(equivFormat->format));
+
+    // Fill the frames with a horizontal blend
+    hwcTestFillColorHBlend(refFrame.get(), refFormat->format,
+                           startRefColor, endRefColor);
+    hwcTestFillColorHBlend(equivFrame.get(), refFormat->format,
+                           startRefColor, endRefColor);
+
+    hwc_layer_list_t *list;
+    size_t size = sizeof(hwc_layer_list) + numFrames * sizeof(hwc_layer_t);
+    if ((list = (hwc_layer_list_t *) calloc(1, size)) == NULL) {
+        testPrintE("Allocate list failed");
+        exit(11);
+    }
+    list->flags = HWC_GEOMETRY_CHANGED;
+    list->numHwLayers = numFrames;
+
+    hwc_layer_t *layer = &list->hwLayers[0];
+    layer->handle = refFrame->handle;
+    layer->blending = HWC_BLENDING_NONE;
+    layer->sourceCrop.left = 0;
+    layer->sourceCrop.top = 0;
+    layer->sourceCrop.right = width;
+    layer->sourceCrop.bottom = refHeight;
+    layer->displayFrame.left = 0;
+    layer->displayFrame.top = 0;
+    layer->displayFrame.right = width;
+    layer->displayFrame.bottom = refHeight;
+    layer->visibleRegionScreen.numRects = 1;
+    layer->visibleRegionScreen.rects = &layer->displayFrame;
+
+    layer++;
+    layer->handle = equivFrame->handle;
+    layer->blending = HWC_BLENDING_NONE;
+    layer->sourceCrop.left = 0;
+    layer->sourceCrop.top = 0;
+    layer->sourceCrop.right = width;
+    layer->sourceCrop.bottom = equivHeight;
+    layer->displayFrame.left = 0;
+    layer->displayFrame.top = refHeight;
+    layer->displayFrame.right = width;
+    layer->displayFrame.bottom = layer->displayFrame.top + equivHeight;
+    layer->visibleRegionScreen.numRects = 1;
+    layer->visibleRegionScreen.rects = &layer->displayFrame;
+
+    // Perform prepare operation
+    if (verbose) { testPrintI("Prepare:"); hwcTestDisplayList(list); }
+    hwcDevice->prepare(hwcDevice, list);
+    if (verbose) {
+        testPrintI("Post Prepare:");
+        hwcTestDisplayListPrepareModifiable(list);
+    }
+
+    // Turn off the geometry changed flag
+    list->flags &= ~HWC_GEOMETRY_CHANGED;
+
+    if (verbose) {hwcTestDisplayListHandles(list); }
+    hwcDevice->set(hwcDevice, dpy, surface, list);
+
+    testDelay(endDelay);
+
+    // Start framework
+    rv = snprintf(cmd, sizeof(cmd), "%s", CMD_START_FRAMEWORK);
+    if (rv >= (signed) sizeof(cmd) - 1) {
+        testPrintE("Command too long for: %s", CMD_START_FRAMEWORK);
+        exit(12);
+    }
+    testExecCmd(cmd);
+
+    return 0;
+}
+
+void init(void)
+{
+    // Seed pseudo random number generator
+    // Seeding causes fill horizontal blend to fill the pad area with
+    // a deterministic set of values.
+    srand48(0);
+
+    hwcTestInitDisplay(verbose, &dpy, &surface, &width, &height);
+
+    hwcTestOpenHwc(&hwcDevice);
+}
+
+void printSyntax(const char *cmd)
+{
+    testPrintE("  %s [options] graphicFormat", cmd);
+    testPrintE("    options:");
+    testPrintE("      -s <0.##, 0.##, 0.##> - Starting reference color");
+    testPrintE("      -e <0.##, 0.##, 0.##> - Ending reference color");
+    testPrintE("      -r format - Reference graphic format");
+    testPrintE("      -D #.## - End of test delay");
+    testPrintE("      -v Verbose");
+    testPrintE("");
+    testPrintE("    graphic formats:");
+    for (unsigned int n1 = 0; n1 < NUMA(hwcTestGraphicFormat); n1++) {
+        testPrintE("      %s", hwcTestGraphicFormat[n1].desc);
+    }
+}
diff --git a/opengl/tests/hwc/hwcCommit.cpp b/opengl/tests/hwc/hwcCommit.cpp
new file mode 100644
index 0000000..66ccdae
--- /dev/null
+++ b/opengl/tests/hwc/hwcCommit.cpp
@@ -0,0 +1,1562 @@
+/*
+ * Copyright (C) 2011 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+/*
+ * Hardware Composer Commit Points
+ *
+ * Synopsis
+ *   hwcCommit [options] graphicFormat ...
+ *     options:
+ *       -s [width, height] - Starting dimension
+ *       -v - Verbose
+ *
+ *      graphic formats:
+ *        RGBA8888 (reference frame default)
+ *        RGBX8888
+ *        RGB888
+ *        RGB565
+ *        BGRA8888
+ *        RGBA5551
+ *        RGBA4444
+ *        YV12
+ *
+ * Description
+ *   The Hardware Composer (HWC) Commit test is a benchmark that
+ *   discovers the points at which the HWC will commit to rendering an
+ *   overlay(s).  Before rendering a set of overlays, the HWC is shown
+ *   the list through a prepare call.  During the prepare call the HWC
+ *   is able to examine the list and specify which overlays it is able
+ *   to handle.  The overlays that it can't handle are typically composited
+ *   by a higher level (e.g. Surface Flinger) and then the original list
+ *   plus a composit of what HWC passed on are provided back to the HWC
+ *   for rendering.
+ *
+ *   Once an implementation of the HWC has been shipped, a regression would
+ *   likely occur if a latter implementation started passing on conditions
+ *   that it used to commit to.  The primary purpose of this benchmark
+ *   is the automated discovery of the commit points, where an implementation
+ *   is on the edge between committing and not committing.  These are commonly
+ *   referred to as commit points.  Between implementations changes to the
+ *   commit points are allowed, as long as they improve what the HWC commits
+ *   to.  Once an implementation of the HWC is shipped, the commit points are
+ *   not allowed to regress in future implementations.
+ *
+ *   This benchmark takes a sampling and then adjusts until it finds a
+ *   commit point.  It doesn't exhaustively check all possible conditions,
+ *   which do to the number of combinations would be impossible.  Instead
+ *   it starts its search from a starting dimension, that can be changed
+ *   via the -s option.  The search is also bounded by a set of search
+ *   limits, that are hard-coded into a structure of constants named
+ *   searchLimits.  Results that happen to reach a searchLimit are prefixed
+ *   with >=, so that it is known that the value could possibly be larger.
+ *
+ *   Measurements are made for each of the graphic formats specified as
+ *   positional parameters on the command-line.  If no graphic formats
+ *   are specified on the command line, then by default measurements are
+ *   made and reported for each of the known graphic format.
+ */
+
+#include <algorithm>
+#include <assert.h>
+#include <cerrno>
+#include <cmath>
+#include <cstdlib>
+#include <ctime>
+#include <iomanip>
+#include <istream>
+#include <libgen.h>
+#include <list>
+#include <sched.h>
+#include <sstream>
+#include <stdint.h>
+#include <string.h>
+#include <unistd.h>
+#include <vector>
+
+#include <sys/syscall.h>
+#include <sys/types.h>
+#include <sys/wait.h>
+
+#include <EGL/egl.h>
+#include <EGL/eglext.h>
+#include <GLES2/gl2.h>
+#include <GLES2/gl2ext.h>
+
+#include <ui/FramebufferNativeWindow.h>
+#include <ui/GraphicBuffer.h>
+#include <ui/EGLUtils.h>
+
+#define LOG_TAG "hwcCommitTest"
+#include <utils/Log.h>
+#include <testUtil.h>
+
+#include <hardware/hwcomposer.h>
+
+#include <glTestLib.h>
+#include <hwc/hwcTestLib.h>
+
+using namespace std;
+using namespace android;
+
+// Defaults
+const HwcTestDim defaultStartDim = HwcTestDim(100, 100);
+const bool defaultVerbose = false;
+
+const uint32_t   defaultFormat = HAL_PIXEL_FORMAT_RGBA_8888;
+const int32_t    defaultTransform = 0;
+const uint32_t   defaultBlend = HWC_BLENDING_NONE;
+const ColorFract defaultColor(0.5, 0.5, 0.5);
+const float      defaultAlpha = 1.0; // Opaque
+const HwcTestDim defaultSourceDim(1, 1);
+const struct hwc_rect defaultSourceCrop = {0, 0, 1, 1};
+const struct hwc_rect defaultDisplayFrame = {0, 0, 100, 100};
+
+// Global Constants
+const uint32_t printFieldWidth = 2;
+const struct searchLimits {
+    uint32_t   numOverlays;
+    HwcTestDim sourceCrop;
+} searchLimits = {
+    10,
+    HwcTestDim(3000, 2000),
+};
+const struct transformType {
+    const char *desc;
+    uint32_t id;
+} transformType[] = {
+    {"fliph",  HWC_TRANSFORM_FLIP_H},
+    {"flipv",  HWC_TRANSFORM_FLIP_V},
+    {"rot90",  HWC_TRANSFORM_ROT_90},
+    {"rot180", HWC_TRANSFORM_ROT_180},
+    {"rot270", HWC_TRANSFORM_ROT_270},
+};
+const struct blendType {
+    const char *desc;
+    uint32_t id;
+} blendType[] = {
+    {"none", HWC_BLENDING_NONE},
+    {"premult", HWC_BLENDING_PREMULT},
+    {"coverage", HWC_BLENDING_COVERAGE},
+};
+
+// Defines
+#define MAXCMD               200
+#define CMD_STOP_FRAMEWORK   "stop 2>&1"
+#define CMD_START_FRAMEWORK  "start 2>&1"
+
+// Macros
+#define NUMA(a) (sizeof(a) / sizeof(a [0])) // Num elements in an array
+
+// Local types
+class Rectangle {
+public:
+    Rectangle(uint32_t graphicFormat = defaultFormat,
+              HwcTestDim dfDim = HwcTestDim(1, 1),
+              HwcTestDim sDim = HwcTestDim(1, 1));
+    void setSourceDim(HwcTestDim dim);
+
+    uint32_t     format;
+    uint32_t     transform;
+    int32_t      blend;
+    ColorFract   color;
+    float        alpha;
+    HwcTestDim   sourceDim;
+    struct hwc_rect   sourceCrop;
+    struct hwc_rect   displayFrame;
+};
+
+class Range {
+public:
+    Range(void) : _l(0), _u(0) {}
+    Range(uint32_t lower, uint32_t upper) : _l(lower), _u(upper) {}
+    uint32_t lower(void) { return _l; }
+    uint32_t upper(void) { return _u; }
+
+    operator string();
+
+private:
+    uint32_t _l; // lower
+    uint32_t _u; // upper
+};
+
+Range::operator string()
+{
+    ostringstream out;
+
+    out << '[' << _l << ", " << _u << ']';
+
+    return out.str();
+}
+
+class Rational {
+public:
+    Rational(void) : _n(0), _d(1) {}
+    Rational(uint32_t n, uint32_t d) : _n(n), _d(d) {}
+    uint32_t numerator(void) { return _n; }
+    uint32_t denominator(void) { return _d; }
+    void setNumerator(uint32_t numerator) { _n = numerator; }
+
+    bool operator==(const Rational& other) const;
+    bool operator!=(const Rational& other) const { return !(*this == other); }
+    bool operator<(const Rational& other) const;
+    bool operator>(const Rational& other) const {
+        return (!(*this == other) && !(*this < other));
+    }
+    static void double2Rational(double f, Range nRange, Range dRange,
+                               Rational& lower, Rational& upper);
+        
+    operator string() const;
+    operator double() const { return (double) _n / (double) _d; }
+
+
+private:
+    uint32_t _n;
+    uint32_t _d;
+};
+
+// Globals
+static const int texUsage = GraphicBuffer::USAGE_HW_TEXTURE |
+        GraphicBuffer::USAGE_SW_WRITE_RARELY;
+static hwc_composer_device_t *hwcDevice;
+static EGLDisplay dpy;
+static EGLSurface surface;
+static EGLint width, height;
+static size_t maxHeadingLen;
+static vector<string> formats;
+
+// Measurements
+struct meas {
+    uint32_t format;
+    uint32_t startDimOverlays;
+    uint32_t maxNonOverlapping;
+    uint32_t maxOverlapping;
+    list<uint32_t> transforms;
+    list<uint32_t> blends;
+    struct displayFrame {
+        uint32_t minWidth;
+        uint32_t minHeight;
+        HwcTestDim minDim;
+        uint32_t maxWidth;
+        uint32_t maxHeight;
+        HwcTestDim maxDim;
+    } df;
+    struct sourceCrop {
+        uint32_t minWidth;
+        uint32_t minHeight;
+        HwcTestDim minDim;
+        uint32_t maxWidth;
+        uint32_t maxHeight;
+        HwcTestDim maxDim;
+        Rational hScale;
+        HwcTestDim hScaleBestDf;
+        HwcTestDim hScaleBestSc;
+        Rational vScale;
+        HwcTestDim vScaleBestDf;
+        HwcTestDim vScaleBestSc;
+    } sc;
+    vector<uint32_t> overlapBlendNone;
+    vector<uint32_t> overlapBlendPremult;
+    vector<uint32_t> overlapBlendCoverage;
+};
+vector<meas> measurements;
+
+// Function prototypes
+uint32_t numOverlays(list<Rectangle>& rectList);
+uint32_t maxOverlays(uint32_t format, bool allowOverlap);
+list<uint32_t> supportedTransforms(uint32_t format);
+list<uint32_t> supportedBlends(uint32_t format);
+uint32_t dfMinWidth(uint32_t format);
+uint32_t dfMinHeight(uint32_t format);
+uint32_t dfMaxWidth(uint32_t format);
+uint32_t dfMaxHeight(uint32_t format);
+HwcTestDim dfMinDim(uint32_t format);
+HwcTestDim dfMaxDim(uint32_t format);
+uint32_t scMinWidth(uint32_t format, const HwcTestDim& dfDim);
+uint32_t scMinHeight(uint32_t format, const HwcTestDim& dfDim);
+uint32_t scMaxWidth(uint32_t format, const HwcTestDim& dfDim);
+uint32_t scMaxHeight(uint32_t format, const HwcTestDim& dfDim);
+HwcTestDim scMinDim(uint32_t format, const HwcTestDim& dfDim);
+HwcTestDim scMaxDim(uint32_t format, const HwcTestDim& dfDim);
+Rational scHScale(uint32_t format,
+                  const HwcTestDim& dfMin, const HwcTestDim& dfMax,
+                  const HwcTestDim& scMin, const HwcTestDim& scMax,
+                  HwcTestDim& outBestDf, HwcTestDim& outBestSc);
+Rational scVScale(uint32_t format,
+                  const HwcTestDim& dfMin, const HwcTestDim& dfMax,
+                  const HwcTestDim& scMin, const HwcTestDim& scMax,
+                  HwcTestDim& outBestDf, HwcTestDim& outBestSc);
+uint32_t numOverlapping(uint32_t backgroundFormat, uint32_t foregroundFormat,
+                        uint32_t backgroundBlend, uint32_t foregroundBlend);
+string transformList2str(const list<uint32_t>& transformList);
+string blendList2str(const list<uint32_t>& blendList);
+void init(void);
+void printFormatHeadings(size_t indent);
+void printOverlapLine(size_t indent, const string formatStr,
+                      const vector<uint32_t>& results);
+void printSyntax(const char *cmd);
+
+// Command-line option settings
+static bool verbose = defaultVerbose;
+static HwcTestDim startDim = defaultStartDim;
+
+/*
+ * Main
+ *
+ * Performs the following high-level sequence of operations:
+ *
+ *   1. Command-line parsing
+ *
+ *   2. Form a list of command-line specified graphic formats.  If
+ *      no formats are specified, then form a list of all known formats.
+ *
+ *   3. Stop framework
+ *      Only one user at a time is allowed to use the HWC.  Surface
+ *      Flinger uses the HWC and is part of the framework.  Need to
+ *      stop the framework so that Surface Flinger will stop using
+ *      the HWC.
+ *   
+ *   4. Initialization
+ *
+ *   5. For each graphic format in the previously formed list perform
+ *      measurements on that format and report the results.
+ *
+ *   6. Start framework
+ */
+int
+main(int argc, char *argv[])
+{
+    int     rv, opt;
+    char   *chptr;
+    bool    error;
+    string  str;
+    char cmd[MAXCMD];
+    list<Rectangle> rectList;
+
+    testSetLogCatTag(LOG_TAG);
+
+    // Parse command line arguments
+    while ((opt = getopt(argc, argv, "s:v?h")) != -1) {
+        switch (opt) {
+
+          case 's': // Start Dimension
+            // Use arguments until next starts with a dash
+            // or current ends with a > or ]
+            str = optarg;
+            while (optind < argc) {
+                if (*argv[optind] == '-') { break; }
+                char endChar = (str.length() > 1) ? str[str.length() - 1] : 0;
+                if ((endChar == '>') || (endChar == ']')) { break; }
+                str += " " + string(argv[optind++]);
+            }
+            {
+                istringstream in(str);
+                startDim = hwcTestParseDim(in, error);
+                // Any parse error or characters not used by parser
+                if (error
+                    || (((unsigned int) in.tellg() != in.str().length())
+                        && (in.tellg() != (streampos) -1))) {
+                    testPrintE("Invalid command-line specified start "
+                               "dimension of: %s", str.c_str());
+                    exit(8);
+                }
+            }
+            break;
+
+          case 'v': // Verbose
+            verbose = true;
+            break;
+
+          case 'h': // Help
+          case '?':
+          default:
+            printSyntax(basename(argv[0]));
+            exit(((optopt == 0) || (optopt == '?')) ? 0 : 11);
+        }
+    }
+
+    // Positional parameters
+    // Positional parameters provide the names of graphic formats that
+    // measurements are to be made on.  Measurements are made on all
+    // known graphic formats when no positional parameters are provided.
+    if (optind == argc) {
+        // No command-line specified graphic formats
+        // Add all graphic formats to the list of formats to be measured
+        for (unsigned int n1 = 0; n1 < NUMA(hwcTestGraphicFormat); n1++) {
+            formats.push_back(hwcTestGraphicFormat[n1].desc);
+        }
+    } else {
+        // Add names of command-line specified graphic formats to the
+        // list of formats to be tested
+        for (; argv[optind] != NULL; optind++) {
+            formats.push_back(argv[optind]);
+        }
+    }
+
+    // Determine length of longest specified graphic format.
+    // This value is used for output formating
+    for (vector<string>::iterator it = formats.begin();
+         it != formats.end(); ++it) {
+         maxHeadingLen = max(maxHeadingLen, it->length());
+    }
+
+    // Stop framework
+    rv = snprintf(cmd, sizeof(cmd), "%s", CMD_STOP_FRAMEWORK);
+    if (rv >= (signed) sizeof(cmd) - 1) {
+        testPrintE("Command too long for: %s", CMD_STOP_FRAMEWORK);
+        exit(14);
+    }
+    testExecCmd(cmd);
+    testDelay(1.0); // TODO - needs means to query whether asynchronous stop
+                    // framework operation has completed.  For now, just wait
+                    // a long time.
+
+    testPrintI("startDim: %s", ((string) startDim).c_str());
+
+    init();
+
+    // For each of the graphic formats
+    for (vector<string>::iterator itFormat = formats.begin();
+         itFormat != formats.end(); ++itFormat) {
+
+        // Locate hwcTestLib structure that describes this format
+        const struct hwcTestGraphicFormat *format;
+        format = hwcTestGraphicFormatLookup((*itFormat).c_str());
+        if (format == NULL) {
+            testPrintE("Unknown graphic format of: %s", (*itFormat).c_str());
+            exit(1);
+        }
+
+        // Display format header
+        testPrintI("format: %s", format->desc);
+
+        // Create area to hold the measurements
+        struct meas meas;
+        struct meas *measPtr;
+        meas.format = format->format;
+        measurements.push_back(meas);
+        measPtr = &measurements[measurements.size() - 1];
+
+        // Start dimension num overlays
+        Rectangle rect(format->format, startDim);
+        rectList.clear();
+        rectList.push_back(rect);
+        measPtr->startDimOverlays = numOverlays(rectList);
+        testPrintI("  startDimOverlays: %u", measPtr->startDimOverlays);
+
+        // Skip the rest of the measurements, when the start dimension
+        // doesn't produce an overlay
+        if (measPtr->startDimOverlays == 0) { continue; }
+
+        // Max Overlays
+        measPtr->maxNonOverlapping = maxOverlays(format->format, false);
+        testPrintI("  max nonOverlapping overlays: %s%u",
+                   (measPtr->maxNonOverlapping == searchLimits.numOverlays)
+                       ? ">= " : "",
+                   measPtr->maxNonOverlapping);
+        measPtr->maxOverlapping = maxOverlays(format->format, true);
+        testPrintI("  max Overlapping overlays: %s%u",
+                   (measPtr->maxOverlapping == searchLimits.numOverlays)
+                       ? ">= " : "",
+                   measPtr->maxOverlapping);
+
+        // Transforms and blends
+        measPtr->transforms = supportedTransforms(format->format);
+        testPrintI("  transforms: %s",
+                   transformList2str(measPtr->transforms).c_str());
+        measPtr->blends = supportedBlends(format->format);
+        testPrintI("  blends: %s",
+                   blendList2str(measPtr->blends).c_str());
+
+        // Display frame measurements
+        measPtr->df.minWidth = dfMinWidth(format->format);
+        testPrintI("  dfMinWidth: %u", measPtr->df.minWidth);
+
+        measPtr->df.minHeight = dfMinHeight(format->format);
+        testPrintI("  dfMinHeight: %u", measPtr->df.minHeight);
+
+        measPtr->df.maxWidth = dfMaxWidth(format->format);
+        testPrintI("  dfMaxWidth: %u", measPtr->df.maxWidth);
+
+        measPtr->df.maxHeight = dfMaxHeight(format->format);
+        testPrintI("  dfMaxHeight: %u", measPtr->df.maxHeight);
+
+        measPtr->df.minDim = dfMinDim(format->format);
+        testPrintI("  dfMinDim: %s", ((string) measPtr->df.minDim).c_str());
+
+        measPtr->df.maxDim = dfMaxDim(format->format);
+        testPrintI("  dfMaxDim: %s", ((string) measPtr->df.maxDim).c_str());
+
+        // Source crop measurements
+        measPtr->sc.minWidth = scMinWidth(format->format, measPtr->df.minDim);
+        testPrintI("  scMinWidth: %u", measPtr->sc.minWidth);
+
+        measPtr->sc.minHeight = scMinHeight(format->format, measPtr->df.minDim);
+        testPrintI("  scMinHeight: %u", measPtr->sc.minHeight);
+
+        measPtr->sc.maxWidth = scMaxWidth(format->format, measPtr->df.maxDim);
+        testPrintI("  scMaxWidth: %s%u", (measPtr->sc.maxWidth
+                   == searchLimits.sourceCrop.width()) ? ">= " : "",
+                   measPtr->sc.maxWidth);
+
+        measPtr->sc.maxHeight = scMaxHeight(format->format, measPtr->df.maxDim);
+        testPrintI("  scMaxHeight: %s%u", (measPtr->sc.maxHeight
+                   == searchLimits.sourceCrop.height()) ? ">= " : "",
+                   measPtr->sc.maxHeight);
+
+        measPtr->sc.minDim = scMinDim(format->format, measPtr->df.minDim);
+        testPrintI("  scMinDim: %s", ((string) measPtr->sc.minDim).c_str());
+
+        measPtr->sc.maxDim = scMaxDim(format->format, measPtr->df.maxDim);
+        testPrintI("  scMaxDim: %s%s", ((measPtr->sc.maxDim.width()
+                         >= searchLimits.sourceCrop.width())
+                         || (measPtr->sc.maxDim.width() >=
+                         searchLimits.sourceCrop.height())) ? ">= " : "",
+                   ((string) measPtr->sc.maxDim).c_str());
+
+        measPtr->sc.hScale = scHScale(format->format,
+                                      measPtr->df.minDim, measPtr->df.maxDim,
+                                      measPtr->sc.minDim, measPtr->sc.maxDim,
+                                      measPtr->sc.hScaleBestDf,
+                                      measPtr->sc.hScaleBestSc);
+        testPrintI("  scHScale: %s%f",
+                   (measPtr->sc.hScale
+                       >= Rational(searchLimits.sourceCrop.width(),
+                                   measPtr->df.minDim.width())) ? ">= " : "",
+                   (double) measPtr->sc.hScale);
+        testPrintI("    HScale Best Display Frame: %s",
+                   ((string) measPtr->sc.hScaleBestDf).c_str());
+        testPrintI("    HScale Best Source Crop: %s",
+                   ((string) measPtr->sc.hScaleBestSc).c_str());
+
+        measPtr->sc.vScale = scVScale(format->format,
+                                      measPtr->df.minDim, measPtr->df.maxDim,
+                                      measPtr->sc.minDim, measPtr->sc.maxDim,
+                                      measPtr->sc.vScaleBestDf,
+                                      measPtr->sc.vScaleBestSc);
+        testPrintI("  scVScale: %s%f",
+                   (measPtr->sc.vScale
+                       >= Rational(searchLimits.sourceCrop.height(),
+                                   measPtr->df.minDim.height())) ? ">= " : "",
+                   (double) measPtr->sc.vScale);
+        testPrintI("    VScale Best Display Frame: %s",
+                   ((string) measPtr->sc.vScaleBestDf).c_str());
+        testPrintI("    VScale Best Source Crop: %s",
+                   ((string) measPtr->sc.vScaleBestSc).c_str());
+
+        // Overlap two graphic formats and different blends
+        // Results displayed after all overlap measurments with
+        // current format in the foreground
+        // TODO: make measurments with background blend other than
+        //       none.  All of these measurements are done with a
+        //       background blend of HWC_BLENDING_NONE, with the
+        //       blend type of the foregound being varied.
+        uint32_t foregroundFormat = format->format;
+        for (vector<string>::iterator it = formats.begin();
+             it != formats.end(); ++it) {
+            uint32_t num;
+
+            const struct hwcTestGraphicFormat *backgroundFormatPtr
+                = hwcTestGraphicFormatLookup((*it).c_str());
+            uint32_t backgroundFormat = backgroundFormatPtr->format;
+
+            num = numOverlapping(backgroundFormat, foregroundFormat,
+                                 HWC_BLENDING_NONE, HWC_BLENDING_NONE);
+            measPtr->overlapBlendNone.push_back(num);
+
+            num = numOverlapping(backgroundFormat, foregroundFormat,
+                                 HWC_BLENDING_NONE, HWC_BLENDING_PREMULT);
+            measPtr->overlapBlendPremult.push_back(num);
+
+            num = numOverlapping(backgroundFormat, foregroundFormat,
+                                 HWC_BLENDING_NONE, HWC_BLENDING_COVERAGE);
+            measPtr->overlapBlendCoverage.push_back(num);
+        }
+
+    }
+
+    // Display overlap results
+    size_t indent = 2;
+    testPrintI("overlapping blend: none");
+    printFormatHeadings(indent);
+    for (vector<string>::iterator it = formats.begin();
+         it != formats.end(); ++it) {
+        printOverlapLine(indent, *it, measurements[it
+                         - formats.begin()].overlapBlendNone);
+    }
+    testPrintI("");
+
+    testPrintI("overlapping blend: premult");
+    printFormatHeadings(indent);
+    for (vector<string>::iterator it = formats.begin();
+         it != formats.end(); ++it) {
+        printOverlapLine(indent, *it, measurements[it
+                         - formats.begin()].overlapBlendPremult);
+    }
+    testPrintI("");
+
+    testPrintI("overlapping blend: coverage");
+    printFormatHeadings(indent);
+    for (vector<string>::iterator it = formats.begin();
+         it != formats.end(); ++it) {
+        printOverlapLine(indent, *it, measurements[it
+                         - formats.begin()].overlapBlendCoverage);
+    }
+    testPrintI("");
+
+    // Start framework
+    rv = snprintf(cmd, sizeof(cmd), "%s", CMD_START_FRAMEWORK);
+    if (rv >= (signed) sizeof(cmd) - 1) {
+        testPrintE("Command too long for: %s", CMD_START_FRAMEWORK);
+        exit(21);
+    }
+    testExecCmd(cmd);
+
+    return 0;
+}
+
+// Determine the maximum number of overlays that are all of the same format
+// that the HWC will commit to.  If allowOverlap is true, then the rectangles
+// are laid out on a diagonal starting from the upper left corner.  With
+// each rectangle adjust one pixel to the right and one pixel down.
+// When allowOverlap is false, the rectangles are tiled in column major
+// order.  Note, column major ordering is used so that the initial rectangles
+// are all on different horizontal scan rows.  It is common that hardware
+// has limits on the number of objects it can handle on any single row.
+uint32_t maxOverlays(uint32_t format, bool allowOverlap)
+{
+    unsigned int max = 0;
+
+    for (unsigned int numRects = 1; numRects <= searchLimits.numOverlays;
+         numRects++) {
+        list<Rectangle> rectList;
+
+        for (unsigned int x = 0;
+             (x + startDim.width()) < (unsigned int) width;
+             x += (allowOverlap) ? 1 : startDim.width()) {
+            for (unsigned int y = 0;
+                 (y + startDim.height()) < (unsigned int) height;
+                 y += (allowOverlap) ? 1 : startDim.height()) {
+                Rectangle rect(format, startDim, startDim);
+                rect.displayFrame.left = x;
+                rect.displayFrame.top = y;
+                rect.displayFrame.right = x + startDim.width();
+                rect.displayFrame.bottom = y + startDim.height();
+
+                rectList.push_back(rect);
+
+                if (rectList.size() >= numRects) { break; }
+            }
+            if (rectList.size() >= numRects) { break; }
+        }
+
+        uint32_t num = numOverlays(rectList);
+        if (num > max) { max = num; }
+    }
+
+    return max;
+}
+
+// Measures what transforms (i.e. flip horizontal, rotate 180) are
+// supported by the specified format
+list<uint32_t> supportedTransforms(uint32_t format)
+{
+    list<uint32_t> rv;
+    list<Rectangle> rectList;
+    Rectangle rect(format, startDim);
+
+    // For each of the transform types
+    for (unsigned int idx = 0; idx < NUMA(transformType); idx++) {
+        unsigned int id = transformType[idx].id;
+
+        rect.transform = id;
+        rectList.clear();
+        rectList.push_back(rect);
+        uint32_t num = numOverlays(rectList);
+
+        if (num == 1) {
+            rv.push_back(id);
+        }
+    }
+
+    return rv;
+}
+
+// Determines which types of blends (i.e. none, premult, coverage) are
+// supported by the specified format
+list<uint32_t> supportedBlends(uint32_t format)
+{
+    list<uint32_t> rv;
+    list<Rectangle> rectList;
+    Rectangle rect(format, startDim);
+
+    // For each of the blend types
+    for (unsigned int idx = 0; idx < NUMA(blendType); idx++) {
+        unsigned int id = blendType[idx].id;
+
+        rect.blend = id;
+        rectList.clear();
+        rectList.push_back(rect);
+        uint32_t num = numOverlays(rectList);
+
+        if (num == 1) {
+            rv.push_back(id);
+        }
+    }
+
+    return rv;
+}
+
+// Determines the minimum width of any display frame of the given format
+// that the HWC will commit to.
+uint32_t dfMinWidth(uint32_t format)
+{
+    uint32_t w;
+    list<Rectangle> rectList;
+
+    for (w = 1; w <= startDim.width(); w++) {
+        HwcTestDim dim(w, startDim.height());
+        Rectangle rect(format, dim);
+        rectList.clear();
+        rectList.push_back(rect);
+        uint32_t num = numOverlays(rectList);
+        if (num > 0) {
+            return w;
+        }
+    }
+    if (w > startDim.width()) {
+        testPrintE("Failed to locate display frame min width");
+        exit(33);
+    }
+
+    return w;
+}
+
+// Display frame minimum height
+uint32_t dfMinHeight(uint32_t format)
+{
+    uint32_t h;
+    list<Rectangle> rectList;
+
+    for (h = 1; h <= startDim.height(); h++) {
+        HwcTestDim dim(startDim.width(), h);
+        Rectangle rect(format, dim);
+        rectList.clear();
+        rectList.push_back(rect);
+        uint32_t num = numOverlays(rectList);
+        if (num > 0) {
+            return h;
+        }
+    }
+    if (h > startDim.height()) {
+        testPrintE("Failed to locate display frame min height");
+        exit(34);
+    }
+
+    return h;
+}
+
+// Display frame maximum width
+uint32_t dfMaxWidth(uint32_t format)
+{
+    uint32_t w;
+    list<Rectangle> rectList;
+
+    for (w = width; w >= startDim.width(); w--) {
+        HwcTestDim dim(w, startDim.height());
+        Rectangle rect(format, dim);
+        rectList.clear();
+        rectList.push_back(rect);
+        uint32_t num = numOverlays(rectList);
+        if (num > 0) {
+            return w;
+        }
+    }
+    if (w < startDim.width()) {
+        testPrintE("Failed to locate display frame max width");
+        exit(35);
+    }
+
+    return w;
+}
+
+// Display frame maximum height
+uint32_t dfMaxHeight(uint32_t format)
+{
+    uint32_t h;
+
+    for (h = height; h >= startDim.height(); h--) {
+        HwcTestDim dim(startDim.width(), h);
+        Rectangle rect(format, dim);
+        list<Rectangle> rectList;
+        rectList.push_back(rect);
+        uint32_t num = numOverlays(rectList);
+        if (num > 0) {
+            return h;
+        }
+    }
+    if (h < startDim.height()) {
+        testPrintE("Failed to locate display frame max height");
+        exit(36);
+    }
+
+    return h;
+}
+
+// Determine the minimum number of pixels that the HWC will ever commit to.
+// Note, this might be different that dfMinWidth * dfMinHeight, in that this
+// function adjusts both the width and height from the starting dimension.
+HwcTestDim dfMinDim(uint32_t format)
+{
+    uint64_t bestMinPixels = 0;
+    HwcTestDim bestDim;
+    bool bestSet = false; // True when value has been assigned to
+                          // bestMinPixels and bestDim
+
+    bool origVerbose = verbose;  // Temporarily turn off verbose
+    verbose = false;
+    for (uint32_t w = 1; w <= startDim.width(); w++) {
+        for (uint32_t h = 1; h <= startDim.height(); h++) {
+            if (bestSet && ((w > bestMinPixels) || (h > bestMinPixels))) {
+                break;
+            }
+
+            HwcTestDim dim(w, h);
+            Rectangle rect(format, dim);
+            list<Rectangle> rectList;
+            rectList.push_back(rect);
+            uint32_t num = numOverlays(rectList);
+            if (num > 0) {
+                uint64_t pixels = dim.width() * dim.height();
+                if (!bestSet || (pixels < bestMinPixels)) {
+                    bestMinPixels = pixels;
+                    bestDim = dim;
+                    bestSet = true;
+                }
+            }
+        }
+    }
+    verbose = origVerbose;
+
+    if (!bestSet) {
+        testPrintE("Unable to locate display frame min dimension");
+        exit(20);
+    }
+
+    return bestDim;
+}
+
+// Display frame maximum dimension
+HwcTestDim dfMaxDim(uint32_t format)
+{
+    uint64_t bestMaxPixels = 0;
+    HwcTestDim bestDim;
+    bool bestSet = false; // True when value has been assigned to
+                          // bestMaxPixels and bestDim;
+
+    // Potentially increase benchmark performance by first checking
+    // for the common case of supporting a full display frame.
+    HwcTestDim dim(width, height);
+    Rectangle rect(format, dim);
+    list<Rectangle> rectList;
+    rectList.push_back(rect);
+    uint32_t num = numOverlays(rectList);
+    if (num == 1) { return dim; }
+
+    // TODO: Use a binary search
+    bool origVerbose = verbose;  // Temporarily turn off verbose
+    verbose = false;
+    for (uint32_t w = startDim.width(); w <= (uint32_t) width; w++) {
+        for (uint32_t h = startDim.height(); h <= (uint32_t) height; h++) {
+            if (bestSet && ((w * h) <= bestMaxPixels)) { continue; }
+
+            HwcTestDim dim(w, h);
+            Rectangle rect(format, dim);
+            list<Rectangle> rectList;
+            rectList.push_back(rect);
+            uint32_t num = numOverlays(rectList);
+            if (num > 0) {
+                uint64_t pixels = dim.width() * dim.height();
+                if (!bestSet || (pixels > bestMaxPixels)) {
+                    bestMaxPixels = pixels;
+                    bestDim = dim;
+                    bestSet = true;
+                }
+            }
+        }
+    }
+    verbose = origVerbose;
+
+    if (!bestSet) {
+        testPrintE("Unable to locate display frame max dimension");
+        exit(21);
+    }
+
+    return bestDim;
+}
+
+// Source crop minimum width
+uint32_t scMinWidth(uint32_t format, const HwcTestDim& dfDim)
+{
+    uint32_t w;
+    list<Rectangle> rectList;
+
+    // Source crop frame min width
+    for (w = 1; w <= dfDim.width(); w++) {
+        Rectangle rect(format, dfDim, HwcTestDim(w, dfDim.height()));
+        rectList.clear();
+        rectList.push_back(rect);
+        uint32_t num = numOverlays(rectList);
+        if (num > 0) {
+            return w;
+        }
+    }
+    testPrintE("Failed to locate source crop min width");
+    exit(35);
+}
+
+// Source crop minimum height
+uint32_t scMinHeight(uint32_t format, const HwcTestDim& dfDim)
+{
+    uint32_t h;
+    list<Rectangle> rectList;
+
+    for (h = 1; h <= dfDim.height(); h++) {
+        Rectangle rect(format, dfDim, HwcTestDim(dfDim.width(), h));
+        rectList.clear();
+        rectList.push_back(rect);
+        uint32_t num = numOverlays(rectList);
+        if (num > 0) {
+            return h;
+        }
+    }
+    testPrintE("Failed to locate source crop min height");
+    exit(36);
+}
+
+// Source crop maximum width
+uint32_t scMaxWidth(uint32_t format, const HwcTestDim& dfDim)
+{
+    uint32_t w;
+    list<Rectangle> rectList;
+
+    for (w = searchLimits.sourceCrop.width(); w >= dfDim.width(); w--) {
+        Rectangle rect(format, dfDim, HwcTestDim(w, dfDim.height()));
+        rectList.clear();
+        rectList.push_back(rect);
+        uint32_t num = numOverlays(rectList);
+        if (num > 0) {
+            return w;
+        }
+    }
+    testPrintE("Failed to locate source crop max width");
+    exit(35);
+}
+
+// Source crop maximum height
+uint32_t scMaxHeight(uint32_t format, const HwcTestDim& dfDim)
+{
+    uint32_t h;
+    list<Rectangle> rectList;
+
+    for (h = searchLimits.sourceCrop.height(); h >= dfDim.height(); h--) {
+        Rectangle rect(format, dfDim, HwcTestDim(dfDim.width(), h));
+        rectList.clear();
+        rectList.push_back(rect);
+        uint32_t num = numOverlays(rectList);
+        if (num > 0) {
+            return h;
+        }
+    }
+    testPrintE("Failed to locate source crop max height");
+    exit(36);
+}
+
+// Source crop minimum dimension
+// Discovers the source crop with the least number of pixels that the
+// HWC will commit to.  Note, this may be different from scMinWidth
+// * scMinHeight, in that this function searches for a combination of
+// width and height.  While the other routines always keep one of the
+// dimensions equal to the corresponding start dimension.
+HwcTestDim scMinDim(uint32_t format, const HwcTestDim& dfDim)
+{
+    uint64_t bestMinPixels = 0;
+    HwcTestDim bestDim;
+    bool bestSet = false; // True when value has been assigned to
+                          // bestMinPixels and bestDim
+
+    bool origVerbose = verbose;  // Temporarily turn off verbose
+    verbose = false;
+    for (uint32_t w = 1; w <= dfDim.width(); w++) {
+        for (uint32_t h = 1; h <= dfDim.height(); h++) {
+            if (bestSet && ((w > bestMinPixels) || (h > bestMinPixels))) {
+                break;
+            }
+
+            HwcTestDim dim(w, h);
+            Rectangle rect(format, dfDim, HwcTestDim(w, h));
+            list<Rectangle> rectList;
+            rectList.push_back(rect);
+            uint32_t num = numOverlays(rectList);
+            if (num > 0) {
+                uint64_t pixels = dim.width() * dim.height();
+                if (!bestSet || (pixels < bestMinPixels)) {
+                    bestMinPixels = pixels;
+                    bestDim = dim;
+                    bestSet = true;
+                }
+            }
+        }
+    }
+    verbose = origVerbose;
+
+    if (!bestSet) {
+        testPrintE("Unable to locate source crop min dimension");
+        exit(20);
+    }
+
+    return bestDim;
+}
+
+// Source crop maximum dimension
+HwcTestDim scMaxDim(uint32_t format, const HwcTestDim& dfDim)
+{
+    uint64_t bestMaxPixels = 0;
+    HwcTestDim bestDim;
+    bool bestSet = false; // True when value has been assigned to
+                          // bestMaxPixels and bestDim;
+
+    // Potentially increase benchmark performance by first checking
+    // for the common case of supporting the maximum checked source size
+    HwcTestDim dim = searchLimits.sourceCrop;
+    Rectangle rect(format, dfDim, searchLimits.sourceCrop);
+    list<Rectangle> rectList;
+    rectList.push_back(rect);
+    uint32_t num = numOverlays(rectList);
+    if (num == 1) { return dim; }
+
+    // TODO: Use a binary search
+    bool origVerbose = verbose;  // Temporarily turn off verbose
+    verbose = false;
+    for (uint32_t w = dfDim.width();
+         w <= searchLimits.sourceCrop.width(); w++) {
+        for (uint32_t h = dfDim.height();
+             h <= searchLimits.sourceCrop.height(); h++) {
+            if (bestSet && ((w * h) <= bestMaxPixels)) { continue; }
+
+            HwcTestDim dim(w, h);
+            Rectangle rect(format, dfDim, dim);
+            list<Rectangle> rectList;
+            rectList.push_back(rect);
+            uint32_t num = numOverlays(rectList);
+            if (num > 0) {
+                uint64_t pixels = dim.width() * dim.height();
+                if (!bestSet || (pixels > bestMaxPixels)) {
+                    bestMaxPixels = pixels;
+                    bestDim = dim;
+                    bestSet = true;
+                }
+            }
+        }
+    }
+    verbose = origVerbose;
+
+    if (!bestSet) {
+        testPrintE("Unable to locate source crop max dimension");
+        exit(21);
+    }
+
+    return bestDim;
+}
+
+// Source crop horizontal scale
+// Determines the maximum factor by which the source crop can be larger
+// that the display frame.  The commit point is discovered through a
+// binary search of rational numbers.  The numerator in each of the
+// rational numbers contains the dimension for the source crop, while
+// the denominator specifies the dimension for the display frame.  On
+// each pass of the binary search the mid-point between the greatest
+// point committed to (best) and the smallest point in which a commit
+// has failed is calculated.  This mid-point is then passed to a function
+// named double2Rational, which determines the closest rational numbers
+// just below and above the mid-point.  By default the lower rational
+// number is used for the scale factor on the next pass of the binary
+// search.  The upper value is only used when best is already equal
+// to the lower value.  This only occurs when the lower value has already
+// been tried.
+Rational scHScale(uint32_t format,
+                      const HwcTestDim& dfMin, const HwcTestDim& dfMax,
+                      const HwcTestDim& scMin, const HwcTestDim& scMax,
+                      HwcTestDim& outBestDf, HwcTestDim& outBestSc)
+{
+    HwcTestDim scDim, dfDim; // Source crop and display frame dimension
+    Rational best(0, 1), minBad;  // Current bounds for a binary search
+                                  // MinGood is set below the lowest
+                                  // possible scale.  The value of minBad,
+                                  // will be set by the first pass
+                                  // of the binary search.
+
+    // Perform the passes of the binary search
+    bool firstPass = true;
+    do {
+        // On first pass try the maximum scale within the search limits
+        if (firstPass) {
+            // Try the maximum possible scale, within the search limits
+            scDim = HwcTestDim(searchLimits.sourceCrop.width(), scMin.height());
+            dfDim = dfMin;
+        } else {
+            // Subsequent pass
+            // Halve the difference between best and minBad.
+            Rational lower, upper, selected;
+
+            // Try the closest ratio halfway between minBood and minBad;
+            // TODO: Avoid rounding issue by using Rational type for
+            //       midpoint.  For now will use double, which should
+            //       have more than sufficient resolution.
+            double mid = (double) best
+                         + ((double) minBad - (double) best) / 2.0;
+            Rational::double2Rational(mid,
+                            Range(scMin.width(), scMax.width()),
+                            Range(dfMin.width(), dfMax.width()),
+                            lower, upper);
+            if (((lower == best) && (upper == minBad))) {
+                return best;
+            }
+
+            // Use lower value unless its already been tried
+            selected = (lower != best) ? lower : upper;
+
+            // Assign the size of the source crop and display frame
+            // from the selected ratio of source crop to display frame.
+            scDim = HwcTestDim(selected.numerator(), scMin.height());
+            dfDim = HwcTestDim(selected.denominator(), dfMin.height());
+        }
+
+        // See if the HWC will commit to this combination
+        Rectangle rect(format, dfDim, scDim);
+        list<Rectangle> rectList;
+        rectList.push_back(rect);
+        uint32_t num = numOverlays(rectList);
+
+        if (verbose) {
+            testPrintI("  scHscale num: %u scale: %f dfDim: %s scDim: %s",
+                       num, (float) Rational(scDim.width(), dfDim.width()),
+                       ((string) dfDim).c_str(), ((string) scDim).c_str());
+        }
+        if (num == 1) {
+            // HWC committed to the combination
+            // This is the best scale factor seen so far.  Report the
+            // dimensions to the caller, in case nothing better is seen.
+            outBestDf = dfDim;
+            outBestSc = scDim;
+
+            // Success on the first pass means the largest possible scale
+            // is supported, in which case no need to search any further.
+            if (firstPass) { return Rational(scDim.width(), dfDim.width()); }
+
+            // Update the lower bound of the binary search
+            best = Rational(scDim.width(), dfDim.width());
+        } else {
+            // HWC didn't commit to this combination, so update the
+            // upper bound of the binary search.
+            minBad = Rational(scDim.width(), dfDim.width());
+        }
+
+        firstPass = false;
+    } while (best != minBad);
+
+    return best;
+}
+
+// Source crop vertical scale
+// Determines the maximum factor by which the source crop can be larger
+// that the display frame.  The commit point is discovered through a
+// binary search of rational numbers.  The numerator in each of the
+// rational numbers contains the dimension for the source crop, while
+// the denominator specifies the dimension for the display frame.  On
+// each pass of the binary search the mid-point between the greatest
+// point committed to (best) and the smallest point in which a commit
+// has failed is calculated.  This mid-point is then passed to a function
+// named double2Rational, which determines the closest rational numbers
+// just below and above the mid-point.  By default the lower rational
+// number is used for the scale factor on the next pass of the binary
+// search.  The upper value is only used when best is already equal
+// to the lower value.  This only occurs when the lower value has already
+// been tried.
+Rational scVScale(uint32_t format,
+                      const HwcTestDim& dfMin, const HwcTestDim& dfMax,
+                      const HwcTestDim& scMin, const HwcTestDim& scMax,
+                      HwcTestDim& outBestDf, HwcTestDim& outBestSc)
+{
+    HwcTestDim scDim, dfDim; // Source crop and display frame dimension
+    Rational best(0, 1), minBad;  // Current bounds for a binary search
+                                  // MinGood is set below the lowest
+                                  // possible scale.  The value of minBad,
+                                  // will be set by the first pass
+                                  // of the binary search.
+
+    // Perform the passes of the binary search
+    bool firstPass = true;
+    do {
+        // On first pass try the maximum scale within the search limits
+        if (firstPass) {
+            // Try the maximum possible scale, within the search limits
+            scDim = HwcTestDim(scMin.width(), searchLimits.sourceCrop.height());
+            dfDim = dfMin;
+        } else {
+            // Subsequent pass
+            // Halve the difference between best and minBad.
+            Rational lower, upper, selected;
+
+            // Try the closest ratio halfway between minBood and minBad;
+            // TODO: Avoid rounding issue by using Rational type for
+            //       midpoint.  For now will use double, which should
+            //       have more than sufficient resolution.
+            double mid = (double) best
+                         + ((double) minBad - (double) best) / 2.0;
+            Rational::double2Rational(mid,
+                            Range(scMin.height(), scMax.height()),
+                            Range(dfMin.height(), dfMax.height()),
+                            lower, upper);
+            if (((lower == best) && (upper == minBad))) {
+                return best;
+            }
+
+            // Use lower value unless its already been tried
+            selected = (lower != best) ? lower : upper;
+
+            // Assign the size of the source crop and display frame
+            // from the selected ratio of source crop to display frame.
+            scDim = HwcTestDim(scMin.width(), selected.numerator());
+            dfDim = HwcTestDim(dfMin.width(), selected.denominator());
+        }
+
+        // See if the HWC will commit to this combination
+        Rectangle rect(format, dfDim, scDim);
+        list<Rectangle> rectList;
+        rectList.push_back(rect);
+        uint32_t num = numOverlays(rectList);
+
+        if (verbose) {
+            testPrintI("  scHscale num: %u scale: %f dfDim: %s scDim: %s",
+                       num, (float) Rational(scDim.height(), dfDim.height()),
+                       ((string) dfDim).c_str(), ((string) scDim).c_str());
+        }
+        if (num == 1) {
+            // HWC committed to the combination
+            // This is the best scale factor seen so far.  Report the
+            // dimensions to the caller, in case nothing better is seen.
+            outBestDf = dfDim;
+            outBestSc = scDim;
+
+            // Success on the first pass means the largest possible scale
+            // is supported, in which case no need to search any further.
+            if (firstPass) { return Rational(scDim.height(), dfDim.height()); }
+
+            // Update the lower bound of the binary search
+            best = Rational(scDim.height(), dfDim.height());
+        } else {
+            // HWC didn't commit to this combination, so update the
+            // upper bound of the binary search.
+            minBad = Rational(scDim.height(), dfDim.height());
+        }
+
+        firstPass = false;
+    } while (best != minBad);
+
+    return best;
+}
+
+uint32_t numOverlapping(uint32_t backgroundFormat, uint32_t foregroundFormat,
+                        uint32_t backgroundBlend, uint32_t foregroundBlend)
+{
+    list<Rectangle> rectList;
+
+    Rectangle background(backgroundFormat, startDim, startDim);
+    background.blend = backgroundBlend;
+    rectList.push_back(background);
+
+    // TODO: Handle cases where startDim is so small that adding 5
+    //       causes frames not to overlap.
+    // TODO: Handle cases where startDim is so large that adding 5
+    //       cause a portion or all of the foreground displayFrame
+    //       to be off the display.
+    Rectangle foreground(foregroundFormat, startDim, startDim);
+    foreground.displayFrame.left += 5;
+    foreground.displayFrame.top += 5;
+    foreground.displayFrame.right += 5;
+    foreground.displayFrame.bottom += 5;
+    background.blend = foregroundBlend;
+    rectList.push_back(foreground);
+
+    uint32_t num = numOverlays(rectList);
+
+    return num;
+}
+
+Rectangle::Rectangle(uint32_t graphicFormat, HwcTestDim dfDim,
+                     HwcTestDim sDim) :
+    format(graphicFormat), transform(defaultTransform),
+    blend(defaultBlend), color(defaultColor), alpha(defaultAlpha),
+    sourceCrop(sDim), displayFrame(dfDim)
+{
+    // Set source dimension
+    // Can't use a base initializer, because the setting of format
+    // must be done before setting the sourceDimension.
+    setSourceDim(sDim);
+}
+
+void Rectangle::setSourceDim(HwcTestDim dim)
+{
+    this->sourceDim = dim;
+
+    const struct hwcTestGraphicFormat *attrib;
+    attrib = hwcTestGraphicFormatLookup(this->format);
+    if (attrib != NULL) {
+        if (sourceDim.width() % attrib->wMod) {
+            sourceDim.setWidth(sourceDim.width() + attrib->wMod
+            - (sourceDim.width() % attrib->wMod));
+        }
+        if (sourceDim.height() % attrib->hMod) {
+            sourceDim.setHeight(sourceDim.height() + attrib->hMod
+            - (sourceDim.height() % attrib->hMod));
+        }
+    }
+}
+
+// Rational member functions
+bool Rational::operator==(const Rational& other) const
+{
+    if (((uint64_t) _n * other._d)
+        == ((uint64_t) _d * other._n)) { return true; }
+
+    return false;
+}
+
+bool Rational::operator<(const Rational& other) const
+{
+    if (((uint64_t) _n * other._d)
+        < ((uint64_t) _d * other._n)) { return true; }
+
+    return false;
+}
+
+Rational::operator string() const
+{
+    ostringstream out;
+
+    out << _n << '/' << _d;
+
+    return out.str();
+}
+
+void Rational::double2Rational(double f, Range nRange, Range dRange,
+                    Rational& lower, Rational& upper)
+{
+    Rational bestLower(nRange.lower(), dRange.upper());
+    Rational bestUpper(nRange.upper(), dRange.lower());
+
+    // Search for a better solution
+    for (uint32_t d = dRange.lower(); d <= dRange.upper(); d++) {
+        Rational val(d * f, d);  // Lower, because double to int cast truncates
+
+        if ((val.numerator() < nRange.lower())
+            || (val.numerator() > nRange.upper())) { continue; }
+
+        if (((double) val > (double) bestLower) && ((double) val <= f)) {
+            bestLower = val;
+        } 
+
+        val.setNumerator(val.numerator() + 1);
+        if (val.numerator() > nRange.upper()) { continue; }
+
+        if (((double) val < (double) bestUpper) && ((double) val >= f)) {
+            bestUpper = val;
+        }
+    }
+
+    lower = bestLower;
+    upper = bestUpper;
+}
+
+// Local functions
+
+// Num Overlays
+// Given a list of rectangles, determine how many HWC will commit to render
+uint32_t numOverlays(list<Rectangle>& rectList)
+{
+    hwc_layer_list_t *hwcList;
+    list<sp<GraphicBuffer> > buffers;
+
+    hwcList = hwcTestCreateLayerList(rectList.size());
+    if (hwcList == NULL) {
+        testPrintE("numOverlays create hwcList failed");
+        exit(30);
+    }
+
+    hwc_layer_t *layer = &hwcList->hwLayers[0];
+    for (std::list<Rectangle>::iterator it = rectList.begin();
+         it != rectList.end(); ++it, ++layer) {
+        // Allocate the texture for the source frame
+        // and push it onto the buffers list, so that it
+        // stays in scope until a return from this function.
+        sp<GraphicBuffer> texture;
+        texture  = new GraphicBuffer(it->sourceDim.width(),
+                                     it->sourceDim.height(),
+                                     it->format, texUsage);
+        buffers.push_back(texture);
+
+        layer->handle = texture->handle;
+        layer->blending = it->blend;
+        layer->transform = it->transform;
+        layer->sourceCrop = it->sourceCrop;
+        layer->displayFrame = it->displayFrame;
+
+        layer->visibleRegionScreen.numRects = 1;
+        layer->visibleRegionScreen.rects = &layer->displayFrame;
+    }
+
+    // Perform prepare operation
+    if (verbose) { testPrintI("Prepare:"); hwcTestDisplayList(hwcList); }
+    hwcDevice->prepare(hwcDevice, hwcList);
+    if (verbose) {
+        testPrintI("Post Prepare:");
+        hwcTestDisplayListPrepareModifiable(hwcList);
+    }
+
+    // Count the number of overlays
+    uint32_t total = 0;
+    for (unsigned int n1 = 0; n1 < hwcList->numHwLayers; n1++) {
+        if (hwcList->hwLayers[n1].compositionType == HWC_OVERLAY) {
+            total++;
+        }
+    }
+
+    // Free the layer list and graphic buffers
+    hwcTestFreeLayerList(hwcList);
+
+    return total;
+}
+
+string transformList2str(const list<uint32_t>& transformList)
+{
+    ostringstream out;
+
+    for (list<uint32_t>::const_iterator it = transformList.begin();
+         it != transformList.end(); ++it) {
+        uint32_t id = *it;
+
+        if (it != transformList.begin()) {
+            out << ", ";
+        }
+        out << id;
+
+        for (unsigned int idx = 0; idx < NUMA(transformType); idx++) {
+            if (id == transformType[idx].id) {
+                out << " (" << transformType[idx].desc << ')';
+                break;
+            }
+        }
+    }
+
+    return out.str();
+}
+
+string blendList2str(const list<uint32_t>& blendList)
+{
+    ostringstream out;
+
+    for (list<uint32_t>::const_iterator it = blendList.begin();
+         it != blendList.end(); ++it) {
+        uint32_t id = *it;
+
+        if (it != blendList.begin()) {
+            out << ", ";
+        }
+        out << id;
+
+        for (unsigned int idx = 0; idx < NUMA(blendType); idx++) {
+            if (id == blendType[idx].id) {
+                out << " (" << blendType[idx].desc << ')';
+                break;
+            }
+        }
+    }
+
+    return out.str();
+}
+
+void init(void)
+{
+    srand48(0);
+
+    hwcTestInitDisplay(verbose, &dpy, &surface, &width, &height);
+
+    hwcTestOpenHwc(&hwcDevice);
+}
+
+void printFormatHeadings(size_t indent)
+{
+    for (size_t row = 0; row <= maxHeadingLen; row++) {
+        ostringstream line;
+        for(vector<string>::iterator it = formats.begin();
+            it != formats.end(); ++it) {
+            if ((maxHeadingLen - row) <= it->length()) {
+                if (row != maxHeadingLen) {
+                    char ch = (*it)[it->length() - (maxHeadingLen - row)];
+                    line << ' ' << setw(printFieldWidth) << ch;
+                } else {
+                    line << ' ' << string(printFieldWidth, '-');
+                }
+            } else {
+               line << ' ' << setw(printFieldWidth) << "";
+            }
+        }
+        testPrintI("%*s%s", indent + maxHeadingLen, "",
+                   line.str().c_str());
+    }
+}
+
+void printOverlapLine(size_t indent, const string formatStr,
+                        const vector<uint32_t>& results)
+{
+    ostringstream line;
+
+    line << setw(indent + maxHeadingLen - formatStr.length()) << "";
+
+    line << formatStr;
+
+    for (vector<uint32_t>::const_iterator it = results.begin();
+         it != results.end(); ++it) {
+        line << ' ' << setw(printFieldWidth) << *it;
+    }
+
+    testPrintI("%s", line.str().c_str());
+}
+
+void printSyntax(const char *cmd)
+{
+    testPrintE("  %s [options] [graphicFormat] ...",
+               cmd);
+    testPrintE("    options:");
+    testPrintE("      -s [width, height] - start dimension");
+    testPrintE("      -v - Verbose");
+    testPrintE("");
+    testPrintE("    graphic formats:");
+    for (unsigned int n1 = 0; n1 < NUMA(hwcTestGraphicFormat); n1++) {
+        testPrintE("      %s", hwcTestGraphicFormat[n1].desc);
+    }
+}
diff --git a/opengl/tests/hwc/hwcRects.cpp b/opengl/tests/hwc/hwcRects.cpp
new file mode 100644
index 0000000..523e3de
--- /dev/null
+++ b/opengl/tests/hwc/hwcRects.cpp
@@ -0,0 +1,577 @@
+/*
+ * Copyright (C) 2011 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+/*
+ * Hardware Composer Rectangles
+ *
+ * Synopsis
+ *   hwcRects [options] (graphicFormat displayFrame [attributes],)...
+ *     options:
+ *       -D #.## - End of test delay
+ *       -v - Verbose
+ *
+ *      graphic formats:
+ *        RGBA8888 (reference frame default)
+ *        RGBX8888
+ *        RGB888
+ *        RGB565
+ *        BGRA8888
+ *        RGBA5551
+ *        RGBA4444
+ *        YV12
+ *
+ *      displayFrame
+ *        [left, top, right, bottom]
+ *
+ *      attributes:
+ *        transform: none | fliph | flipv | rot90 | rot180 | rot270
+ *        blend: none | premult | coverage
+ *        color: [0.##, 0.##, 0.##]
+ *        alpha: 0.##
+ *        sourceDim: [width, height]
+ *        sourceCrop: [left, top, right, bottom]
+ *
+ *      Example:
+ *        # White YV12 rectangle, with overlapping turquoise
+ *        #  RGBA8888 rectangle at 30%% (alpha: 0.7) transparency
+ *        hwcRects -v -D 30.0 \
+ *          YV12 [50, 80, 200, 300] transform: none \
+ *            color: [1.0, 0.5, 0.5], \
+ *          RGBA8888 [100, 150, 300, 400] blend: coverage \
+ *            color: [0.251, 0.878, 0.816] alpha: 0.7 \
+ *            sourceDim: [50, 60] sourceCrop: [5, 8, 12, 15]
+ *
+ * Description
+ *   Constructs a Hardware Composer (HWC) list of frames from
+ *   command-line specified parameters.  Then sends it to the HWC
+ *   be rendered.  The intended purpose of this tool is as a means to
+ *   reproduce and succinctly specify an observed HWC operation, with
+ *   no need to modify/compile a program.
+ *
+ *   The command-line syntax consists of a few standard command-line
+ *   options and then a description of one or more frames.  The frame
+ *   descriptions are separated from one another via a comma.  The
+ *   beginning of a frame description requires the specification
+ *   of the graphic format and then the display frame rectangle where
+ *   the frame will be displayed.  The display frame rectangle is
+ *   specified as follows, with the right and bottom coordinates being
+ *   exclusive values:
+ *
+ *     [left, top, right, bottom]
+ *    
+ *   After these two required parameters each frame description can
+ *   specify 1 or more optional attributes.  The name of each optional
+ *   attribute is preceded by a colon.  The current implementation
+ *   then requires white space after the colon and then the value of
+ *   the attribute is specified.  See the synopsis section above for
+ *   a list of attributes and the format of their expected value.
+ */
+
+#include <algorithm>
+#include <assert.h>
+#include <cerrno>
+#include <cmath>
+#include <cstdlib>
+#include <ctime>
+#include <istream>
+#include <libgen.h>
+#include <list>
+#include <sched.h>
+#include <sstream>
+#include <stdint.h>
+#include <string.h>
+#include <unistd.h>
+
+#include <sys/syscall.h>
+#include <sys/types.h>
+#include <sys/wait.h>
+
+#include <EGL/egl.h>
+#include <EGL/eglext.h>
+#include <GLES2/gl2.h>
+#include <GLES2/gl2ext.h>
+
+#include <ui/FramebufferNativeWindow.h>
+#include <ui/GraphicBuffer.h>
+#include <ui/EGLUtils.h>
+
+#define LOG_TAG "hwcRectsTest"
+#include <utils/Log.h>
+#include <testUtil.h>
+
+#include <hardware/hwcomposer.h>
+
+#include <glTestLib.h>
+#include <hwc/hwcTestLib.h>
+
+using namespace std;
+using namespace android;
+
+// Defaults
+const bool defaultVerbose = false;
+const float defaultEndDelay = 2.0; // Default delay after rendering graphics
+
+const uint32_t   defaultFormat = HAL_PIXEL_FORMAT_RGBA_8888;
+const int32_t    defaultTransform = 0;
+const uint32_t   defaultBlend = HWC_BLENDING_NONE;
+const ColorFract defaultColor(0.5, 0.5, 0.5);
+const float      defaultAlpha = 1.0; // Opaque
+const HwcTestDim defaultSourceDim(1, 1);
+const struct hwc_rect defaultSourceCrop = {0, 0, 1, 1};
+const struct hwc_rect defaultDisplayFrame = {0, 0, 100, 100};
+
+// Defines
+#define MAXCMD               200
+#define CMD_STOP_FRAMEWORK   "stop 2>&1"
+#define CMD_START_FRAMEWORK  "start 2>&1"
+
+// Macros
+#define NUMA(a) (sizeof(a) / sizeof(a [0])) // Num elements in an array
+
+// Local types
+class Rectangle {
+public:
+    Rectangle() : format(defaultFormat), transform(defaultTransform),
+                  blend(defaultBlend), color(defaultColor),
+                  alpha(defaultAlpha), sourceDim(defaultSourceDim),
+                  sourceCrop(defaultSourceCrop),
+                  displayFrame(defaultDisplayFrame) {};
+
+    uint32_t     format;
+    uint32_t     transform;
+    int32_t      blend;
+    ColorFract   color;
+    float        alpha;
+    HwcTestDim   sourceDim;
+    struct hwc_rect   sourceCrop;
+    struct hwc_rect   displayFrame;
+
+    sp<GraphicBuffer> texture;
+};
+
+// Globals
+list<Rectangle> rectangle;
+static const int texUsage = GraphicBuffer::USAGE_HW_TEXTURE |
+        GraphicBuffer::USAGE_SW_WRITE_RARELY;
+static hwc_composer_device_t *hwcDevice;
+static EGLDisplay dpy;
+static EGLSurface surface;
+static EGLint width, height;
+
+// Function prototypes
+static Rectangle parseRect(string rectStr);
+void init(void);
+void printSyntax(const char *cmd);
+
+// Command-line option settings
+static bool verbose = defaultVerbose;
+static float endDelay = defaultEndDelay;
+
+/*
+ * Main
+ *
+ * Performs the following high-level sequence of operations:
+ *
+ *   1. Parse command-line options
+ *
+ *   2. Stop framework
+ *
+ *   3. Initialization
+ *
+ *   4. Parse frame descriptions
+ *
+ *   5. Create HWC list from frame descriptions
+ *
+ *   6. Have HWC render the list description of the frames
+ *
+ *   7. Delay for amount of time given by endDelay
+ *
+ *   8. Start framework
+ */
+int
+main(int argc, char *argv[])
+{
+    int     rv, opt;
+    char   *chptr;
+    bool    error;
+    string  str;
+    char cmd[MAXCMD];
+
+    testSetLogCatTag(LOG_TAG);
+
+    // Parse command line arguments
+    while ((opt = getopt(argc, argv, "D:v?h")) != -1) {
+        switch (opt) {
+          case 'D': // End of test delay
+            endDelay = strtod(optarg, &chptr);
+            if ((*chptr != '\0') || (endDelay < 0.0)) {
+                testPrintE("Invalid command-line specified end of test delay "
+                           "of: %s", optarg);
+                exit(1);
+            }
+            break;
+
+          case 'v': // Verbose
+            verbose = true;
+            break;
+
+          case 'h': // Help
+          case '?':
+          default:
+            printSyntax(basename(argv[0]));
+            exit(((optopt == 0) || (optopt == '?')) ? 0 : 2);
+        }
+    }
+
+    // Stop framework
+    rv = snprintf(cmd, sizeof(cmd), "%s", CMD_STOP_FRAMEWORK);
+    if (rv >= (signed) sizeof(cmd) - 1) {
+        testPrintE("Command too long for: %s", CMD_STOP_FRAMEWORK);
+        exit(3);
+    }
+    testExecCmd(cmd);
+    testDelay(1.0); // TODO - needs means to query whether asyncronous stop
+                    // framework operation has completed.  For now, just wait
+                    // a long time.
+
+    init();
+
+    // Parse rectangle descriptions
+    int numOpen = 0; // Current number of unmatched <[
+    string rectDesc(""); // String description of a single rectangle
+    while (optind < argc) {
+        string argNext = string(argv[optind++]);
+
+        if (rectDesc.length()) { rectDesc += ' '; }
+        rectDesc += argNext;
+
+        // Count number of opening <[ and matching >]
+        // At this point not worried about an opening character being
+        // matched by it's corresponding closing character.  For example,
+        // "<1.0, 2.0]" is incorrect because the opening < should be matched
+        // with a closing >, instead of the closing ].  Such errors are
+        // detected when the actual value is parsed.
+        for (unsigned int n1 = 0; n1 < argNext.length(); n1++) {
+            switch(argNext[n1]) {
+              case '[':
+              case '<':
+                numOpen++;
+                break;
+
+              case ']':
+              case '>':
+                numOpen--;
+                break;
+            }
+
+            // Error anytime there is more closing then opening characters
+            if (numOpen < 0) {
+                testPrintI("Mismatched number of opening <[ with "
+                           "closing >] in: %s", rectDesc.c_str());
+                exit(4);
+            }
+        }
+
+        // Description of a rectangle is complete when all opening
+        // <[ are closed with >] and the string ends with a comma or
+        // there are no more args.
+        if ((numOpen == 0) && rectDesc.length()
+            && ((rectDesc[rectDesc.length() - 1] == ',')
+                || (optind == argc))) {
+            // Remove trailing comma if it is present
+            if (rectDesc[rectDesc.length() - 1] == ',') {
+                rectDesc.erase(rectDesc.length() - 1);
+            }
+
+            // Parse string description of rectangle
+            Rectangle rect = parseRect(rectDesc);
+
+            // Add to the list of rectangles
+            rectangle.push_back(rect);
+
+            // Prepare for description of another rectangle
+            rectDesc = string("");
+        }
+    }
+
+    // Create list of frames
+    hwc_layer_list_t *list;
+    list = hwcTestCreateLayerList(rectangle.size());
+    if (list == NULL) {
+        testPrintE("hwcTestCreateLayerList failed");
+        exit(5);
+    }
+
+    hwc_layer_t *layer = &list->hwLayers[0];
+    for (std::list<Rectangle>::iterator it = rectangle.begin();
+         it != rectangle.end(); ++it, ++layer) {
+        layer->handle = it->texture->handle;
+        layer->blending = it->blend;
+        layer->transform = it->transform;
+        layer->sourceCrop = it->sourceCrop;
+        layer->displayFrame = it->displayFrame;
+
+        layer->visibleRegionScreen.numRects = 1;
+        layer->visibleRegionScreen.rects = &layer->displayFrame;
+    }
+
+    // Perform prepare operation
+    if (verbose) { testPrintI("Prepare:"); hwcTestDisplayList(list); }
+    hwcDevice->prepare(hwcDevice, list);
+    if (verbose) {
+        testPrintI("Post Prepare:");
+        hwcTestDisplayListPrepareModifiable(list);
+    }
+
+    // Turn off the geometry changed flag
+    list->flags &= ~HWC_GEOMETRY_CHANGED;
+
+    // Perform the set operation(s)
+    if (verbose) {testPrintI("Set:"); }
+    if (verbose) { hwcTestDisplayListHandles(list); }
+    hwcDevice->set(hwcDevice, dpy, surface, list);
+
+    testDelay(endDelay);
+
+    // Start framework
+    rv = snprintf(cmd, sizeof(cmd), "%s", CMD_START_FRAMEWORK);
+    if (rv >= (signed) sizeof(cmd) - 1) {
+        testPrintE("Command too long for: %s", CMD_START_FRAMEWORK);
+        exit(6);
+    }
+    testExecCmd(cmd);
+
+    return 0;
+}
+
+// Parse string description of rectangle and add it to list of rectangles
+// to be rendered.
+static Rectangle parseRect(string rectStr)
+{
+    int rv;
+    string str;
+    bool   error;
+    istringstream in(rectStr);
+    const struct hwcTestGraphicFormat *format;
+    Rectangle rect;
+    struct hwc_rect hwcRect;
+
+    // Graphic Format
+    in >> str;
+    if (!in) {
+        testPrintE("Error parsing format from: %s", rectStr.c_str());
+        exit(20);
+    }
+    format = hwcTestGraphicFormatLookup(str.c_str());
+    if (format == NULL) {
+        testPrintE("Unknown graphic format in: %s", rectStr.c_str());
+        exit(21);
+    }
+    rect.format = format->format;
+
+    // Display Frame
+    rect.displayFrame = hwcTestParseHwcRect(in, error);
+    if (error) {
+        testPrintE("Invalid display frame in: %s", rectStr.c_str());
+        exit(22);
+    }
+
+    // Set default sourceDim and sourceCrop based on size of display frame.
+    // Default is source size equal to the size of the display frame, with
+    // the source crop being the entire size of the source frame.
+    rect.sourceDim = HwcTestDim(rect.displayFrame.right
+                                     - rect.displayFrame.left,
+                                 rect.displayFrame.bottom
+                                     - rect.displayFrame.top);
+    rect.sourceCrop.left = 0;
+    rect.sourceCrop.top = 0;
+    rect.sourceCrop.right = rect.sourceDim.width();
+    rect.sourceCrop.bottom = rect.sourceDim.height();
+
+    // Optional settings
+    while ((in.tellg() < (streampos) in.str().length())
+           && (in.tellg() != (streampos) -1)) {
+        string attrName;
+
+        in >> attrName;
+        if (in.eof()) { break; }
+        if (!in) {
+            testPrintE("Error reading attribute name in: %s",
+                       rectStr.c_str());
+            exit(23);
+        }
+
+        // Transform
+        if (attrName == "transform:") { // Transform
+            string str;
+
+            in >> str;
+            if (str == "none") {
+                rect.transform = 0;
+            } else if (str == "fliph") {
+                rect.transform = HWC_TRANSFORM_FLIP_H;
+            } else if (str == "flipv") {
+                rect.transform = HWC_TRANSFORM_FLIP_V;
+            } else if (str == "rot90") {
+                rect.transform = HWC_TRANSFORM_ROT_90;
+            } else if (str == "rot180") {
+                rect.transform = HWC_TRANSFORM_ROT_180;
+            } else if (str == "rot270") {
+                rect.transform = HWC_TRANSFORM_ROT_270;
+            } else {
+                testPrintE("Unknown transform of \"%s\" in: %s", str.c_str(),
+                           rectStr.c_str());
+                exit(24);
+            }
+        } else if (attrName == "blend:") { // Blend
+            string str;
+
+            in >> str;
+            if (str == string("none")) {
+                rect.blend = HWC_BLENDING_NONE;
+            } else if (str == "premult") {
+                rect.blend = HWC_BLENDING_PREMULT;
+            } else if (str == "coverage") {
+                rect.blend = HWC_BLENDING_COVERAGE;
+            } else {
+                testPrintE("Unknown blend of \"%s\" in: %s", str.c_str(),
+                           rectStr.c_str());
+                exit(25);
+            }
+        } else if (attrName == "color:") { // Color
+            rect.color = hwcTestParseColor(in, error);
+            if (error) {
+                testPrintE("Error parsing color in: %s", rectStr.c_str());
+                exit(26);
+            }
+        } else if (attrName == "alpha:") { // Alpha
+            in >> rect.alpha;
+            if (!in) {
+                testPrintE("Error parsing value for alpha attribute in: %s",
+                           rectStr.c_str());
+                exit(27);
+            }
+        } else if (attrName == "sourceDim:") { // Source Dimension
+           rect.sourceDim = hwcTestParseDim(in, error);
+            if (error) {
+                testPrintE("Error parsing source dimenision in: %s",
+                           rectStr.c_str());
+                exit(28);
+            }
+        } else if (attrName == "sourceCrop:") { // Source Crop
+            rect.sourceCrop = hwcTestParseHwcRect(in, error);
+            if (error) {
+                testPrintE("Error parsing source crop in: %s",
+                           rectStr.c_str());
+                exit(29);
+            }
+        } else { // Unknown attribute
+            testPrintE("Unknown attribute of \"%s\" in: %s", attrName.c_str(),
+                       rectStr.c_str());
+            exit(30);
+        }
+    }
+
+    // Validate
+    if (((uint32_t) rect.sourceCrop.left >= rect.sourceDim.width())
+        || ((uint32_t) rect.sourceCrop.right > rect.sourceDim.width())
+        || ((uint32_t) rect.sourceCrop.top >= rect.sourceDim.height())
+        || ((uint32_t) rect.sourceCrop.bottom > rect.sourceDim.height())) {
+        testPrintE("Invalid source crop in: %s", rectStr.c_str());
+        exit(31);
+    }
+    if ((rect.displayFrame.left >= width)
+        || (rect.displayFrame.right > width)
+        || (rect.displayFrame.top >= height)
+        || (rect.displayFrame.bottom > height)) {
+        testPrintE("Invalid display frame in: %s", rectStr.c_str());
+        exit(32);
+    }
+    if ((rect.alpha < 0.0) || (rect.alpha > 1.0)) {
+        testPrintE("Invalid alpha in: %s", rectStr.c_str());
+        exit(33);
+    }
+
+    // Create source texture
+    rect.texture = new GraphicBuffer(rect.sourceDim.width(),
+                                     rect.sourceDim.height(),
+                                     rect.format, texUsage);
+    if ((rv = rect.texture->initCheck()) != NO_ERROR) {
+        testPrintE("source texture initCheck failed, rv: %i", rv);
+        testPrintE("  %s", rectStr.c_str());
+
+    }
+
+    // Fill with uniform color
+    hwcTestFillColor(rect.texture.get(), rect.color, rect.alpha);
+    if (verbose) {
+        testPrintI("    buf: %p handle: %p format: %s width: %u height: %u "
+                   "color: %s alpha: %f",
+                   rect.texture.get(), rect.texture->handle, format->desc,
+                   rect.sourceDim.width(), rect.sourceDim.height(),
+                   string(rect.color).c_str(), rect.alpha);
+    }
+
+    return rect;
+}
+
+void init(void)
+{
+    // Seed pseudo random number generator
+    // Needed so that the pad areas of frames are filled with a deterministic
+    // pseudo random value.
+    srand48(0);
+
+    hwcTestInitDisplay(verbose, &dpy, &surface, &width, &height);
+
+    hwcTestOpenHwc(&hwcDevice);
+}
+
+void printSyntax(const char *cmd)
+{
+    testPrintE("  %s [options] (graphicFormat displayFrame [attributes],)...",
+               cmd);
+    testPrintE("    options:");
+    testPrintE("      -D End of test delay");
+    testPrintE("      -v Verbose");
+    testPrintE("");
+    testPrintE("    graphic formats:");
+    for (unsigned int n1 = 0; n1 < NUMA(hwcTestGraphicFormat); n1++) {
+        testPrintE("      %s", hwcTestGraphicFormat[n1].desc);
+    }
+    testPrintE("");
+    testPrintE("    displayFrame");
+    testPrintE("      [left, top, right, bottom]");
+    testPrintE("");
+    testPrintE("    attributes:");
+    testPrintE("      transform: none | fliph | flipv | rot90 | rot180 "
+               " | rot270");
+    testPrintE("      blend: none | premult | coverage");
+    testPrintE("      color: [0.##, 0.##, 0.##]");
+    testPrintE("      alpha: 0.##");
+    testPrintE("      sourceDim: [width, height]");
+    testPrintE("      sourceCrop: [left, top, right, bottom]");
+    testPrintE("");
+    testPrintE("    Example:");
+    testPrintE("      # White YV12 rectangle, with overlapping turquoise ");
+    testPrintE("      #  RGBA8888 rectangle at 30%% (alpha: 0.7) transparency");
+    testPrintE("      %s -v -D 30.0 \\", cmd);
+    testPrintE("        YV12 [50, 80, 200, 300] transform: none \\");
+    testPrintE("          color: [1.0, 0.5, 0.5], \\");
+    testPrintE("        RGBA8888 [100, 150, 300, 400] blend: coverage \\");
+    testPrintE("          color: [0.251, 0.878, 0.816] alpha: 0.7 \\");
+    testPrintE("          sourceDim: [50, 60] sourceCrop: [5, 8, 12, 15]");
+}
diff --git a/opengl/tests/hwc/hwcStress.cpp b/opengl/tests/hwc/hwcStress.cpp
new file mode 100644
index 0000000..1cefb4b
--- /dev/null
+++ b/opengl/tests/hwc/hwcStress.cpp
@@ -0,0 +1,645 @@
+/*
+ * Copyright (C) 2010 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+/*
+ * Hardware Composer stress test
+ *
+ * Performs a pseudo-random (prandom) sequence of operations to the
+ * Hardware Composer (HWC), for a specified number of passes or for
+ * a specified period of time.  By default the period of time is FLT_MAX,
+ * so that the number of passes will take precedence.
+ *
+ * The passes are grouped together, where (pass / passesPerGroup) specifies
+ * which group a particular pass is in.  This causes every passesPerGroup
+ * worth of sequential passes to be within the same group.  Computationally
+ * intensive operations are performed just once at the beginning of a group
+ * of passes and then used by all the passes in that group.  This is done
+ * so as to increase both the average and peak rate of graphic operations,
+ * by moving computationally intensive operations to the beginning of a group.
+ * In particular, at the start of each group of passes a set of
+ * graphic buffers are created, then used by the first and remaining
+ * passes of that group of passes.
+ *
+ * The per-group initialization of the graphic buffers is performed
+ * by a function called initFrames.  This function creates an array
+ * of smart pointers to the graphic buffers, in the form of a vector
+ * of vectors.  The array is accessed in row major order, so each
+ * row is a vector of smart pointers.  All the pointers of a single
+ * row point to graphic buffers which use the same pixel format and
+ * have the same dimension, although it is likely that each one is
+ * filled with a different color.  This is done so that after doing
+ * the first HWC prepare then set call, subsequent set calls can
+ * be made with each of the layer handles changed to a different
+ * graphic buffer within the same row.  Since the graphic buffers
+ * in a particular row have the same pixel format and dimension,
+ * additional HWC set calls can be made, without having to perform
+ * an HWC prepare call.
+ *
+ * This test supports the following command-line options:
+ *
+ *   -v        Verbose
+ *   -s num    Starting pass
+ *   -e num    Ending pass
+ *   -p num    Execute the single pass specified by num
+ *   -n num    Number of set operations to perform after each prepare operation
+ *   -t float  Maximum time in seconds to execute the test
+ *   -d float  Delay in seconds performed after each set operation
+ *   -D float  Delay in seconds performed after the last pass is executed
+ *
+ * Typically the test is executed for a large range of passes.  By default
+ * passes 0 through 99999 (100,000 passes) are executed.  Although this test
+ * does not validate the generated image, at times it is useful to reexecute
+ * a particular pass and leave the displayed image on the screen for an
+ * extended period of time.  This can be done either by setting the -s
+ * and -e options to the desired pass, along with a large value for -D.
+ * This can also be done via the -p option, again with a large value for
+ * the -D options.
+ *
+ * So far this test only contains code to create graphic buffers with
+ * a continuous solid color.  Although this test is unable to validate the
+ * image produced, any image that contains other than rectangles of a solid
+ * color are incorrect.  Note that the rectangles may use a transparent
+ * color and have a blending operation that causes the color in overlapping
+ * rectangles to be mixed.  In such cases the overlapping portions may have
+ * a different color from the rest of the rectangle.
+ */
+
+#include <algorithm>
+#include <assert.h>
+#include <cerrno>
+#include <cmath>
+#include <cstdlib>
+#include <ctime>
+#include <libgen.h>
+#include <sched.h>
+#include <sstream>
+#include <stdint.h>
+#include <string.h>
+#include <unistd.h>
+#include <vector>
+
+#include <sys/syscall.h>
+#include <sys/types.h>
+#include <sys/wait.h>
+
+#include <EGL/egl.h>
+#include <EGL/eglext.h>
+#include <GLES2/gl2.h>
+#include <GLES2/gl2ext.h>
+
+#include <ui/FramebufferNativeWindow.h>
+#include <ui/GraphicBuffer.h>
+#include <ui/EGLUtils.h>
+
+#define LOG_TAG "hwcStressTest"
+#include <utils/Log.h>
+#include <testUtil.h>
+
+#include <hardware/hwcomposer.h>
+
+#include <glTestLib.h>
+#include <hwc/hwcTestLib.h>
+
+using namespace std;
+using namespace android;
+
+const float maxSizeRatio = 1.3;  // Graphic buffers can be upto this munch
+                                 // larger than the default screen size
+const unsigned int passesPerGroup = 10; // A group of passes all use the same
+                                        // graphic buffers
+
+// Ratios at which rare and frequent conditions should be produced
+const float rareRatio = 0.1;
+const float freqRatio = 0.9;
+
+// Defaults for command-line options
+const bool defaultVerbose = false;
+const unsigned int defaultStartPass = 0;
+const unsigned int defaultEndPass = 99999;
+const unsigned int defaultPerPassNumSet = 10;
+const float defaultPerSetDelay = 0.0; // Default delay after each set
+                                      // operation.  Default delay of
+                                      // zero used so as to perform the
+                                      // the set operations as quickly
+                                      // as possible.
+const float defaultEndDelay = 2.0; // Default delay between completion of
+                                   // final pass and restart of framework
+const float defaultDuration = FLT_MAX; // A fairly long time, so that
+                                       // range of passes will have
+                                       // precedence
+
+// Command-line option settings
+static bool verbose = defaultVerbose;
+static unsigned int startPass = defaultStartPass;
+static unsigned int endPass = defaultEndPass;
+static unsigned int numSet = defaultPerPassNumSet;
+static float perSetDelay = defaultPerSetDelay;
+static float endDelay = defaultEndDelay;
+static float duration = defaultDuration;
+
+// Command-line mutual exclusion detection flags.
+// Corresponding flag set true once an option is used.
+bool eFlag, sFlag, pFlag;
+
+#define MAXSTR               100
+#define MAXCMD               200
+#define BITSPERBYTE            8 // TODO: Obtain from <values.h>, once
+                                 // it has been added
+
+#define CMD_STOP_FRAMEWORK   "stop 2>&1"
+#define CMD_START_FRAMEWORK  "start 2>&1"
+
+#define NUMA(a) (sizeof(a) / sizeof(a [0]))
+#define MEMCLR(addr, size) do { \
+        memset((addr), 0, (size)); \
+    } while (0)
+
+// File scope constants
+const unsigned int blendingOps[] = {
+    HWC_BLENDING_NONE,
+    HWC_BLENDING_PREMULT,
+    HWC_BLENDING_COVERAGE,
+};
+const unsigned int layerFlags[] = {
+    HWC_SKIP_LAYER,
+};
+const vector<unsigned int> vecLayerFlags(layerFlags,
+    layerFlags + NUMA(layerFlags));
+
+const unsigned int transformFlags[] = {
+    HWC_TRANSFORM_FLIP_H,
+    HWC_TRANSFORM_FLIP_V,
+    HWC_TRANSFORM_ROT_90,
+    // ROT_180 & ROT_270 intentionally not listed, because they
+    // they are formed from combinations of the flags already listed.
+};
+const vector<unsigned int> vecTransformFlags(transformFlags,
+    transformFlags + NUMA(transformFlags));
+
+// File scope globals
+static const int texUsage = GraphicBuffer::USAGE_HW_TEXTURE |
+        GraphicBuffer::USAGE_SW_WRITE_RARELY;
+static hwc_composer_device_t *hwcDevice;
+static EGLDisplay dpy;
+static EGLSurface surface;
+static EGLint width, height;
+static vector <vector <sp<GraphicBuffer> > > frames;
+
+// File scope prototypes
+void init(void);
+void initFrames(unsigned int seed);
+template <class T> vector<T> vectorRandSelect(const vector<T>& vec, size_t num);
+template <class T> T vectorOr(const vector<T>& vec);
+
+/*
+ * Main
+ *
+ * Performs the following high-level sequence of operations:
+ *
+ *   1. Command-line parsing
+ *
+ *   2. Initialization
+ *
+ *   3. For each pass:
+ *
+ *        a. If pass is first pass or in a different group from the
+ *           previous pass, initialize the array of graphic buffers.
+ *
+ *        b. Create a HWC list with room to specify a prandomly
+ *           selected number of layers.
+ *
+ *        c. Select a subset of the rows from the graphic buffer array,
+ *           such that there is a unique row to be used for each
+ *           of the layers in the HWC list.
+ *
+ *        d. Prandomly fill in the HWC list with handles
+ *           selected from any of the columns of the selected row.
+ *
+ *        e. Pass the populated list to the HWC prepare call.
+ *
+ *        f. Pass the populated list to the HWC set call.
+ *
+ *        g. If additional set calls are to be made, then for each
+ *           additional set call, select a new set of handles and
+ *           perform the set call.
+ */
+int
+main(int argc, char *argv[])
+{
+    int rv, opt;
+    char *chptr;
+    unsigned int pass;
+    char cmd[MAXCMD];
+    struct timeval startTime, currentTime, delta;
+
+    testSetLogCatTag(LOG_TAG);
+
+    // Parse command line arguments
+    while ((opt = getopt(argc, argv, "vp:d:D:n:s:e:t:?h")) != -1) {
+        switch (opt) {
+          case 'd': // Delay after each set operation
+            perSetDelay = strtod(optarg, &chptr);
+            if ((*chptr != '\0') || (perSetDelay < 0.0)) {
+                testPrintE("Invalid command-line specified per pass delay of: "
+                           "%s", optarg);
+                exit(1);
+            }
+            break;
+
+          case 'D': // End of test delay
+                    // Delay between completion of final pass and restart
+                    // of framework
+            endDelay = strtod(optarg, &chptr);
+            if ((*chptr != '\0') || (endDelay < 0.0)) {
+                testPrintE("Invalid command-line specified end of test delay "
+                           "of: %s", optarg);
+                exit(2);
+            }
+            break;
+
+          case 't': // Duration
+            duration = strtod(optarg, &chptr);
+            if ((*chptr != '\0') || (duration < 0.0)) {
+                testPrintE("Invalid command-line specified duration of: %s",
+                           optarg);
+                exit(3);
+            }
+            break;
+
+          case 'n': // Num set operations per pass
+            numSet = strtoul(optarg, &chptr, 10);
+            if (*chptr != '\0') {
+                testPrintE("Invalid command-line specified num set per pass "
+                           "of: %s", optarg);
+                exit(4);
+            }
+            break;
+
+          case 's': // Starting Pass
+            sFlag = true;
+            if (pFlag) {
+                testPrintE("Invalid combination of command-line options.");
+                testPrintE("  The -p option is mutually exclusive from the");
+                testPrintE("  -s and -e options.");
+                exit(5);
+            }
+            startPass = strtoul(optarg, &chptr, 10);
+            if (*chptr != '\0') {
+                testPrintE("Invalid command-line specified starting pass "
+                           "of: %s", optarg);
+                exit(6);
+            }
+            break;
+
+          case 'e': // Ending Pass
+            eFlag = true;
+            if (pFlag) {
+                testPrintE("Invalid combination of command-line options.");
+                testPrintE("  The -p option is mutually exclusive from the");
+                testPrintE("  -s and -e options.");
+                exit(7);
+            }
+            endPass = strtoul(optarg, &chptr, 10);
+            if (*chptr != '\0') {
+                testPrintE("Invalid command-line specified ending pass "
+                           "of: %s", optarg);
+                exit(8);
+            }
+            break;
+
+          case 'p': // Run a single specified pass
+            pFlag = true;
+            if (sFlag || eFlag) {
+                testPrintE("Invalid combination of command-line options.");
+                testPrintE("  The -p option is mutually exclusive from the");
+                testPrintE("  -s and -e options.");
+                exit(9);
+            }
+            startPass = endPass = strtoul(optarg, &chptr, 10);
+            if (*chptr != '\0') {
+                testPrintE("Invalid command-line specified pass of: %s",
+                           optarg);
+                exit(10);
+            }
+            break;
+
+          case 'v': // Verbose
+            verbose = true;
+            break;
+
+          case 'h': // Help
+          case '?':
+          default:
+            testPrintE("  %s [options]", basename(argv[0]));
+            testPrintE("    options:");
+            testPrintE("      -p Execute specified pass");
+            testPrintE("      -s Starting pass");
+            testPrintE("      -e Ending pass");
+            testPrintE("      -t Duration");
+            testPrintE("      -d Delay after each set operation");
+            testPrintE("      -D End of test delay");
+            testPrintE("      -n Num set operations per pass");
+            testPrintE("      -v Verbose");
+            exit(((optopt == 0) || (optopt == '?')) ? 0 : 11);
+        }
+    }
+    if (endPass < startPass) {
+        testPrintE("Unexpected ending pass before starting pass");
+        testPrintE("  startPass: %u endPass: %u", startPass, endPass);
+        exit(12);
+    }
+    if (argc != optind) {
+        testPrintE("Unexpected command-line postional argument");
+        testPrintE("  %s [-s start_pass] [-e end_pass] [-t duration]",
+            basename(argv[0]));
+        exit(13);
+    }
+    testPrintI("duration: %g", duration);
+    testPrintI("startPass: %u", startPass);
+    testPrintI("endPass: %u", endPass);
+    testPrintI("numSet: %u", numSet);
+
+    // Stop framework
+    rv = snprintf(cmd, sizeof(cmd), "%s", CMD_STOP_FRAMEWORK);
+    if (rv >= (signed) sizeof(cmd) - 1) {
+        testPrintE("Command too long for: %s", CMD_STOP_FRAMEWORK);
+        exit(14);
+    }
+    testExecCmd(cmd);
+    testDelay(1.0); // TODO - need means to query whether asyncronous stop
+                    // framework operation has completed.  For now, just wait
+                    // a long time.
+
+    init();
+
+    // For each pass
+    gettimeofday(&startTime, NULL);
+    for (pass = startPass; pass <= endPass; pass++) {
+        // Stop if duration of work has already been performed
+        gettimeofday(&currentTime, NULL);
+        delta = tvDelta(&startTime, &currentTime);
+        if (tv2double(&delta) > duration) { break; }
+
+        // Regenerate a new set of test frames when this pass is
+        // either the first pass or is in a different group then
+        // the previous pass.  A group of passes are passes that
+        // all have the same quotient when their pass number is
+        // divided by passesPerGroup.
+        if ((pass == startPass)
+            || ((pass / passesPerGroup) != ((pass - 1) / passesPerGroup))) {
+            initFrames(pass / passesPerGroup);
+        }
+
+        testPrintI("==== Starting pass: %u", pass);
+
+        // Cause deterministic sequence of prandom numbers to be
+        // generated for this pass.
+        srand48(pass);
+
+        hwc_layer_list_t *list;
+        list = hwcTestCreateLayerList(testRandMod(frames.size()) + 1);
+        if (list == NULL) {
+            testPrintE("hwcTestCreateLayerList failed");
+            exit(20);
+        }
+
+        // Prandomly select a subset of frames to be used by this pass.
+        vector <vector <sp<GraphicBuffer> > > selectedFrames;
+        selectedFrames = vectorRandSelect(frames, list->numHwLayers);
+
+        // Any transform tends to create a layer that the hardware
+        // composer is unable to support and thus has to leave for
+        // SurfaceFlinger.  Place heavy bias on specifying no transforms.
+        bool noTransform = testRandFract() > rareRatio;
+
+        for (unsigned int n1 = 0; n1 < list->numHwLayers; n1++) {
+            unsigned int idx = testRandMod(selectedFrames[n1].size());
+            sp<GraphicBuffer> gBuf = selectedFrames[n1][idx];
+            hwc_layer_t *layer = &list->hwLayers[n1];
+            layer->handle = gBuf->handle;
+
+            layer->blending = blendingOps[testRandMod(NUMA(blendingOps))];
+            layer->flags = (testRandFract() > rareRatio) ? 0
+                : vectorOr(vectorRandSelect(vecLayerFlags,
+                           testRandMod(vecLayerFlags.size() + 1)));
+            layer->transform = (noTransform || testRandFract() > rareRatio) ? 0
+                : vectorOr(vectorRandSelect(vecTransformFlags,
+                           testRandMod(vecTransformFlags.size() + 1)));
+            layer->sourceCrop.left = testRandMod(gBuf->getWidth());
+            layer->sourceCrop.top = testRandMod(gBuf->getHeight());
+            layer->sourceCrop.right = layer->sourceCrop.left
+                + testRandMod(gBuf->getWidth() - layer->sourceCrop.left) + 1;
+            layer->sourceCrop.bottom = layer->sourceCrop.top
+                + testRandMod(gBuf->getHeight() - layer->sourceCrop.top) + 1;
+            layer->displayFrame.left = testRandMod(width);
+            layer->displayFrame.top = testRandMod(height);
+            layer->displayFrame.right = layer->displayFrame.left
+                + testRandMod(width - layer->displayFrame.left) + 1;
+            layer->displayFrame.bottom = layer->displayFrame.top
+                + testRandMod(height - layer->displayFrame.top) + 1;
+
+            // Increase the frequency that a scale factor of 1.0 from
+            // the sourceCrop to displayFrame occurs.  This is the
+            // most common scale factor used by applications and would
+            // be rarely produced by this stress test without this
+            // logic.
+            if (testRandFract() <= freqRatio) {
+                // Only change to scale factor to 1.0 if both the
+                // width and height will fit.
+                int sourceWidth = layer->sourceCrop.right
+                                  - layer->sourceCrop.left;
+                int sourceHeight = layer->sourceCrop.bottom
+                                   - layer->sourceCrop.top;
+                if (((layer->displayFrame.left + sourceWidth) <= width)
+                    && ((layer->displayFrame.top + sourceHeight) <= height)) {
+                    layer->displayFrame.right = layer->displayFrame.left
+                                                + sourceWidth;
+                    layer->displayFrame.bottom = layer->displayFrame.top
+                                                 + sourceHeight;
+                }
+            }
+
+            layer->visibleRegionScreen.numRects = 1;
+            layer->visibleRegionScreen.rects = &layer->displayFrame;
+        }
+
+        // Perform prepare operation
+        if (verbose) { testPrintI("Prepare:"); hwcTestDisplayList(list); }
+        hwcDevice->prepare(hwcDevice, list);
+        if (verbose) {
+            testPrintI("Post Prepare:");
+            hwcTestDisplayListPrepareModifiable(list);
+        }
+
+        // Turn off the geometry changed flag
+        list->flags &= ~HWC_GEOMETRY_CHANGED;
+
+        // Perform the set operation(s)
+        if (verbose) {testPrintI("Set:"); }
+        for (unsigned int n1 = 0; n1 < numSet; n1++) {
+            if (verbose) { hwcTestDisplayListHandles(list); }
+            hwcDevice->set(hwcDevice, dpy, surface, list);
+
+            // Prandomly select a new set of handles
+            for (unsigned int n1 = 0; n1 < list->numHwLayers; n1++) {
+                unsigned int idx = testRandMod(selectedFrames[n1].size());
+                sp<GraphicBuffer> gBuf = selectedFrames[n1][idx];
+                hwc_layer_t *layer = &list->hwLayers[n1];
+                layer->handle = (native_handle_t *) gBuf->handle;
+            }
+
+            testDelay(perSetDelay);
+        }
+
+        hwcTestFreeLayerList(list);
+        testPrintI("==== Completed pass: %u", pass);
+    }
+
+    testDelay(endDelay);
+
+    // Start framework
+    rv = snprintf(cmd, sizeof(cmd), "%s", CMD_START_FRAMEWORK);
+    if (rv >= (signed) sizeof(cmd) - 1) {
+        testPrintE("Command too long for: %s", CMD_START_FRAMEWORK);
+        exit(21);
+    }
+    testExecCmd(cmd);
+
+    testPrintI("Successfully completed %u passes", pass - startPass);
+
+    return 0;
+}
+
+void init(void)
+{
+    srand48(0); // Defensively set pseudo random number generator.
+                // Should not need to set this, because a stress test
+                // sets the seed on each pass.  Defensively set it here
+                // so that future code that uses pseudo random numbers
+                // before the first pass will be deterministic.
+
+    hwcTestInitDisplay(verbose, &dpy, &surface, &width, &height);
+
+    hwcTestOpenHwc(&hwcDevice);
+}
+
+/*
+ * Initialize Frames
+ *
+ * Creates an array of graphic buffers, within the global variable
+ * named frames.  The graphic buffers are contained within a vector of
+ * vectors.  All the graphic buffers in a particular row are of the same
+ * format and dimension.  Each graphic buffer is uniformly filled with a
+ * prandomly selected color.  It is likely that each buffer, even
+ * in the same row, will be filled with a unique color.
+ */
+void initFrames(unsigned int seed)
+{
+    int rv;
+    const size_t maxRows = 5;
+    const size_t minCols = 2;  // Need at least double buffering
+    const size_t maxCols = 4;  // One more than triple buffering
+
+    if (verbose) { testPrintI("initFrames seed: %u", seed); }
+    srand48(seed);
+    size_t rows = testRandMod(maxRows) + 1;
+
+    frames.clear();
+    frames.resize(rows);
+
+    for (unsigned int row = 0; row < rows; row++) {
+        // All frames within a row have to have the same format and
+        // dimensions.  Width and height need to be >= 1.
+        unsigned int formatIdx = testRandMod(NUMA(hwcTestGraphicFormat));
+        const struct hwcTestGraphicFormat *formatPtr
+            = &hwcTestGraphicFormat[formatIdx];
+        int format = formatPtr->format;
+
+        // Pick width and height, which must be >= 1 and the size
+        // mod the wMod/hMod value must be equal to 0.
+        size_t w = (width * maxSizeRatio) * testRandFract();
+        size_t h = (height * maxSizeRatio) * testRandFract();
+        w = max(1u, w);
+        h = max(1u, h);
+        if ((w % formatPtr->wMod) != 0) {
+            w += formatPtr->wMod - (w % formatPtr->wMod);
+        }
+        if ((h % formatPtr->hMod) != 0) {
+            h += formatPtr->hMod - (h % formatPtr->hMod);
+        }
+        if (verbose) {
+            testPrintI("  frame %u width: %u height: %u format: %u %s",
+                       row, w, h, format, hwcTestGraphicFormat2str(format));
+        }
+
+        size_t cols = testRandMod((maxCols + 1) - minCols) + minCols;
+        frames[row].resize(cols);
+        for (unsigned int col = 0; col < cols; col++) {
+            ColorFract color(testRandFract(), testRandFract(), testRandFract());
+            float alpha = testRandFract();
+
+            frames[row][col] = new GraphicBuffer(w, h, format, texUsage);
+            if ((rv = frames[row][col]->initCheck()) != NO_ERROR) {
+                testPrintE("GraphicBuffer initCheck failed, rv: %i", rv);
+                testPrintE("  frame %u width: %u height: %u format: %u %s",
+                           row, w, h, format, hwcTestGraphicFormat2str(format));
+                exit(80);
+            }
+
+            hwcTestFillColor(frames[row][col].get(), color, alpha);
+            if (verbose) {
+                testPrintI("    buf: %p handle: %p color: %s alpha: %f",
+                           frames[row][col].get(), frames[row][col]->handle,
+                           string(color).c_str(), alpha);
+            }
+        }
+    }
+}
+
+/*
+ * Vector Random Select
+ *
+ * Prandomly selects and returns num elements from vec.
+ */
+template <class T>
+vector<T> vectorRandSelect(const vector<T>& vec, size_t num)
+{
+    vector<T> rv = vec;
+
+    while (rv.size() > num) {
+        rv.erase(rv.begin() + testRandMod(rv.size()));
+    }
+
+    return rv;
+}
+
+/*
+ * Vector Or
+ *
+ * Or's togethen the values of each element of vec and returns the result.
+ */
+template <class T>
+T vectorOr(const vector<T>& vec)
+{
+    T rv = 0;
+
+    for (size_t n1 = 0; n1 < vec.size(); n1++) {
+        rv |= vec[n1];
+    }
+
+    return rv;
+}
diff --git a/opengl/tests/hwc/hwcTestLib.cpp b/opengl/tests/hwc/hwcTestLib.cpp
new file mode 100644
index 0000000..925405e
--- /dev/null
+++ b/opengl/tests/hwc/hwcTestLib.cpp
@@ -0,0 +1,1028 @@
+/*
+ * Copyright (C) 2011 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+/*
+ * Hardware Composer Test Library
+ * Utility library functions for use by the Hardware Composer test cases
+ */
+
+#include <sstream>
+#include <string>
+
+#include <arpa/inet.h> // For ntohl() and htonl()
+
+#include <hwc/hwcTestLib.h>
+
+// Defines
+#define NUMA(a) (sizeof(a) / sizeof(a [0]))
+
+// Function Prototypes
+static void printGLString(const char *name, GLenum s);
+static void checkEglError(const char* op, EGLBoolean returnVal = EGL_TRUE);
+static void checkGlError(const char* op);
+static void printEGLConfiguration(EGLDisplay dpy, EGLConfig config);
+
+using namespace std;
+using namespace android;
+
+
+#define BITSPERBYTE            8 // TODO: Obtain from <values.h>, once
+                                 // it has been added
+
+// Initialize Display
+void hwcTestInitDisplay(bool verbose, EGLDisplay *dpy, EGLSurface *surface,
+    EGLint *width, EGLint *height)
+{
+    static EGLContext context;
+
+    int rv;
+
+    EGLBoolean returnValue;
+    EGLConfig myConfig = {0};
+    EGLint contextAttribs[] = { EGL_CONTEXT_CLIENT_VERSION, 2, EGL_NONE };
+    EGLint sConfigAttribs[] = {
+        EGL_SURFACE_TYPE, EGL_WINDOW_BIT,
+        EGL_RENDERABLE_TYPE, EGL_OPENGL_ES2_BIT,
+        EGL_NONE };
+    EGLint majorVersion, minorVersion;
+
+    checkEglError("<init>");
+    *dpy = eglGetDisplay(EGL_DEFAULT_DISPLAY);
+    checkEglError("eglGetDisplay");
+    if (*dpy == EGL_NO_DISPLAY) {
+        testPrintE("eglGetDisplay returned EGL_NO_DISPLAY");
+        exit(70);
+    }
+
+    returnValue = eglInitialize(*dpy, &majorVersion, &minorVersion);
+    checkEglError("eglInitialize", returnValue);
+    if (verbose) {
+        testPrintI("EGL version %d.%d", majorVersion, minorVersion);
+    }
+    if (returnValue != EGL_TRUE) {
+        testPrintE("eglInitialize failed");
+        exit(71);
+    }
+
+    EGLNativeWindowType window = android_createDisplaySurface();
+    if (window == NULL) {
+        testPrintE("android_createDisplaySurface failed");
+        exit(72);
+    }
+    returnValue = EGLUtils::selectConfigForNativeWindow(*dpy,
+        sConfigAttribs, window, &myConfig);
+    if (returnValue) {
+        testPrintE("EGLUtils::selectConfigForNativeWindow() returned %d",
+            returnValue);
+        exit(73);
+    }
+    checkEglError("EGLUtils::selectConfigForNativeWindow");
+
+    if (verbose) {
+        testPrintI("Chose this configuration:");
+        printEGLConfiguration(*dpy, myConfig);
+    }
+
+    *surface = eglCreateWindowSurface(*dpy, myConfig, window, NULL);
+    checkEglError("eglCreateWindowSurface");
+    if (*surface == EGL_NO_SURFACE) {
+        testPrintE("gelCreateWindowSurface failed.");
+        exit(74);
+    }
+
+    context = eglCreateContext(*dpy, myConfig, EGL_NO_CONTEXT, contextAttribs);
+    checkEglError("eglCreateContext");
+    if (context == EGL_NO_CONTEXT) {
+        testPrintE("eglCreateContext failed");
+        exit(75);
+    }
+    returnValue = eglMakeCurrent(*dpy, *surface, *surface, context);
+    checkEglError("eglMakeCurrent", returnValue);
+    if (returnValue != EGL_TRUE) {
+        testPrintE("eglMakeCurrent failed");
+        exit(76);
+    }
+    eglQuerySurface(*dpy, *surface, EGL_WIDTH, width);
+    checkEglError("eglQuerySurface");
+    eglQuerySurface(*dpy, *surface, EGL_HEIGHT, height);
+    checkEglError("eglQuerySurface");
+
+    if (verbose) {
+        testPrintI("Window dimensions: %d x %d", *width, *height);
+
+        printGLString("Version", GL_VERSION);
+        printGLString("Vendor", GL_VENDOR);
+        printGLString("Renderer", GL_RENDERER);
+        printGLString("Extensions", GL_EXTENSIONS);
+    }
+}
+
+// Open Hardware Composer Device
+void hwcTestOpenHwc(hwc_composer_device_t **hwcDevicePtr)
+{
+    int rv;
+    hw_module_t const *hwcModule;
+
+    if ((rv = hw_get_module(HWC_HARDWARE_MODULE_ID, &hwcModule)) != 0) {
+        testPrintE("hw_get_module failed, rv: %i", rv);
+        errno = -rv;
+        perror(NULL);
+        exit(77);
+    }
+    if ((rv = hwc_open(hwcModule, hwcDevicePtr)) != 0) {
+        testPrintE("hwc_open failed, rv: %i", rv);
+        errno = -rv;
+        perror(NULL);
+        exit(78);
+    }
+}
+
+// Color fraction class to string conversion
+ColorFract::operator string()
+{
+    ostringstream out;
+
+    out << '[' << this->c1() << ", "
+        << this->c2() << ", "
+        << this->c3() << ']';
+
+    return out.str();
+}
+
+// Dimension class to string conversion
+HwcTestDim::operator string()
+{
+    ostringstream out;
+
+    out << '[' << this->width() << ", "
+        << this->height() << ']';
+
+    return out.str();
+}
+
+// Dimension class to hwc_rect conversion
+HwcTestDim::operator hwc_rect() const
+{
+    hwc_rect rect;
+
+    rect.left = rect.top = 0;
+
+    rect.right = this->_w;
+    rect.bottom = this->_h;
+
+    return rect;
+}
+
+// Hardware Composer rectangle to string conversion
+string hwcTestRect2str(const struct hwc_rect& rect)
+{
+    ostringstream out;
+
+    out << '[';
+    out << rect.left << ", ";
+    out << rect.top << ", ";
+    out << rect.right << ", ";
+    out << rect.bottom;
+    out << ']';
+
+    return out.str();
+}
+
+// Parse HWC rectangle description of form [left, top, right, bottom]
+struct hwc_rect hwcTestParseHwcRect(istringstream& in, bool& error)
+{
+    struct hwc_rect rect;
+    char chStart, ch;
+
+    // Defensively specify that an error occurred.  Will clear
+    // error flag if all of parsing succeeds.
+    error = true;
+
+    // First character should be a [ or <
+    in >> chStart;
+    if (!in || ((chStart != '<') && (chStart != '['))) { return rect; }
+
+    // Left
+    in >> rect.left;
+    if (!in) { return rect; }
+    in >> ch;
+    if (!in || (ch != ',')) { return rect; }
+
+    // Top
+    in >> rect.top;
+    if (!in) { return rect; }
+    in >> ch;
+    if (!in || (ch != ',')) { return rect; }
+
+    // Right
+    in >> rect.right;
+    if (!in) { return rect; }
+    in >> ch;
+    if (!in || (ch != ',')) { return rect; }
+
+    // Bottom
+    in >> rect.bottom;
+    if (!in) { return rect; }
+
+    // Closing > or ]
+    in >> ch;
+    if (!in) { return rect; }
+    if (((chStart == '<') && (ch != '>'))
+        || ((chStart == '[') && (ch != ']'))) { return rect; }
+
+    // Validate right and bottom are greater than left and top
+    if ((rect.right <= rect.left) || (rect.bottom <= rect.top)) { return rect; }
+
+    // Made It, clear error indicator
+    error = false;
+
+    return rect;
+}
+
+// Parse dimension of form [width, height]
+HwcTestDim hwcTestParseDim(istringstream& in, bool& error)
+{
+    HwcTestDim dim;
+    char chStart, ch;
+    uint32_t val;
+
+    // Defensively specify that an error occurred.  Will clear
+    // error flag if all of parsing succeeds.
+    error = true;
+
+    // First character should be a [ or <
+    in >> chStart;
+    if (!in || ((chStart != '<') && (chStart != '['))) { return dim; }
+
+    // Width
+    in >> val;
+    if (!in) { return dim; }
+    dim.setWidth(val);
+    in >> ch;
+    if (!in || (ch != ',')) { return dim; }
+
+    // Height
+    in >> val;
+    if (!in) { return dim; }
+    dim.setHeight(val);
+
+    // Closing > or ]
+    in >> ch;
+    if (!in) { return dim; }
+    if (((chStart == '<') && (ch != '>'))
+        || ((chStart == '[') && (ch != ']'))) { return dim; }
+
+    // Validate width and height greater than 0
+    if ((dim.width() <= 0) || (dim.height() <= 0)) { return dim; }
+
+    // Made It, clear error indicator
+    error = false;
+    return dim;
+}
+
+// Parse fractional color of form [0.##, 0.##, 0.##]
+// Fractional values can be from 0.0 to 1.0 inclusive.  Note, integer
+// values of 0.0 and 1.0, which are non-fractional, are considered valid.
+// They are an exception, all other valid inputs are fractions.
+ColorFract hwcTestParseColor(istringstream& in, bool& error)
+{
+    ColorFract color;
+    char chStart, ch;
+    float c1, c2, c3;
+
+    // Defensively specify that an error occurred.  Will clear
+    // error flag if all of parsing succeeds.
+    error = true;
+
+    // First character should be a [ or <
+    in >> chStart;
+    if (!in || ((chStart != '<') && (chStart != '['))) { return color; }
+
+    // 1st Component
+    in >> c1;
+    if (!in) { return color; }
+    if ((c1 < 0.0) || (c1 > 1.0)) { return color; }
+    in >> ch;
+    if (!in || (ch != ',')) { return color; }
+
+    // 2nd Component
+    in >> c2;
+    if (!in) { return color; }
+    if ((c2 < 0.0) || (c2 > 1.0)) { return color; }
+    in >> ch;
+    if (!in || (ch != ',')) { return color; }
+
+    // 3rd Component
+    in >> c3;
+    if (!in) { return color; }
+    if ((c3 < 0.0) || (c3 > 1.0)) { return color; }
+
+    // Closing > or ]
+    in >> ch;
+    if (!in) { return color; }
+    if (((chStart == '<') && (ch != '>'))
+        || ((chStart == '[') && (ch != ']'))) { return color; }
+
+    // Are all the components fractional
+    if ((c1 < 0.0) || (c1 > 1.0)
+        || (c2 < 0.0) || (c2 > 1.0)
+        || (c3 < 0.0) || (c3 > 1.0)) { return color; }
+
+    // Made It, clear error indicator
+    error = false;
+
+    return ColorFract(c1, c2, c3);
+}
+
+// Look up and return pointer to structure with the characteristics
+// of the graphic format named by the desc parameter.  Search failure
+// indicated by the return of NULL.
+const struct hwcTestGraphicFormat *hwcTestGraphicFormatLookup(const char *desc)
+{
+    for (unsigned int n1 = 0; n1 < NUMA(hwcTestGraphicFormat); n1++) {
+        if (string(desc) == string(hwcTestGraphicFormat[n1].desc)) {
+            return &hwcTestGraphicFormat[n1];
+        }
+    }
+
+    return NULL;
+}
+
+// Look up and return pointer to structure with the characteristics
+// of the graphic format specified by the id parameter.  Search failure
+// indicated by the return of NULL.
+const struct hwcTestGraphicFormat *hwcTestGraphicFormatLookup(uint32_t id)
+{
+    for (unsigned int n1 = 0; n1 < NUMA(hwcTestGraphicFormat); n1++) {
+        if (id == hwcTestGraphicFormat[n1].format) {
+            return &hwcTestGraphicFormat[n1];
+        }
+    }
+
+    return NULL;
+}
+
+
+// Given the integer ID of a graphic format, return a pointer to
+// a string that describes the format.
+const char *hwcTestGraphicFormat2str(uint32_t format)
+{
+    const static char *unknown = "unknown";
+
+    for (unsigned int n1 = 0; n1 < NUMA(hwcTestGraphicFormat); n1++) {
+        if (format == hwcTestGraphicFormat[n1].format) {
+            return hwcTestGraphicFormat[n1].desc;
+        }
+    }
+
+    return unknown;
+}
+
+/*
+ * hwcTestCreateLayerList
+ * Dynamically creates layer list with numLayers worth
+ * of hwLayers entries.
+ */
+hwc_layer_list_t *hwcTestCreateLayerList(size_t numLayers)
+{
+    hwc_layer_list_t *list;
+
+    size_t size = sizeof(hwc_layer_list) + numLayers * sizeof(hwc_layer_t);
+    if ((list = (hwc_layer_list_t *) calloc(1, size)) == NULL) {
+        return NULL;
+    }
+    list->flags = HWC_GEOMETRY_CHANGED;
+    list->numHwLayers = numLayers;
+
+    return list;
+}
+
+/*
+ * hwcTestFreeLayerList
+ * Frees memory previous allocated via hwcTestCreateLayerList().
+ */
+void hwcTestFreeLayerList(hwc_layer_list_t *list)
+{
+    free(list);
+}
+
+// Display the settings of the layer list pointed to by list
+void hwcTestDisplayList(hwc_layer_list_t *list)
+{
+    testPrintI("  flags: %#x%s", list->flags,
+               (list->flags & HWC_GEOMETRY_CHANGED) ? " GEOMETRY_CHANGED" : "");
+    testPrintI("  numHwLayers: %u", list->numHwLayers);
+
+    for (unsigned int layer = 0; layer < list->numHwLayers; layer++) {
+        testPrintI("    layer %u compositionType: %#x%s%s", layer,
+                   list->hwLayers[layer].compositionType,
+                   (list->hwLayers[layer].compositionType == HWC_FRAMEBUFFER)
+                       ? " FRAMEBUFFER" : "",
+                   (list->hwLayers[layer].compositionType == HWC_OVERLAY)
+                       ? " OVERLAY" : "");
+
+        testPrintI("      hints: %#x",
+                   list->hwLayers[layer].hints,
+                   (list->hwLayers[layer].hints & HWC_HINT_TRIPLE_BUFFER)
+                       ? " TRIPLE_BUFFER" : "",
+                   (list->hwLayers[layer].hints & HWC_HINT_CLEAR_FB)
+                       ? " CLEAR_FB" : "");
+
+        testPrintI("      flags: %#x%s",
+                   list->hwLayers[layer].flags,
+                   (list->hwLayers[layer].flags & HWC_SKIP_LAYER)
+                       ? " SKIP_LAYER" : "");
+
+        testPrintI("      handle: %p",
+                   list->hwLayers[layer].handle);
+
+        // Intentionally skipped display of ROT_180 & ROT_270,
+        // which are formed from combinations of the other flags.
+        testPrintI("      transform: %#x%s%s%s",
+                   list->hwLayers[layer].transform,
+                   (list->hwLayers[layer].transform & HWC_TRANSFORM_FLIP_H)
+                       ? " FLIP_H" : "",
+                   (list->hwLayers[layer].transform & HWC_TRANSFORM_FLIP_V)
+                       ? " FLIP_V" : "",
+                   (list->hwLayers[layer].transform & HWC_TRANSFORM_ROT_90)
+                       ? " ROT_90" : "");
+
+        testPrintI("      blending: %#x%s%s%s",
+                   list->hwLayers[layer].blending,
+                   (list->hwLayers[layer].blending == HWC_BLENDING_NONE)
+                       ? " NONE" : "",
+                   (list->hwLayers[layer].blending == HWC_BLENDING_PREMULT)
+                       ? " PREMULT" : "",
+                   (list->hwLayers[layer].blending == HWC_BLENDING_COVERAGE)
+                       ? " COVERAGE" : "");
+
+        testPrintI("      sourceCrop: %s",
+                   hwcTestRect2str(list->hwLayers[layer].sourceCrop).c_str());
+        testPrintI("      displayFrame: %s",
+                   hwcTestRect2str(list->hwLayers[layer].displayFrame).c_str());
+        testPrintI("      scaleFactor: [%f, %f]",
+                   (float) (list->hwLayers[layer].sourceCrop.right
+                            - list->hwLayers[layer].sourceCrop.left)
+                       / (float) (list->hwLayers[layer].displayFrame.right
+                            - list->hwLayers[layer].displayFrame.left),
+                   (float) (list->hwLayers[layer].sourceCrop.bottom
+                            - list->hwLayers[layer].sourceCrop.top)
+                       / (float) (list->hwLayers[layer].displayFrame.bottom
+                            - list->hwLayers[layer].displayFrame.top));
+    }
+}
+
+/*
+ * Display List Prepare Modifiable
+ *
+ * Displays the portions of a list that are meant to be modified by
+ * a prepare call.
+ */
+void hwcTestDisplayListPrepareModifiable(hwc_layer_list_t *list)
+{
+    uint32_t numOverlays = 0;
+    for (unsigned int layer = 0; layer < list->numHwLayers; layer++) {
+        if (list->hwLayers[layer].compositionType == HWC_OVERLAY) {
+            numOverlays++;
+        }
+        testPrintI("    layer %u compositionType: %#x%s%s", layer,
+                   list->hwLayers[layer].compositionType,
+                   (list->hwLayers[layer].compositionType == HWC_FRAMEBUFFER)
+                       ? " FRAMEBUFFER" : "",
+                   (list->hwLayers[layer].compositionType == HWC_OVERLAY)
+                       ? " OVERLAY" : "");
+        testPrintI("      hints: %#x%s%s",
+                   list->hwLayers[layer].hints,
+                   (list->hwLayers[layer].hints & HWC_HINT_TRIPLE_BUFFER)
+                       ? " TRIPLE_BUFFER" : "",
+                   (list->hwLayers[layer].hints & HWC_HINT_CLEAR_FB)
+                       ? " CLEAR_FB" : "");
+    }
+    testPrintI("    numOverlays: %u", numOverlays);
+}
+
+/*
+ * Display List Handles
+ *
+ * Displays the handles of all the graphic buffers in the list.
+ */
+void hwcTestDisplayListHandles(hwc_layer_list_t *list)
+{
+    const unsigned int maxLayersPerLine = 6;
+
+    ostringstream str("  layers:");
+    for (unsigned int layer = 0; layer < list->numHwLayers; layer++) {
+        str << ' ' << list->hwLayers[layer].handle;
+        if (((layer % maxLayersPerLine) == (maxLayersPerLine - 1))
+            && (layer != list->numHwLayers - 1)) {
+            testPrintI("%s", str.str().c_str());
+            str.str("    ");
+        }
+    }
+    testPrintI("%s", str.str().c_str());
+}
+
+// Returns a uint32_t that contains a format specific representation of a
+// single pixel of the given color and alpha values.
+uint32_t hwcTestColor2Pixel(uint32_t format, ColorFract color, float alpha)
+{
+    const struct attrib {
+        uint32_t format;
+        bool   hostByteOrder;
+        size_t bytes;
+        size_t c1Offset;
+        size_t c1Size;
+        size_t c2Offset;
+        size_t c2Size;
+        size_t c3Offset;
+        size_t c3Size;
+        size_t aOffset;
+        size_t aSize;
+    } attributes[] = {
+        {HAL_PIXEL_FORMAT_RGBA_8888, false, 4,  0, 8,  8, 8, 16, 8, 24, 8},
+        {HAL_PIXEL_FORMAT_RGBX_8888, false, 4,  0, 8,  8, 8, 16, 8,  0, 0},
+        {HAL_PIXEL_FORMAT_RGB_888,   false, 3,  0, 8,  8, 8, 16, 8,  0, 0},
+        {HAL_PIXEL_FORMAT_RGB_565,   true,  2,  0, 5,  5, 6, 11, 5,  0, 0},
+        {HAL_PIXEL_FORMAT_BGRA_8888, false, 4, 16, 8,  8, 8,  0, 8, 24, 8},
+        {HAL_PIXEL_FORMAT_RGBA_5551, true , 2,  0, 5,  5, 5, 10, 5, 15, 1},
+        {HAL_PIXEL_FORMAT_RGBA_4444, false, 2, 12, 4,  0, 4,  4, 4,  8, 4},
+        {HAL_PIXEL_FORMAT_YV12,      true,  3, 16, 8,  8, 8,  0, 8,  0, 0},  
+    };
+
+    const struct attrib *attrib;
+    for (attrib = attributes; attrib < attributes + NUMA(attributes);
+         attrib++) {
+        if (attrib->format == format) { break; }
+    }
+    if (attrib >= attributes + NUMA(attributes)) {
+        testPrintE("colorFract2Pixel unsupported format of: %u", format);
+        exit(80);
+    }
+
+    uint32_t pixel;
+    pixel = htonl((uint32_t) round((((1 << attrib->c1Size) - 1) * color.c1()))
+         << ((sizeof(pixel) * BITSPERBYTE)
+             - (attrib->c1Offset + attrib->c1Size)));
+    pixel |= htonl((uint32_t) round((((1 << attrib->c2Size) - 1) * color.c2()))
+         << ((sizeof(pixel) * BITSPERBYTE)
+             - (attrib->c2Offset + attrib->c2Size)));
+    pixel |= htonl((uint32_t) round((((1 << attrib->c3Size) - 1) * color.c3()))
+         << ((sizeof(pixel) * BITSPERBYTE)
+             - (attrib->c3Offset + attrib->c3Size)));
+    if (attrib->aSize) {
+        pixel |= htonl((uint32_t) round((((1 << attrib->aSize) - 1) * alpha))
+             << ((sizeof(pixel) * BITSPERBYTE)
+                 - (attrib->aOffset + attrib->aSize)));
+    }
+    if (attrib->hostByteOrder) {
+        pixel = ntohl(pixel);
+        pixel >>= sizeof(pixel) * BITSPERBYTE - attrib->bytes * BITSPERBYTE;
+    }
+
+    return pixel;
+}
+
+// Sets the pixel at the given x and y coordinates to the color and alpha
+// value given by pixel.  The contents of pixel is format specific.  It's
+// value should come from a call to hwcTestColor2Pixel().
+void hwcTestSetPixel(GraphicBuffer *gBuf, unsigned char *buf,
+              uint32_t x, uint32_t y, uint32_t pixel)
+{
+
+    const struct attrib {
+        int format;
+        size_t bytes;
+    } attributes[] = {
+        {HAL_PIXEL_FORMAT_RGBA_8888,  4},
+        {HAL_PIXEL_FORMAT_RGBX_8888,  4},
+        {HAL_PIXEL_FORMAT_RGB_888,    3},
+        {HAL_PIXEL_FORMAT_RGB_565,    2},
+        {HAL_PIXEL_FORMAT_BGRA_8888,  4},
+        {HAL_PIXEL_FORMAT_RGBA_5551,  2},
+        {HAL_PIXEL_FORMAT_RGBA_4444,  2},
+    };
+
+    if (gBuf->getPixelFormat() == HAL_PIXEL_FORMAT_YV12) {
+        uint32_t yPlaneOffset, uPlaneOffset, vPlaneOffset;
+        uint32_t yPlaneStride = gBuf->getStride();
+        uint32_t uPlaneStride = ((gBuf->getStride() / 2) + 0xf) & ~0xf;
+        uint32_t vPlaneStride = uPlaneStride;
+        yPlaneOffset = 0;
+        vPlaneOffset = yPlaneOffset + yPlaneStride * gBuf->getHeight();
+        uPlaneOffset = vPlaneOffset
+                       + vPlaneStride * (gBuf->getHeight() / 2);
+        *(buf + yPlaneOffset + y * yPlaneStride + x) = pixel & 0xff;
+        *(buf + uPlaneOffset + (y / 2) * uPlaneStride + (x / 2))
+            = (pixel & 0xff00) >> 8;
+        *(buf + vPlaneOffset + (y / 2) * vPlaneStride + (x / 2))
+            = (pixel & 0xff0000) >> 16;
+
+        return;
+    }
+
+    const struct attrib *attrib;
+    for (attrib = attributes; attrib < attributes + NUMA(attributes);
+         attrib++) {
+        if (attrib->format == gBuf->getPixelFormat()) { break; }
+    }
+    if (attrib >= attributes + NUMA(attributes)) {
+        testPrintE("setPixel unsupported format of: %u",
+                   gBuf->getPixelFormat());
+        exit(90);
+    }
+
+    memmove(buf + ((gBuf->getStride() * attrib->bytes) * y)
+            + (attrib->bytes * x), &pixel, attrib->bytes);
+}
+
+// Fill a given graphic buffer with a uniform color and alpha
+void hwcTestFillColor(GraphicBuffer *gBuf, ColorFract color, float alpha)
+{
+    unsigned char* buf = NULL;
+    status_t err;
+    uint32_t pixel;
+
+    pixel = hwcTestColor2Pixel(gBuf->getPixelFormat(), color, alpha);
+
+    err = gBuf->lock(GRALLOC_USAGE_SW_WRITE_OFTEN, (void**)(&buf));
+    if (err != 0) {
+        testPrintE("hwcTestFillColor lock failed: %d", err);
+        exit(100);
+    }
+
+    for (unsigned int x = 0; x < gBuf->getStride(); x++) {
+        for (unsigned int y = 0; y < gBuf->getHeight(); y++) {
+            uint32_t val = pixel;
+            hwcTestSetPixel(gBuf, buf, x, y, (x < gBuf->getWidth())
+                            ? pixel : testRand());
+        }
+    }
+
+    err = gBuf->unlock();
+    if (err != 0) {
+        testPrintE("hwcTestFillColor unlock failed: %d", err);
+        exit(101);
+    }
+}
+
+// Fill the given buffer with a horizontal blend of colors, with the left
+// side color given by startColor and the right side color given by
+// endColor.  The startColor and endColor values are specified in the format
+// given by colorFormat, which might be different from the format of the
+// graphic buffer.  When different, a color conversion is done when possible
+// to the graphic format of the graphic buffer.  A color of black is
+// produced for cases where the conversion is impossible (e.g. out of gamut
+// values).
+void hwcTestFillColorHBlend(GraphicBuffer *gBuf, uint32_t colorFormat,
+                            ColorFract startColor, ColorFract endColor)
+{
+    status_t err;
+    unsigned char* buf = NULL;
+    const uint32_t width = gBuf->getWidth();
+    const uint32_t height = gBuf->getHeight();
+    const uint32_t stride = gBuf->getStride();
+
+    err = gBuf->lock(GRALLOC_USAGE_SW_WRITE_OFTEN, (void**)(&buf));
+    if (err != 0) {
+        testPrintE("hwcTestFillColorHBlend lock failed: %d", err);
+        exit(110);
+    }
+
+    for (unsigned int x = 0; x < stride; x++) {
+        uint32_t pixel;
+        if (x < width) {
+            ColorFract color(startColor.c1() + (endColor.c1() - startColor.c1())
+                                 * ((float) x / (float) (width - 1)),
+                             startColor.c2() + (endColor.c2() - startColor.c2())
+                                 * ((float) x / (float) (width - 1)),
+                             startColor.c3() + (endColor.c3() - startColor.c3())
+                                 * ((float) x / (float) (width - 1)));
+
+            // When formats differ, convert colors.
+            // Important to not convert when formats are the same, since
+            // out of gamut colors are always converted to black.
+            if (colorFormat != (uint32_t) gBuf->getPixelFormat()) {
+                hwcTestColorConvert(colorFormat, gBuf->getPixelFormat(), color);
+            }
+            pixel = hwcTestColor2Pixel(gBuf->getPixelFormat(), color, 1.0);
+        } else {
+            // Fill pad with random values
+            pixel = testRand();
+        }
+
+        for (unsigned int y = 0; y < height; y++) {
+            hwcTestSetPixel(gBuf, buf, x, y, pixel);
+        }
+    }
+
+    err = gBuf->unlock();
+    if (err != 0) {
+        testPrintE("hwcTestFillColorHBlend unlock failed: %d", err);
+        exit(111);
+    }
+}
+
+/*
+ * When possible, converts color specified as a full range value in
+ * the fromFormat, into an equivalent full range color in the toFormat.
+ * When conversion is impossible (e.g. out of gamut color) a color
+ * or black in the full range output format is produced.  The input
+ * color is given as a fractional color in the parameter named color.
+ * The produced color is written over the same parameter used to
+ * provide the input color.
+ *
+ * Each graphic format has 3 color components and each of these
+ * components has both a full and in gamut range.  This function uses
+ * a table that provides the full and in gamut ranges of each of the
+ * supported graphic formats.  The full range is given by members named
+ * c[123]Min to c[123]Max, while the in gamut range is given by members
+ * named c[123]Low to c[123]High.  In most cases the full and in gamut
+ * ranges are equivalent.  This occurs when the c[123]Min == c[123]Low and
+ * c[123]High == c[123]Max.
+ *
+ * The input and produced colors are both specified as a fractional amount
+ * of the full range.  The diagram below provides an overview of the
+ * conversion process.  The main steps are:
+ *
+ *   1. Produce black if the input color is out of gamut.
+ *
+ *   2. Convert the in gamut color into the fraction of the fromFromat
+ *      in gamut range.
+ *
+ *   3. Convert from the fraction of the in gamut from format range to
+ *      the fraction of the in gamut to format range.  Produce black
+ *      if an equivalent color does not exists.
+ *
+ *   4. Covert from the fraction of the in gamut to format to the
+ *      fraction of the full range to format.
+ *
+ *       From Format                 To Format
+ *    max           high            high        max
+ *    ----+                 +-----------+
+ *    high \               /             \      high
+ *    ------\-------------+               +-------->
+ *           \
+ *            \                   +--- black --+
+ *             \                 /              \
+ *              \               /                +-->
+ *    low        \             /                  low
+ *    -------- ---+-- black --+
+ *    min             low           low           min
+ *     ^               ^      ^      ^             ^
+ *     |               |      |      |             |
+ *     |               |      |      |             +-- fraction of full range
+ *     |               |      |      +-- fraction of valid range
+ *     |               |      +-- fromFormat to toFormat color conversion
+ *     |               +-- fraction of valid range
+ *     +-- fraction of full range
+ */
+void hwcTestColorConvert(uint32_t fromFormat, uint32_t toFormat,
+                  ColorFract& color)
+{
+    const struct attrib {
+        uint32_t     format;
+        bool         rgb;
+        bool         yuv;
+        int          c1Min, c1Low, c1High, c1Max;
+        int          c2Min, c2Low, c2High, c2Max;
+        int          c3Min, c3Low, c3High, c3Max;
+    } attributes[] = {
+        {HAL_PIXEL_FORMAT_RGBA_8888, true,  false,
+         0, 0, 255, 255, 0, 0, 255, 255, 0, 0, 255, 255},
+        {HAL_PIXEL_FORMAT_RGBX_8888, true,  false,
+         0, 0, 255, 255, 0, 0, 255, 255, 0, 0, 255, 255},
+        {HAL_PIXEL_FORMAT_RGB_888,   true,  false,
+         0, 0, 255, 255, 0, 0, 255, 255, 0, 0, 255, 255},
+        {HAL_PIXEL_FORMAT_RGB_565,   true,  false,
+         0, 0, 31, 31, 0, 0, 63, 63, 0, 0, 31, 31},
+        {HAL_PIXEL_FORMAT_BGRA_8888, true,  false,
+         0, 0, 255, 255, 0, 0, 255, 255, 0, 0, 255, 255},
+        {HAL_PIXEL_FORMAT_RGBA_5551, true,  false,
+         0, 0, 31, 31, 0, 0, 31, 31, 0, 0, 31, 31},
+        {HAL_PIXEL_FORMAT_RGBA_4444, true,  false,
+         0, 0, 15, 15, 0, 0, 15, 15, 0, 0, 15, 15},
+        {HAL_PIXEL_FORMAT_YV12,      false, true,
+         0, 16, 235, 255, 0, 16, 240, 255, 0, 16, 240, 255},
+    };
+
+    const struct attrib *fromAttrib;
+    for (fromAttrib = attributes; fromAttrib < attributes + NUMA(attributes);
+         fromAttrib++) {
+        if (fromAttrib->format == fromFormat) { break; }
+    }
+    if (fromAttrib >= attributes + NUMA(attributes)) {
+        testPrintE("hwcTestColorConvert unsupported from format of: %u",
+                   fromFormat);
+        exit(120);
+    }
+
+    const struct attrib *toAttrib;
+    for (toAttrib = attributes; toAttrib < attributes + NUMA(attributes);
+         toAttrib++) {
+        if (toAttrib->format == toFormat) { break; }
+    }
+    if (toAttrib >= attributes + NUMA(attributes)) {
+        testPrintE("hwcTestColorConvert unsupported to format of: %u",
+                   toFormat);
+        exit(121);
+    }
+
+    // Produce black if any of the from components are outside the
+    // valid color range
+    float c1Val = fromAttrib->c1Min
+        + ((float) (fromAttrib->c1Max - fromAttrib->c1Min) * color.c1());
+    float c2Val = fromAttrib->c2Min
+        + ((float) (fromAttrib->c2Max - fromAttrib->c2Min) * color.c2());
+    float c3Val = fromAttrib->c3Min
+        + ((float) (fromAttrib->c3Max - fromAttrib->c3Min) * color.c3());
+    if ((c1Val < fromAttrib->c1Low) || (c1Val > fromAttrib->c1High)
+        || (c2Val < fromAttrib->c2Low) || (c2Val > fromAttrib->c2High)
+        || (c3Val < fromAttrib->c3Low) || (c3Val > fromAttrib->c3High)) {
+
+        // Return black
+        // Will use representation of black from RGBA8888 graphic format
+        // and recursively convert it to the requested graphic format.
+        color = ColorFract(0.0, 0.0, 0.0);
+        hwcTestColorConvert(HAL_PIXEL_FORMAT_RGBA_8888, toFormat, color);
+        return;
+    }
+
+    // Within from format, convert from fraction of full range
+    // to fraction of valid range
+    color = ColorFract((c1Val - fromAttrib->c1Low)
+                           / (fromAttrib->c1High - fromAttrib->c1Low),
+                       (c2Val - fromAttrib->c2Low)
+                           / (fromAttrib->c2High - fromAttrib->c2Low),
+                       (c3Val - fromAttrib->c3Low)
+                           / (fromAttrib->c3High - fromAttrib->c3Low));
+
+    // If needed perform RGB to YUV conversion
+    float wr = 0.2126, wg = 0.7152, wb = 0.0722; // ITU709 recommended constants
+    if (fromAttrib->rgb && toAttrib->yuv) {
+        float r = color.c1(), g = color.c2(), b = color.c3();
+        float y = wr * r + wg * g + wb * b;
+        float u = 0.5 * ((b - y) / (1.0 - wb)) + 0.5;
+        float v = 0.5 * ((r - y) / (1.0 - wr)) + 0.5;
+
+        // Produce black if color is outside the YUV gamut
+        if ((y < 0.0) || (y > 1.0)
+            || (u < 0.0) || (u > 1.0)
+            || (v < 0.0) || (v > 1.0)) {
+            y = 0.0;
+            u = v = 0.5;
+        }
+
+        color = ColorFract(y, u, v);
+    }
+
+    // If needed perform YUV to RGB conversion
+    // Equations determined from the ITU709 equations for RGB to YUV
+    // conversion, plus the following algebra:
+    //
+    //   u = 0.5 * ((b - y) / (1.0 - wb)) + 0.5
+    //   0.5 * ((b - y) / (1.0 - wb)) = u - 0.5
+    //   (b - y) / (1.0 - wb) = 2 * (u - 0.5)
+    //   b - y = 2 * (u - 0.5) * (1.0 - wb)
+    //   b = 2 * (u - 0.5) * (1.0 - wb) + y
+    //
+    //   v = 0.5 * ((r -y) / (1.0 - wr)) + 0.5
+    //   0.5 * ((r - y) / (1.0 - wr)) = v - 0.5
+    //   (r - y) / (1.0 - wr) = 2 * (v - 0.5)
+    //   r - y = 2 * (v - 0.5) * (1.0 - wr)
+    //   r = 2 * (v - 0.5) * (1.0 - wr) + y
+    //
+    //   y = wr * r + wg * g + wb * b
+    //   wr * r + wg * g + wb * b = y
+    //   wg * g = y - wr * r - wb * b
+    //   g = (y - wr * r - wb * b) / wg
+    if (fromAttrib->yuv && toAttrib->rgb) {
+        float y = color.c1(), u = color.c2(), v = color.c3();
+        float r = 2.0 * (v - 0.5) * (1.0 - wr) + y;
+        float b = 2.0 * (u - 0.5) * (1.0 - wb) + y;
+        float g = (y - wr * r - wb * b) / wg;
+
+        // Produce black if color is outside the RGB gamut
+        if ((r < 0.0) || (r > 1.0)
+            || (g < 0.0) || (g > 1.0)
+            || (b < 0.0) || (b > 1.0)) {
+            r = g = b = 0.0;
+        }
+
+        color = ColorFract(r, g, b);
+    }
+
+    // Within to format, convert from fraction of valid range
+    // to fraction of full range
+    c1Val = (toAttrib->c1Low
+        + (float) (toAttrib->c1High - toAttrib->c1Low) * color.c1());
+    c2Val = (toAttrib->c1Low
+        + (float) (toAttrib->c2High - toAttrib->c2Low) * color.c2());
+    c3Val = (toAttrib->c1Low
+        + (float) (toAttrib->c3High - toAttrib->c3Low) * color.c3());
+    color = ColorFract((float) (c1Val - toAttrib->c1Min)
+                           / (float) (toAttrib->c1Max - toAttrib->c1Min),
+                       (float) (c2Val - toAttrib->c2Min)
+                           / (float) (toAttrib->c2Max - toAttrib->c2Min),
+                       (float) (c3Val - toAttrib->c3Min)
+                           / (float) (toAttrib->c3Max - toAttrib->c3Min));
+}
+
+// TODO: Use PrintGLString, CechckGlError, and PrintEGLConfiguration
+//       from libglTest
+static void printGLString(const char *name, GLenum s)
+{
+    const char *v = (const char *) glGetString(s);
+
+    if (v == NULL) {
+        testPrintI("GL %s unknown", name);
+    } else {
+        testPrintI("GL %s = %s", name, v);
+    }
+}
+
+static void checkEglError(const char* op, EGLBoolean returnVal)
+{
+    if (returnVal != EGL_TRUE) {
+        testPrintE("%s() returned %d", op, returnVal);
+    }
+
+    for (EGLint error = eglGetError(); error != EGL_SUCCESS; error
+            = eglGetError()) {
+        testPrintE("after %s() eglError %s (0x%x)",
+                   op, EGLUtils::strerror(error), error);
+    }
+}
+
+static void checkGlError(const char* op)
+{
+    for (GLint error = glGetError(); error; error
+            = glGetError()) {
+        testPrintE("after %s() glError (0x%x)", op, error);
+    }
+}
+
+static void printEGLConfiguration(EGLDisplay dpy, EGLConfig config)
+{
+
+#define X(VAL) {VAL, #VAL}
+    struct {EGLint attribute; const char* name;} names[] = {
+    X(EGL_BUFFER_SIZE),
+    X(EGL_ALPHA_SIZE),
+    X(EGL_BLUE_SIZE),
+    X(EGL_GREEN_SIZE),
+    X(EGL_RED_SIZE),
+    X(EGL_DEPTH_SIZE),
+    X(EGL_STENCIL_SIZE),
+    X(EGL_CONFIG_CAVEAT),
+    X(EGL_CONFIG_ID),
+    X(EGL_LEVEL),
+    X(EGL_MAX_PBUFFER_HEIGHT),
+    X(EGL_MAX_PBUFFER_PIXELS),
+    X(EGL_MAX_PBUFFER_WIDTH),
+    X(EGL_NATIVE_RENDERABLE),
+    X(EGL_NATIVE_VISUAL_ID),
+    X(EGL_NATIVE_VISUAL_TYPE),
+    X(EGL_SAMPLES),
+    X(EGL_SAMPLE_BUFFERS),
+    X(EGL_SURFACE_TYPE),
+    X(EGL_TRANSPARENT_TYPE),
+    X(EGL_TRANSPARENT_RED_VALUE),
+    X(EGL_TRANSPARENT_GREEN_VALUE),
+    X(EGL_TRANSPARENT_BLUE_VALUE),
+    X(EGL_BIND_TO_TEXTURE_RGB),
+    X(EGL_BIND_TO_TEXTURE_RGBA),
+    X(EGL_MIN_SWAP_INTERVAL),
+    X(EGL_MAX_SWAP_INTERVAL),
+    X(EGL_LUMINANCE_SIZE),
+    X(EGL_ALPHA_MASK_SIZE),
+    X(EGL_COLOR_BUFFER_TYPE),
+    X(EGL_RENDERABLE_TYPE),
+    X(EGL_CONFORMANT),
+   };
+#undef X
+
+    for (size_t j = 0; j < sizeof(names) / sizeof(names[0]); j++) {
+        EGLint value = -1;
+        EGLint returnVal = eglGetConfigAttrib(dpy, config, names[j].attribute,
+                                              &value);
+        EGLint error = eglGetError();
+        if (returnVal && error == EGL_SUCCESS) {
+            testPrintI(" %s: %d (%#x)", names[j].name, value, value);
+        }
+    }
+    testPrintI("");
+}
diff --git a/opengl/tests/hwc/hwcTestLib.h b/opengl/tests/hwc/hwcTestLib.h
new file mode 100644
index 0000000..99ee608
--- /dev/null
+++ b/opengl/tests/hwc/hwcTestLib.h
@@ -0,0 +1,135 @@
+/*
+ * Copyright (C) 2011 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+/*
+ * Hardware Composer Test Library Header
+ */
+
+#include <sstream>
+#include <string>
+
+#include <EGL/egl.h>
+#include <EGL/eglext.h>
+#include <GLES2/gl2.h>
+#include <GLES2/gl2ext.h>
+
+#include <ui/FramebufferNativeWindow.h>
+#include <ui/GraphicBuffer.h>
+#include <ui/EGLUtils.h>
+
+#include <utils/Log.h>
+#include <testUtil.h>
+
+#include <hardware/hwcomposer.h>
+
+// Characteristics of known graphic formats
+const struct hwcTestGraphicFormat {
+    uint32_t format;
+    const char *desc;
+    uint32_t wMod, hMod; // Width/height mod this value must equal zero
+} hwcTestGraphicFormat[] = {
+    {HAL_PIXEL_FORMAT_RGBA_8888, "RGBA8888", 1, 1},
+    {HAL_PIXEL_FORMAT_RGBX_8888, "RGBX8888", 1, 1},
+    {HAL_PIXEL_FORMAT_RGB_888,   "RGB888",   1, 1},
+    {HAL_PIXEL_FORMAT_RGB_565,   "RGB565",   1, 1},
+    {HAL_PIXEL_FORMAT_BGRA_8888, "BGRA8888", 1, 1},
+    {HAL_PIXEL_FORMAT_RGBA_5551, "RGBA5551", 1, 1},
+    {HAL_PIXEL_FORMAT_RGBA_4444, "RGBA4444", 1, 1},
+    {HAL_PIXEL_FORMAT_YV12,      "YV12",     2, 2},
+};
+
+// Represent RGB color as fraction of color components.
+// Each of the color components are expected in the range [0.0, 1.0]
+class ColorFract {
+  public:
+    ColorFract(): _c1(0.0), _c2(0.0), _c3(0.0) {};
+    ColorFract(float c1, float c2, float c3): _c1(c1), _c2(c2), _c3(c3) {};
+    float c1(void) const { return _c1; }
+    float c2(void) const { return _c2; }
+    float c3(void) const { return _c3; }
+
+    operator std::string();
+
+  private:
+    float _c1;
+    float _c2;
+    float _c3;
+};
+
+// Represent RGB color as fraction of color components.
+// Each of the color components are expected in the range [0.0, 1.0]
+class ColorRGB {
+  public:
+    ColorRGB(): _r(0.0), _g(0.0), _b(0.0) {};
+    ColorRGB(float f): _r(f), _g(f), _b(f) {}; // Gray
+    ColorRGB(float r, float g, float b): _r(r), _g(g), _b(b) {};
+    float r(void) const { return _r; }
+    float g(void) const { return _g; }
+    float b(void) const { return _b; }
+
+  private:
+    float _r;
+    float _g;
+    float _b;
+};
+
+// Dimension - width and height of a rectanguler area
+class HwcTestDim {
+  public:
+    HwcTestDim(): _w(0), _h(0) {};
+    HwcTestDim(uint32_t w, uint32_t h) : _w(w), _h(h) {}
+    uint32_t width(void) const { return _w; }
+    uint32_t height(void) const { return _h; }
+    void setWidth(uint32_t w) { _w = w; }
+    void setHeight(uint32_t h) { _h = h; }
+
+    operator std::string();
+    operator hwc_rect() const;
+
+  private:
+    uint32_t _w;
+    uint32_t _h;
+};
+
+// Function Prototypes
+void hwcTestInitDisplay(bool verbose, EGLDisplay *dpy, EGLSurface *surface,
+    EGLint *width, EGLint *height);
+void hwcTestOpenHwc(hwc_composer_device_t **hwcDevicePtr);
+const struct hwcTestGraphicFormat *hwcTestGraphicFormatLookup(const char *desc);
+const struct hwcTestGraphicFormat *hwcTestGraphicFormatLookup(uint32_t id);
+const char *hwcTestGraphicFormat2str(uint32_t format);
+std::string hwcTestRect2str(const struct hwc_rect& rect);
+
+hwc_layer_list_t *hwcTestCreateLayerList(size_t numLayers);
+void hwcTestFreeLayerList(hwc_layer_list_t *list);
+void hwcTestDisplayList(hwc_layer_list_t *list);
+void hwcTestDisplayListPrepareModifiable(hwc_layer_list_t *list);
+void hwcTestDisplayListHandles(hwc_layer_list_t *list);
+
+uint32_t hwcTestColor2Pixel(uint32_t format, ColorFract color, float alpha);
+void hwcTestColorConvert(uint32_t fromFormat, uint32_t toFormat,
+                  ColorFract& color);
+void hwcTestSetPixel(android::GraphicBuffer *gBuf, unsigned char *buf,
+                     uint32_t x, uint32_t y, uint32_t pixel);
+void hwcTestFillColor(android::GraphicBuffer *gBuf, ColorFract color,
+                      float alpha);
+void hwcTestFillColorHBlend(android::GraphicBuffer *gBuf,
+                            uint32_t colorFormat,
+                            ColorFract startColor, ColorFract endColor);
+ColorFract hwcTestParseColor(std::istringstream& in, bool& error);
+struct hwc_rect hwcTestParseHwcRect(std::istringstream& in, bool& error);
+HwcTestDim hwcTestParseDim(std::istringstream& in, bool& error);
diff --git a/opengl/tests/hwc/hwc_stress.cpp b/opengl/tests/hwc/hwc_stress.cpp
deleted file mode 100644
index 580eb83..0000000
--- a/opengl/tests/hwc/hwc_stress.cpp
+++ /dev/null
@@ -1,1262 +0,0 @@
-/*
- * Copyright (C) 2010 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- *
- */
-
-/*
- * Hardware Composer stress test
- *
- * Performs a pseudo-random (prandom) sequence of operations to the
- * Hardware Composer (HWC), for a specified number of passes or for
- * a specified period of time.  By default the period of time is FLT_MAX,
- * so that the number of passes will take precedence.
- *
- * The passes are grouped together, where (pass / passesPerGroup) specifies
- * which group a particular pass is in.  This causes every passesPerGroup
- * worth of sequential passes to be within the same group.  Computationally
- * intensive operations are performed just once at the beginning of a group
- * of passes and then used by all the passes in that group.  This is done
- * so as to increase both the average and peak rate of graphic operations,
- * by moving computationally intensive operations to the beginning of a group.
- * In particular, at the start of each group of passes a set of
- * graphic buffers are created, then used by the first and remaining
- * passes of that group of passes.
- *
- * The per-group initialization of the graphic buffers is performed
- * by a function called initFrames.  This function creates an array
- * of smart pointers to the graphic buffers, in the form of a vector
- * of vectors.  The array is accessed in row major order, so each
- * row is a vector of smart pointers.  All the pointers of a single
- * row point to graphic buffers which use the same pixel format and
- * have the same dimension, although it is likely that each one is
- * filled with a different color.  This is done so that after doing
- * the first HWC prepare then set call, subsequent set calls can
- * be made with each of the layer handles changed to a different
- * graphic buffer within the same row.  Since the graphic buffers
- * in a particular row have the same pixel format and dimension,
- * additional HWC set calls can be made, without having to perform
- * an HWC prepare call.
- *
- * This test supports the following command-line options:
- *
- *   -v        Verbose
- *   -s num    Starting pass
- *   -e num    Ending pass
- *   -p num    Execute the single pass specified by num
- *   -n num    Number of set operations to perform after each prepare operation
- *   -t float  Maximum time in seconds to execute the test
- *   -d float  Delay in seconds performed after each set operation
- *   -D float  Delay in seconds performed after the last pass is executed
- *
- * Typically the test is executed for a large range of passes.  By default
- * passes 0 through 99999 (100,000 passes) are executed.  Although this test
- * does not validate the generated image, at times it is useful to reexecute
- * a particular pass and leave the displayed image on the screen for an
- * extended period of time.  This can be done either by setting the -s
- * and -e options to the desired pass, along with a large value for -D.
- * This can also be done via the -p option, again with a large value for
- * the -D options.
- *
- * So far this test only contains code to create graphic buffers with
- * a continuous solid color.  Although this test is unable to validate the
- * image produced, any image that contains other than rectangles of a solid
- * color are incorrect.  Note that the rectangles may use a transparent
- * color and have a blending operation that causes the color in overlapping
- * rectangles to be mixed.  In such cases the overlapping portions may have
- * a different color from the rest of the rectangle.
- */
-
-#include <algorithm>
-#include <assert.h>
-#include <cerrno>
-#include <cmath>
-#include <cstdlib>
-#include <ctime>
-#include <libgen.h>
-#include <sched.h>
-#include <sstream>
-#include <stdint.h>
-#include <string.h>
-#include <unistd.h>
-#include <vector>
-
-#include <arpa/inet.h> // For ntohl() and htonl()
-
-#include <sys/syscall.h>
-#include <sys/types.h>
-#include <sys/wait.h>
-
-#include <EGL/egl.h>
-#include <EGL/eglext.h>
-#include <GLES2/gl2.h>
-#include <GLES2/gl2ext.h>
-
-#include <ui/FramebufferNativeWindow.h>
-#include <ui/GraphicBuffer.h>
-#include <ui/EGLUtils.h>
-
-#define LOG_TAG "hwcStressTest"
-#include <utils/Log.h>
-#include <testUtil.h>
-
-#include <hardware/hwcomposer.h>
-
-using namespace std;
-using namespace android;
-
-const float maxSizeRatio = 1.3;  // Graphic buffers can be upto this munch
-                                 // larger than the default screen size
-const unsigned int passesPerGroup = 10; // A group of passes all use the same
-                                        // graphic buffers
-
-// Ratios at which rare and frequent conditions should be produced
-const float rareRatio = 0.1;
-const float freqRatio = 0.9;
-
-// Defaults for command-line options
-const bool defaultVerbose = false;
-const unsigned int defaultStartPass = 0;
-const unsigned int defaultEndPass = 99999;
-const unsigned int defaultPerPassNumSet = 10;
-const float defaultPerSetDelay = 0.0; // Default delay after each set
-                                      // operation.  Default delay of
-                                      // zero used so as to perform the
-                                      // the set operations as quickly
-                                      // as possible.
-const float defaultEndDelay = 2.0; // Default delay between completion of
-                                   // final pass and restart of framework
-const float defaultDuration = FLT_MAX; // A fairly long time, so that
-                                       // range of passes will have
-                                       // precedence
-
-// Command-line option settings
-static bool verbose = defaultVerbose;
-static unsigned int startPass = defaultStartPass;
-static unsigned int endPass = defaultEndPass;
-static unsigned int numSet = defaultPerPassNumSet;
-static float perSetDelay = defaultPerSetDelay;
-static float endDelay = defaultEndDelay;
-static float duration = defaultDuration;
-
-// Command-line mutual exclusion detection flags.
-// Corresponding flag set true once an option is used.
-bool eFlag, sFlag, pFlag;
-
-#define MAXSTR               100
-#define MAXCMD               200
-#define BITSPERBYTE            8 // TODO: Obtain from <values.h>, once
-                                 // it has been added
-
-#define CMD_STOP_FRAMEWORK   "stop 2>&1"
-#define CMD_START_FRAMEWORK  "start 2>&1"
-
-#define NUMA(a) (sizeof(a) / sizeof(a [0]))
-#define MEMCLR(addr, size) do { \
-        memset((addr), 0, (size)); \
-    } while (0)
-
-// Represent RGB color as fraction of color components.
-// Each of the color components are expected in the range [0.0, 1.0]
-class RGBColor {
-  public:
-    RGBColor(): _r(0.0), _g(0.0), _b(0.0) {};
-    RGBColor(float f): _r(f), _g(f), _b(f) {}; // Gray
-    RGBColor(float r, float g, float b): _r(r), _g(g), _b(b) {};
-    float r(void) const { return _r; }
-    float g(void) const { return _g; }
-    float b(void) const { return _b; }
-
-  private:
-    float _r;
-    float _g;
-    float _b;
-};
-
-// Represent YUV color as fraction of color components.
-// Each of the color components are expected in the range [0.0, 1.0]
-class YUVColor {
-  public:
-    YUVColor(): _y(0.0), _u(0.0), _v(0.0) {};
-    YUVColor(float f): _y(f), _u(0.0), _v(0.0) {}; // Gray
-    YUVColor(float y, float u, float v): _y(y), _u(u), _v(v) {};
-    float y(void) const { return _y; }
-    float u(void) const { return _u; }
-    float v(void) const { return _v; }
-
-  private:
-    float _y;
-    float _u;
-    float _v;
-};
-
-// File scope constants
-static const struct graphicFormat {
-    unsigned int format;
-    const char *desc;
-    unsigned int wMod, hMod; // Width/height mod this value must equal zero
-} graphicFormat[] = {
-    {HAL_PIXEL_FORMAT_RGBA_8888, "RGBA8888", 1, 1},
-    {HAL_PIXEL_FORMAT_RGBX_8888, "RGBX8888", 1, 1},
-    {HAL_PIXEL_FORMAT_RGB_888, "RGB888", 1, 1},
-    {HAL_PIXEL_FORMAT_RGB_565, "RGB565", 1, 1},
-    {HAL_PIXEL_FORMAT_BGRA_8888, "BGRA8888", 1, 1},
-    {HAL_PIXEL_FORMAT_RGBA_5551, "RGBA5551", 1, 1},
-    {HAL_PIXEL_FORMAT_RGBA_4444, "RGBA4444", 1, 1},
-    {HAL_PIXEL_FORMAT_YV12, "YV12", 2, 2},
-};
-const unsigned int blendingOps[] = {
-    HWC_BLENDING_NONE,
-    HWC_BLENDING_PREMULT,
-    HWC_BLENDING_COVERAGE,
-};
-const unsigned int layerFlags[] = {
-    HWC_SKIP_LAYER,
-};
-const vector<unsigned int> vecLayerFlags(layerFlags,
-    layerFlags + NUMA(layerFlags));
-
-const unsigned int transformFlags[] = {
-    HWC_TRANSFORM_FLIP_H,
-    HWC_TRANSFORM_FLIP_V,
-    HWC_TRANSFORM_ROT_90,
-    // ROT_180 & ROT_270 intentionally not listed, because they
-    // they are formed from combinations of the flags already listed.
-};
-const vector<unsigned int> vecTransformFlags(transformFlags,
-    transformFlags + NUMA(transformFlags));
-
-// File scope globals
-static const int texUsage = GraphicBuffer::USAGE_HW_TEXTURE |
-        GraphicBuffer::USAGE_SW_WRITE_RARELY;
-static hw_module_t const *hwcModule;
-static hwc_composer_device_t *hwcDevice;
-static vector <vector <sp<GraphicBuffer> > > frames;
-static EGLDisplay dpy;
-static EGLContext context;
-static EGLSurface surface;
-static EGLint width, height;
-
-// File scope prototypes
-static void execCmd(const char *cmd);
-static void checkEglError(const char* op, EGLBoolean returnVal = EGL_TRUE);
-static void checkGlError(const char* op);
-static void printEGLConfiguration(EGLDisplay dpy, EGLConfig config);
-static void printGLString(const char *name, GLenum s);
-static hwc_layer_list_t *createLayerList(size_t numLayers);
-static void freeLayerList(hwc_layer_list_t *list);
-static void fillColor(GraphicBuffer *gBuf, RGBColor color, float trans);
-static void fillColor(GraphicBuffer *gBuf, YUVColor color, float trans);
-void init(void);
-void initFrames(unsigned int seed);
-void displayList(hwc_layer_list_t *list);
-void displayListPrepareModifiable(hwc_layer_list_t *list);
-void displayListHandles(hwc_layer_list_t *list);
-const char *graphicFormat2str(unsigned int format);
-template <class T> vector<T> vectorRandSelect(const vector<T>& vec, size_t num);
-template <class T> T vectorOr(const vector<T>& vec);
-
-/*
- * Main
- *
- * Performs the following high-level sequence of operations:
- *
- *   1. Command-line parsing
- *
- *   2. Initialization
- *
- *   3. For each pass:
- *
- *        a. If pass is first pass or in a different group from the
- *           previous pass, initialize the array of graphic buffers.
- *
- *        b. Create a HWC list with room to specify a prandomly
- *           selected number of layers.
- *
- *        c. Select a subset of the rows from the graphic buffer array,
- *           such that there is a unique row to be used for each
- *           of the layers in the HWC list.
- *
- *        d. Prandomly fill in the HWC list with handles
- *           selected from any of the columns of the selected row.
- *
- *        e. Pass the populated list to the HWC prepare call.
- *
- *        f. Pass the populated list to the HWC set call.
- *
- *        g. If additional set calls are to be made, then for each
- *           additional set call, select a new set of handles and
- *           perform the set call.
- */
-int
-main(int argc, char *argv[])
-{
-    int rv, opt;
-    char *chptr;
-    unsigned int pass;
-    char cmd[MAXCMD];
-    struct timeval startTime, currentTime, delta;
-
-    testSetLogCatTag(LOG_TAG);
-
-    // Parse command line arguments
-    while ((opt = getopt(argc, argv, "vp:d:D:n:s:e:t:?h")) != -1) {
-        switch (opt) {
-          case 'd': // Delay after each set operation
-            perSetDelay = strtod(optarg, &chptr);
-            if ((*chptr != '\0') || (perSetDelay < 0.0)) {
-                testPrintE("Invalid command-line specified per pass delay of: "
-                           "%s", optarg);
-                exit(1);
-            }
-            break;
-
-          case 'D': // End of test delay
-                    // Delay between completion of final pass and restart
-                    // of framework
-            endDelay = strtod(optarg, &chptr);
-            if ((*chptr != '\0') || (endDelay < 0.0)) {
-                testPrintE("Invalid command-line specified end of test delay "
-                           "of: %s", optarg);
-                exit(2);
-            }
-            break;
-
-          case 't': // Duration
-            duration = strtod(optarg, &chptr);
-            if ((*chptr != '\0') || (duration < 0.0)) {
-                testPrintE("Invalid command-line specified duration of: %s",
-                           optarg);
-                exit(3);
-            }
-            break;
-
-          case 'n': // Num set operations per pass
-            numSet = strtoul(optarg, &chptr, 10);
-            if (*chptr != '\0') {
-                testPrintE("Invalid command-line specified num set per pass "
-                           "of: %s", optarg);
-                exit(4);
-            }
-            break;
-
-          case 's': // Starting Pass
-            sFlag = true;
-            if (pFlag) {
-                testPrintE("Invalid combination of command-line options.");
-                testPrintE("  The -p option is mutually exclusive from the");
-                testPrintE("  -s and -e options.");
-                exit(5);
-            }
-            startPass = strtoul(optarg, &chptr, 10);
-            if (*chptr != '\0') {
-                testPrintE("Invalid command-line specified starting pass "
-                           "of: %s", optarg);
-                exit(6);
-            }
-            break;
-
-          case 'e': // Ending Pass
-            eFlag = true;
-            if (pFlag) {
-                testPrintE("Invalid combination of command-line options.");
-                testPrintE("  The -p option is mutually exclusive from the");
-                testPrintE("  -s and -e options.");
-                exit(7);
-            }
-            endPass = strtoul(optarg, &chptr, 10);
-            if (*chptr != '\0') {
-                testPrintE("Invalid command-line specified ending pass "
-                           "of: %s", optarg);
-                exit(8);
-            }
-            break;
-
-          case 'p': // Run a single specified pass
-            pFlag = true;
-            if (sFlag || eFlag) {
-                testPrintE("Invalid combination of command-line options.");
-                testPrintE("  The -p option is mutually exclusive from the");
-                testPrintE("  -s and -e options.");
-                exit(9);
-            }
-            startPass = endPass = strtoul(optarg, &chptr, 10);
-            if (*chptr != '\0') {
-                testPrintE("Invalid command-line specified pass of: %s",
-                           optarg);
-                exit(10);
-            }
-            break;
-
-          case 'v': // Verbose
-            verbose = true;
-            break;
-
-          case 'h': // Help
-          case '?':
-          default:
-            testPrintE("  %s [options]", basename(argv[0]));
-            testPrintE("    options:");
-            testPrintE("      -p Execute specified pass");
-            testPrintE("      -s Starting pass");
-            testPrintE("      -e Ending pass");
-            testPrintE("      -t Duration");
-            testPrintE("      -d Delay after each set operation");
-            testPrintE("      -D End of test delay");
-            testPrintE("      -n Num set operations per pass");
-            testPrintE("      -v Verbose");
-            exit(((optopt == 0) || (optopt == '?')) ? 0 : 11);
-        }
-    }
-    if (endPass < startPass) {
-        testPrintE("Unexpected ending pass before starting pass");
-        testPrintE("  startPass: %u endPass: %u", startPass, endPass);
-        exit(12);
-    }
-    if (argc != optind) {
-        testPrintE("Unexpected command-line postional argument");
-        testPrintE("  %s [-s start_pass] [-e end_pass] [-t duration]",
-            basename(argv[0]));
-        exit(13);
-    }
-    testPrintI("duration: %g", duration);
-    testPrintI("startPass: %u", startPass);
-    testPrintI("endPass: %u", endPass);
-    testPrintI("numSet: %u", numSet);
-
-    // Stop framework
-    rv = snprintf(cmd, sizeof(cmd), "%s", CMD_STOP_FRAMEWORK);
-    if (rv >= (signed) sizeof(cmd) - 1) {
-        testPrintE("Command too long for: %s", CMD_STOP_FRAMEWORK);
-        exit(14);
-    }
-    execCmd(cmd);
-    testDelay(1.0); // TODO - needs means to query whether asyncronous stop
-                    // framework operation has completed.  For now, just wait
-                    // a long time.
-
-    init();
-
-    // For each pass
-    gettimeofday(&startTime, NULL);
-    for (pass = startPass; pass <= endPass; pass++) {
-        // Stop if duration of work has already been performed
-        gettimeofday(&currentTime, NULL);
-        delta = tvDelta(&startTime, &currentTime);
-        if (tv2double(&delta) > duration) { break; }
-
-        // Regenerate a new set of test frames when this pass is
-        // either the first pass or is in a different group then
-        // the previous pass.  A group of passes are passes that
-        // all have the same quotient when their pass number is
-        // divided by passesPerGroup.
-        if ((pass == startPass)
-            || ((pass / passesPerGroup) != ((pass - 1) / passesPerGroup))) {
-            initFrames(pass / passesPerGroup);
-        }
-
-        testPrintI("==== Starting pass: %u", pass);
-
-        // Cause deterministic sequence of prandom numbers to be
-        // generated for this pass.
-        srand48(pass);
-
-        hwc_layer_list_t *list;
-        list = createLayerList(testRandMod(frames.size()) + 1);
-        if (list == NULL) {
-            testPrintE("createLayerList failed");
-            exit(20);
-        }
-
-        // Prandomly select a subset of frames to be used by this pass.
-        vector <vector <sp<GraphicBuffer> > > selectedFrames;
-        selectedFrames = vectorRandSelect(frames, list->numHwLayers);
-
-        // Any transform tends to create a layer that the hardware
-        // composer is unable to support and thus has to leave for
-        // SurfaceFlinger.  Place heavy bias on specifying no transforms.
-        bool noTransform = testRandFract() > rareRatio;
-
-        for (unsigned int n1 = 0; n1 < list->numHwLayers; n1++) {
-            unsigned int idx = testRandMod(selectedFrames[n1].size());
-            sp<GraphicBuffer> gBuf = selectedFrames[n1][idx];
-            hwc_layer_t *layer = &list->hwLayers[n1];
-            layer->handle = gBuf->handle;
-
-            layer->blending = blendingOps[testRandMod(NUMA(blendingOps))];
-            layer->flags = (testRandFract() > rareRatio) ? 0
-                : vectorOr(vectorRandSelect(vecLayerFlags,
-                           testRandMod(vecLayerFlags.size() + 1)));
-            layer->transform = (noTransform || testRandFract() > rareRatio) ? 0
-                : vectorOr(vectorRandSelect(vecTransformFlags,
-                           testRandMod(vecTransformFlags.size() + 1)));
-            layer->sourceCrop.left = testRandMod(gBuf->getWidth());
-            layer->sourceCrop.top = testRandMod(gBuf->getHeight());
-            layer->sourceCrop.right = layer->sourceCrop.left
-                + testRandMod(gBuf->getWidth() - layer->sourceCrop.left) + 1;
-            layer->sourceCrop.bottom = layer->sourceCrop.top
-                + testRandMod(gBuf->getHeight() - layer->sourceCrop.top) + 1;
-            layer->displayFrame.left = testRandMod(width);
-            layer->displayFrame.top = testRandMod(height);
-            layer->displayFrame.right = layer->displayFrame.left
-                + testRandMod(width - layer->displayFrame.left) + 1;
-            layer->displayFrame.bottom = layer->displayFrame.top
-                + testRandMod(height - layer->displayFrame.top) + 1;
-
-            // Increase the frequency that a scale factor of 1.0 from
-            // the sourceCrop to displayFrame occurs.  This is the
-            // most common scale factor used by applications and would
-            // be rarely produced by this stress test without this
-            // logic.
-            if (testRandFract() <= freqRatio) {
-                // Only change to scale factor to 1.0 if both the
-                // width and height will fit.
-                int sourceWidth = layer->sourceCrop.right
-                                  - layer->sourceCrop.left;
-                int sourceHeight = layer->sourceCrop.bottom
-                                   - layer->sourceCrop.top;
-                if (((layer->displayFrame.left + sourceWidth) <= width)
-                    && ((layer->displayFrame.top + sourceHeight) <= height)) {
-                    layer->displayFrame.right = layer->displayFrame.left
-                                                + sourceWidth;
-                    layer->displayFrame.bottom = layer->displayFrame.top
-                                                 + sourceHeight;
-                }
-            }
-
-            layer->visibleRegionScreen.numRects = 1;
-            layer->visibleRegionScreen.rects = &layer->displayFrame;
-        }
-
-        // Perform prepare operation
-        if (verbose) { testPrintI("Prepare:"); displayList(list); }
-        hwcDevice->prepare(hwcDevice, list);
-        if (verbose) {
-            testPrintI("Post Prepare:");
-            displayListPrepareModifiable(list);
-        }
-
-        // Turn off the geometry changed flag
-        list->flags &= ~HWC_GEOMETRY_CHANGED;
-
-        // Perform the set operation(s)
-        if (verbose) {testPrintI("Set:"); }
-        for (unsigned int n1 = 0; n1 < numSet; n1++) {
-            if (verbose) {displayListHandles(list); }
-            hwcDevice->set(hwcDevice, dpy, surface, list);
-
-            // Prandomly select a new set of handles
-            for (unsigned int n1 = 0; n1 < list->numHwLayers; n1++) {
-                unsigned int idx = testRandMod(selectedFrames[n1].size());
-                sp<GraphicBuffer> gBuf = selectedFrames[n1][idx];
-                hwc_layer_t *layer = &list->hwLayers[n1];
-                layer->handle = (native_handle_t *) gBuf->handle;
-            }
-
-            testDelay(perSetDelay);
-        }
-
-
-        freeLayerList(list);
-        testPrintI("==== Completed pass: %u", pass);
-    }
-
-    testDelay(endDelay);
-
-    // Start framework
-    rv = snprintf(cmd, sizeof(cmd), "%s", CMD_START_FRAMEWORK);
-    if (rv >= (signed) sizeof(cmd) - 1) {
-        testPrintE("Command too long for: %s", CMD_START_FRAMEWORK);
-        exit(21);
-    }
-    execCmd(cmd);
-
-    testPrintI("Successfully completed %u passes", pass - startPass);
-
-    return 0;
-}
-
-/*
- * Execute Command
- *
- * Executes the command pointed to by cmd.  Output from the
- * executed command is captured and sent to LogCat Info.  Once
- * the command has finished execution, it's exit status is captured
- * and checked for an exit status of zero.  Any other exit status
- * causes diagnostic information to be printed and an immediate
- * testcase failure.
- */
-static void execCmd(const char *cmd)
-{
-    FILE *fp;
-    int rv;
-    int status;
-    char str[MAXSTR];
-
-    // Display command to be executed
-    testPrintI("cmd: %s", cmd);
-
-    // Execute the command
-    fflush(stdout);
-    if ((fp = popen(cmd, "r")) == NULL) {
-        testPrintE("execCmd popen failed, errno: %i", errno);
-        exit(30);
-    }
-
-    // Obtain and display each line of output from the executed command
-    while (fgets(str, sizeof(str), fp) != NULL) {
-        if ((strlen(str) > 1) && (str[strlen(str) - 1] == '\n')) {
-            str[strlen(str) - 1] = '\0';
-        }
-        testPrintI(" out: %s", str);
-    }
-
-    // Obtain and check return status of executed command.
-    // Fail on non-zero exit status
-    status = pclose(fp);
-    if (!(WIFEXITED(status) && (WEXITSTATUS(status) == 0))) {
-        testPrintE("Unexpected command failure");
-        testPrintE("  status: %#x", status);
-        if (WIFEXITED(status)) {
-            testPrintE("WEXITSTATUS: %i", WEXITSTATUS(status));
-        }
-        if (WIFSIGNALED(status)) {
-            testPrintE("WTERMSIG: %i", WTERMSIG(status));
-        }
-        exit(31);
-    }
-}
-
-static void checkEglError(const char* op, EGLBoolean returnVal) {
-    if (returnVal != EGL_TRUE) {
-        testPrintE("%s() returned %d", op, returnVal);
-    }
-
-    for (EGLint error = eglGetError(); error != EGL_SUCCESS; error
-            = eglGetError()) {
-        testPrintE("after %s() eglError %s (0x%x)",
-                   op, EGLUtils::strerror(error), error);
-    }
-}
-
-static void checkGlError(const char* op) {
-    for (GLint error = glGetError(); error; error
-            = glGetError()) {
-        testPrintE("after %s() glError (0x%x)", op, error);
-    }
-}
-
-static void printEGLConfiguration(EGLDisplay dpy, EGLConfig config) {
-
-#define X(VAL) {VAL, #VAL}
-    struct {EGLint attribute; const char* name;} names[] = {
-    X(EGL_BUFFER_SIZE),
-    X(EGL_ALPHA_SIZE),
-    X(EGL_BLUE_SIZE),
-    X(EGL_GREEN_SIZE),
-    X(EGL_RED_SIZE),
-    X(EGL_DEPTH_SIZE),
-    X(EGL_STENCIL_SIZE),
-    X(EGL_CONFIG_CAVEAT),
-    X(EGL_CONFIG_ID),
-    X(EGL_LEVEL),
-    X(EGL_MAX_PBUFFER_HEIGHT),
-    X(EGL_MAX_PBUFFER_PIXELS),
-    X(EGL_MAX_PBUFFER_WIDTH),
-    X(EGL_NATIVE_RENDERABLE),
-    X(EGL_NATIVE_VISUAL_ID),
-    X(EGL_NATIVE_VISUAL_TYPE),
-    X(EGL_SAMPLES),
-    X(EGL_SAMPLE_BUFFERS),
-    X(EGL_SURFACE_TYPE),
-    X(EGL_TRANSPARENT_TYPE),
-    X(EGL_TRANSPARENT_RED_VALUE),
-    X(EGL_TRANSPARENT_GREEN_VALUE),
-    X(EGL_TRANSPARENT_BLUE_VALUE),
-    X(EGL_BIND_TO_TEXTURE_RGB),
-    X(EGL_BIND_TO_TEXTURE_RGBA),
-    X(EGL_MIN_SWAP_INTERVAL),
-    X(EGL_MAX_SWAP_INTERVAL),
-    X(EGL_LUMINANCE_SIZE),
-    X(EGL_ALPHA_MASK_SIZE),
-    X(EGL_COLOR_BUFFER_TYPE),
-    X(EGL_RENDERABLE_TYPE),
-    X(EGL_CONFORMANT),
-   };
-#undef X
-
-    for (size_t j = 0; j < sizeof(names) / sizeof(names[0]); j++) {
-        EGLint value = -1;
-        EGLint returnVal = eglGetConfigAttrib(dpy, config, names[j].attribute, &value);
-        EGLint error = eglGetError();
-        if (returnVal && error == EGL_SUCCESS) {
-            testPrintI(" %s: %d (%#x)", names[j].name, value, value);
-        }
-    }
-    testPrintI("");
-}
-
-static void printGLString(const char *name, GLenum s)
-{
-    const char *v = (const char *) glGetString(s);
-
-    if (v == NULL) {
-        testPrintI("GL %s unknown", name);
-    } else {
-        testPrintI("GL %s = %s", name, v);
-    }
-}
-
-/*
- * createLayerList
- * dynamically creates layer list with numLayers worth
- * of hwLayers entries.
- */
-static hwc_layer_list_t *createLayerList(size_t numLayers)
-{
-    hwc_layer_list_t *list;
-
-    size_t size = sizeof(hwc_layer_list) + numLayers * sizeof(hwc_layer_t);
-    if ((list = (hwc_layer_list_t *) calloc(1, size)) == NULL) {
-        return NULL;
-    }
-    list->flags = HWC_GEOMETRY_CHANGED;
-    list->numHwLayers = numLayers;
-
-    return list;
-}
-
-/*
- * freeLayerList
- * Frees memory previous allocated via createLayerList().
- */
-static void freeLayerList(hwc_layer_list_t *list)
-{
-    free(list);
-}
-
-static void fillColor(GraphicBuffer *gBuf, RGBColor color, float trans)
-{
-    unsigned char* buf = NULL;
-    status_t err;
-    uint32_t pixel;
-
-    // RGB 2 YUV conversion ratios
-    const struct rgb2yuvRatios {
-        int format;
-        float weightRed;
-        float weightBlu;
-        float weightGrn;
-    } rgb2yuvRatios[] = {
-        { HAL_PIXEL_FORMAT_YV12, 0.299, 0.114, 0.587 },
-    };
-
-    const struct rgbAttrib {
-        int format;
-        bool   hostByteOrder;
-        size_t bytes;
-        size_t rOffset;
-        size_t rSize;
-        size_t gOffset;
-        size_t gSize;
-        size_t bOffset;
-        size_t bSize;
-        size_t aOffset;
-        size_t aSize;
-    } rgbAttributes[] = {
-        {HAL_PIXEL_FORMAT_RGBA_8888, false, 4,  0, 8,  8, 8, 16, 8, 24, 8},
-        {HAL_PIXEL_FORMAT_RGBX_8888, false, 4,  0, 8,  8, 8, 16, 8,  0, 0},
-        {HAL_PIXEL_FORMAT_RGB_888,   false, 3,  0, 8,  8, 8, 16, 8,  0, 0},
-        {HAL_PIXEL_FORMAT_RGB_565,   true,  2,  0, 5,  5, 6, 11, 5,  0, 0},
-        {HAL_PIXEL_FORMAT_BGRA_8888, false, 4, 16, 8,  8, 8,  0, 8, 24, 8},
-        {HAL_PIXEL_FORMAT_RGBA_5551, true , 2,  0, 5,  5, 5, 10, 5, 15, 1},
-        {HAL_PIXEL_FORMAT_RGBA_4444, false, 2, 12, 4,  0, 4,  4, 4,  8, 4},
-    };
-
-    // If YUV format, convert color and pass work to YUV color fill
-    for (unsigned int n1 = 0; n1 < NUMA(rgb2yuvRatios); n1++) {
-        if (gBuf->getPixelFormat() == rgb2yuvRatios[n1].format) {
-            float wr = rgb2yuvRatios[n1].weightRed;
-            float wb = rgb2yuvRatios[n1].weightBlu;
-            float wg = rgb2yuvRatios[n1].weightGrn;
-            float y = wr * color.r() + wb * color.b() + wg * color.g();
-            float u = 0.5 * ((color.b() - y) / (1 - wb)) + 0.5;
-            float v = 0.5 * ((color.r() - y) / (1 - wr)) + 0.5;
-            YUVColor yuvColor(y, u, v);
-            fillColor(gBuf, yuvColor, trans);
-            return;
-        }
-    }
-
-    const struct rgbAttrib *attrib;
-    for (attrib = rgbAttributes; attrib < rgbAttributes + NUMA(rgbAttributes);
-         attrib++) {
-        if (attrib->format == gBuf->getPixelFormat()) { break; }
-    }
-    if (attrib >= rgbAttributes + NUMA(rgbAttributes)) {
-        testPrintE("fillColor rgb unsupported format of: %u",
-        gBuf->getPixelFormat());
-        exit(50);
-    }
-
-    pixel = htonl((uint32_t) (((1 << attrib->rSize) - 1) * color.r())
-         << ((sizeof(pixel) * BITSPERBYTE)
-             - (attrib->rOffset + attrib->rSize)));
-    pixel |= htonl((uint32_t) (((1 << attrib->gSize) - 1) * color.g())
-         << ((sizeof(pixel) * BITSPERBYTE)
-             - (attrib->gOffset + attrib->gSize)));
-    pixel |= htonl((uint32_t) (((1 << attrib->bSize) - 1) * color.b())
-         << ((sizeof(pixel) * BITSPERBYTE)
-             - (attrib->bOffset + attrib->bSize)));
-    if (attrib->aSize) {
-        pixel |= htonl((uint32_t) (((1 << attrib->aSize) - 1) * trans)
-             << ((sizeof(pixel) * BITSPERBYTE)
-                 - (attrib->aOffset + attrib->aSize)));
-    }
-    if (attrib->hostByteOrder) {
-        pixel = ntohl(pixel);
-        pixel >>= sizeof(pixel) * BITSPERBYTE - attrib->bytes * BITSPERBYTE;
-    }
-
-    err = gBuf->lock(GRALLOC_USAGE_SW_WRITE_OFTEN, (void**)(&buf));
-    if (err != 0) {
-        testPrintE("fillColor rgb lock failed: %d", err);
-        exit(51);
-    }
-
-    for (unsigned int row = 0; row < gBuf->getHeight(); row++) {
-        for (unsigned int col = 0; col < gBuf->getWidth(); col++) {
-          memmove(buf, &pixel, attrib->bytes);
-          buf += attrib->bytes;
-        }
-        for (unsigned int pad = 0;
-             pad < (gBuf->getStride() - gBuf->getWidth()) * attrib->bytes;
-             pad++) {
-            *buf++ = testRandMod(256);
-        }
-    }
-
-    err = gBuf->unlock();
-    if (err != 0) {
-        testPrintE("fillColor rgb unlock failed: %d", err);
-        exit(52);
-    }
-}
-
-static void fillColor(GraphicBuffer *gBuf, YUVColor color, float trans)
-{
-    unsigned char* buf = NULL;
-    status_t err;
-    unsigned int width = gBuf->getWidth();
-    unsigned int height = gBuf->getHeight();
-
-    const struct yuvAttrib {
-        int format;
-        bool   planar;
-        unsigned int uSubSampX;
-        unsigned int uSubSampY;
-        unsigned int vSubSampX;
-        unsigned int vSubSampY;
-    } yuvAttributes[] = {
-        { HAL_PIXEL_FORMAT_YV12, true, 2, 2, 2, 2},
-    };
-
-    const struct yuvAttrib *attrib;
-    for (attrib = yuvAttributes; attrib < yuvAttributes + NUMA(yuvAttributes);
-         attrib++) {
-        if (attrib->format == gBuf->getPixelFormat()) { break; }
-    }
-    if (attrib >= yuvAttributes + NUMA(yuvAttributes)) {
-        testPrintE("fillColor yuv unsupported format of: %u",
-        gBuf->getPixelFormat());
-        exit(60);
-    }
-
-    assert(attrib->planar == true); // So far, only know how to handle planar
-
-    err = gBuf->lock(GRALLOC_USAGE_SW_WRITE_OFTEN, (void**)(&buf));
-    if (err != 0) {
-        testPrintE("fillColor lock failed: %d", err);
-        exit(61);
-    }
-
-    // Fill in Y component
-    for (unsigned int row = 0; row < height; row++) {
-        for (unsigned int col = 0; col < width; col++) {
-            *buf++ = 255 * color.y();
-        }
-        for (unsigned int pad = 0; pad < gBuf->getStride() - gBuf->getWidth();
-             pad++) {
-             *buf++ = testRandMod(256);
-        }
-    }
-
-    // Fill in U component
-    for (unsigned int row = 0; row < height; row += attrib->uSubSampY) {
-        for (unsigned int col = 0; col < width; col += attrib->uSubSampX) {
-            *buf++ = 255 * color.u();
-        }
-        for (unsigned int pad = 0; pad < gBuf->getStride() - gBuf->getWidth();
-             pad += attrib->uSubSampX) {
-            *buf++ = testRandMod(256);
-        }
-    }
-
-    // Fill in V component
-    for (unsigned int row = 0; row < height; row += attrib->vSubSampY) {
-        for (unsigned int col = 0; col < width; col += attrib->vSubSampX) {
-            *buf++ = 255 * color.v();
-        }
-        for (unsigned int pad = 0; pad < gBuf->getStride() - gBuf->getWidth();
-             pad += attrib->vSubSampX) {
-            *buf++ = testRandMod(256);
-        }
-    }
-
-    err = gBuf->unlock();
-    if (err != 0) {
-        testPrintE("fillColor unlock failed: %d", err);
-        exit(62);
-    }
-}
-
-void init(void)
-{
-    int rv;
-
-    EGLBoolean returnValue;
-    EGLConfig myConfig = {0};
-    EGLint contextAttribs[] = { EGL_CONTEXT_CLIENT_VERSION, 2, EGL_NONE };
-    EGLint sConfigAttribs[] = {
-        EGL_SURFACE_TYPE, EGL_WINDOW_BIT,
-        EGL_RENDERABLE_TYPE, EGL_OPENGL_ES2_BIT,
-        EGL_NONE };
-    EGLint majorVersion, minorVersion;
-
-    checkEglError("<init>");
-    dpy = eglGetDisplay(EGL_DEFAULT_DISPLAY);
-    checkEglError("eglGetDisplay");
-    if (dpy == EGL_NO_DISPLAY) {
-        testPrintE("eglGetDisplay returned EGL_NO_DISPLAY");
-        exit(70);
-    }
-
-    returnValue = eglInitialize(dpy, &majorVersion, &minorVersion);
-    checkEglError("eglInitialize", returnValue);
-    testPrintI("EGL version %d.%d", majorVersion, minorVersion);
-    if (returnValue != EGL_TRUE) {
-        testPrintE("eglInitialize failed");
-        exit(71);
-    }
-
-    EGLNativeWindowType window = android_createDisplaySurface();
-    if (window == NULL) {
-        testPrintE("android_createDisplaySurface failed");
-        exit(72);
-    }
-    returnValue = EGLUtils::selectConfigForNativeWindow(dpy,
-        sConfigAttribs, window, &myConfig);
-    if (returnValue) {
-        testPrintE("EGLUtils::selectConfigForNativeWindow() returned %d",
-            returnValue);
-        exit(73);
-    }
-    checkEglError("EGLUtils::selectConfigForNativeWindow");
-
-    testPrintI("Chose this configuration:");
-    printEGLConfiguration(dpy, myConfig);
-
-    surface = eglCreateWindowSurface(dpy, myConfig, window, NULL);
-    checkEglError("eglCreateWindowSurface");
-    if (surface == EGL_NO_SURFACE) {
-        testPrintE("gelCreateWindowSurface failed.");
-        exit(74);
-    }
-
-    context = eglCreateContext(dpy, myConfig, EGL_NO_CONTEXT, contextAttribs);
-    checkEglError("eglCreateContext");
-    if (context == EGL_NO_CONTEXT) {
-        testPrintE("eglCreateContext failed");
-        exit(75);
-    }
-    returnValue = eglMakeCurrent(dpy, surface, surface, context);
-    checkEglError("eglMakeCurrent", returnValue);
-    if (returnValue != EGL_TRUE) {
-        testPrintE("eglMakeCurrent failed");
-        exit(76);
-    }
-    eglQuerySurface(dpy, surface, EGL_WIDTH, &width);
-    checkEglError("eglQuerySurface");
-    eglQuerySurface(dpy, surface, EGL_HEIGHT, &height);
-    checkEglError("eglQuerySurface");
-
-    testPrintI("Window dimensions: %d x %d", width, height);
-
-    printGLString("Version", GL_VERSION);
-    printGLString("Vendor", GL_VENDOR);
-    printGLString("Renderer", GL_RENDERER);
-    printGLString("Extensions", GL_EXTENSIONS);
-
-    if ((rv = hw_get_module(HWC_HARDWARE_MODULE_ID, &hwcModule)) != 0) {
-        testPrintE("hw_get_module failed, rv: %i", rv);
-        errno = -rv;
-        perror(NULL);
-        exit(77);
-    }
-    if ((rv = hwc_open(hwcModule, &hwcDevice)) != 0) {
-        testPrintE("hwc_open failed, rv: %i", rv);
-        errno = -rv;
-        perror(NULL);
-        exit(78);
-    }
-
-    testPrintI("");
-}
-
-/*
- * Initialize Frames
- *
- * Creates an array of graphic buffers, within the global variable
- * named frames.  The graphic buffers are contained within a vector of
- * vectors.  All the graphic buffers in a particular row are of the same
- * format and dimension.  Each graphic buffer is uniformly filled with a
- * prandomly selected color.  It is likely that each buffer, even
- * in the same row, will be filled with a unique color.
- */
-void initFrames(unsigned int seed)
-{
-    int rv;
-    const size_t maxRows = 5;
-    const size_t minCols = 2;  // Need at least double buffering
-    const size_t maxCols = 4;  // One more than triple buffering
-
-    if (verbose) { testPrintI("initFrames seed: %u", seed); }
-    srand48(seed);
-    size_t rows = testRandMod(maxRows) + 1;
-
-    frames.clear();
-    frames.resize(rows);
-
-    for (unsigned int row = 0; row < rows; row++) {
-        // All frames within a row have to have the same format and
-        // dimensions.  Width and height need to be >= 1.
-        unsigned int formatIdx = testRandMod(NUMA(graphicFormat));
-        const struct graphicFormat *formatPtr = &graphicFormat[formatIdx];
-        int format = formatPtr->format;
-
-        // Pick width and height, which must be >= 1 and the size
-        // mod the wMod/hMod value must be equal to 0.
-        size_t w = (width * maxSizeRatio) * testRandFract();
-        size_t h = (height * maxSizeRatio) * testRandFract();
-        w = max(1u, w);
-        h = max(1u, h);
-        if ((w % formatPtr->wMod) != 0) {
-            w += formatPtr->wMod - (w % formatPtr->wMod);
-        }
-        if ((h % formatPtr->hMod) != 0) {
-            h += formatPtr->hMod - (h % formatPtr->hMod);
-        }
-        if (verbose) {
-            testPrintI("  frame %u width: %u height: %u format: %u %s",
-                       row, w, h, format, graphicFormat2str(format));
-        }
-
-        size_t cols = testRandMod((maxCols + 1) - minCols) + minCols;
-        frames[row].resize(cols);
-        for (unsigned int col = 0; col < cols; col++) {
-            RGBColor color(testRandFract(), testRandFract(), testRandFract());
-            float transp = testRandFract();
-
-            frames[row][col] = new GraphicBuffer(w, h, format, texUsage);
-            if ((rv = frames[row][col]->initCheck()) != NO_ERROR) {
-                testPrintE("GraphicBuffer initCheck failed, rv: %i", rv);
-                testPrintE("  frame %u width: %u height: %u format: %u %s",
-                           row, w, h, format, graphicFormat2str(format));
-                exit(80);
-            }
-
-            fillColor(frames[row][col].get(), color, transp);
-            if (verbose) {
-                testPrintI("    buf: %p handle: %p color: <%f, %f, %f> "
-                           "transp: %f",
-                           frames[row][col].get(), frames[row][col]->handle,
-                           color.r(), color.g(), color.b(), transp);
-            }
-        }
-    }
-}
-
-void displayList(hwc_layer_list_t *list)
-{
-    testPrintI("  flags: %#x%s", list->flags,
-               (list->flags & HWC_GEOMETRY_CHANGED) ? " GEOMETRY_CHANGED" : "");
-    testPrintI("  numHwLayers: %u", list->numHwLayers);
-
-    for (unsigned int layer = 0; layer < list->numHwLayers; layer++) {
-        testPrintI("    layer %u compositionType: %#x%s%s", layer,
-                   list->hwLayers[layer].compositionType,
-                   (list->hwLayers[layer].compositionType == HWC_FRAMEBUFFER)
-                       ? " FRAMEBUFFER" : "",
-                   (list->hwLayers[layer].compositionType == HWC_OVERLAY)
-                       ? " OVERLAY" : "");
-
-        testPrintI("      hints: %#x",
-                   list->hwLayers[layer].hints,
-                   (list->hwLayers[layer].hints & HWC_HINT_TRIPLE_BUFFER)
-                       ? " TRIPLE_BUFFER" : "",
-                   (list->hwLayers[layer].hints & HWC_HINT_CLEAR_FB)
-                       ? " CLEAR_FB" : "");
-
-        testPrintI("      flags: %#x%s",
-                   list->hwLayers[layer].flags,
-                   (list->hwLayers[layer].flags & HWC_SKIP_LAYER)
-                       ? " SKIP_LAYER" : "");
-
-        testPrintI("      handle: %p",
-                   list->hwLayers[layer].handle);
-
-        // Intentionally skipped display of ROT_180 & ROT_270,
-        // which are formed from combinations of the other flags.
-        testPrintI("      transform: %#x%s%s%s",
-                   list->hwLayers[layer].transform,
-                   (list->hwLayers[layer].transform & HWC_TRANSFORM_FLIP_H)
-                       ? " FLIP_H" : "",
-                   (list->hwLayers[layer].transform & HWC_TRANSFORM_FLIP_V)
-                       ? " FLIP_V" : "",
-                   (list->hwLayers[layer].transform & HWC_TRANSFORM_ROT_90)
-                       ? " ROT_90" : "");
-
-        testPrintI("      blending: %#x",
-                   list->hwLayers[layer].blending,
-                   (list->hwLayers[layer].blending == HWC_BLENDING_NONE)
-                       ? " NONE" : "",
-                   (list->hwLayers[layer].blending == HWC_BLENDING_PREMULT)
-                       ? " PREMULT" : "",
-                   (list->hwLayers[layer].blending == HWC_BLENDING_COVERAGE)
-                       ? " COVERAGE" : "");
-
-        testPrintI("      sourceCrop: [%i, %i, %i, %i]",
-                   list->hwLayers[layer].sourceCrop.left,
-                   list->hwLayers[layer].sourceCrop.top,
-                   list->hwLayers[layer].sourceCrop.right,
-                   list->hwLayers[layer].sourceCrop.bottom);
-
-        testPrintI("      displayFrame: [%i, %i, %i, %i]",
-                   list->hwLayers[layer].displayFrame.left,
-                   list->hwLayers[layer].displayFrame.top,
-                   list->hwLayers[layer].displayFrame.right,
-                   list->hwLayers[layer].displayFrame.bottom);
-        testPrintI("      scaleFactor: [%f %f]",
-                   (float) (list->hwLayers[layer].displayFrame.right
-                            - list->hwLayers[layer].displayFrame.left)
-                       / (float) (list->hwLayers[layer].sourceCrop.right
-                            - list->hwLayers[layer].sourceCrop.left),
-                   (float) (list->hwLayers[layer].displayFrame.bottom
-                            - list->hwLayers[layer].displayFrame.top)
-                       / (float) (list->hwLayers[layer].sourceCrop.bottom
-                            - list->hwLayers[layer].sourceCrop.top));
-    }
-}
-
-/*
- * Display List Prepare Modifiable
- *
- * Displays the portions of a list that are meant to be modified by
- * a prepare call.
- */
-void displayListPrepareModifiable(hwc_layer_list_t *list)
-{
-    for (unsigned int layer = 0; layer < list->numHwLayers; layer++) {
-        testPrintI("    layer %u compositionType: %#x%s%s", layer,
-                   list->hwLayers[layer].compositionType,
-                   (list->hwLayers[layer].compositionType == HWC_FRAMEBUFFER)
-                       ? " FRAMEBUFFER" : "",
-                   (list->hwLayers[layer].compositionType == HWC_OVERLAY)
-                       ? " OVERLAY" : "");
-        testPrintI("      hints: %#x%s%s",
-                   list->hwLayers[layer].hints,
-                   (list->hwLayers[layer].hints & HWC_HINT_TRIPLE_BUFFER)
-                       ? " TRIPLE_BUFFER" : "",
-                   (list->hwLayers[layer].hints & HWC_HINT_CLEAR_FB)
-                       ? " CLEAR_FB" : "");
-    }
-}
-
-/*
- * Display List Handles
- *
- * Displays the handles of all the graphic buffers in the list.
- */
-void displayListHandles(hwc_layer_list_t *list)
-{
-    const unsigned int maxLayersPerLine = 6;
-
-    ostringstream str("  layers:");
-    for (unsigned int layer = 0; layer < list->numHwLayers; layer++) {
-        str << ' ' << list->hwLayers[layer].handle;
-        if (((layer % maxLayersPerLine) == (maxLayersPerLine - 1))
-            && (layer != list->numHwLayers - 1)) {
-            testPrintI("%s", str.str().c_str());
-            str.str("    ");
-        }
-    }
-    testPrintI("%s", str.str().c_str());
-}
-
-const char *graphicFormat2str(unsigned int format)
-{
-    const static char *unknown = "unknown";
-
-    for (unsigned int n1 = 0; n1 < NUMA(graphicFormat); n1++) {
-        if (format == graphicFormat[n1].format) {
-            return graphicFormat[n1].desc;
-        }
-    }
-
-    return unknown;
-}
-
-/*
- * Vector Random Select
- *
- * Prandomly selects and returns num elements from vec.
- */
-template <class T>
-vector<T> vectorRandSelect(const vector<T>& vec, size_t num)
-{
-    vector<T> rv = vec;
-
-    while (rv.size() > num) {
-        rv.erase(rv.begin() + testRandMod(rv.size()));
-    }
-
-    return rv;
-}
-
-/*
- * Vector Or
- *
- * Or's togethen the values of each element of vec and returns the result.
- */
-template <class T>
-T vectorOr(const vector<T>& vec)
-{
-    T rv = 0;
-
-    for (size_t n1 = 0; n1 < vec.size(); n1++) {
-        rv |= vec[n1];
-    }
-
-    return rv;
-}
diff --git a/opengl/tests/include/glTestLib.h b/opengl/tests/include/glTestLib.h
new file mode 100644
index 0000000..06fbf5d
--- /dev/null
+++ b/opengl/tests/include/glTestLib.h
@@ -0,0 +1,34 @@
+/*
+ * Copyright (C) 2011 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+/*
+ * Graphics Test Library Header
+ */
+
+#include <EGL/egl.h>
+#include <EGL/eglext.h>
+#include <GLES2/gl2.h>
+#include <GLES2/gl2ext.h>
+
+//#include <ui/FramebufferNativeWindow.h>
+//#include <ui/GraphicBuffer.h>
+#include <ui/EGLUtils.h>
+
+void glTestPrintGLString(const char *name, GLenum s);
+void glTestCheckEglError(const char* op, EGLBoolean returnVal = EGL_TRUE);
+void glTestCheckGlError(const char* op);
+void glTestPrintEGLConfiguration(EGLDisplay dpy, EGLConfig config);
diff --git a/opengl/tests/lib/Android.mk b/opengl/tests/lib/Android.mk
new file mode 100644
index 0000000..7542ac4
--- /dev/null
+++ b/opengl/tests/lib/Android.mk
@@ -0,0 +1,32 @@
+# Copyright (C) 2010 The Android Open Source Project
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+#      http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+
+LOCAL_PATH:= $(call my-dir)
+
+include $(CLEAR_VARS)
+LOCAL_MODULE_TAGS := tests
+LOCAL_MODULE:= libglTest
+LOCAL_SRC_FILES:= glTestLib.cpp
+LOCAL_C_INCLUDES += system/extras/tests/include \
+    bionic \
+    bionic/libstdc++/include \
+    external/stlport/stlport \
+    frameworks/base/opengl/tests/include \
+
+LOCAL_CFLAGS := -DGL_GLEXT_PROTOTYPES -DEGL_EGLEXT_PROTOTYPES
+
+LOCAL_SHARED_LIBRARIES += libcutils libutils libstlport
+LOCAL_PRELINK_MODULE := false
+
+include $(BUILD_STATIC_LIBRARY)
diff --git a/opengl/tests/lib/glTestLib.cpp b/opengl/tests/lib/glTestLib.cpp
new file mode 100644
index 0000000..052cbd7
--- /dev/null
+++ b/opengl/tests/lib/glTestLib.cpp
@@ -0,0 +1,119 @@
+/*
+ * Copyright (C) 2011 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+/*
+ * Graphics Test Library
+ */
+
+#include <glTestLib.h>
+
+#include <EGL/egl.h>
+#include <EGL/eglext.h>
+#include <GLES2/gl2.h>
+#include <GLES2/gl2ext.h>
+
+#include <ui/EGLUtils.h>
+
+#include <utils/Log.h>
+#include <testUtil.h>
+
+using namespace std;
+using namespace android;
+
+void glTestPrintGLString(const char *name, GLenum s)
+{
+    const char *v = (const char *) glGetString(s);
+
+    if (v == NULL) {
+        testPrintI("GL %s unknown", name);
+    } else {
+        testPrintI("GL %s = %s", name, v);
+    }
+}
+
+void glTestCheckEglError(const char* op, EGLBoolean returnVal)
+{
+    if (returnVal != EGL_TRUE) {
+        testPrintE("%s() returned %d", op, returnVal);
+    }
+
+    for (EGLint error = eglGetError(); error != EGL_SUCCESS; error
+            = eglGetError()) {
+        testPrintE("after %s() eglError %s (0x%x)",
+                   op, EGLUtils::strerror(error), error);
+    }
+}
+
+void glTestCheckGlError(const char* op)
+{
+    for (GLint error = glGetError(); error; error
+            = glGetError()) {
+        testPrintE("after %s() glError (0x%x)", op, error);
+    }
+}
+
+void glTestPrintEGLConfiguration(EGLDisplay dpy, EGLConfig config)
+{
+
+#define X(VAL) {VAL, #VAL}
+    struct {EGLint attribute; const char* name;} names[] = {
+    X(EGL_BUFFER_SIZE),
+    X(EGL_ALPHA_SIZE),
+    X(EGL_BLUE_SIZE),
+    X(EGL_GREEN_SIZE),
+    X(EGL_RED_SIZE),
+    X(EGL_DEPTH_SIZE),
+    X(EGL_STENCIL_SIZE),
+    X(EGL_CONFIG_CAVEAT),
+    X(EGL_CONFIG_ID),
+    X(EGL_LEVEL),
+    X(EGL_MAX_PBUFFER_HEIGHT),
+    X(EGL_MAX_PBUFFER_PIXELS),
+    X(EGL_MAX_PBUFFER_WIDTH),
+    X(EGL_NATIVE_RENDERABLE),
+    X(EGL_NATIVE_VISUAL_ID),
+    X(EGL_NATIVE_VISUAL_TYPE),
+    X(EGL_SAMPLES),
+    X(EGL_SAMPLE_BUFFERS),
+    X(EGL_SURFACE_TYPE),
+    X(EGL_TRANSPARENT_TYPE),
+    X(EGL_TRANSPARENT_RED_VALUE),
+    X(EGL_TRANSPARENT_GREEN_VALUE),
+    X(EGL_TRANSPARENT_BLUE_VALUE),
+    X(EGL_BIND_TO_TEXTURE_RGB),
+    X(EGL_BIND_TO_TEXTURE_RGBA),
+    X(EGL_MIN_SWAP_INTERVAL),
+    X(EGL_MAX_SWAP_INTERVAL),
+    X(EGL_LUMINANCE_SIZE),
+    X(EGL_ALPHA_MASK_SIZE),
+    X(EGL_COLOR_BUFFER_TYPE),
+    X(EGL_RENDERABLE_TYPE),
+    X(EGL_CONFORMANT),
+   };
+#undef X
+
+    for (size_t j = 0; j < sizeof(names) / sizeof(names[0]); j++) {
+        EGLint value = -1;
+        EGLint returnVal = eglGetConfigAttrib(dpy, config, names[j].attribute,
+                                              &value);
+        EGLint error = eglGetError();
+        if (returnVal && error == EGL_SUCCESS) {
+            testPrintI(" %s: %d (%#x)", names[j].name, value, value);
+        }
+    }
+    testPrintI("");
+}
diff --git a/services/surfaceflinger/LayerBase.cpp b/services/surfaceflinger/LayerBase.cpp
index 8a021cb..0c1fcf9 100644
--- a/services/surfaceflinger/LayerBase.cpp
+++ b/services/surfaceflinger/LayerBase.cpp
@@ -503,12 +503,18 @@
 
 void LayerBase::setBufferCrop(const Rect& crop) {
     if (!crop.isEmpty()) {
-        mBufferCrop = crop;
+        if (mBufferCrop != crop) {
+            mBufferCrop = crop;
+            mFlinger->invalidateHwcGeometry();
+        }
     }
 }
 
 void LayerBase::setBufferTransform(uint32_t transform) {
-    mBufferTransform = transform;
+    if (mBufferTransform != transform) {
+        mBufferTransform = transform;
+        mFlinger->invalidateHwcGeometry();
+    }
 }
 
 void LayerBase::dump(String8& result, char* buffer, size_t SIZE) const
diff --git a/services/surfaceflinger/SurfaceFlinger.cpp b/services/surfaceflinger/SurfaceFlinger.cpp
index 7c4790f..154b822 100644
--- a/services/surfaceflinger/SurfaceFlinger.cpp
+++ b/services/surfaceflinger/SurfaceFlinger.cpp
@@ -144,6 +144,11 @@
     return bclient;
 }
 
+sp<IGraphicBufferAlloc> SurfaceFlinger::createGraphicBufferAlloc()
+{
+    sp<GraphicBufferAlloc> gba(new GraphicBufferAlloc());
+    return gba;
+}
 
 const GraphicPlane& SurfaceFlinger::graphicPlane(int dpy) const
 {
@@ -460,7 +465,7 @@
         handleTransactionLocked(transactionFlags, ditchedLayers);
         mLastTransactionTime = systemTime() - now;
         mDebugInTransaction = 0;
-        mHwWorkListDirty = true;
+        invalidateHwcGeometry();
         // here the transaction has been committed
     }
 
@@ -726,13 +731,18 @@
 
             mWormholeRegion = screenRegion.subtract(opaqueRegion);
             mVisibleRegionsDirty = false;
-            mHwWorkListDirty = true;
+            invalidateHwcGeometry();
         }
 
     unlockPageFlip(currentLayers);
     mDirtyRegion.andSelf(screenRegion);
 }
 
+void SurfaceFlinger::invalidateHwcGeometry()
+{
+    mHwWorkListDirty = true;
+}
+
 bool SurfaceFlinger::lockPageFlip(const LayerVector& currentLayers)
 {
     bool recomputeVisibleRegions = false;
@@ -1099,8 +1109,12 @@
 
 status_t SurfaceFlinger::purgatorizeLayer_l(const sp<LayerBase>& layerBase)
 {
-    // remove the layer from the main list (through a transaction).
+    // First add the layer to the purgatory list, which makes sure it won't
+    // go away, then remove it from the main list (through a transaction).
     ssize_t err = removeLayer_l(layerBase);
+    if (err >= 0) {
+        mLayerPurgatory.add(layerBase);
+    }
 
     layerBase->onRemoved();
 
@@ -1349,6 +1363,19 @@
              * to use the purgatory.
              */
             status_t err = flinger->removeLayer_l(l);
+            if (err == NAME_NOT_FOUND) {
+                // The surface wasn't in the current list, which means it was
+                // removed already, which means it is in the purgatory,
+                // and need to be removed from there.
+                // This needs to happen from the main thread since its dtor
+                // must run from there (b/c of OpenGL ES). Additionally, we
+                // can't really acquire our internal lock from
+                // destroySurface() -- see postMessage() below.
+                ssize_t idx = flinger->mLayerPurgatory.remove(l);
+                LOGE_IF(idx < 0,
+                        "layer=%p is not in the purgatory list", l.get());
+            }
+
             LOGE_IF(err<0 && err != NAME_NOT_FOUND,
                     "error removing layer=%p (%s)", l.get(), strerror(-err));
             return true;
@@ -1586,7 +1613,7 @@
             case 1008:  // toggle use of hw composer
                 n = data.readInt32();
                 mDebugDisableHWC = n ? 1 : 0;
-                mHwWorkListDirty = true;
+                invalidateHwcGeometry();
                 // fall-through...
             case 1004:{ // repaint everything
                 Mutex::Autolock _l(mStateLock);
@@ -2123,6 +2150,7 @@
 
         // invert everything, b/c glReadPixel() below will invert the FB
         glViewport(0, 0, sw, sh);
+        glScissor(0, 0, sw, sh);
         glMatrixMode(GL_PROJECTION);
         glPushMatrix();
         glLoadIdentity();
@@ -2132,6 +2160,7 @@
         // redraw the screen entirely...
         glClearColor(0,0,0,1);
         glClear(GL_COLOR_BUFFER_BIT);
+
         const Vector< sp<LayerBase> >& layers(mVisibleLayersSortedByZ);
         const size_t count = layers.size();
         for (size_t i=0 ; i<count ; ++i) {
@@ -2169,7 +2198,6 @@
                 result = NO_MEMORY;
             }
         }
-
         glEnable(GL_SCISSOR_TEST);
         glViewport(0, 0, hw_w, hw_h);
         glMatrixMode(GL_PROJECTION);
@@ -2445,6 +2473,39 @@
 
 // ---------------------------------------------------------------------------
 
+GraphicBufferAlloc::GraphicBufferAlloc() {}
+
+GraphicBufferAlloc::~GraphicBufferAlloc() {}
+
+sp<GraphicBuffer> GraphicBufferAlloc::createGraphicBuffer(uint32_t w, uint32_t h,
+        PixelFormat format, uint32_t usage) {
+    sp<GraphicBuffer> graphicBuffer(new GraphicBuffer(w, h, format, usage));
+    status_t err = graphicBuffer->initCheck();
+    if (err != 0) {
+        LOGE("createGraphicBuffer: init check failed: %d", err);
+        return 0;
+    } else if (graphicBuffer->handle == 0) {
+        LOGE("createGraphicBuffer: unable to create GraphicBuffer");
+        return 0;
+    }
+    Mutex::Autolock _l(mLock);
+    mBuffers.add(graphicBuffer);
+    return graphicBuffer;
+}
+
+void GraphicBufferAlloc::freeAllGraphicBuffersExcept(int bufIdx) {
+    Mutex::Autolock _l(mLock);
+    if (0 <= bufIdx && bufIdx < mBuffers.size()) {
+        sp<GraphicBuffer> b(mBuffers[bufIdx]);
+        mBuffers.clear();
+        mBuffers.add(b);
+    } else {
+        mBuffers.clear();
+    }
+}
+
+// ---------------------------------------------------------------------------
+
 GraphicPlane::GraphicPlane()
     : mHw(0)
 {
diff --git a/services/surfaceflinger/SurfaceFlinger.h b/services/surfaceflinger/SurfaceFlinger.h
index ca7d27d..eabdc64 100644
--- a/services/surfaceflinger/SurfaceFlinger.h
+++ b/services/surfaceflinger/SurfaceFlinger.h
@@ -34,6 +34,7 @@
 #include <ui/PixelFormat.h>
 #include <surfaceflinger/ISurfaceComposer.h>
 #include <surfaceflinger/ISurfaceComposerClient.h>
+#include <surfaceflinger/IGraphicBufferAlloc.h>
 
 #include "Barrier.h"
 #include "Layer.h"
@@ -119,6 +120,21 @@
     sp<SurfaceFlinger> mFlinger;
 };
 
+class GraphicBufferAlloc : public BnGraphicBufferAlloc
+{
+public:
+    GraphicBufferAlloc();
+    virtual ~GraphicBufferAlloc();
+
+    virtual sp<GraphicBuffer> createGraphicBuffer(uint32_t w, uint32_t h,
+        PixelFormat format, uint32_t usage);
+    virtual void freeAllGraphicBuffersExcept(int bufIdx);
+
+private:
+    Vector<sp<GraphicBuffer> > mBuffers;
+    Mutex mLock;
+};
+
 // ---------------------------------------------------------------------------
 
 class GraphicPlane
@@ -184,6 +200,7 @@
     // ISurfaceComposer interface
     virtual sp<ISurfaceComposerClient>  createConnection();
     virtual sp<ISurfaceComposerClient>  createClientConnection();
+    virtual sp<IGraphicBufferAlloc>     createGraphicBufferAlloc();
     virtual sp<IMemoryHeap>             getCblk() const;
     virtual void                        bootFinished();
     virtual void                        openGlobalTransaction();
@@ -208,6 +225,7 @@
     status_t removeLayer(const sp<LayerBase>& layer);
     status_t addLayer(const sp<LayerBase>& layer);
     status_t invalidateLayerVisibility(const sp<LayerBase>& layer);
+    void invalidateHwcGeometry();
 
     sp<Layer> getLayer(const sp<ISurface>& sur) const;
 
@@ -357,6 +375,7 @@
     volatile    int32_t                 mTransactionFlags;
     volatile    int32_t                 mTransactionCount;
                 Condition               mTransactionCV;
+                SortedVector< sp<LayerBase> > mLayerPurgatory;
                 bool                    mResizeTransationPending;
 
                 // protected by mStateLock (but we could use another lock)