summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--camera/libcameraservice/Android.mk20
-rw-r--r--camera/libcameraservice/CameraHardwareStub.cpp19
-rw-r--r--camera/libcameraservice/CameraHardwareStub.h2
-rw-r--r--camera/libcameraservice/CameraService.cpp66
-rw-r--r--camera/libcameraservice/CameraService.h3
-rw-r--r--include/private/surfaceflinger/SharedBufferStack.h16
-rw-r--r--include/surfaceflinger/Surface.h6
-rw-r--r--include/ui/EventHub.h157
-rw-r--r--include/ui/Input.h310
-rw-r--r--include/ui/InputDispatchPolicy.h198
-rw-r--r--include/ui/InputDispatcher.h409
-rw-r--r--include/ui/InputManager.h134
-rw-r--r--include/ui/InputReader.h472
-rw-r--r--include/ui/InputTransport.h331
-rw-r--r--include/utils/BitSet.h67
-rw-r--r--include/utils/Buffer.h107
-rw-r--r--include/utils/PollLoop.h137
-rw-r--r--include/utils/Pool.h71
-rw-r--r--include/utils/StopWatch.h2
-rw-r--r--include/utils/Vector.h16
-rw-r--r--include/utils/VectorImpl.h4
-rw-r--r--libs/surfaceflinger/Layer.cpp48
-rw-r--r--libs/surfaceflinger/Layer.h11
-rw-r--r--libs/surfaceflinger/SurfaceFlinger.cpp22
-rw-r--r--libs/surfaceflinger_client/SharedBufferStack.cpp4
-rw-r--r--libs/surfaceflinger_client/Surface.cpp55
-rw-r--r--libs/surfaceflinger_client/SurfaceComposerClient.cpp4
-rw-r--r--libs/ui/Android.mk5
-rw-r--r--libs/ui/EventHub.cpp172
-rw-r--r--libs/ui/GraphicBuffer.cpp3
-rw-r--r--libs/ui/Input.cpp238
-rw-r--r--libs/ui/InputDispatcher.cpp1313
-rw-r--r--libs/ui/InputManager.cpp114
-rw-r--r--libs/ui/InputReader.cpp1843
-rw-r--r--libs/ui/InputTransport.cpp684
-rw-r--r--libs/ui/tests/Android.mk34
-rw-r--r--libs/ui/tests/InputDispatcher_test.cpp19
-rw-r--r--libs/ui/tests/region/Android.mk16
-rw-r--r--libs/ui/tests/region/region.cpp (renamed from libs/ui/tests/region.cpp)0
-rw-r--r--libs/utils/Android.mk8
-rw-r--r--libs/utils/PollLoop.cpp267
-rw-r--r--libs/utils/Pool.cpp37
-rw-r--r--libs/utils/StopWatch.cpp11
-rw-r--r--libs/utils/String8.cpp12
-rw-r--r--libs/utils/VectorImpl.cpp12
-rw-r--r--libs/utils/tests/Android.mk33
-rw-r--r--libs/utils/tests/PollLoop_test.cpp398
-rw-r--r--libs/utils/tests/TestHelpers.h44
-rw-r--r--opengl/include/EGL/egl.h3
-rw-r--r--opengl/include/EGL/eglext.h98
-rw-r--r--opengl/include/EGL/eglplatform.h6
-rw-r--r--opengl/include/GLES/gl.h5
-rw-r--r--opengl/include/GLES/glext.h400
-rw-r--r--opengl/include/GLES/glplatform.h7
-rw-r--r--opengl/include/GLES2/gl2.h43
-rw-r--r--opengl/include/GLES2/gl2ext.h413
-rw-r--r--opengl/include/GLES2/gl2platform.h5
-rw-r--r--opengl/libs/GLES2/gl2_api.in40
-rw-r--r--opengl/libs/GLES2/gl2ext_api.in97
-rw-r--r--opengl/libs/GLES_CM/gl_api.in2
-rw-r--r--opengl/libs/GLES_CM/glext_api.in110
-rw-r--r--opengl/libs/entries.in77
-rw-r--r--opengl/tests/gl2_basic/gl2_basic.cpp1
-rw-r--r--opengl/tests/gl_basic/gl_basic.cpp1
64 files changed, 8735 insertions, 527 deletions
diff --git a/camera/libcameraservice/Android.mk b/camera/libcameraservice/Android.mk
index a0d6ee1..87975af 100644
--- a/camera/libcameraservice/Android.mk
+++ b/camera/libcameraservice/Android.mk
@@ -7,15 +7,11 @@ ifneq ($(filter sooner generic sim,$(TARGET_DEVICE)),)
USE_CAMERA_STUB:=true
endif
-ifeq ($(USE_CAMERA_STUB),true)
- INCLUDE_CAMERA_STUB:=true
- INCLUDE_CAMERA_HARDWARE:=false
-else
- INCLUDE_CAMERA_STUB:=true # set this to true temporarily for testing
- INCLUDE_CAMERA_HARDWARE:=true
+ifeq ($(USE_CAMERA_STUB),)
+ USE_CAMERA_STUB:=false
endif
-ifeq ($(INCLUDE_CAMERA_STUB),true)
+ifeq ($(USE_CAMERA_STUB),true)
#
# libcamerastub
#
@@ -35,7 +31,7 @@ endif
LOCAL_SHARED_LIBRARIES:= libui
include $(BUILD_STATIC_LIBRARY)
-endif # INCLUDE_CAMERA_STUB
+endif # USE_CAMERA_STUB
#
# libcameraservice
@@ -61,13 +57,9 @@ ifeq ($(TARGET_SIMULATOR),true)
LOCAL_CFLAGS += -DSINGLE_PROCESS
endif
-ifeq ($(INCLUDE_CAMERA_STUB), true)
+ifeq ($(USE_CAMERA_STUB), true)
LOCAL_STATIC_LIBRARIES += libcamerastub
-LOCAL_CFLAGS += -DINCLUDE_CAMERA_STUB
-endif
-
-ifeq ($(INCLUDE_CAMERA_HARDWARE),true)
-LOCAL_CFLAGS += -DINCLUDE_CAMERA_HARDWARE
+else
LOCAL_SHARED_LIBRARIES += libcamera
endif
diff --git a/camera/libcameraservice/CameraHardwareStub.cpp b/camera/libcameraservice/CameraHardwareStub.cpp
index fda48e8..b3e0ee6 100644
--- a/camera/libcameraservice/CameraHardwareStub.cpp
+++ b/camera/libcameraservice/CameraHardwareStub.cpp
@@ -385,7 +385,24 @@ sp<CameraHardwareInterface> CameraHardwareStub::createInstance()
return new CameraHardwareStub();
}
-extern "C" sp<CameraHardwareInterface> openCameraHardwareStub()
+static CameraInfo sCameraInfo[] = {
+ {
+ CAMERA_FACING_BACK,
+ 90, /* orientation */
+ }
+};
+
+extern "C" int HAL_getNumberOfCameras()
+{
+ return sizeof(sCameraInfo) / sizeof(sCameraInfo[0]);
+}
+
+extern "C" void HAL_getCameraInfo(int cameraId, struct CameraInfo* cameraInfo)
+{
+ memcpy(cameraInfo, &sCameraInfo[cameraId], sizeof(CameraInfo));
+}
+
+extern "C" sp<CameraHardwareInterface> HAL_openCameraHardware(int cameraId)
{
return CameraHardwareStub::createInstance();
}
diff --git a/camera/libcameraservice/CameraHardwareStub.h b/camera/libcameraservice/CameraHardwareStub.h
index d194f3c..d3427ba 100644
--- a/camera/libcameraservice/CameraHardwareStub.h
+++ b/camera/libcameraservice/CameraHardwareStub.h
@@ -128,8 +128,6 @@ private:
int mCurrentPreviewFrame;
};
-extern "C" sp<CameraHardwareInterface> openCameraHardwareStub();
-
}; // namespace android
#endif
diff --git a/camera/libcameraservice/CameraService.cpp b/camera/libcameraservice/CameraService.cpp
index 4f684b7..75948a5 100644
--- a/camera/libcameraservice/CameraService.cpp
+++ b/camera/libcameraservice/CameraService.cpp
@@ -37,37 +37,9 @@
#include <utils/String16.h>
#include "CameraService.h"
-#ifdef INCLUDE_CAMERA_STUB
-#include "CameraHardwareStub.h"
-#endif
namespace android {
-/* This determines the number of cameras available */
-#if defined(INCLUDE_CAMERA_HARDWARE) && defined(INCLUDE_CAMERA_STUB)
- #define NUM_CAMERAS 2
-#elif defined(INCLUDE_CAMERA_HARDWARE) || defined(INCLUDE_CAMERA_STUB)
- #define NUM_CAMERAS 1
-#else
- #error "Should have at least one camera"
-#endif
-
-/* Make sure we have enough array space allocated */
-#if NUM_CAMERAS > MAX_CAMERAS
- #error "Need to increase MAX_CAMERAS"
-#endif
-
-/* This defines the "open" function for each camera */
-extern "C" typedef sp<CameraHardwareInterface> (*OpenCameraHardwareFunction)();
-static OpenCameraHardwareFunction sOpenCameraTable[] = {
-#ifdef INCLUDE_CAMERA_HARDWARE
- &openCameraHardware,
-#endif
-#ifdef INCLUDE_CAMERA_STUB
- &openCameraHardwareStub,
-#endif
-};
-
// ----------------------------------------------------------------------------
// Logging support -- this is for debugging only
// Use "adb shell dumpsys media.camera -v 1" to change it.
@@ -101,7 +73,14 @@ CameraService::CameraService()
{
LOGI("CameraService started (pid=%d)", getpid());
- for (int i = 0; i < NUM_CAMERAS; i++) {
+ mNumberOfCameras = HAL_getNumberOfCameras();
+ if (mNumberOfCameras > MAX_CAMERAS) {
+ LOGE("Number of cameras(%d) > MAX_CAMERAS(%d).",
+ mNumberOfCameras, MAX_CAMERAS);
+ mNumberOfCameras = MAX_CAMERAS;
+ }
+
+ for (int i = 0; i < mNumberOfCameras; i++) {
setCameraFree(i);
}
@@ -109,7 +88,7 @@ CameraService::CameraService()
}
CameraService::~CameraService() {
- for (int i = 0; i < NUM_CAMERAS; i++) {
+ for (int i = 0; i < mNumberOfCameras; i++) {
if (mBusy[i]) {
LOGE("camera %d is still in use in destructor!", i);
}
@@ -119,7 +98,17 @@ CameraService::~CameraService() {
}
int32_t CameraService::getNumberOfCameras() {
- return NUM_CAMERAS;
+ return mNumberOfCameras;
+}
+
+status_t CameraService::getCameraInfo(int cameraId,
+ struct CameraInfo* cameraInfo) {
+ if (cameraId < 0 || cameraId >= mNumberOfCameras) {
+ return BAD_VALUE;
+ }
+
+ HAL_getCameraInfo(cameraId, cameraInfo);
+ return OK;
}
sp<ICamera> CameraService::connect(
@@ -128,7 +117,7 @@ sp<ICamera> CameraService::connect(
LOG1("CameraService::connect E (pid %d, id %d)", callingPid, cameraId);
sp<Client> client;
- if (cameraId < 0 || cameraId >= NUM_CAMERAS) {
+ if (cameraId < 0 || cameraId >= mNumberOfCameras) {
LOGE("CameraService::connect X (pid %d) rejected (invalid cameraId %d).",
callingPid, cameraId);
return NULL;
@@ -167,7 +156,7 @@ void CameraService::removeClient(const sp<ICameraClient>& cameraClient) {
int callingPid = getCallingPid();
LOG1("CameraService::removeClient E (pid %d)", callingPid);
- for (int i = 0; i < NUM_CAMERAS; i++) {
+ for (int i = 0; i < mNumberOfCameras; i++) {
// Declare this before the lock to make absolutely sure the
// destructor won't be called with the lock held.
sp<Client> client;
@@ -199,7 +188,7 @@ void CameraService::removeClient(const sp<ICameraClient>& cameraClient) {
}
sp<CameraService::Client> CameraService::getClientById(int cameraId) {
- if (cameraId < 0 || cameraId >= NUM_CAMERAS) return NULL;
+ if (cameraId < 0 || cameraId >= mNumberOfCameras) return NULL;
return mClient[cameraId].promote();
}
@@ -311,7 +300,7 @@ CameraService::Client::Client(const sp<CameraService>& cameraService,
mCameraId = cameraId;
mClientPid = clientPid;
- mHardware = sOpenCameraTable[cameraId]();
+ mHardware = HAL_openCameraHardware(cameraId);
mUseOverlay = mHardware->useOverlay();
mMsgEnabled = 0;
@@ -371,10 +360,7 @@ CameraService::Client::~Client() {
status_t CameraService::Client::checkPid() const {
int callingPid = getCallingPid();
if (callingPid == mClientPid) return NO_ERROR;
- if (callingPid == getpid()) {
- LOGW("FIXME: use camera from mediaserver without permission.");
- return NO_ERROR;
- }
+
LOGW("attempt to use a locked camera from a different process"
" (old pid %d, new pid %d)", mClientPid, callingPid);
return EBUSY;
@@ -1249,7 +1235,7 @@ status_t CameraService::dump(int fd, const Vector<String16>& args) {
}
bool hasClient = false;
- for (int i = 0; i < NUM_CAMERAS; i++) {
+ for (int i = 0; i < mNumberOfCameras; i++) {
sp<Client> client = mClient[i].promote();
if (client == 0) continue;
hasClient = true;
diff --git a/camera/libcameraservice/CameraService.h b/camera/libcameraservice/CameraService.h
index 86986ca..8193e77 100644
--- a/camera/libcameraservice/CameraService.h
+++ b/camera/libcameraservice/CameraService.h
@@ -40,6 +40,8 @@ public:
virtual ~CameraService();
virtual int32_t getNumberOfCameras();
+ virtual status_t getCameraInfo(int cameraId,
+ struct CameraInfo* cameraInfo);
virtual sp<ICamera> connect(const sp<ICameraClient>& cameraClient, int cameraId);
virtual void removeClient(const sp<ICameraClient>& cameraClient);
virtual sp<Client> getClientById(int cameraId);
@@ -61,6 +63,7 @@ public:
private:
Mutex mServiceLock;
wp<Client> mClient[MAX_CAMERAS]; // protected by mServiceLock
+ int mNumberOfCameras;
// atomics to record whether the hardware is allocated to some client.
volatile int32_t mBusy[MAX_CAMERAS];
diff --git a/include/private/surfaceflinger/SharedBufferStack.h b/include/private/surfaceflinger/SharedBufferStack.h
index c11c855..633b543 100644
--- a/include/private/surfaceflinger/SharedBufferStack.h
+++ b/include/private/surfaceflinger/SharedBufferStack.h
@@ -43,15 +43,6 @@ namespace android {
* unless they are in use by the server, which is only the case for the last
* dequeue-able buffer. When these various conditions are not met, the caller
* waits until the condition is met.
- *
- *
- * CAVEATS:
- *
- * In the current implementation there are several limitations:
- * - buffers must be locked in the same order they've been dequeued
- * - buffers must be enqueued in the same order they've been locked
- * - dequeue() is not reentrant
- * - no error checks are done on the condition above
*
*/
@@ -269,7 +260,9 @@ private:
// ----------------------------------------------------------------------------
-class SharedBufferServer : public SharedBufferBase
+class SharedBufferServer
+ : public SharedBufferBase,
+ public LightRefBase<SharedBufferServer>
{
public:
SharedBufferServer(SharedClient* sharedClient, int surface, int num,
@@ -290,6 +283,9 @@ public:
private:
+ friend class LightRefBase<SharedBufferServer>;
+ ~SharedBufferServer();
+
/*
* BufferList is basically a fixed-capacity sorted-vector of
* unsigned 5-bits ints using a 32-bits int as storage.
diff --git a/include/surfaceflinger/Surface.h b/include/surfaceflinger/Surface.h
index ac01ce5..f333911 100644
--- a/include/surfaceflinger/Surface.h
+++ b/include/surfaceflinger/Surface.h
@@ -60,7 +60,6 @@ public:
static bool isSameSurface(
const sp<SurfaceControl>& lhs, const sp<SurfaceControl>& rhs);
- SurfaceID ID() const { return mToken; }
uint32_t getFlags() const { return mFlags; }
uint32_t getIdentity() const { return mIdentity; }
@@ -145,6 +144,9 @@ public:
uint32_t reserved[2];
};
+ static status_t writeToParcel(
+ const sp<Surface>& control, Parcel* parcel);
+
static sp<Surface> readFromParcel(
const Parcel& data, const sp<Surface>& other);
@@ -153,7 +155,6 @@ public:
}
bool isValid();
- SurfaceID ID() const { return mToken; }
uint32_t getFlags() const { return mFlags; }
uint32_t getIdentity() const { return mIdentity; }
@@ -267,7 +268,6 @@ private:
SharedBufferClient* mSharedBufferClient;
status_t mInitCheck;
sp<ISurface> mSurface;
- SurfaceID mToken;
uint32_t mIdentity;
PixelFormat mFormat;
uint32_t mFlags;
diff --git a/include/ui/EventHub.h b/include/ui/EventHub.h
index 3b18c77..d322a34 100644
--- a/include/ui/EventHub.h
+++ b/include/ui/EventHub.h
@@ -18,6 +18,7 @@
#ifndef _RUNTIME_EVENT_HUB_H
#define _RUNTIME_EVENT_HUB_H
+#include <android/input.h>
#include <utils/String8.h>
#include <utils/threads.h>
#include <utils/Log.h>
@@ -27,6 +28,31 @@
#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 {
@@ -34,62 +60,101 @@ namespace android {
class KeyLayoutMap;
/*
- * Grand Central Station for events. With a single call to waitEvent()
- * you can wait for:
- * - input events from the keypad of a real device
- * - input events and meta-events (e.g. "quit") from the simulator
- * - synthetic events from the runtime (e.g. "URL fetch completed")
- * - real or forged "vsync" events
+ * Grand Central Station for events.
*
- * Do not instantiate this class. Instead, call startUp().
+ * 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 EventHub : public RefBase
+class EventHubInterface : public virtual RefBase {
+protected:
+ EventHubInterface() { }
+ virtual ~EventHubInterface() { }
+
+public:
+ // Synthetic raw event type codes produced when devices are added or removed.
+ enum {
+ DEVICE_ADDED = 0x10000000,
+ DEVICE_REMOVED = 0x20000000
+ };
+
+ virtual uint32_t getDeviceClasses(int32_t deviceId) const = 0;
+
+ virtual String8 getDeviceName(int32_t deviceId) const = 0;
+
+ virtual int getAbsoluteInfo(int32_t deviceId, int axis, int *outMinValue,
+ int* outMaxValue, int* outFlat, int* outFuzz) 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(int32_t* outDeviceId, int32_t* outType,
+ int32_t* outScancode, int32_t* outKeycode, uint32_t *outFlags,
+ int32_t* outValue, nsecs_t* outWhen) = 0;
+
+ /*
+ * Query current input state.
+ * deviceId may be -1 to search for the device automatically, filtered by class.
+ * deviceClasses may be -1 to ignore device class while searching.
+ */
+ virtual int32_t getScanCodeState(int32_t deviceId, int32_t deviceClasses,
+ int32_t scanCode) const = 0;
+ virtual int32_t getKeyCodeState(int32_t deviceId, int32_t deviceClasses,
+ int32_t keyCode) const = 0;
+ virtual int32_t getSwitchState(int32_t deviceId, int32_t deviceClasses,
+ int32_t sw) const = 0;
+
+ /*
+ * Examine key input devices for specific framework keycode support
+ */
+ virtual bool hasKeys(size_t numCodes, const int32_t* keyCodes,
+ uint8_t* outFlags) const = 0;
+};
+
+class EventHub : public EventHubInterface
{
public:
EventHub();
-
+
status_t errorCheck() const;
+
+ virtual uint32_t getDeviceClasses(int32_t deviceId) const;
- // bit fields for classes of devices.
- enum {
- CLASS_KEYBOARD = 0x00000001,
- CLASS_ALPHAKEY = 0x00000002,
- CLASS_TOUCHSCREEN = 0x00000004,
- CLASS_TRACKBALL = 0x00000008,
- CLASS_TOUCHSCREEN_MT= 0x00000010,
- CLASS_DPAD = 0x00000020
- };
- uint32_t getDeviceClasses(int32_t deviceId) const;
-
- String8 getDeviceName(int32_t deviceId) const;
+ virtual String8 getDeviceName(int32_t deviceId) const;
- int getAbsoluteInfo(int32_t deviceId, int axis, int *outMinValue,
+ virtual int getAbsoluteInfo(int32_t deviceId, int axis, int *outMinValue,
int* outMaxValue, int* outFlat, int* outFuzz) const;
- int getSwitchState(int sw) const;
- int getSwitchState(int32_t deviceId, int sw) const;
-
- int getScancodeState(int key) const;
- int getScancodeState(int32_t deviceId, int key) const;
-
- int getKeycodeState(int key) const;
- int getKeycodeState(int32_t deviceId, int key) const;
-
- status_t scancodeToKeycode(int32_t deviceId, int scancode,
+ virtual status_t scancodeToKeycode(int32_t deviceId, int scancode,
int32_t* outKeycode, uint32_t* outFlags) const;
- // exclude a particular device from opening
- // this can be used to ignore input devices for sensors
- void addExcludedDevice(const char* deviceName);
+ virtual void addExcludedDevice(const char* deviceName);
- // special type codes when devices are added/removed.
- enum {
- DEVICE_ADDED = 0x10000000,
- DEVICE_REMOVED = 0x20000000
- };
-
- // examine key input devices for specific framework keycode support
- bool hasKeys(size_t numCodes, int32_t* keyCodes, uint8_t* outFlags);
+ virtual int32_t getScanCodeState(int32_t deviceId, int32_t deviceClasses,
+ int32_t scanCode) const;
+ virtual int32_t getKeyCodeState(int32_t deviceId, int32_t deviceClasses,
+ int32_t keyCode) const;
+ virtual int32_t getSwitchState(int32_t deviceId, int32_t deviceClasses,
+ int32_t sw) const;
+
+ virtual bool hasKeys(size_t numCodes, const int32_t* keyCodes, uint8_t* outFlags) const;
virtual bool getEvent(int32_t* outDeviceId, int32_t* outType,
int32_t* outScancode, int32_t* outKeycode, uint32_t *outFlags,
@@ -126,6 +191,10 @@ private:
device_t* getDevice(int32_t deviceId) const;
bool hasKeycode(device_t* device, int keycode) const;
+ int32_t getScanCodeStateLocked(device_t* device, int32_t scanCode) const;
+ int32_t getKeyCodeStateLocked(device_t* device, int32_t keyCode) const;
+ int32_t getSwitchStateLocked(device_t* device, int32_t sw) const;
+
// Protect all internal state.
mutable Mutex mLock;
@@ -151,7 +220,7 @@ private:
// device ids that report particular switches.
#ifdef EV_SW
- int32_t mSwitches[SW_MAX+1];
+ int32_t mSwitches[SW_MAX + 1];
#endif
};
diff --git a/include/ui/Input.h b/include/ui/Input.h
new file mode 100644
index 0000000..6a5c8a8
--- /dev/null
+++ b/include/ui/Input.h
@@ -0,0 +1,310 @@
+/*
+ * 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_H
+#define _UI_INPUT_H
+
+/**
+ * Native input event structures.
+ */
+
+#include <android/input.h>
+#include <utils/Vector.h>
+#include <utils/Timers.h>
+
+/*
+ * Additional private constants not defined in ndk/ui/input.h.
+ */
+enum {
+ /*
+ * Private control to determine when an app is tracking a key sequence.
+ */
+ KEY_EVENT_FLAG_START_TRACKING = 0x40000000
+};
+
+/*
+ * Maximum number of pointers supported per motion event.
+ */
+#define MAX_POINTERS 10
+
+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;
+};
+
+/*
+ * Flags that flow alongside events in the input dispatch system to help with certain
+ * policy decisions such as waking from device sleep.
+ *
+ * TODO This enumeration should probably be split up or relabeled for clarity.
+ */
+enum {
+ /* These flags originate in RawEvents and are generally set in the key map. */
+
+ POLICY_FLAG_WAKE = 0x00000001,
+ POLICY_FLAG_WAKE_DROPPED = 0x00000002,
+ POLICY_FLAG_SHIFT = 0x00000004,
+ POLICY_FLAG_CAPS_LOCK = 0x00000008,
+ POLICY_FLAG_ALT = 0x00000010,
+ POLICY_FLAG_ALT_GR = 0x00000020,
+ POLICY_FLAG_MENU = 0x00000040,
+ POLICY_FLAG_LAUNCHER = 0x00000080,
+
+ /* These flags are set by the input dispatch policy as it intercepts each event. */
+
+ // Indicates that the screen was off when the event was received and the event
+ // should wake the device.
+ POLICY_FLAG_WOKE_HERE = 0x10000000,
+
+ // Indicates that the screen was dim when the event was received and the event
+ // should brighten the device.
+ POLICY_FLAG_BRIGHT_HERE = 0x20000000,
+};
+
+/*
+ * Pointer coordinate data.
+ */
+struct PointerCoords {
+ float x;
+ float y;
+ float pressure;
+ float size;
+};
+
+/*
+ * Input events.
+ */
+struct input_event_t { };
+
+class InputEvent : public input_event_t {
+public:
+ virtual ~InputEvent() { }
+
+ virtual int32_t getType() const = 0;
+
+ inline int32_t getDeviceId() const { return mDeviceId; }
+
+ inline int32_t getNature() const { return mNature; }
+
+protected:
+ void initialize(int32_t deviceId, int32_t nature);
+
+private:
+ int32_t mDeviceId;
+ int32_t mNature;
+};
+
+class KeyEvent : public InputEvent {
+public:
+ virtual ~KeyEvent() { }
+
+ virtual int32_t getType() const { return INPUT_EVENT_TYPE_KEY; }
+
+ inline int32_t getAction() const { return mAction; }
+
+ inline int32_t getFlags() const { return mFlags; }
+
+ inline int32_t getKeyCode() const { return mKeyCode; }
+
+ inline int32_t getScanCode() const { return mScanCode; }
+
+ inline int32_t getMetaState() const { return mMetaState; }
+
+ inline int32_t getRepeatCount() const { return mRepeatCount; }
+
+ inline nsecs_t getDownTime() const { return mDownTime; }
+
+ inline nsecs_t getEventTime() const { return mEventTime; }
+
+ void initialize(
+ int32_t deviceId,
+ int32_t nature,
+ int32_t action,
+ int32_t flags,
+ int32_t keyCode,
+ int32_t scanCode,
+ int32_t metaState,
+ int32_t repeatCount,
+ nsecs_t downTime,
+ nsecs_t eventTime);
+
+private:
+ int32_t mAction;
+ int32_t mFlags;
+ int32_t mKeyCode;
+ int32_t mScanCode;
+ int32_t mMetaState;
+ int32_t mRepeatCount;
+ nsecs_t mDownTime;
+ nsecs_t mEventTime;
+};
+
+class MotionEvent : public InputEvent {
+public:
+ virtual ~MotionEvent() { }
+
+ virtual int32_t getType() const { return INPUT_EVENT_TYPE_MOTION; }
+
+ inline int32_t getAction() const { return mAction; }
+
+ inline int32_t getEdgeFlags() const { return mEdgeFlags; }
+
+ inline int32_t getMetaState() const { return mMetaState; }
+
+ inline float getXPrecision() const { return mXPrecision; }
+
+ inline float getYPrecision() const { return mYPrecision; }
+
+ inline nsecs_t getDownTime() const { return mDownTime; }
+
+ inline size_t getPointerCount() const { return mPointerIds.size(); }
+
+ inline int32_t getPointerId(size_t pointerIndex) const { return mPointerIds[pointerIndex]; }
+
+ inline nsecs_t getEventTime() const { return mSampleEventTimes[getHistorySize()]; }
+
+ inline float getRawX() const { return mRawX; }
+
+ inline float getRawY() const { return mRawY; }
+
+ inline float getX(size_t pointerIndex) const {
+ return getCurrentPointerCoords(pointerIndex).x;
+ }
+
+ inline float getY(size_t pointerIndex) const {
+ return getCurrentPointerCoords(pointerIndex).y;
+ }
+
+ inline float getPressure(size_t pointerIndex) const {
+ return getCurrentPointerCoords(pointerIndex).pressure;
+ }
+
+ inline float getSize(size_t pointerIndex) const {
+ return getCurrentPointerCoords(pointerIndex).size;
+ }
+
+ inline size_t getHistorySize() const { return mSampleEventTimes.size() - 1; }
+
+ inline nsecs_t getHistoricalEventTime(size_t historicalIndex) const {
+ return mSampleEventTimes[historicalIndex];
+ }
+
+ inline float getHistoricalX(size_t pointerIndex, size_t historicalIndex) const {
+ return getHistoricalPointerCoords(pointerIndex, historicalIndex).x;
+ }
+
+ inline float getHistoricalY(size_t pointerIndex, size_t historicalIndex) const {
+ return getHistoricalPointerCoords(pointerIndex, historicalIndex).y;
+ }
+
+ inline float getHistoricalPressure(size_t pointerIndex, size_t historicalIndex) const {
+ return getHistoricalPointerCoords(pointerIndex, historicalIndex).pressure;
+ }
+
+ inline float getHistoricalSize(size_t pointerIndex, size_t historicalIndex) const {
+ return getHistoricalPointerCoords(pointerIndex, historicalIndex).size;
+ }
+
+ void initialize(
+ int32_t deviceId,
+ int32_t nature,
+ int32_t action,
+ int32_t edgeFlags,
+ int32_t metaState,
+ float rawX,
+ float rawY,
+ float xPrecision,
+ float yPrecision,
+ nsecs_t downTime,
+ nsecs_t eventTime,
+ size_t pointerCount,
+ const int32_t* pointerIds,
+ const PointerCoords* pointerCoords);
+
+ void addSample(
+ nsecs_t eventTime,
+ const PointerCoords* pointerCoords);
+
+ void offsetLocation(float xOffset, float yOffset);
+
+private:
+ int32_t mAction;
+ int32_t mEdgeFlags;
+ int32_t mMetaState;
+ float mRawX;
+ float mRawY;
+ float mXPrecision;
+ float mYPrecision;
+ nsecs_t mDownTime;
+ Vector<int32_t> mPointerIds;
+ Vector<nsecs_t> mSampleEventTimes;
+ Vector<PointerCoords> mSamplePointerCoords;
+
+ inline const PointerCoords& getCurrentPointerCoords(size_t pointerIndex) const {
+ return mSamplePointerCoords[getHistorySize() * getPointerCount() + pointerIndex];
+ }
+
+ inline const PointerCoords& getHistoricalPointerCoords(
+ size_t pointerIndex, size_t historicalIndex) const {
+ return mSamplePointerCoords[historicalIndex * getPointerCount() + pointerIndex];
+ }
+};
+
+/*
+ * Input event factory.
+ */
+class InputEventFactoryInterface {
+protected:
+ virtual ~InputEventFactoryInterface() { }
+
+public:
+ InputEventFactoryInterface() { }
+
+ virtual KeyEvent* createKeyEvent() = 0;
+ virtual MotionEvent* createMotionEvent() = 0;
+};
+
+/*
+ * A simple input event factory implementation that uses a single preallocated instance
+ * of each type of input event that are reused for each request.
+ */
+class PreallocatedInputEventFactory : public InputEventFactoryInterface {
+public:
+ PreallocatedInputEventFactory() { }
+ virtual ~PreallocatedInputEventFactory() { }
+
+ virtual KeyEvent* createKeyEvent() { return & mKeyEvent; }
+ virtual MotionEvent* createMotionEvent() { return & mMotionEvent; }
+
+private:
+ KeyEvent mKeyEvent;
+ MotionEvent mMotionEvent;
+};
+
+
+} // namespace android
+
+#endif // _UI_INPUT_H
diff --git a/include/ui/InputDispatchPolicy.h b/include/ui/InputDispatchPolicy.h
new file mode 100644
index 0000000..3546813
--- /dev/null
+++ b/include/ui/InputDispatchPolicy.h
@@ -0,0 +1,198 @@
+/*
+ * 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_DISPATCH_POLICY_H
+#define _UI_INPUT_DISPATCH_POLICY_H
+
+/**
+ * Native input dispatch policy.
+ */
+
+#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;
+
+/*
+ * 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 subsequent event delivery should be held until the
+ * current event is delivered to this target or a timeout occurs. */
+ FLAG_SYNC = 0x01,
+
+ /* This flag indicates that a MotionEvent with ACTION_DOWN falls outside of the area of
+ * this target and so should instead be delivered as an ACTION_OUTSIDE to this target. */
+ FLAG_OUTSIDE = 0x02,
+
+ /* This flag indicates that a KeyEvent or MotionEvent is being canceled.
+ * In the case of a key event, it should be delivered with KeyEvent.FLAG_CANCELED set.
+ * In the case of a motion event, it should be delivered as MotionEvent.ACTION_CANCEL. */
+ FLAG_CANCEL = 0x04
+ };
+
+ // The input channel to be targeted.
+ sp<InputChannel> inputChannel;
+
+ // Flags for the input target.
+ int32_t flags;
+
+ // The timeout for event delivery to this target in nanoseconds. Or -1 if none.
+ nsecs_t timeout;
+
+ // The x and y offset to add to a MotionEvent as it is delivered.
+ // (ignored for KeyEvents)
+ float xOffset, yOffset;
+};
+
+/*
+ * Input dispatch policy interface.
+ *
+ * The input dispatch policy is used by the input dispatcher to interact with the
+ * Window Manager and other system components. This separation of concerns keeps
+ * the input dispatcher relatively free of special case logic such as is required
+ * to determine the target of iput events, when to wake the device, how to interact
+ * with key guard, and when to transition to the home screen.
+ *
+ * The actual implementation is partially supported by callbacks into the DVM
+ * via JNI. This class is also mocked in the input dispatcher unit tests since
+ * it is an ideal test seam.
+ */
+class InputDispatchPolicyInterface : public virtual RefBase {
+protected:
+ InputDispatchPolicyInterface() { }
+ virtual ~InputDispatchPolicyInterface() { }
+
+public:
+ enum {
+ ROTATION_0 = 0,
+ ROTATION_90 = 1,
+ ROTATION_180 = 2,
+ ROTATION_270 = 3
+ };
+
+ enum {
+ // The input dispatcher should do nothing and discard the input unless other
+ // flags are set.
+ ACTION_NONE = 0,
+
+ // The input dispatcher should dispatch the input to the application.
+ ACTION_DISPATCH = 0x00000001,
+
+ // The input dispatcher should perform special filtering in preparation for
+ // a pending app switch.
+ ACTION_APP_SWITCH_COMING = 0x00000002,
+
+ // The input dispatcher should add POLICY_FLAG_WOKE_HERE to the policy flags it
+ // passes through the dispatch pipeline.
+ ACTION_WOKE_HERE = 0x00000004,
+
+ // The input dispatcher should add POLICY_FLAG_BRIGHT_HERE to the policy flags it
+ // passes through the dispatch pipeline.
+ ACTION_BRIGHT_HERE = 0x00000008
+ };
+
+ enum {
+ TOUCHSCREEN_UNDEFINED = 0,
+ TOUCHSCREEN_NOTOUCH = 1,
+ TOUCHSCREEN_STYLUS = 2,
+ TOUCHSCREEN_FINGER = 3
+ };
+
+ enum {
+ KEYBOARD_UNDEFINED = 0,
+ KEYBOARD_NOKEYS = 1,
+ KEYBOARD_QWERTY = 2,
+ KEYBOARD_12KEY = 3
+ };
+
+ enum {
+ NAVIGATION_UNDEFINED = 0,
+ NAVIGATION_NONAV = 1,
+ NAVIGATION_DPAD = 2,
+ NAVIGATION_TRACKBALL = 3,
+ NAVIGATION_WHEEL = 4
+ };
+
+ struct VirtualKeyDefinition {
+ int32_t scanCode;
+
+ // configured position data, specified in display coords
+ int32_t centerX;
+ int32_t centerY;
+ int32_t width;
+ int32_t height;
+ };
+
+ /* 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;
+
+ virtual void notifyConfigurationChanged(nsecs_t when,
+ int32_t touchScreenConfig, int32_t keyboardConfig, int32_t navigationConfig) = 0;
+
+ virtual void notifyLidSwitchChanged(nsecs_t when, bool lidOpen) = 0;
+
+ virtual void virtualKeyFeedback(nsecs_t when, int32_t deviceId,
+ int32_t action, int32_t flags, int32_t keyCode,
+ int32_t scanCode, int32_t metaState, nsecs_t downTime) = 0;
+
+ virtual int32_t interceptKey(nsecs_t when, int32_t deviceId,
+ bool down, int32_t keyCode, int32_t scanCode, uint32_t policyFlags) = 0;
+
+ virtual int32_t interceptTrackball(nsecs_t when, bool buttonChanged, bool buttonDown,
+ bool rolled) = 0;
+
+ virtual int32_t interceptTouch(nsecs_t when) = 0;
+
+ virtual bool allowKeyRepeat() = 0;
+ virtual nsecs_t getKeyRepeatTimeout() = 0;
+
+ virtual void getKeyEventTargets(KeyEvent* keyEvent, uint32_t policyFlags,
+ Vector<InputTarget>& outTargets) = 0;
+ virtual void getMotionEventTargets(MotionEvent* motionEvent, uint32_t policyFlags,
+ Vector<InputTarget>& outTargets) = 0;
+
+ /* Determine 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;
+
+ /* Determine whether to turn on some hacks to improve touch interaction with another device
+ * where touch coordinate data can get corrupted.
+ */
+ virtual bool filterJumpyTouchEvents() = 0;
+
+ virtual void getVirtualKeyDefinitions(const String8& deviceName,
+ Vector<VirtualKeyDefinition>& outVirtualKeyDefinitions) = 0;
+ virtual void getExcludedDeviceNames(Vector<String8>& outExcludedDeviceNames) = 0;
+};
+
+} // namespace android
+
+#endif // _UI_INPUT_DISPATCH_POLICY_H
diff --git a/include/ui/InputDispatcher.h b/include/ui/InputDispatcher.h
new file mode 100644
index 0000000..bde07f2
--- /dev/null
+++ b/include/ui/InputDispatcher.h
@@ -0,0 +1,409 @@
+/*
+ * 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/InputDispatchPolicy.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/PollLoop.h>
+#include <utils/Pool.h>
+
+#include <stddef.h>
+#include <unistd.h>
+
+
+namespace android {
+
+/* 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:
+ /* 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.
+ * The dispatcher will process most of these events asynchronously although some
+ * policy processing may occur synchronously.
+ *
+ * These methods should only be called on the input reader thread.
+ */
+ virtual void notifyConfigurationChanged(nsecs_t eventTime,
+ int32_t touchScreenConfig, int32_t keyboardConfig, int32_t navigationConfig) = 0;
+ virtual void notifyLidSwitchChanged(nsecs_t eventTime, bool lidOpen) = 0;
+ virtual void notifyAppSwitchComing(nsecs_t eventTime) = 0;
+ virtual void notifyKey(nsecs_t eventTime, int32_t deviceId, int32_t nature,
+ 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 nature,
+ uint32_t policyFlags, int32_t action, int32_t metaState, int32_t edgeFlags,
+ uint32_t pointerCount, const int32_t* pointerIds, const PointerCoords* pointerCoords,
+ float xPrecision, float yPrecision, nsecs_t downTime) = 0;
+
+ /* Registers or unregister input channels that may be used as targets for input events.
+ *
+ * These methods may be called on any thread (usually by the input manager).
+ */
+ virtual status_t registerInputChannel(const sp<InputChannel>& inputChannel) = 0;
+ virtual status_t unregisterInputChannel(const sp<InputChannel>& inputChannel) = 0;
+};
+
+/* Dispatches events. */
+class InputDispatcher : public InputDispatcherInterface {
+protected:
+ virtual ~InputDispatcher();
+
+public:
+ explicit InputDispatcher(const sp<InputDispatchPolicyInterface>& policy);
+
+ virtual void dispatchOnce();
+
+ virtual void notifyConfigurationChanged(nsecs_t eventTime,
+ int32_t touchScreenConfig, int32_t keyboardConfig, int32_t navigationConfig);
+ virtual void notifyLidSwitchChanged(nsecs_t eventTime, bool lidOpen);
+ virtual void notifyAppSwitchComing(nsecs_t eventTime);
+ virtual void notifyKey(nsecs_t eventTime, int32_t deviceId, int32_t nature,
+ 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 nature,
+ uint32_t policyFlags, int32_t action, int32_t metaState, int32_t edgeFlags,
+ uint32_t pointerCount, const int32_t* pointerIds, const PointerCoords* pointerCoords,
+ float xPrecision, float yPrecision, nsecs_t downTime);
+
+ virtual status_t registerInputChannel(const sp<InputChannel>& inputChannel);
+ virtual status_t unregisterInputChannel(const sp<InputChannel>& inputChannel);
+
+private:
+ template <typename T>
+ struct Link {
+ T* next;
+ T* prev;
+ };
+
+ struct EventEntry : Link<EventEntry> {
+ enum {
+ TYPE_SENTINEL,
+ TYPE_CONFIGURATION_CHANGED,
+ TYPE_KEY,
+ TYPE_MOTION
+ };
+
+ int32_t refCount;
+ int32_t type;
+ nsecs_t eventTime;
+ };
+
+ struct ConfigurationChangedEntry : EventEntry {
+ int32_t touchScreenConfig;
+ int32_t keyboardConfig;
+ int32_t navigationConfig;
+ };
+
+ struct KeyEntry : EventEntry {
+ int32_t deviceId;
+ int32_t nature;
+ uint32_t policyFlags;
+ int32_t action;
+ int32_t flags;
+ int32_t keyCode;
+ int32_t scanCode;
+ int32_t metaState;
+ int32_t repeatCount;
+ nsecs_t downTime;
+ };
+
+ struct MotionSample {
+ MotionSample* next;
+
+ nsecs_t eventTime;
+ PointerCoords pointerCoords[MAX_POINTERS];
+ };
+
+ struct MotionEntry : EventEntry {
+ int32_t deviceId;
+ int32_t nature;
+ uint32_t policyFlags;
+ int32_t action;
+ 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;
+ };
+
+ struct DispatchEntry : Link<DispatchEntry> {
+ EventEntry* eventEntry; // the event to dispatch
+ int32_t targetFlags;
+ float xOffset;
+ float yOffset;
+ nsecs_t timeout;
+
+ // 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;
+ };
+
+ template <typename T>
+ struct Queue {
+ T head;
+ T tail;
+
+ inline Queue() {
+ head.prev = NULL;
+ head.next = & tail;
+ tail.prev = & head;
+ tail.next = NULL;
+ }
+
+ inline bool isEmpty() {
+ return head.next == & tail;
+ }
+
+ inline void enqueueAtTail(T* entry) {
+ T* last = tail.prev;
+ last->next = entry;
+ entry->prev = last;
+ entry->next = & tail;
+ tail.prev = entry;
+ }
+
+ inline void enqueueAtHead(T* entry) {
+ T* first = head.next;
+ head.next = entry;
+ entry->prev = & head;
+ 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 = head.next;
+ dequeue(first);
+ return first;
+ }
+ };
+
+ /* Allocates queue entries and performs reference counting as needed. */
+ class Allocator {
+ public:
+ Allocator();
+
+ ConfigurationChangedEntry* obtainConfigurationChangedEntry();
+ KeyEntry* obtainKeyEntry();
+ MotionEntry* obtainMotionEntry();
+ DispatchEntry* obtainDispatchEntry(EventEntry* eventEntry);
+
+ void releaseEventEntry(EventEntry* entry);
+ void releaseConfigurationChangedEntry(ConfigurationChangedEntry* entry);
+ void releaseKeyEntry(KeyEntry* entry);
+ void releaseMotionEntry(MotionEntry* entry);
+ void releaseDispatchEntry(DispatchEntry* entry);
+
+ void appendMotionSample(MotionEntry* motionEntry,
+ nsecs_t eventTime, int32_t pointerCount, const PointerCoords* pointerCoords);
+ void freeMotionSample(MotionSample* sample);
+ void freeMotionSampleList(MotionSample* head);
+
+ private:
+ Pool<ConfigurationChangedEntry> mConfigurationChangeEntryPool;
+ Pool<KeyEntry> mKeyEntryPool;
+ Pool<MotionEntry> mMotionEntryPool;
+ Pool<MotionSample> mMotionSamplePool;
+ Pool<DispatchEntry> mDispatchEntryPool;
+ };
+
+ /* 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 client is not responding.
+ STATUS_NOT_RESPONDING,
+ // The input channel has been unregistered.
+ STATUS_ZOMBIE
+ };
+
+ Status status;
+ sp<InputChannel> inputChannel;
+ InputPublisher inputPublisher;
+ Queue<DispatchEntry> outboundQueue;
+ nsecs_t nextTimeoutTime; // next timeout time (LONG_LONG_MAX if none)
+
+ nsecs_t lastEventTime; // the time when the event was originally captured
+ nsecs_t lastDispatchTime; // the time when the last event was dispatched
+ nsecs_t lastANRTime; // the time when the last ANR was recorded
+
+ explicit Connection(const sp<InputChannel>& inputChannel);
+
+ inline const char* getInputChannelName() { return inputChannel->getName().string(); }
+
+ // Finds a DispatchEntry in the outbound queue associated with the specified event.
+ // Returns NULL if not found.
+ DispatchEntry* findQueuedDispatchEntryForEvent(const EventEntry* eventEntry) const;
+
+ // Determine whether this connection has a pending synchronous dispatch target.
+ // Since there can only ever be at most one such target at a time, if there is one,
+ // it must be at the tail because nothing else can be enqueued after it.
+ inline bool hasPendingSyncTarget() {
+ return ! outboundQueue.isEmpty()
+ && (outboundQueue.tail.prev->targetFlags & InputTarget::FLAG_SYNC);
+ }
+
+ // Gets the time since the current event was originally obtained from the input driver.
+ inline double getEventLatencyMillis(nsecs_t currentTime) {
+ return (currentTime - lastEventTime) / 1000000.0;
+ }
+
+ // Gets the time since the current event entered the outbound dispatch queue.
+ inline double getDispatchLatencyMillis(nsecs_t currentTime) {
+ return (currentTime - lastDispatchTime) / 1000000.0;
+ }
+
+ // Gets the time since the current event ANR was declared, if applicable.
+ inline double getANRLatencyMillis(nsecs_t currentTime) {
+ return (currentTime - lastANRTime) / 1000000.0;
+ }
+
+ status_t initialize();
+ };
+
+ sp<InputDispatchPolicyInterface> mPolicy;
+
+ Mutex mLock;
+
+ Queue<EventEntry> mInboundQueue;
+ Allocator mAllocator;
+
+ sp<PollLoop> mPollLoop;
+
+ // All registered connections mapped by receive pipe file descriptor.
+ KeyedVector<int, sp<Connection> > mConnectionsByReceiveFd;
+
+ // Active connections are connections that have a non-empty outbound queue.
+ Vector<Connection*> mActiveConnections;
+
+ // Pool of key and motion event objects used only to ask the input dispatch policy
+ // for the targets of an event that is to be dispatched.
+ KeyEvent mReusableKeyEvent;
+ MotionEvent mReusableMotionEvent;
+
+ // The input targets that were most recently identified for dispatch.
+ // If there is a synchronous event dispatch in progress, the current input targets will
+ // remain unchanged until the dispatch has completed or been aborted.
+ Vector<InputTarget> mCurrentInputTargets;
+
+ // Key repeat tracking.
+ // XXX Move this up to the input reader instead.
+ struct KeyRepeatState {
+ KeyEntry* lastKeyEntry; // or null if no repeat
+ nsecs_t nextRepeatTime;
+ } mKeyRepeatState;
+
+ void resetKeyRepeatLocked();
+
+ // Process events that have just been dequeued from the head of the input queue.
+ void processConfigurationChangedLocked(nsecs_t currentTime, ConfigurationChangedEntry* entry);
+ void processKeyLocked(nsecs_t currentTime, KeyEntry* entry);
+ void processKeyRepeatLocked(nsecs_t currentTime);
+ void processMotionLocked(nsecs_t currentTime, MotionEntry* entry);
+
+ // Identify input targets for an event and dispatch to them.
+ void identifyInputTargetsAndDispatchKeyLocked(nsecs_t currentTime, KeyEntry* entry);
+ void identifyInputTargetsAndDispatchMotionLocked(nsecs_t currentTime, MotionEntry* entry);
+ void dispatchEventToCurrentInputTargetsLocked(nsecs_t currentTime, EventEntry* entry,
+ bool resumeWithAppendedMotionSample);
+
+ // Manage the dispatch cycle for a single connection.
+ void prepareDispatchCycleLocked(nsecs_t currentTime, Connection* connection,
+ EventEntry* eventEntry, const InputTarget* inputTarget,
+ bool resumeWithAppendedMotionSample);
+ void startDispatchCycleLocked(nsecs_t currentTime, Connection* connection);
+ void finishDispatchCycleLocked(nsecs_t currentTime, Connection* connection);
+ bool timeoutDispatchCycleLocked(nsecs_t currentTime, Connection* connection);
+ bool abortDispatchCycleLocked(nsecs_t currentTime, Connection* connection,
+ bool broken);
+ static bool handleReceiveCallback(int receiveFd, int events, void* data);
+
+ // 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, Connection* connection);
+ void onDispatchCycleFinishedLocked(nsecs_t currentTime, Connection* connection,
+ bool recoveredFromANR);
+ void onDispatchCycleANRLocked(nsecs_t currentTime, Connection* connection);
+ void onDispatchCycleBrokenLocked(nsecs_t currentTime, Connection* connection);
+};
+
+/* 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_PRIV_H
diff --git a/include/ui/InputManager.h b/include/ui/InputManager.h
new file mode 100644
index 0000000..eb27513
--- /dev/null
+++ b/include/ui/InputManager.h
@@ -0,0 +1,134 @@
+/*
+ * 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 <ui/InputDispatchPolicy.h>
+#include <utils/Errors.h>
+#include <utils/Vector.h>
+#include <utils/Timers.h>
+#include <utils/RefBase.h>
+#include <utils/String8.h>
+
+namespace android {
+
+class InputReader;
+class InputDispatcher;
+class InputReaderThread;
+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;
+
+ /* Registers an input channel prior to using it as the target of an event. */
+ virtual status_t registerInputChannel(const sp<InputChannel>& inputChannel) = 0;
+
+ /* Unregisters an input channel. */
+ virtual status_t unregisterInputChannel(const sp<InputChannel>& inputChannel) = 0;
+
+ /*
+ * Query current input state.
+ * deviceId may be -1 to search for the device automatically, filtered by class.
+ * deviceClasses may be -1 to ignore device class while searching.
+ */
+ virtual int32_t getScanCodeState(int32_t deviceId, int32_t deviceClasses,
+ int32_t scanCode) const = 0;
+ virtual int32_t getKeyCodeState(int32_t deviceId, int32_t deviceClasses,
+ int32_t keyCode) const = 0;
+ virtual int32_t getSwitchState(int32_t deviceId, int32_t deviceClasses,
+ int32_t sw) const = 0;
+
+ /* Determine whether physical keys exist for the given framework-domain key codes. */
+ virtual bool hasKeys(size_t numCodes, const int32_t* keyCodes, uint8_t* outFlags) const = 0;
+};
+
+class InputManager : public InputManagerInterface {
+protected:
+ virtual ~InputManager();
+
+public:
+ /*
+ * Creates an input manager that reads events from the given
+ * event hub and applies the given input dispatch policy.
+ */
+ InputManager(const sp<EventHubInterface>& eventHub,
+ const sp<InputDispatchPolicyInterface>& policy);
+
+ virtual status_t start();
+ virtual status_t stop();
+
+ virtual status_t registerInputChannel(const sp<InputChannel>& inputChannel);
+ virtual status_t unregisterInputChannel(const sp<InputChannel>& inputChannel);
+
+ virtual int32_t getScanCodeState(int32_t deviceId, int32_t deviceClasses,
+ int32_t scanCode) const;
+ virtual int32_t getKeyCodeState(int32_t deviceId, int32_t deviceClasses,
+ int32_t keyCode) const;
+ virtual int32_t getSwitchState(int32_t deviceId, int32_t deviceClasses,
+ int32_t sw) const;
+ virtual bool hasKeys(size_t numCodes, const int32_t* keyCodes, uint8_t* outFlags) const;
+
+private:
+ sp<EventHubInterface> mEventHub;
+ sp<InputDispatchPolicyInterface> mPolicy;
+
+ sp<InputDispatcher> mDispatcher;
+ sp<InputDispatcherThread> mDispatcherThread;
+
+ sp<InputReader> mReader;
+ sp<InputReaderThread> mReaderThread;
+
+ void configureExcludedDevices();
+};
+
+} // namespace android
+
+#endif // _UI_INPUT_MANAGER_H
diff --git a/include/ui/InputReader.h b/include/ui/InputReader.h
new file mode 100644
index 0000000..7e7a64c
--- /dev/null
+++ b/include/ui/InputReader.h
@@ -0,0 +1,472 @@
+/*
+ * 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/InputDispatchPolicy.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>
+
+/* Maximum pointer id value supported.
+ * (This is limited by our use of BitSet32 to track pointer assignments.) */
+#define MAX_POINTER_ID 32
+
+/** Amount that trackball needs to move in order to generate a key event. */
+#define TRACKBALL_MOVEMENT_THRESHOLD 6
+
+/* Slop distance for jumpy pointer detection.
+ * The vertical range of the screen divided by this is our epsilon value. */
+#define JUMPY_EPSILON_DIVISOR 212
+
+/* Number of jumpy points to drop for touchscreens that need it. */
+#define JUMPY_TRANSITION_DROPS 3
+#define JUMPY_DROP_LIMIT 3
+
+/* Maximum squared distance for averaging.
+ * If moving farther than this, turn of averaging to avoid lag in response. */
+#define AVERAGING_DISTANCE_LIMIT (75 * 75)
+
+/* Maximum number of historical samples to average. */
+#define AVERAGING_HISTORY_SIZE 5
+
+
+namespace android {
+
+extern int32_t updateMetaState(int32_t keyCode, bool down, int32_t oldMetaState);
+extern int32_t rotateKeyCode(int32_t keyCode, int32_t orientation);
+
+/*
+ * An input device structure tracks the state of a single input device.
+ *
+ * This structure is only used by ReaderThread and is not intended to be shared with
+ * DispatcherThread (because that would require locking). This works out fine because
+ * DispatcherThread is only interested in cooked event data anyways and does not need
+ * any of the low-level data from InputDevice.
+ */
+struct InputDevice {
+ struct AbsoluteAxisInfo {
+ int32_t minValue; // minimum value
+ int32_t maxValue; // maximum value
+ int32_t range; // range of values, equal to maxValue - minValue
+ 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
+ };
+
+ 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;
+ }
+ };
+
+ struct KeyboardState {
+ struct Current {
+ int32_t metaState;
+ nsecs_t downTime; // time of most recent key down
+ } current;
+
+ void reset();
+ };
+
+ struct TrackballState {
+ 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;
+ }
+
+ inline bool isDirty() {
+ return fields != 0;
+ }
+ } accumulator;
+
+ struct Current {
+ bool down;
+ nsecs_t downTime;
+ } current;
+
+ struct Precalculated {
+ float xScale;
+ float yScale;
+ float xPrecision;
+ float yPrecision;
+ } precalculated;
+
+ void reset();
+ };
+
+ struct SingleTouchScreenState {
+ 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;
+ }
+
+ inline bool isDirty() {
+ return fields != 0;
+ }
+ } accumulator;
+
+ struct Current {
+ bool down;
+ int32_t x;
+ int32_t y;
+ int32_t pressure;
+ int32_t size;
+ } current;
+
+ void reset();
+ };
+
+ struct MultiTouchScreenState {
+ struct Accumulator {
+ enum {
+ FIELD_ABS_MT_POSITION_X = 1,
+ FIELD_ABS_MT_POSITION_Y = 2,
+ FIELD_ABS_MT_TOUCH_MAJOR = 4,
+ FIELD_ABS_MT_WIDTH_MAJOR = 8,
+ FIELD_ABS_MT_TRACKING_ID = 16
+ };
+
+ uint32_t pointerCount;
+ struct Pointer {
+ uint32_t fields;
+
+ int32_t absMTPositionX;
+ int32_t absMTPositionY;
+ int32_t absMTTouchMajor;
+ int32_t absMTWidthMajor;
+ int32_t absMTTrackingId;
+
+ 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();
+ }
+
+ inline bool isDirty() {
+ return pointerCount != 0;
+ }
+ } accumulator;
+
+ void reset();
+ };
+
+ struct PointerData {
+ uint32_t id;
+ int32_t x;
+ int32_t y;
+ int32_t pressure;
+ int32_t size;
+ };
+
+ struct TouchData {
+ uint32_t pointerCount;
+ PointerData pointers[MAX_POINTERS];
+ BitSet32 idBits;
+ uint32_t idToIndex[MAX_POINTER_ID];
+
+ void copyFrom(const TouchData& other);
+
+ inline void clear() {
+ pointerCount = 0;
+ idBits.clear();
+ }
+ };
+
+ // common state used for both single-touch and multi-touch screens after the initial
+ // touch decoding has been performed
+ struct TouchScreenState {
+ Vector<VirtualKey> virtualKeys;
+
+ struct Parameters {
+ bool useBadTouchFilter;
+ bool useJumpyTouchFilter;
+ bool useAveragingTouchFilter;
+
+ AbsoluteAxisInfo xAxis;
+ AbsoluteAxisInfo yAxis;
+ AbsoluteAxisInfo pressureAxis;
+ AbsoluteAxisInfo sizeAxis;
+ } parameters;
+
+ // The touch data of the current sample being processed.
+ TouchData currentTouch;
+
+ // The touch data of the previous sample that was processed. This is updated
+ // incrementally while the current sample is being processed.
+ TouchData lastTouch;
+
+ // The time the primary pointer last went down.
+ nsecs_t downTime;
+
+ struct CurrentVirtualKeyState {
+ bool down;
+ nsecs_t downTime;
+ int32_t keyCode;
+ int32_t scanCode;
+ } currentVirtualKey;
+
+ 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];
+ } averagingTouchFilter;
+
+ struct JumpTouchFilterState {
+ int32_t jumpyPointsDropped;
+ } jumpyTouchFilter;
+
+ struct Precalculated {
+ float xScale;
+ float yScale;
+ float pressureScale;
+ float sizeScale;
+ } precalculated;
+
+ void reset();
+
+ bool applyBadTouchFilter();
+ bool applyJumpyTouchFilter();
+ void applyAveragingTouchFilter();
+ void calculatePointerIds();
+
+ bool isPointInsideDisplay(int32_t x, int32_t y) const;
+ };
+
+ InputDevice(int32_t id, uint32_t classes, String8 name);
+
+ int32_t id;
+ uint32_t classes;
+ String8 name;
+ bool ignored;
+
+ KeyboardState keyboard;
+ TrackballState trackball;
+ TouchScreenState touchScreen;
+ union {
+ SingleTouchScreenState singleTouchScreen;
+ MultiTouchScreenState multiTouchScreen;
+ };
+
+ void reset();
+
+ inline bool isKeyboard() const { return classes & INPUT_DEVICE_CLASS_KEYBOARD; }
+ inline bool isAlphaKey() const { return classes & INPUT_DEVICE_CLASS_ALPHAKEY; }
+ inline bool isTrackball() const { return classes & INPUT_DEVICE_CLASS_TRACKBALL; }
+ inline bool isDPad() const { return classes & INPUT_DEVICE_CLASS_DPAD; }
+ inline bool isSingleTouchScreen() const { return (classes
+ & (INPUT_DEVICE_CLASS_TOUCHSCREEN | INPUT_DEVICE_CLASS_TOUCHSCREEN_MT))
+ == INPUT_DEVICE_CLASS_TOUCHSCREEN; }
+ inline bool isMultiTouchScreen() const { return classes
+ & INPUT_DEVICE_CLASS_TOUCHSCREEN_MT; }
+ inline bool isTouchScreen() const { return classes
+ & (INPUT_DEVICE_CLASS_TOUCHSCREEN | INPUT_DEVICE_CLASS_TOUCHSCREEN_MT); }
+};
+
+
+/* Processes raw input events and sends cooked event data to an input dispatcher
+ * in accordance with the input dispatch policy. */
+class InputReaderInterface : public virtual RefBase {
+protected:
+ InputReaderInterface() { }
+ virtual ~InputReaderInterface() { }
+
+public:
+ /* 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 virtual key. Returns false if not down.
+ *
+ * This method may be called on any thread (usually by the input manager).
+ */
+ virtual bool getCurrentVirtualKey(int32_t* outKeyCode, int32_t* outScanCode) const = 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 are controlled
+ * by the input dispatch policy, such as early event filtering in low power states.
+ */
+class InputReader : public InputReaderInterface {
+public:
+ InputReader(const sp<EventHubInterface>& eventHub,
+ const sp<InputDispatchPolicyInterface>& policy,
+ const sp<InputDispatcherInterface>& dispatcher);
+ virtual ~InputReader();
+
+ virtual void loopOnce();
+
+ virtual bool getCurrentVirtualKey(int32_t* outKeyCode, int32_t* outScanCode) const;
+
+private:
+ // Lock that must be acquired while manipulating state that may be concurrently accessed
+ // from other threads by input state query methods. It should be held for as short a
+ // time as possible.
+ //
+ // Exported state:
+ // - global virtual key code and scan code
+ // - device list and immutable properties of devices such as id, name, and class
+ // (but not other internal device state)
+ mutable Mutex mExportedStateLock;
+
+ // current virtual key information
+ int32_t mGlobalVirtualKeyCode;
+ int32_t mGlobalVirtualScanCode;
+
+ // combined key meta state
+ int32_t mGlobalMetaState;
+
+ sp<EventHubInterface> mEventHub;
+ sp<InputDispatchPolicyInterface> mPolicy;
+ sp<InputDispatcherInterface> mDispatcher;
+
+ KeyedVector<int32_t, InputDevice*> mDevices;
+
+ // display properties needed to translate touch screen coordinates into display coordinates
+ int32_t mDisplayOrientation;
+ int32_t mDisplayWidth;
+ int32_t mDisplayHeight;
+
+ // low-level input event decoding
+ void process(const RawEvent* rawEvent);
+ void handleDeviceAdded(const RawEvent* rawEvent);
+ void handleDeviceRemoved(const RawEvent* rawEvent);
+ void handleSync(const RawEvent* rawEvent);
+ void handleKey(const RawEvent* rawEvent);
+ void handleRelativeMotion(const RawEvent* rawEvent);
+ void handleAbsoluteMotion(const RawEvent* rawEvent);
+ void handleSwitch(const RawEvent* rawEvent);
+
+ // input policy processing and dispatch
+ void onKey(nsecs_t when, InputDevice* device, bool down,
+ int32_t keyCode, int32_t scanCode, uint32_t policyFlags);
+ void onSwitch(nsecs_t when, InputDevice* device, bool down, int32_t code);
+ void onSingleTouchScreenStateChanged(nsecs_t when, InputDevice* device);
+ void onMultiTouchScreenStateChanged(nsecs_t when, InputDevice* device);
+ void onTouchScreenChanged(nsecs_t when, InputDevice* device, bool havePointerIds);
+ void onTrackballStateChanged(nsecs_t when, InputDevice* device);
+ void onConfigurationChanged(nsecs_t when);
+
+ bool applyStandardInputDispatchPolicyActions(nsecs_t when,
+ int32_t policyActions, uint32_t* policyFlags);
+
+ bool consumeVirtualKeyTouches(nsecs_t when, InputDevice* device, uint32_t policyFlags);
+ void dispatchVirtualKey(nsecs_t when, InputDevice* device, uint32_t policyFlags,
+ int32_t keyEventAction, int32_t keyEventFlags);
+ void dispatchTouches(nsecs_t when, InputDevice* device, uint32_t policyFlags);
+ void dispatchTouch(nsecs_t when, InputDevice* device, uint32_t policyFlags,
+ InputDevice::TouchData* touch, BitSet32 idBits, int32_t motionEventAction);
+
+ // display
+ void resetDisplayProperties();
+ bool refreshDisplayProperties();
+
+ // device management
+ InputDevice* getDevice(int32_t deviceId);
+ InputDevice* getNonIgnoredDevice(int32_t deviceId);
+ void addDevice(nsecs_t when, int32_t deviceId);
+ void removeDevice(nsecs_t when, InputDevice* device);
+ void configureDevice(InputDevice* device);
+ void configureDeviceForCurrentDisplaySize(InputDevice* device);
+ void configureVirtualKeys(InputDevice* device);
+ void configureAbsoluteAxisInfo(InputDevice* device, int axis, const char* name,
+ InputDevice::AbsoluteAxisInfo* out);
+
+ // global meta state management for all devices
+ void resetGlobalMetaState();
+ int32_t globalMetaState();
+
+ // virtual key management
+ void updateGlobalVirtualKeyState();
+};
+
+
+/* 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();
+};
+
+} // namespace android
+
+#endif // _UI_INPUT_READER_H
diff --git a/include/ui/InputTransport.h b/include/ui/InputTransport.h
new file mode 100644
index 0000000..9537523
--- /dev/null
+++ b/include/ui/InputTransport.h
@@ -0,0 +1,331 @@
+/*
+ * 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_TRANSPORT_H
+#define _UI_INPUT_TRANSPORT_H
+
+/**
+ * Native input transport.
+ *
+ * Uses anonymous shared memory as a whiteboard for sending input events from an
+ * InputPublisher to an InputConsumer and ensuring appropriate synchronization.
+ * One interesting feature is that published events can be updated in place as long as they
+ * have not yet been consumed.
+ *
+ * The InputPublisher and InputConsumer only take care of transferring event data
+ * over an InputChannel and sending synchronization signals. The InputDispatcher and InputQueue
+ * build on these abstractions to add multiplexing and queueing.
+ */
+
+#include <semaphore.h>
+#include <ui/Input.h>
+#include <utils/Errors.h>
+#include <utils/Timers.h>
+#include <utils/RefBase.h>
+#include <utils/String8.h>
+
+namespace android {
+
+/*
+ * An input channel consists of a shared memory buffer and a pair of pipes
+ * used to send input messages from an InputPublisher to an InputConsumer
+ * across processes. Each channel has a descriptive name for debugging purposes.
+ *
+ * Each endpoint has its own InputChannel object that specifies its own file descriptors.
+ *
+ * The input channel is closed when all references to it are released.
+ */
+class InputChannel : public RefBase {
+protected:
+ virtual ~InputChannel();
+
+public:
+ InputChannel(const String8& name, int32_t ashmemFd, int32_t receivePipeFd,
+ int32_t sendPipeFd);
+
+ /* Creates a pair of input channels and their underlying shared memory buffers
+ * and pipes.
+ *
+ * Returns OK on success.
+ */
+ static status_t openInputChannelPair(const String8& name,
+ InputChannel** outServerChannel, InputChannel** outClientChannel);
+
+ inline String8 getName() const { return mName; }
+ inline int32_t getAshmemFd() const { return mAshmemFd; }
+ inline int32_t getReceivePipeFd() const { return mReceivePipeFd; }
+ inline int32_t getSendPipeFd() const { return mSendPipeFd; }
+
+ /* Sends a signal to the other endpoint.
+ *
+ * Returns OK on success.
+ * Errors probably indicate that the channel is broken.
+ */
+ status_t sendSignal(char signal);
+
+ /* Receives a signal send by the other endpoint.
+ * (Should only call this after poll() indicates that the receivePipeFd has available input.)
+ *
+ * Returns OK on success.
+ * Returns WOULD_BLOCK if there is no signal present.
+ * Other errors probably indicate that the channel is broken.
+ */
+ status_t receiveSignal(char* outSignal);
+
+private:
+ String8 mName;
+ int32_t mAshmemFd;
+ int32_t mReceivePipeFd;
+ int32_t mSendPipeFd;
+};
+
+/*
+ * Private intermediate representation of input events as messages written into an
+ * ashmem buffer.
+ */
+struct InputMessage {
+ /* Semaphore count is set to 1 when the message is published.
+ * It becomes 0 transiently while the publisher updates the message.
+ * It becomes 0 permanently when the consumer consumes the message.
+ */
+ sem_t semaphore;
+
+ /* Initialized to false by the publisher.
+ * Set to true by the consumer when it consumes the message.
+ */
+ bool consumed;
+
+ int32_t type;
+
+ struct SampleData {
+ nsecs_t eventTime;
+ PointerCoords coords[0]; // variable length
+ };
+
+ int32_t deviceId;
+ int32_t nature;
+
+ union {
+ struct {
+ int32_t action;
+ int32_t flags;
+ int32_t keyCode;
+ int32_t scanCode;
+ int32_t metaState;
+ int32_t repeatCount;
+ nsecs_t downTime;
+ nsecs_t eventTime;
+ } key;
+
+ struct {
+ int32_t action;
+ int32_t metaState;
+ int32_t edgeFlags;
+ nsecs_t downTime;
+ float xOffset;
+ float yOffset;
+ float xPrecision;
+ float yPrecision;
+ size_t pointerCount;
+ int32_t pointerIds[MAX_POINTERS];
+ size_t sampleCount;
+ SampleData sampleData[0]; // variable length
+ } motion;
+ };
+
+ /* Gets the number of bytes to add to step to the next SampleData object in a motion
+ * event message for a given number of pointers.
+ */
+ static inline size_t sampleDataStride(size_t pointerCount) {
+ return sizeof(InputMessage::SampleData) + pointerCount * sizeof(PointerCoords);
+ }
+
+ /* Adds the SampleData stride to the given pointer. */
+ static inline SampleData* sampleDataPtrIncrement(SampleData* ptr, size_t stride) {
+ return reinterpret_cast<InputMessage::SampleData*>(reinterpret_cast<char*>(ptr) + stride);
+ }
+};
+
+/*
+ * Publishes input events to an anonymous shared memory buffer.
+ * Uses atomic operations to coordinate shared access with a single concurrent consumer.
+ */
+class InputPublisher {
+public:
+ /* Creates a publisher associated with an input channel. */
+ explicit InputPublisher(const sp<InputChannel>& channel);
+
+ /* Destroys the publisher and releases its input channel. */
+ ~InputPublisher();
+
+ /* Gets the underlying input channel. */
+ inline sp<InputChannel> getChannel() { return mChannel; }
+
+ /* Prepares the publisher for use. Must be called before it is used.
+ * Returns OK on success.
+ *
+ * This method implicitly calls reset(). */
+ status_t initialize();
+
+ /* Resets the publisher to its initial state and unpins its ashmem buffer.
+ * Returns OK on success.
+ *
+ * Should be called after an event has been consumed to release resources used by the
+ * publisher until the next event is ready to be published.
+ */
+ status_t reset();
+
+ /* Publishes a key event to the ashmem buffer.
+ *
+ * Returns OK on success.
+ * Returns INVALID_OPERATION if the publisher has not been reset.
+ */
+ status_t publishKeyEvent(
+ int32_t deviceId,
+ int32_t nature,
+ int32_t action,
+ int32_t flags,
+ int32_t keyCode,
+ int32_t scanCode,
+ int32_t metaState,
+ int32_t repeatCount,
+ nsecs_t downTime,
+ nsecs_t eventTime);
+
+ /* Publishes a motion event to the ashmem buffer.
+ *
+ * Returns OK on success.
+ * Returns INVALID_OPERATION if the publisher has not been reset.
+ * Returns BAD_VALUE if pointerCount is less than 1 or greater than MAX_POINTERS.
+ */
+ status_t publishMotionEvent(
+ int32_t deviceId,
+ int32_t nature,
+ int32_t action,
+ int32_t edgeFlags,
+ int32_t metaState,
+ float xOffset,
+ float yOffset,
+ float xPrecision,
+ float yPrecision,
+ nsecs_t downTime,
+ nsecs_t eventTime,
+ size_t pointerCount,
+ const int32_t* pointerIds,
+ const PointerCoords* pointerCoords);
+
+ /* Appends a motion sample to a motion event unless already consumed.
+ *
+ * Returns OK on success.
+ * Returns INVALID_OPERATION if the current event is not a MOTION_EVENT_ACTION_MOVE event.
+ * Returns FAILED_TRANSACTION if the current event has already been consumed.
+ * Returns NO_MEMORY if the buffer is full and no additional samples can be added.
+ */
+ status_t appendMotionSample(
+ nsecs_t eventTime,
+ const PointerCoords* pointerCoords);
+
+ /* Sends a dispatch signal to the consumer to inform it that a new message is available.
+ *
+ * Returns OK on success.
+ * Errors probably indicate that the channel is broken.
+ */
+ status_t sendDispatchSignal();
+
+ /* Receives the finished signal from the consumer in reply to the original dispatch signal.
+ *
+ * Returns OK on success.
+ * Returns WOULD_BLOCK if there is no signal present.
+ * Other errors probably indicate that the channel is broken.
+ */
+ status_t receiveFinishedSignal();
+
+private:
+ sp<InputChannel> mChannel;
+
+ size_t mAshmemSize;
+ InputMessage* mSharedMessage;
+ bool mPinned;
+ bool mSemaphoreInitialized;
+ bool mWasDispatched;
+
+ size_t mMotionEventPointerCount;
+ InputMessage::SampleData* mMotionEventSampleDataTail;
+ size_t mMotionEventSampleDataStride;
+
+ status_t publishInputEvent(
+ int32_t type,
+ int32_t deviceId,
+ int32_t nature);
+};
+
+/*
+ * Consumes input events from an anonymous shared memory buffer.
+ * Uses atomic operations to coordinate shared access with a single concurrent publisher.
+ */
+class InputConsumer {
+public:
+ /* Creates a consumer associated with an input channel. */
+ explicit InputConsumer(const sp<InputChannel>& channel);
+
+ /* Destroys the consumer and releases its input channel. */
+ ~InputConsumer();
+
+ /* Gets the underlying input channel. */
+ inline sp<InputChannel> getChannel() { return mChannel; }
+
+ /* Prepares the consumer for use. Must be called before it is used. */
+ status_t initialize();
+
+ /* Consumes the input event in the buffer and copies its contents into
+ * an InputEvent object created using the specified factory.
+ * This operation will block if the publisher is updating the event.
+ *
+ * Returns OK on success.
+ * Returns INVALID_OPERATION if there is no currently published event.
+ * Returns NO_MEMORY if the event could not be created.
+ */
+ status_t consume(InputEventFactoryInterface* factory, InputEvent** event);
+
+ /* Sends a finished signal to the publisher to inform it that the current message is
+ * finished processing.
+ *
+ * Returns OK on success.
+ * Errors probably indicate that the channel is broken.
+ */
+ status_t sendFinishedSignal();
+
+ /* Receives the dispatched signal from the publisher.
+ *
+ * Returns OK on success.
+ * Returns WOULD_BLOCK if there is no signal present.
+ * Other errors probably indicate that the channel is broken.
+ */
+ status_t receiveDispatchSignal();
+
+private:
+ sp<InputChannel> mChannel;
+
+ size_t mAshmemSize;
+ InputMessage* mSharedMessage;
+
+ void populateKeyEvent(KeyEvent* keyEvent) const;
+ void populateMotionEvent(MotionEvent* motionEvent) const;
+};
+
+} // namespace android
+
+#endif // _UI_INPUT_TRANSPORT_H
diff --git a/include/utils/BitSet.h b/include/utils/BitSet.h
new file mode 100644
index 0000000..19c8bf0
--- /dev/null
+++ b/include/utils/BitSet.h
@@ -0,0 +1,67 @@
+/*
+ * 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 UTILS_BITSET_H
+#define UTILS_BITSET_H
+
+#include <stdint.h>
+
+/*
+ * Contains some bit manipulation helpers.
+ */
+
+namespace android {
+
+// A simple set of 32 bits that can be individually marked or cleared.
+struct BitSet32 {
+ uint32_t value;
+
+ inline BitSet32() : value(0) { }
+ explicit inline BitSet32(uint32_t value) : value(value) { }
+
+ // Gets the value associated with a particular bit index.
+ static inline uint32_t valueForBit(uint32_t n) { return 0x80000000 >> n; }
+
+ // Clears the bit set.
+ inline void clear() { value = 0; }
+
+ // Returns true if the bit set does not contain any marked bits.
+ inline bool isEmpty() const { return ! value; }
+
+ // Returns true if the specified bit is marked.
+ inline bool hasBit(uint32_t n) const { return value & valueForBit(n); }
+
+ // Marks the specified bit.
+ inline void markBit(uint32_t n) { value |= valueForBit(n); }
+
+ // Clears the specified bit.
+ inline void clearBit(uint32_t n) { value &= ~ valueForBit(n); }
+
+ // Finds the first marked bit in the set.
+ // Result is undefined if all bits are unmarked.
+ inline uint32_t firstMarkedBit() const { return __builtin_clz(value); }
+
+ // Finds the first unmarked bit in the set.
+ // Result is undefined if all bits are marked.
+ inline uint32_t firstUnmarkedBit() const { return __builtin_clz(~ value); }
+
+ inline bool operator== (const BitSet32& other) const { return value == other.value; }
+ inline bool operator!= (const BitSet32& other) const { return value != other.value; }
+};
+
+} // namespace android
+
+#endif // UTILS_BITSET_H
diff --git a/include/utils/Buffer.h b/include/utils/Buffer.h
deleted file mode 100644
index 8e22b0f..0000000
--- a/include/utils/Buffer.h
+++ /dev/null
@@ -1,107 +0,0 @@
-/*
- * Copyright (C) 2008 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 __UTILS_BUFFER_H__
-#define __UTILS_BUFFER_H__ 1
-
-#include <stdio.h>
-#include <stdlib.h>
-#include <string.h>
-
-namespace android {
-
-class Buffer
-{
-private:
- char *buf;
- int bufsiz;
- int used;
- void ensureCapacity(int len);
-
- void
- makeRoomFor(int len)
- {
- if (len + used >= bufsiz) {
- bufsiz = (len + used) * 3/2 + 2;
- char *blah = new char[bufsiz];
-
- memcpy(blah, buf, used);
- delete[] buf;
- buf = blah;
- }
- }
-
-public:
- Buffer()
- {
- bufsiz = 16;
- buf = new char[bufsiz];
- clear();
- }
-
- ~Buffer()
- {
- delete[] buf;
- }
-
- void
- clear()
- {
- buf[0] = '\0';
- used = 0;
- }
-
- int
- length()
- {
- return used;
- }
-
- void
- append(const char c)
- {
- makeRoomFor(1);
- buf[used] = c;
- used++;
- buf[used] = '\0';
- }
-
- void
- append(const char *s, int len)
- {
- makeRoomFor(len);
-
- memcpy(buf + used, s, len);
- used += len;
- buf[used] = '\0';
- }
-
- void
- append(const char *s)
- {
- append(s, strlen(s));
- }
-
- char *
- getBytes()
- {
- return buf;
- }
-};
-
-}; // namespace android
-
-#endif
diff --git a/include/utils/PollLoop.h b/include/utils/PollLoop.h
new file mode 100644
index 0000000..c9d951f
--- /dev/null
+++ b/include/utils/PollLoop.h
@@ -0,0 +1,137 @@
+/*
+ * 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 UTILS_POLL_LOOP_H
+#define UTILS_POLL_LOOP_H
+
+#include <utils/Vector.h>
+#include <utils/threads.h>
+
+#include <sys/poll.h>
+
+namespace android {
+
+/**
+ * A basic file descriptor polling loop based on poll() with callbacks.
+ */
+class PollLoop : public RefBase {
+protected:
+ virtual ~PollLoop();
+
+public:
+ PollLoop();
+
+ /**
+ * A callback that it to be invoked when an event occurs on a file descriptor.
+ * Specifies the events that were triggered and the user data provided when the
+ * callback was set.
+ *
+ * Returns true if the callback should be kept, false if it should be removed automatically
+ * after the callback returns.
+ */
+ typedef bool (*Callback)(int fd, int events, void* data);
+
+ /**
+ * Performs a single call to poll() with optional timeout in milliseconds.
+ * Invokes callbacks for all file descriptors on which an event occurred.
+ *
+ * If the timeout is zero, returns immediately without blocking.
+ * If the timeout is negative, waits indefinitely until awoken.
+ *
+ * Returns true if a callback was invoked or if the loop was awoken by wake().
+ * Returns false if a timeout or error occurred.
+ *
+ * This method must only be called on the main thread.
+ * This method blocks until either a file descriptor is signalled, a timeout occurs,
+ * or wake() is called.
+ * This method does not return until it has finished invoking the appropriate callbacks
+ * for all file descriptors that were signalled.
+ */
+ bool pollOnce(int timeoutMillis);
+
+ /**
+ * Wakes the loop asynchronously.
+ *
+ * This method can be called on any thread.
+ * This method returns immediately.
+ */
+ void wake();
+
+ /**
+ * Sets the callback for a file descriptor, replacing the existing one, if any.
+ * It is an error to call this method with events == 0 or callback == NULL.
+ *
+ * Note that a callback can be invoked with the POLLERR, POLLHUP or POLLNVAL events
+ * even if it is not explicitly requested when registered.
+ *
+ * This method can be called on any thread.
+ * This method may block briefly if it needs to wake the poll loop.
+ */
+ void setCallback(int fd, int events, Callback callback, void* data = NULL);
+
+ /**
+ * Removes the callback for a file descriptor, if one exists.
+ *
+ * When this method returns, it is safe to close the file descriptor since the poll loop
+ * will no longer have a reference to it. However, it is possible for the callback to
+ * already be running or for it to run one last time if the file descriptor was already
+ * signalled. Calling code is responsible for ensuring that this case is safely handled.
+ * For example, if the callback takes care of removing itself during its own execution either
+ * by returning false or calling this method, then it can be guaranteed to not be invoked
+ * again at any later time unless registered anew.
+ *
+ * This method can be called on any thread.
+ * This method may block briefly if it needs to wake the poll loop.
+ *
+ * Returns true if a callback was actually removed, false if none was registered.
+ */
+ bool removeCallback(int fd);
+
+private:
+ struct RequestedCallback {
+ Callback callback;
+ void* data;
+ };
+
+ struct PendingCallback {
+ int fd;
+ int events;
+ Callback callback;
+ void* data;
+ };
+
+ Mutex mLock;
+ Condition mAwake;
+ bool mPolling;
+
+ int mWakeReadPipeFd;
+ int mWakeWritePipeFd;
+
+ Vector<struct pollfd> mRequestedFds;
+ Vector<RequestedCallback> mRequestedCallbacks;
+
+ Vector<PendingCallback> mPendingCallbacks; // used privately by pollOnce
+
+ void openWakePipe();
+ void closeWakePipe();
+
+ ssize_t getRequestIndexLocked(int fd);
+ void wakeAndLock();
+};
+
+} // namespace android
+
+#endif // UTILS_POLL_LOOP_H
diff --git a/include/utils/Pool.h b/include/utils/Pool.h
new file mode 100644
index 0000000..2ee768e
--- /dev/null
+++ b/include/utils/Pool.h
@@ -0,0 +1,71 @@
+/*
+ * 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 UTILS_POOL_H
+#define UTILS_POOL_H
+
+#include <utils/TypeHelpers.h>
+
+namespace android {
+
+class PoolImpl {
+public:
+ PoolImpl(size_t objSize);
+ ~PoolImpl();
+
+ void* allocImpl();
+ void freeImpl(void* obj);
+
+private:
+ size_t mObjSize;
+};
+
+/*
+ * A homogeneous typed memory pool for fixed size objects.
+ * Not intended to be thread-safe.
+ */
+template<typename T>
+class Pool : private PoolImpl {
+public:
+ /* Creates an initially empty pool. */
+ Pool() : PoolImpl(sizeof(T)) { }
+
+ /* Destroys the pool.
+ * Assumes that the pool is empty. */
+ ~Pool() { }
+
+ /* Allocates an object from the pool, growing the pool if needed. */
+ inline T* alloc() {
+ void* mem = allocImpl();
+ if (! traits<T>::has_trivial_ctor) {
+ return new (mem) T();
+ } else {
+ return static_cast<T*>(mem);
+ }
+ }
+
+ /* Frees an object from the pool. */
+ inline void free(T* obj) {
+ if (! traits<T>::has_trivial_dtor) {
+ obj->~T();
+ }
+ freeImpl(obj);
+ }
+};
+
+} // namespace android
+
+#endif // UTILS_POOL_H
diff --git a/include/utils/StopWatch.h b/include/utils/StopWatch.h
index cc0bebc..693dd3c 100644
--- a/include/utils/StopWatch.h
+++ b/include/utils/StopWatch.h
@@ -37,6 +37,8 @@ public:
const char* name() const;
nsecs_t lap();
nsecs_t elapsedTime() const;
+
+ void reset();
private:
const char* mName;
diff --git a/include/utils/Vector.h b/include/utils/Vector.h
index ad59fd6..d40ae16 100644
--- a/include/utils/Vector.h
+++ b/include/utils/Vector.h
@@ -114,6 +114,12 @@ public:
ssize_t appendVector(const Vector<TYPE>& vector);
+ //! insert an array at a given index
+ ssize_t insertArrayAt(const TYPE* array, size_t index, size_t numItems);
+
+ //! append an array at the end of this vector
+ ssize_t appendArray(const TYPE* array, size_t numItems);
+
/*!
* add/insert/replace items
*/
@@ -259,6 +265,16 @@ ssize_t Vector<TYPE>::appendVector(const Vector<TYPE>& vector) {
}
template<class TYPE> inline
+ssize_t Vector<TYPE>::insertArrayAt(const TYPE* array, size_t index, size_t numItems) {
+ return VectorImpl::insertAt(array, index, numItems);
+}
+
+template<class TYPE> inline
+ssize_t Vector<TYPE>::appendArray(const TYPE* array, size_t numItems) {
+ return VectorImpl::add(array, numItems);
+}
+
+template<class TYPE> inline
ssize_t Vector<TYPE>::insertAt(const TYPE& item, size_t index, size_t numItems) {
return VectorImpl::insertAt(&item, index, numItems);
}
diff --git a/include/utils/VectorImpl.h b/include/utils/VectorImpl.h
index 49b03f1..46a7bc2 100644
--- a/include/utils/VectorImpl.h
+++ b/include/utils/VectorImpl.h
@@ -76,7 +76,7 @@ public:
void push();
void push(const void* item);
ssize_t add();
- ssize_t add(const void* item);
+ ssize_t add(const void* item, size_t numItems = 1);
ssize_t replaceAt(size_t index);
ssize_t replaceAt(const void* item, size_t index);
@@ -184,6 +184,8 @@ private:
void push(const void* item);
ssize_t insertVectorAt(const VectorImpl& vector, size_t index);
ssize_t appendVector(const VectorImpl& vector);
+ ssize_t insertArrayAt(const void* array, size_t index, size_t numItems);
+ ssize_t appendArray(const void* array, size_t numItems);
ssize_t insertAt(size_t where, size_t numItems = 1);
ssize_t insertAt(const void* item, size_t where, size_t numItems = 1);
ssize_t replaceAt(size_t index);
diff --git a/libs/surfaceflinger/Layer.cpp b/libs/surfaceflinger/Layer.cpp
index a94fdd4..e7247bd 100644
--- a/libs/surfaceflinger/Layer.cpp
+++ b/libs/surfaceflinger/Layer.cpp
@@ -76,15 +76,18 @@ Layer::~Layer()
status_t Layer::setToken(const sp<UserClient>& userClient,
SharedClient* sharedClient, int32_t token)
{
- SharedBufferServer* lcblk = new SharedBufferServer(
+ sp<SharedBufferServer> lcblk = new SharedBufferServer(
sharedClient, token, mBufferManager.getDefaultBufferCount(),
getIdentity());
status_t err = mUserClientRef.setToken(userClient, lcblk, token);
- if (err != NO_ERROR) {
- LOGE("ClientRef::setToken(%p, %p, %u) failed",
- userClient.get(), lcblk, token);
- delete lcblk;
+
+ LOGE_IF(err != NO_ERROR,
+ "ClientRef::setToken(%p, %p, %u) failed",
+ userClient.get(), lcblk.get(), token);
+
+ if (err == NO_ERROR) {
+ // we need to free the buffers associated with this surface
}
return err;
@@ -95,6 +98,11 @@ int32_t Layer::getToken() const
return mUserClientRef.getToken();
}
+sp<UserClient> Layer::getClient() const
+{
+ return mUserClientRef.getClient();
+}
+
// called with SurfaceFlinger::mStateLock as soon as the layer is entered
// in the purgatory list
void Layer::onRemoved()
@@ -626,11 +634,10 @@ void Layer::dump(String8& result, char* buffer, size_t SIZE) const
// ---------------------------------------------------------------------------
Layer::ClientRef::ClientRef()
- : mToken(-1) {
+ : mControlBlock(0), mToken(-1) {
}
Layer::ClientRef::~ClientRef() {
- delete lcblk;
}
int32_t Layer::ClientRef::getToken() const {
@@ -638,14 +645,25 @@ int32_t Layer::ClientRef::getToken() const {
return mToken;
}
+sp<UserClient> Layer::ClientRef::getClient() const {
+ Mutex::Autolock _l(mLock);
+ return mUserClient.promote();
+}
+
status_t Layer::ClientRef::setToken(const sp<UserClient>& uc,
- SharedBufferServer* sharedClient, int32_t token) {
+ const sp<SharedBufferServer>& sharedClient, int32_t token) {
Mutex::Autolock _l(mLock);
- if (mToken >= 0)
- return INVALID_OPERATION;
+
+ { // scope for strong mUserClient reference
+ sp<UserClient> userClient(mUserClient.promote());
+ if (mUserClient != 0 && mControlBlock != 0) {
+ mControlBlock->setStatus(NO_INIT);
+ }
+ }
+
mUserClient = uc;
mToken = token;
- lcblk = sharedClient;
+ mControlBlock = sharedClient;
return NO_ERROR;
}
@@ -657,12 +675,16 @@ sp<UserClient> Layer::ClientRef::getUserClientUnsafe() const {
// it makes sure the UserClient (and its associated shared memory)
// won't go away while we're accessing it.
Layer::ClientRef::Access::Access(const ClientRef& ref)
- : lcblk(0)
+ : mControlBlock(0)
{
Mutex::Autolock _l(ref.mLock);
mUserClientStrongRef = ref.mUserClient.promote();
if (mUserClientStrongRef != 0)
- lcblk = ref.lcblk;
+ mControlBlock = ref.mControlBlock;
+}
+
+Layer::ClientRef::Access::~Access()
+{
}
// ---------------------------------------------------------------------------
diff --git a/libs/surfaceflinger/Layer.h b/libs/surfaceflinger/Layer.h
index d396ecf..dcb27a0 100644
--- a/libs/surfaceflinger/Layer.h
+++ b/libs/surfaceflinger/Layer.h
@@ -60,6 +60,7 @@ public:
// associate a UserClient to this Layer
status_t setToken(const sp<UserClient>& uc, SharedClient* sc, int32_t idx);
int32_t getToken() const;
+ sp<UserClient> getClient() const;
// Set this Layer's buffers size
void setBufferSize(uint32_t w, uint32_t h);
@@ -119,24 +120,26 @@ private:
ClientRef& operator = (const ClientRef& rhs);
mutable Mutex mLock;
// binder thread, page-flip thread
- SharedBufferServer* lcblk;
+ sp<SharedBufferServer> mControlBlock;
wp<UserClient> mUserClient;
int32_t mToken;
public:
ClientRef();
~ClientRef();
int32_t getToken() const;
+ sp<UserClient> getClient() const;
status_t setToken(const sp<UserClient>& uc,
- SharedBufferServer* sharedClient, int32_t token);
+ const sp<SharedBufferServer>& sharedClient, int32_t token);
sp<UserClient> getUserClientUnsafe() const;
class Access {
Access(const Access& rhs);
Access& operator = (const Access& rhs);
sp<UserClient> mUserClientStrongRef;
- SharedBufferServer* lcblk;
+ sp<SharedBufferServer> mControlBlock;
public:
Access(const ClientRef& ref);
- inline SharedBufferServer* get() const { return lcblk; }
+ ~Access();
+ inline SharedBufferServer* get() const { return mControlBlock.get(); }
};
friend class Access;
};
diff --git a/libs/surfaceflinger/SurfaceFlinger.cpp b/libs/surfaceflinger/SurfaceFlinger.cpp
index 0f73774..4dea62f 100644
--- a/libs/surfaceflinger/SurfaceFlinger.cpp
+++ b/libs/surfaceflinger/SurfaceFlinger.cpp
@@ -1718,7 +1718,10 @@ void UserClient::detachLayer(const Layer* layer)
{
int32_t name = layer->getToken();
if (name >= 0) {
- android_atomic_and(~(1LU<<name), &mBitmap);
+ int32_t mask = 1LU<<name;
+ if ((android_atomic_and(~mask, &mBitmap) & mask) == 0) {
+ LOGW("token %d wasn't marked as used %08x", name, int(mBitmap));
+ }
}
}
@@ -1732,24 +1735,31 @@ ssize_t UserClient::getTokenForSurface(const sp<ISurface>& sur) const
sp<Layer> layer(mFlinger->getLayer(sur));
if (layer == 0) return name;
- // this layer already has a token, just return it
- // FIXME: we should check that this token is for the same client
+ // if this layer already has a token, just return it
name = layer->getToken();
- if (name >= 0) return name;
+ if ((name >= 0) && (layer->getClient() == this))
+ return name;
name = 0;
do {
int32_t mask = 1LU<<name;
if ((android_atomic_or(mask, &mBitmap) & mask) == 0) {
// we found and locked that name
- layer->setToken(const_cast<UserClient*>(this), ctrlblk, name);
+ status_t err = layer->setToken(
+ const_cast<UserClient*>(this), ctrlblk, name);
+ if (err != NO_ERROR) {
+ // free the name
+ android_atomic_and(~mask, &mBitmap);
+ name = err;
+ }
break;
}
if (++name > 31)
name = NO_MEMORY;
} while(name >= 0);
- //LOGD("getTokenForSurface(%p) => %d", sur->asBinder().get(), name);
+ //LOGD("getTokenForSurface(%p) => %d (client=%p, bitmap=%08lx)",
+ // sur->asBinder().get(), name, this, mBitmap);
return name;
}
diff --git a/libs/surfaceflinger_client/SharedBufferStack.cpp b/libs/surfaceflinger_client/SharedBufferStack.cpp
index 1dd8642..d67a589 100644
--- a/libs/surfaceflinger_client/SharedBufferStack.cpp
+++ b/libs/surfaceflinger_client/SharedBufferStack.cpp
@@ -494,6 +494,10 @@ SharedBufferServer::SharedBufferServer(SharedClient* sharedClient,
}
}
+SharedBufferServer::~SharedBufferServer()
+{
+}
+
ssize_t SharedBufferServer::retireAndLock()
{
RWLock::AutoRLock _l(mLock);
diff --git a/libs/surfaceflinger_client/Surface.cpp b/libs/surfaceflinger_client/Surface.cpp
index 6fe4c4a..8617d94 100644
--- a/libs/surfaceflinger_client/Surface.cpp
+++ b/libs/surfaceflinger_client/Surface.cpp
@@ -236,17 +236,15 @@ status_t SurfaceControl::validate() const
status_t SurfaceControl::writeSurfaceToParcel(
const sp<SurfaceControl>& control, Parcel* parcel)
{
- uint32_t flags = 0;
- uint32_t format = 0;
+ sp<ISurface> sur;
uint32_t identity = 0;
uint32_t width = 0;
uint32_t height = 0;
- sp<SurfaceComposerClient> client;
- sp<ISurface> sur;
+ uint32_t format = 0;
+ uint32_t flags = 0;
if (SurfaceControl::isValid(control)) {
- identity = control->mIdentity;
- client = control->mClient;
sur = control->mSurface;
+ identity = control->mIdentity;
width = control->mWidth;
height = control->mHeight;
format = control->mFormat;
@@ -349,6 +347,33 @@ Surface::Surface(const Parcel& parcel, const sp<IBinder>& ref)
init();
}
+status_t Surface::writeToParcel(
+ const sp<Surface>& surface, Parcel* parcel)
+{
+ sp<ISurface> sur;
+ uint32_t identity = 0;
+ uint32_t width = 0;
+ uint32_t height = 0;
+ uint32_t format = 0;
+ uint32_t flags = 0;
+ if (Surface::isValid(surface)) {
+ sur = surface->mSurface;
+ identity = surface->mIdentity;
+ width = surface->mWidth;
+ height = surface->mHeight;
+ format = surface->mFormat;
+ flags = surface->mFlags;
+ }
+ parcel->writeStrongBinder(sur!=0 ? sur->asBinder() : NULL);
+ parcel->writeInt32(identity);
+ parcel->writeInt32(width);
+ parcel->writeInt32(height);
+ parcel->writeInt32(format);
+ parcel->writeInt32(flags);
+ return NO_ERROR;
+
+}
+
sp<Surface> Surface::readFromParcel(
const Parcel& data, const sp<Surface>& other)
{
@@ -385,11 +410,11 @@ void Surface::init()
mBuffers.insertAt(0, 2);
if (mSurface != 0 && mClient.initCheck() == NO_ERROR) {
- mToken = mClient.getTokenForSurface(mSurface);
- if (mToken >= 0) {
+ int32_t token = mClient.getTokenForSurface(mSurface);
+ if (token >= 0) {
mSharedBufferClient = new SharedBufferClient(
- mClient.getSharedClient(), mToken, 2, mIdentity);
- mInitCheck = mClient.getSharedClient()->validate(mToken);
+ mClient.getSharedClient(), token, 2, mIdentity);
+ mInitCheck = mClient.getSharedClient()->validate(token);
}
}
}
@@ -421,7 +446,7 @@ status_t Surface::validate() const
{
// check that we initialized ourself properly
if (mInitCheck != NO_ERROR) {
- LOGE("invalid token (%d, identity=%u)", mToken, mIdentity);
+ LOGE("invalid token (identity=%u)", mIdentity);
return mInitCheck;
}
@@ -437,17 +462,17 @@ status_t Surface::validate() const
}
if (mIdentity != identity) {
- LOGE("[Surface] using an invalid surface id=%d, "
+ LOGE("[Surface] using an invalid surface, "
"identity=%u should be %d",
- mToken, mIdentity, identity);
+ mIdentity, identity);
return NO_INIT;
}
// check the surface didn't become invalid
status_t err = mSharedBufferClient->getStatus();
if (err != NO_ERROR) {
- LOGE("surface (id=%d, identity=%u) is invalid, err=%d (%s)",
- mToken, mIdentity, err, strerror(-err));
+ LOGE("surface (identity=%u) is invalid, err=%d (%s)",
+ mIdentity, err, strerror(-err));
return err;
}
diff --git a/libs/surfaceflinger_client/SurfaceComposerClient.cpp b/libs/surfaceflinger_client/SurfaceComposerClient.cpp
index 5ac0d5d..4096ac6 100644
--- a/libs/surfaceflinger_client/SurfaceComposerClient.cpp
+++ b/libs/surfaceflinger_client/SurfaceComposerClient.cpp
@@ -305,9 +305,7 @@ sp<SurfaceControl> SurfaceComposerClient::createSurface(
sp<ISurface> surface = mClient->createSurface(&data, pid, name,
display, w, h, format, flags);
if (surface != 0) {
- if (uint32_t(data.token) < SharedBufferStack::NUM_LAYERS_MAX) {
- result = new SurfaceControl(this, surface, data, w, h, format, flags);
- }
+ result = new SurfaceControl(this, surface, data, w, h, format, flags);
}
}
return result;
diff --git a/libs/ui/Android.mk b/libs/ui/Android.mk
index f7acd97..24cdc78 100644
--- a/libs/ui/Android.mk
+++ b/libs/ui/Android.mk
@@ -11,6 +11,11 @@ LOCAL_SRC_FILES:= \
GraphicBufferMapper.cpp \
KeyLayoutMap.cpp \
KeyCharacterMap.cpp \
+ Input.cpp \
+ InputDispatcher.cpp \
+ InputManager.cpp \
+ InputReader.cpp \
+ InputTransport.cpp \
IOverlay.cpp \
Overlay.cpp \
PixelFormat.cpp \
diff --git a/libs/ui/EventHub.cpp b/libs/ui/EventHub.cpp
index d45eaf0..27895f2 100644
--- a/libs/ui/EventHub.cpp
+++ b/libs/ui/EventHub.cpp
@@ -155,77 +155,70 @@ int EventHub::getAbsoluteInfo(int32_t deviceId, int axis, int *outMinValue,
return 0;
}
-int EventHub::getSwitchState(int sw) const
-{
-#ifdef EV_SW
- if (sw >= 0 && sw <= SW_MAX) {
- int32_t devid = mSwitches[sw];
- if (devid != 0) {
- return getSwitchState(devid, sw);
+int32_t EventHub::getScanCodeState(int32_t deviceId, int32_t deviceClasses,
+ int32_t scanCode) const {
+ if (scanCode >= 0 && scanCode <= KEY_MAX) {
+ AutoMutex _l(mLock);
+
+ if (deviceId == -1) {
+ for (int i = 0; i < mNumDevicesById; i++) {
+ device_t* device = mDevicesById[i].device;
+ if (device != NULL && (device->classes & deviceClasses) != 0) {
+ int32_t result = getScanCodeStateLocked(device, scanCode);
+ if (result >= KEY_STATE_DOWN) {
+ return result;
+ }
+ }
+ }
+ return KEY_STATE_UP;
+ } else {
+ device_t* device = getDevice(deviceId);
+ if (device != NULL) {
+ return getScanCodeStateLocked(device, scanCode);
+ }
}
}
-#endif
- return -1;
+ return KEY_STATE_UNKNOWN;
}
-int EventHub::getSwitchState(int32_t deviceId, int sw) const
-{
-#ifdef EV_SW
- AutoMutex _l(mLock);
- device_t* device = getDevice(deviceId);
- if (device == NULL) return -1;
-
- if (sw >= 0 && sw <= SW_MAX) {
- uint8_t sw_bitmask[(SW_MAX+7)/8];
- memset(sw_bitmask, 0, sizeof(sw_bitmask));
- if (ioctl(mFDs[id_to_index(device->id)].fd,
- EVIOCGSW(sizeof(sw_bitmask)), sw_bitmask) >= 0) {
- return test_bit(sw, sw_bitmask) ? 1 : 0;
- }
+int32_t EventHub::getScanCodeStateLocked(device_t* device, int32_t scanCode) const {
+ uint8_t key_bitmask[(KEY_MAX + 7) / 8];
+ memset(key_bitmask, 0, sizeof(key_bitmask));
+ if (ioctl(mFDs[id_to_index(device->id)].fd,
+ EVIOCGKEY(sizeof(key_bitmask)), key_bitmask) >= 0) {
+ return test_bit(scanCode, key_bitmask) ? KEY_STATE_DOWN : KEY_STATE_UP;
}
-#endif
-
- return -1;
+ return KEY_STATE_UNKNOWN;
}
-int EventHub::getScancodeState(int code) const
-{
- return getScancodeState(mFirstKeyboardId, code);
-}
+int32_t EventHub::getKeyCodeState(int32_t deviceId, int32_t deviceClasses,
+ int32_t keyCode) const {
-int EventHub::getScancodeState(int32_t deviceId, int code) const
-{
- AutoMutex _l(mLock);
- device_t* device = getDevice(deviceId);
- if (device == NULL) return -1;
-
- if (code >= 0 && code <= KEY_MAX) {
- uint8_t key_bitmask[(KEY_MAX+7)/8];
- memset(key_bitmask, 0, sizeof(key_bitmask));
- if (ioctl(mFDs[id_to_index(device->id)].fd,
- EVIOCGKEY(sizeof(key_bitmask)), key_bitmask) >= 0) {
- return test_bit(code, key_bitmask) ? 1 : 0;
+ if (deviceId == -1) {
+ for (int i = 0; i < mNumDevicesById; i++) {
+ device_t* device = mDevicesById[i].device;
+ if (device != NULL && (device->classes & deviceClasses) != 0) {
+ int32_t result = getKeyCodeStateLocked(device, keyCode);
+ if (result >= KEY_STATE_DOWN) {
+ return result;
+ }
+ }
+ }
+ return KEY_STATE_UP;
+ } else {
+ device_t* device = getDevice(deviceId);
+ if (device != NULL) {
+ return getKeyCodeStateLocked(device, keyCode);
}
}
-
- return -1;
-}
-
-int EventHub::getKeycodeState(int code) const
-{
- return getKeycodeState(mFirstKeyboardId, code);
+ return KEY_STATE_UNKNOWN;
}
-int EventHub::getKeycodeState(int32_t deviceId, int code) const
-{
- AutoMutex _l(mLock);
- device_t* device = getDevice(deviceId);
- if (device == NULL || device->layoutMap == NULL) return -1;
-
+int32_t EventHub::getKeyCodeStateLocked(device_t* device, int32_t keyCode) const {
Vector<int32_t> scanCodes;
- device->layoutMap->findScancodes(code, &scanCodes);
-
- uint8_t key_bitmask[(KEY_MAX+7)/8];
+ device->layoutMap->findScancodes(keyCode, &scanCodes);
+
+ uint8_t key_bitmask[(KEY_MAX + 7) / 8];
memset(key_bitmask, 0, sizeof(key_bitmask));
if (ioctl(mFDs[id_to_index(device->id)].fd,
EVIOCGKEY(sizeof(key_bitmask)), key_bitmask) >= 0) {
@@ -239,12 +232,45 @@ int EventHub::getKeycodeState(int32_t deviceId, int code) const
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 1;
+ return KEY_STATE_DOWN;
}
}
+ return KEY_STATE_UP;
}
-
- return 0;
+ return KEY_STATE_UNKNOWN;
+}
+
+int32_t EventHub::getSwitchState(int32_t deviceId, int32_t deviceClasses, int32_t sw) const {
+#ifdef EV_SW
+ if (sw >= 0 && sw <= SW_MAX) {
+ AutoMutex _l(mLock);
+
+ if (deviceId == -1) {
+ deviceId = mSwitches[sw];
+ if (deviceId == 0) {
+ return KEY_STATE_UNKNOWN;
+ }
+ }
+
+ device_t* device = getDevice(deviceId);
+ if (device == NULL) {
+ return KEY_STATE_UNKNOWN;
+ }
+
+ return getSwitchStateLocked(device, sw);
+ }
+#endif
+ return KEY_STATE_UNKNOWN;
+}
+
+int32_t EventHub::getSwitchStateLocked(device_t* device, int32_t sw) const {
+ uint8_t sw_bitmask[(SW_MAX + 7) / 8];
+ memset(sw_bitmask, 0, sizeof(sw_bitmask));
+ if (ioctl(mFDs[id_to_index(device->id)].fd,
+ EVIOCGSW(sizeof(sw_bitmask)), sw_bitmask) >= 0) {
+ return test_bit(sw, sw_bitmask) ? KEY_STATE_DOWN : KEY_STATE_UP;
+ }
+ return KEY_STATE_UNKNOWN;
}
status_t EventHub::scancodeToKeycode(int32_t deviceId, int scancode,
@@ -309,9 +335,6 @@ bool EventHub::getEvent(int32_t* outDeviceId, int32_t* outType,
status_t err;
- fd_set readfds;
- int maxFd = -1;
- int cc;
int i;
int res;
int pollres;
@@ -457,7 +480,7 @@ bool EventHub::openPlatformInput(void)
* Inspect the known devices to determine whether physical keys exist for the given
* framework-domain key codes.
*/
-bool EventHub::hasKeys(size_t numCodes, int32_t* keyCodes, uint8_t* outFlags) {
+bool EventHub::hasKeys(size_t numCodes, const int32_t* keyCodes, uint8_t* outFlags) const {
for (size_t codeIndex = 0; codeIndex < numCodes; codeIndex++) {
outFlags[codeIndex] = 0;
@@ -465,7 +488,8 @@ bool EventHub::hasKeys(size_t numCodes, int32_t* keyCodes, uint8_t* outFlags) {
Vector<int32_t> scanCodes;
for (int n = 0; (n < mFDCount) && (outFlags[codeIndex] == 0); n++) {
if (mDevices[n]) {
- status_t err = mDevices[n]->layoutMap->findScancodes(keyCodes[codeIndex], &scanCodes);
+ status_t err = mDevices[n]->layoutMap->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
@@ -618,11 +642,11 @@ int EventHub::open_device(const char *deviceName)
//}
for (int i=0; i<((BTN_MISC+7)/8); i++) {
if (key_bitmask[i] != 0) {
- device->classes |= CLASS_KEYBOARD;
+ device->classes |= INPUT_DEVICE_CLASS_KEYBOARD;
break;
}
}
- if ((device->classes & CLASS_KEYBOARD) != 0) {
+ if ((device->classes & INPUT_DEVICE_CLASS_KEYBOARD) != 0) {
device->keyBitmask = new uint8_t[sizeof(key_bitmask)];
if (device->keyBitmask != NULL) {
memcpy(device->keyBitmask, key_bitmask, sizeof(key_bitmask));
@@ -642,7 +666,7 @@ int EventHub::open_device(const char *deviceName)
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 |= CLASS_TRACKBALL;
+ device->classes |= INPUT_DEVICE_CLASS_TRACKBALL;
}
}
}
@@ -656,12 +680,12 @@ int EventHub::open_device(const char *deviceName)
if (test_bit(ABS_MT_TOUCH_MAJOR, abs_bitmask)
&& test_bit(ABS_MT_POSITION_X, abs_bitmask)
&& test_bit(ABS_MT_POSITION_Y, abs_bitmask)) {
- device->classes |= CLASS_TOUCHSCREEN | CLASS_TOUCHSCREEN_MT;
+ 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 |= CLASS_TOUCHSCREEN;
+ device->classes |= INPUT_DEVICE_CLASS_TOUCHSCREEN;
}
#ifdef EV_SW
@@ -680,7 +704,7 @@ int EventHub::open_device(const char *deviceName)
}
#endif
- if ((device->classes&CLASS_KEYBOARD) != 0) {
+ if ((device->classes & INPUT_DEVICE_CLASS_KEYBOARD) != 0) {
char tmpfn[sizeof(name)];
char keylayoutFilename[300];
@@ -723,7 +747,7 @@ int EventHub::open_device(const char *deviceName)
// 'Q' key support = cheap test of whether this is an alpha-capable kbd
if (hasKeycode(device, kKeyCodeQ)) {
- device->classes |= CLASS_ALPHAKEY;
+ device->classes |= INPUT_DEVICE_CLASS_ALPHAKEY;
}
// See if this has a DPAD.
@@ -732,7 +756,7 @@ int EventHub::open_device(const char *deviceName)
hasKeycode(device, kKeyCodeDpadLeft) &&
hasKeycode(device, kKeyCodeDpadRight) &&
hasKeycode(device, kKeyCodeDpadCenter)) {
- device->classes |= CLASS_DPAD;
+ device->classes |= INPUT_DEVICE_CLASS_DPAD;
}
LOGI("New keyboard: device->id=0x%x devname='%s' propName='%s' keylayout='%s'\n",
diff --git a/libs/ui/GraphicBuffer.cpp b/libs/ui/GraphicBuffer.cpp
index 3ddde38..4b5f025 100644
--- a/libs/ui/GraphicBuffer.cpp
+++ b/libs/ui/GraphicBuffer.cpp
@@ -111,6 +111,9 @@ status_t GraphicBuffer::reallocate(uint32_t w, uint32_t h, PixelFormat f,
if (mOwner != ownData)
return INVALID_OPERATION;
+ if (handle && w==width && h==height && f==format && reqUsage==usage)
+ return NO_ERROR;
+
if (handle) {
GraphicBufferAllocator& allocator(GraphicBufferAllocator::get());
allocator.free(handle);
diff --git a/libs/ui/Input.cpp b/libs/ui/Input.cpp
new file mode 100644
index 0000000..d367708
--- /dev/null
+++ b/libs/ui/Input.cpp
@@ -0,0 +1,238 @@
+//
+// Copyright 2010 The Android Open Source Project
+//
+// Provides a pipe-based transport for native events in the NDK.
+//
+#define LOG_TAG "Input"
+
+//#define LOG_NDEBUG 0
+
+#include <ui/Input.h>
+
+namespace android {
+
+// class InputEvent
+
+void InputEvent::initialize(int32_t deviceId, int32_t nature) {
+ mDeviceId = deviceId;
+ mNature = nature;
+}
+
+// class KeyEvent
+
+void KeyEvent::initialize(
+ int32_t deviceId,
+ int32_t nature,
+ int32_t action,
+ int32_t flags,
+ int32_t keyCode,
+ int32_t scanCode,
+ int32_t metaState,
+ int32_t repeatCount,
+ nsecs_t downTime,
+ nsecs_t eventTime) {
+ InputEvent::initialize(deviceId, nature);
+ mAction = action;
+ mFlags = flags;
+ mKeyCode = keyCode;
+ mScanCode = scanCode;
+ mMetaState = metaState;
+ mRepeatCount = repeatCount;
+ mDownTime = downTime;
+ mEventTime = eventTime;
+}
+
+// class MotionEvent
+
+void MotionEvent::initialize(
+ int32_t deviceId,
+ int32_t nature,
+ int32_t action,
+ int32_t edgeFlags,
+ int32_t metaState,
+ float rawX,
+ float rawY,
+ float xPrecision,
+ float yPrecision,
+ nsecs_t downTime,
+ nsecs_t eventTime,
+ size_t pointerCount,
+ const int32_t* pointerIds,
+ const PointerCoords* pointerCoords) {
+ InputEvent::initialize(deviceId, nature);
+ mAction = action;
+ mEdgeFlags = edgeFlags;
+ mMetaState = metaState;
+ mRawX = rawX;
+ mRawY = rawY;
+ mXPrecision = xPrecision;
+ mYPrecision = yPrecision;
+ mDownTime = downTime;
+ mPointerIds.clear();
+ mPointerIds.appendArray(pointerIds, pointerCount);
+ mSampleEventTimes.clear();
+ mSamplePointerCoords.clear();
+ addSample(eventTime, pointerCoords);
+}
+
+void MotionEvent::addSample(
+ int64_t eventTime,
+ const PointerCoords* pointerCoords) {
+ mSampleEventTimes.push(eventTime);
+ mSamplePointerCoords.appendArray(pointerCoords, getPointerCount());
+}
+
+void MotionEvent::offsetLocation(float xOffset, float yOffset) {
+ if (xOffset != 0 || yOffset != 0) {
+ for (size_t i = 0; i < mSamplePointerCoords.size(); i++) {
+ PointerCoords& pointerCoords = mSamplePointerCoords.editItemAt(i);
+ pointerCoords.x += xOffset;
+ pointerCoords.y += yOffset;
+ }
+ }
+}
+
+} // namespace android
+
+// NDK APIs
+
+using android::InputEvent;
+using android::KeyEvent;
+using android::MotionEvent;
+
+int32_t input_event_get_type(const input_event_t* event) {
+ return reinterpret_cast<const InputEvent*>(event)->getType();
+}
+
+int32_t input_event_get_device_id(const input_event_t* event) {
+ return reinterpret_cast<const InputEvent*>(event)->getDeviceId();
+}
+
+int32_t input_event_get_nature(const input_event_t* event) {
+ return reinterpret_cast<const InputEvent*>(event)->getNature();
+}
+
+int32_t key_event_get_action(const input_event_t* key_event) {
+ return reinterpret_cast<const KeyEvent*>(key_event)->getAction();
+}
+
+int32_t key_event_get_flags(const input_event_t* key_event) {
+ return reinterpret_cast<const KeyEvent*>(key_event)->getFlags();
+}
+
+int32_t key_event_get_key_code(const input_event_t* key_event) {
+ return reinterpret_cast<const KeyEvent*>(key_event)->getKeyCode();
+}
+
+int32_t key_event_get_scan_code(const input_event_t* key_event) {
+ return reinterpret_cast<const KeyEvent*>(key_event)->getScanCode();
+}
+
+int32_t key_event_get_meta_state(const input_event_t* key_event) {
+ return reinterpret_cast<const KeyEvent*>(key_event)->getMetaState();
+}
+int32_t key_event_get_repeat_count(const input_event_t* key_event) {
+ return reinterpret_cast<const KeyEvent*>(key_event)->getRepeatCount();
+}
+
+int64_t key_event_get_down_time(const input_event_t* key_event) {
+ return reinterpret_cast<const KeyEvent*>(key_event)->getDownTime();
+}
+
+int64_t key_event_get_event_time(const input_event_t* key_event) {
+ return reinterpret_cast<const KeyEvent*>(key_event)->getEventTime();
+}
+
+int32_t motion_event_get_action(const input_event_t* motion_event) {
+ return reinterpret_cast<const MotionEvent*>(motion_event)->getAction();
+}
+
+int32_t motion_event_get_meta_state(const input_event_t* motion_event) {
+ return reinterpret_cast<const MotionEvent*>(motion_event)->getMetaState();
+}
+
+int32_t motion_event_get_edge_flags(const input_event_t* motion_event) {
+ return reinterpret_cast<const MotionEvent*>(motion_event)->getEdgeFlags();
+}
+
+int64_t motion_event_get_down_time(const input_event_t* motion_event) {
+ return reinterpret_cast<const MotionEvent*>(motion_event)->getDownTime();
+}
+
+int64_t motion_event_get_event_time(const input_event_t* motion_event) {
+ return reinterpret_cast<const MotionEvent*>(motion_event)->getEventTime();
+}
+
+float motion_event_get_x_precision(const input_event_t* motion_event) {
+ return reinterpret_cast<const MotionEvent*>(motion_event)->getXPrecision();
+}
+
+float motion_event_get_y_precision(const input_event_t* motion_event) {
+ return reinterpret_cast<const MotionEvent*>(motion_event)->getYPrecision();
+}
+
+size_t motion_event_get_pointer_count(const input_event_t* motion_event) {
+ return reinterpret_cast<const MotionEvent*>(motion_event)->getPointerCount();
+}
+
+int32_t motion_event_get_pointer_id(const input_event_t* motion_event, size_t pointer_index) {
+ return reinterpret_cast<const MotionEvent*>(motion_event)->getPointerId(pointer_index);
+}
+
+float motion_event_get_raw_x(const input_event_t* motion_event) {
+ return reinterpret_cast<const MotionEvent*>(motion_event)->getRawX();
+}
+
+float motion_event_get_raw_y(const input_event_t* motion_event) {
+ return reinterpret_cast<const MotionEvent*>(motion_event)->getRawY();
+}
+
+float motion_event_get_x(const input_event_t* motion_event, size_t pointer_index) {
+ return reinterpret_cast<const MotionEvent*>(motion_event)->getX(pointer_index);
+}
+
+float motion_event_get_y(const input_event_t* motion_event, size_t pointer_index) {
+ return reinterpret_cast<const MotionEvent*>(motion_event)->getY(pointer_index);
+}
+
+float motion_event_get_pressure(const input_event_t* motion_event, size_t pointer_index) {
+ return reinterpret_cast<const MotionEvent*>(motion_event)->getPressure(pointer_index);
+}
+
+float motion_event_get_size(const input_event_t* motion_event, size_t pointer_index) {
+ return reinterpret_cast<const MotionEvent*>(motion_event)->getSize(pointer_index);
+}
+
+size_t motion_event_get_history_size(const input_event_t* motion_event) {
+ return reinterpret_cast<const MotionEvent*>(motion_event)->getHistorySize();
+}
+
+int64_t motion_event_get_historical_event_time(input_event_t* motion_event,
+ size_t history_index) {
+ return reinterpret_cast<const MotionEvent*>(motion_event)->getHistoricalEventTime(
+ history_index);
+}
+
+float motion_event_get_historical_x(input_event_t* motion_event, size_t pointer_index,
+ size_t history_index) {
+ return reinterpret_cast<const MotionEvent*>(motion_event)->getHistoricalX(
+ pointer_index, history_index);
+}
+
+float motion_event_get_historical_y(input_event_t* motion_event, size_t pointer_index,
+ size_t history_index) {
+ return reinterpret_cast<const MotionEvent*>(motion_event)->getHistoricalY(
+ pointer_index, history_index);
+}
+
+float motion_event_get_historical_pressure(input_event_t* motion_event, size_t pointer_index,
+ size_t history_index) {
+ return reinterpret_cast<const MotionEvent*>(motion_event)->getHistoricalPressure(
+ pointer_index, history_index);
+}
+
+float motion_event_get_historical_size(input_event_t* motion_event, size_t pointer_index,
+ size_t history_index) {
+ return reinterpret_cast<const MotionEvent*>(motion_event)->getHistoricalSize(
+ pointer_index, history_index);
+}
diff --git a/libs/ui/InputDispatcher.cpp b/libs/ui/InputDispatcher.cpp
new file mode 100644
index 0000000..0ccde0d
--- /dev/null
+++ b/libs/ui/InputDispatcher.cpp
@@ -0,0 +1,1313 @@
+//
+// 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 1
+
+// Log detailed debug messages about each outbound event processed by the dispatcher.
+#define DEBUG_OUTBOUND_EVENT_DETAILS 1
+
+// Log debug messages about batching.
+#define DEBUG_BATCHING 1
+
+// Log debug messages about the dispatch cycle.
+#define DEBUG_DISPATCH_CYCLE 1
+
+// Log debug messages about performance statistics.
+#define DEBUG_PERFORMANCE_STATISTICS 1
+
+#include <cutils/log.h>
+#include <ui/InputDispatcher.h>
+
+#include <stddef.h>
+#include <unistd.h>
+#include <errno.h>
+#include <limits.h>
+
+namespace android {
+
+// TODO, this needs to be somewhere else, perhaps in the policy
+static inline bool isMovementKey(int32_t keyCode) {
+ return keyCode == KEYCODE_DPAD_UP
+ || keyCode == KEYCODE_DPAD_DOWN
+ || keyCode == KEYCODE_DPAD_LEFT
+ || keyCode == KEYCODE_DPAD_RIGHT;
+}
+
+// --- InputDispatcher ---
+
+InputDispatcher::InputDispatcher(const sp<InputDispatchPolicyInterface>& policy) :
+ mPolicy(policy) {
+ mPollLoop = new PollLoop();
+
+ mInboundQueue.head.refCount = -1;
+ mInboundQueue.head.type = EventEntry::TYPE_SENTINEL;
+ mInboundQueue.head.eventTime = LONG_LONG_MIN;
+
+ mInboundQueue.tail.refCount = -1;
+ mInboundQueue.tail.type = EventEntry::TYPE_SENTINEL;
+ mInboundQueue.tail.eventTime = LONG_LONG_MAX;
+
+ mKeyRepeatState.lastKeyEntry = NULL;
+}
+
+InputDispatcher::~InputDispatcher() {
+ resetKeyRepeatLocked();
+
+ while (mConnectionsByReceiveFd.size() != 0) {
+ unregisterInputChannel(mConnectionsByReceiveFd.valueAt(0)->inputChannel);
+ }
+
+ for (EventEntry* entry = mInboundQueue.head.next; entry != & mInboundQueue.tail; ) {
+ EventEntry* next = entry->next;
+ mAllocator.releaseEventEntry(next);
+ entry = next;
+ }
+}
+
+void InputDispatcher::dispatchOnce() {
+ bool allowKeyRepeat = mPolicy->allowKeyRepeat();
+
+ nsecs_t currentTime;
+ nsecs_t nextWakeupTime = LONG_LONG_MAX;
+ { // acquire lock
+ AutoMutex _l(mLock);
+ currentTime = systemTime(SYSTEM_TIME_MONOTONIC);
+
+ // 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.
+ // XXX we should handle resetting input state coming out of sleep more generally elsewhere
+ if (! allowKeyRepeat) {
+ resetKeyRepeatLocked();
+ }
+
+ // Process timeouts for all connections and determine if there are any synchronous
+ // event dispatches pending.
+ bool hasPendingSyncTarget = false;
+ for (size_t i = 0; i < mActiveConnections.size(); ) {
+ Connection* connection = mActiveConnections.itemAt(i);
+
+ nsecs_t connectionTimeoutTime = connection->nextTimeoutTime;
+ if (connectionTimeoutTime <= currentTime) {
+ bool deactivated = timeoutDispatchCycleLocked(currentTime, connection);
+ if (deactivated) {
+ // Don't increment i because the connection has been removed
+ // from mActiveConnections (hence, deactivated).
+ continue;
+ }
+ }
+
+ if (connectionTimeoutTime < nextWakeupTime) {
+ nextWakeupTime = connectionTimeoutTime;
+ }
+
+ if (connection->hasPendingSyncTarget()) {
+ hasPendingSyncTarget = true;
+ }
+
+ i += 1;
+ }
+
+ // If we don't have a pending sync target, then we can begin delivering a new event.
+ // (Otherwise we wait for dispatch to complete for that target.)
+ if (! hasPendingSyncTarget) {
+ if (mInboundQueue.isEmpty()) {
+ if (mKeyRepeatState.lastKeyEntry) {
+ if (currentTime >= mKeyRepeatState.nextRepeatTime) {
+ processKeyRepeatLocked(currentTime);
+ return; // dispatched once
+ } else {
+ if (mKeyRepeatState.nextRepeatTime < nextWakeupTime) {
+ nextWakeupTime = mKeyRepeatState.nextRepeatTime;
+ }
+ }
+ }
+ } else {
+ // Inbound queue has at least one entry. Dequeue it and begin dispatching.
+ // Note that we do not hold the lock for this process because dispatching may
+ // involve making many callbacks.
+ EventEntry* entry = mInboundQueue.dequeueAtHead();
+
+ switch (entry->type) {
+ case EventEntry::TYPE_CONFIGURATION_CHANGED: {
+ ConfigurationChangedEntry* typedEntry =
+ static_cast<ConfigurationChangedEntry*>(entry);
+ processConfigurationChangedLocked(currentTime, typedEntry);
+ mAllocator.releaseConfigurationChangedEntry(typedEntry);
+ break;
+ }
+
+ case EventEntry::TYPE_KEY: {
+ KeyEntry* typedEntry = static_cast<KeyEntry*>(entry);
+ processKeyLocked(currentTime, typedEntry);
+ mAllocator.releaseKeyEntry(typedEntry);
+ break;
+ }
+
+ case EventEntry::TYPE_MOTION: {
+ MotionEntry* typedEntry = static_cast<MotionEntry*>(entry);
+ processMotionLocked(currentTime, typedEntry);
+ mAllocator.releaseMotionEntry(typedEntry);
+ break;
+ }
+
+ default:
+ assert(false);
+ break;
+ }
+ return; // dispatched once
+ }
+ }
+ } // release lock
+
+ // Wait for callback or timeout or wake.
+ nsecs_t timeout = nanoseconds_to_milliseconds(nextWakeupTime - currentTime);
+ int32_t timeoutMillis = timeout > INT_MAX ? -1 : timeout > 0 ? int32_t(timeout) : 0;
+ mPollLoop->pollOnce(timeoutMillis);
+}
+
+void InputDispatcher::processConfigurationChangedLocked(nsecs_t currentTime,
+ ConfigurationChangedEntry* entry) {
+#if DEBUG_OUTBOUND_EVENT_DETAILS
+ LOGD("processConfigurationChanged - eventTime=%lld, touchScreenConfig=%d, "
+ "keyboardConfig=%d, navigationConfig=%d", entry->eventTime,
+ entry->touchScreenConfig, entry->keyboardConfig, entry->navigationConfig);
+#endif
+
+ mPolicy->notifyConfigurationChanged(entry->eventTime, entry->touchScreenConfig,
+ entry->keyboardConfig, entry->navigationConfig);
+}
+
+void InputDispatcher::processKeyLocked(nsecs_t currentTime, KeyEntry* entry) {
+#if DEBUG_OUTBOUND_EVENT_DETAILS
+ LOGD("processKey - eventTime=%lld, deviceId=0x%x, nature=0x%x, policyFlags=0x%x, action=0x%x, "
+ "flags=0x%x, keyCode=0x%x, scanCode=0x%x, metaState=0x%x, downTime=%lld",
+ entry->eventTime, entry->deviceId, entry->nature, entry->policyFlags, entry->action,
+ entry->flags, entry->keyCode, entry->scanCode, entry->metaState,
+ entry->downTime);
+#endif
+
+ // TODO: Poke user activity.
+
+ if (entry->action == KEY_EVENT_ACTION_DOWN) {
+ 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 + mPolicy->getKeyRepeatTimeout();
+ }
+ mKeyRepeatState.lastKeyEntry = entry;
+ entry->refCount += 1;
+ } else {
+ resetKeyRepeatLocked();
+ }
+
+ identifyInputTargetsAndDispatchKeyLocked(currentTime, entry);
+}
+
+void InputDispatcher::processKeyRepeatLocked(nsecs_t currentTime) {
+ // TODO Old WindowManagerServer code sniffs the input queue for following key up
+ // events and drops the repeat if one is found. We should do something similar.
+ // One good place to do it is in notifyKey as soon as the key up enters the
+ // inbound event queue.
+
+ // Synthesize a key repeat after the repeat timeout expired.
+ // We reuse the previous key entry if otherwise unreferenced.
+ KeyEntry* entry = mKeyRepeatState.lastKeyEntry;
+ if (entry->refCount == 1) {
+ entry->repeatCount += 1;
+ } else {
+ KeyEntry* newEntry = mAllocator.obtainKeyEntry();
+ newEntry->deviceId = entry->deviceId;
+ newEntry->nature = entry->nature;
+ newEntry->policyFlags = entry->policyFlags;
+ newEntry->action = entry->action;
+ newEntry->flags = entry->flags;
+ newEntry->keyCode = entry->keyCode;
+ newEntry->scanCode = entry->scanCode;
+ newEntry->metaState = entry->metaState;
+ newEntry->repeatCount = entry->repeatCount + 1;
+
+ mKeyRepeatState.lastKeyEntry = newEntry;
+ mAllocator.releaseKeyEntry(entry);
+
+ entry = newEntry;
+ }
+ entry->eventTime = currentTime;
+ entry->downTime = currentTime;
+ entry->policyFlags = 0;
+
+ mKeyRepeatState.nextRepeatTime = currentTime + mPolicy->getKeyRepeatTimeout();
+
+#if DEBUG_OUTBOUND_EVENT_DETAILS
+ LOGD("processKeyRepeat - eventTime=%lld, deviceId=0x%x, nature=0x%x, policyFlags=0x%x, "
+ "action=0x%x, flags=0x%x, keyCode=0x%x, scanCode=0x%x, metaState=0x%x, "
+ "repeatCount=%d, downTime=%lld",
+ entry->eventTime, entry->deviceId, entry->nature, entry->policyFlags,
+ entry->action, entry->flags, entry->keyCode, entry->scanCode, entry->metaState,
+ entry->repeatCount, entry->downTime);
+#endif
+
+ identifyInputTargetsAndDispatchKeyLocked(currentTime, entry);
+}
+
+void InputDispatcher::processMotionLocked(nsecs_t currentTime, MotionEntry* entry) {
+#if DEBUG_OUTBOUND_EVENT_DETAILS
+ LOGD("processMotion - eventTime=%lld, deviceId=0x%x, nature=0x%x, policyFlags=0x%x, action=0x%x, "
+ "metaState=0x%x, edgeFlags=0x%x, xPrecision=%f, yPrecision=%f, downTime=%lld",
+ entry->eventTime, entry->deviceId, entry->nature, entry->policyFlags, entry->action,
+ 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;
+ 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",
+ i, entry->pointerIds[i],
+ sample->pointerCoords[i].x,
+ sample->pointerCoords[i].y,
+ sample->pointerCoords[i].pressure,
+ sample->pointerCoords[i].size);
+ }
+
+ // 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 == MOTION_EVENT_ACTION_MOVE) {
+ LOGD(" ... Total movement samples currently batched %d ...", sampleCount);
+ }
+#endif
+
+ identifyInputTargetsAndDispatchMotionLocked(currentTime, entry);
+}
+
+void InputDispatcher::identifyInputTargetsAndDispatchKeyLocked(
+ nsecs_t currentTime, KeyEntry* entry) {
+#if DEBUG_DISPATCH_CYCLE
+ LOGD("identifyInputTargetsAndDispatchKey");
+#endif
+
+ mReusableKeyEvent.initialize(entry->deviceId, entry->nature, entry->action, entry->flags,
+ entry->keyCode, entry->scanCode, entry->metaState, entry->repeatCount,
+ entry->downTime, entry->eventTime);
+
+ mCurrentInputTargets.clear();
+ mPolicy->getKeyEventTargets(& mReusableKeyEvent, entry->policyFlags,
+ mCurrentInputTargets);
+
+ dispatchEventToCurrentInputTargetsLocked(currentTime, entry, false);
+}
+
+void InputDispatcher::identifyInputTargetsAndDispatchMotionLocked(
+ nsecs_t currentTime, MotionEntry* entry) {
+#if DEBUG_DISPATCH_CYCLE
+ LOGD("identifyInputTargetsAndDispatchMotion");
+#endif
+
+ mReusableMotionEvent.initialize(entry->deviceId, entry->nature, entry->action,
+ entry->edgeFlags, entry->metaState,
+ entry->firstSample.pointerCoords[0].x, entry->firstSample.pointerCoords[0].y,
+ entry->xPrecision, entry->yPrecision,
+ entry->downTime, entry->eventTime, entry->pointerCount, entry->pointerIds,
+ entry->firstSample.pointerCoords);
+
+ mCurrentInputTargets.clear();
+ mPolicy->getMotionEventTargets(& mReusableMotionEvent, entry->policyFlags,
+ mCurrentInputTargets);
+
+ dispatchEventToCurrentInputTargetsLocked(currentTime, entry, false);
+}
+
+void InputDispatcher::dispatchEventToCurrentInputTargetsLocked(nsecs_t currentTime,
+ EventEntry* eventEntry, bool resumeWithAppendedMotionSample) {
+#if DEBUG_DISPATCH_CYCLE
+ LOGD("dispatchEventToCurrentInputTargets, "
+ "resumeWithAppendedMotionSample=%s",
+ resumeWithAppendedMotionSample ? "true" : "false");
+#endif
+
+ for (size_t i = 0; i < mCurrentInputTargets.size(); i++) {
+ const InputTarget& inputTarget = mCurrentInputTargets.itemAt(i);
+
+ ssize_t connectionIndex = mConnectionsByReceiveFd.indexOfKey(
+ inputTarget.inputChannel->getReceivePipeFd());
+ if (connectionIndex >= 0) {
+ sp<Connection> connection = mConnectionsByReceiveFd.valueAt(connectionIndex);
+ prepareDispatchCycleLocked(currentTime, connection.get(), eventEntry, & inputTarget,
+ resumeWithAppendedMotionSample);
+ } else {
+ LOGW("Framework requested delivery of an input event to channel '%s' but it "
+ "is not registered with the input dispatcher.",
+ inputTarget.inputChannel->getName().string());
+ }
+ }
+}
+
+void InputDispatcher::prepareDispatchCycleLocked(nsecs_t currentTime, Connection* connection,
+ EventEntry* eventEntry, const InputTarget* inputTarget,
+ bool resumeWithAppendedMotionSample) {
+#if DEBUG_DISPATCH_CYCLE
+ LOGD("channel '%s' ~ prepareDispatchCycle, flags=%d, timeout=%lldns, "
+ "xOffset=%f, yOffset=%f, resumeWithAppendedMotionSample=%s",
+ connection->getInputChannelName(), inputTarget->flags, inputTarget->timeout,
+ inputTarget->xOffset, inputTarget->yOffset,
+ resumeWithAppendedMotionSample ? "true" : "false");
+#endif
+
+ // Skip this event if the connection status is not normal.
+ // We don't want to queue outbound events at all if the connection is broken or
+ // not responding.
+ if (connection->status != Connection::STATUS_NORMAL) {
+ LOGV("channel '%s' ~ Dropping event because the channel status is %s",
+ connection->status == Connection::STATUS_BROKEN ? "BROKEN" : "NOT RESPONDING");
+ return;
+ }
+
+ // 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).
+ MotionSample* appendedMotionSample = static_cast<MotionEntry*>(eventEntry)->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 "
+ "dispatchedmove 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
+ dispatchEntry->targetFlags = inputTarget->flags;
+ dispatchEntry->xOffset = inputTarget->xOffset;
+ dispatchEntry->yOffset = inputTarget->yOffset;
+ dispatchEntry->timeout = inputTarget->timeout;
+ dispatchEntry->inProgress = false;
+ dispatchEntry->headMotionSample = NULL;
+ dispatchEntry->tailMotionSample = NULL;
+
+ // 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);
+ startDispatchCycleLocked(currentTime, connection);
+ }
+}
+
+void InputDispatcher::startDispatchCycleLocked(nsecs_t currentTime, 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.head.next;
+ assert(! dispatchEntry->inProgress);
+
+ // TODO throttle successive ACTION_MOVE motion events for the same device
+ // possible implementation could set a brief poll timeout here and resume starting the
+ // dispatch cycle when elapsed
+
+ // Publish the event.
+ status_t status;
+ switch (dispatchEntry->eventEntry->type) {
+ case EventEntry::TYPE_KEY: {
+ KeyEntry* keyEntry = static_cast<KeyEntry*>(dispatchEntry->eventEntry);
+
+ // Apply target flags.
+ int32_t action = keyEntry->action;
+ int32_t flags = keyEntry->flags;
+ if (dispatchEntry->targetFlags & InputTarget::FLAG_CANCEL) {
+ flags |= KEY_EVENT_FLAG_CANCELED;
+ }
+
+ // Publish the key event.
+ status = connection->inputPublisher.publishKeyEvent(keyEntry->deviceId, keyEntry->nature,
+ 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);
+ abortDispatchCycleLocked(currentTime, connection, true /*broken*/);
+ return;
+ }
+ break;
+ }
+
+ case EventEntry::TYPE_MOTION: {
+ MotionEntry* motionEntry = static_cast<MotionEntry*>(dispatchEntry->eventEntry);
+
+ // Apply target flags.
+ int32_t action = motionEntry->action;
+ if (dispatchEntry->targetFlags & InputTarget::FLAG_OUTSIDE) {
+ action = MOTION_EVENT_ACTION_OUTSIDE;
+ }
+ if (dispatchEntry->targetFlags & InputTarget::FLAG_CANCEL) {
+ action = MOTION_EVENT_ACTION_CANCEL;
+ }
+
+ // 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;
+ }
+
+ // Publish the motion event and the first motion sample.
+ status = connection->inputPublisher.publishMotionEvent(motionEntry->deviceId,
+ motionEntry->nature, action, motionEntry->edgeFlags, motionEntry->metaState,
+ dispatchEntry->xOffset, dispatchEntry->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);
+ abortDispatchCycleLocked(currentTime, connection, true /*broken*/);
+ 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);
+ abortDispatchCycleLocked(currentTime, connection, true /*broken*/);
+ 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);
+ abortDispatchCycleLocked(currentTime, connection, true /*broken*/);
+ return;
+ }
+
+ // Record information about the newly started dispatch cycle.
+ dispatchEntry->inProgress = true;
+
+ connection->lastEventTime = dispatchEntry->eventEntry->eventTime;
+ connection->lastDispatchTime = currentTime;
+
+ nsecs_t timeout = dispatchEntry->timeout;
+ connection->nextTimeoutTime = (timeout >= 0) ? currentTime + timeout : LONG_LONG_MAX;
+
+ // Notify other system components.
+ onDispatchCycleStartedLocked(currentTime, connection);
+}
+
+void InputDispatcher::finishDispatchCycleLocked(nsecs_t currentTime, Connection* connection) {
+#if DEBUG_DISPATCH_CYCLE
+ LOGD("channel '%s' ~ finishDispatchCycle: %01.1fms since event, "
+ "%01.1fms since dispatch",
+ connection->getInputChannelName(),
+ connection->getEventLatencyMillis(currentTime),
+ connection->getDispatchLatencyMillis(currentTime));
+#endif
+
+ if (connection->status == Connection::STATUS_BROKEN) {
+ return;
+ }
+
+ // Clear the pending timeout.
+ connection->nextTimeoutTime = LONG_LONG_MAX;
+
+ if (connection->status == Connection::STATUS_NOT_RESPONDING) {
+ // Recovering from an ANR.
+ connection->status = Connection::STATUS_NORMAL;
+
+ // Notify other system components.
+ onDispatchCycleFinishedLocked(currentTime, connection, true /*recoveredFromANR*/);
+ } else {
+ // Normal finish. Not much to do here.
+
+ // Notify other system components.
+ onDispatchCycleFinishedLocked(currentTime, connection, false /*recoveredFromANR*/);
+ }
+
+ // 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);
+ abortDispatchCycleLocked(currentTime, connection, true /*broken*/);
+ return;
+ }
+
+ // Start the next dispatch cycle for this connection.
+ while (! connection->outboundQueue.isEmpty()) {
+ DispatchEntry* dispatchEntry = connection->outboundQueue.head.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();
+ 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 (due to ANR).
+ // So just start the next event for this connection.
+ startDispatchCycleLocked(currentTime, connection);
+ return;
+ }
+ }
+
+ // Outbound queue is empty, deactivate the connection.
+ deactivateConnectionLocked(connection);
+}
+
+bool InputDispatcher::timeoutDispatchCycleLocked(nsecs_t currentTime, Connection* connection) {
+#if DEBUG_DISPATCH_CYCLE
+ LOGD("channel '%s' ~ timeoutDispatchCycle",
+ connection->getInputChannelName());
+#endif
+
+ if (connection->status != Connection::STATUS_NORMAL) {
+ return false;
+ }
+
+ // Enter the not responding state.
+ connection->status = Connection::STATUS_NOT_RESPONDING;
+ connection->lastANRTime = currentTime;
+ bool deactivated = abortDispatchCycleLocked(currentTime, connection, false /*(not) broken*/);
+
+ // Notify other system components.
+ onDispatchCycleANRLocked(currentTime, connection);
+ return deactivated;
+}
+
+bool InputDispatcher::abortDispatchCycleLocked(nsecs_t currentTime, Connection* connection,
+ bool broken) {
+#if DEBUG_DISPATCH_CYCLE
+ LOGD("channel '%s' ~ abortDispatchCycle, broken=%s",
+ connection->getInputChannelName(), broken ? "true" : "false");
+#endif
+
+ if (connection->status == Connection::STATUS_BROKEN) {
+ return false;
+ }
+
+ // Clear the pending timeout.
+ connection->nextTimeoutTime = LONG_LONG_MAX;
+
+ // Clear the outbound queue.
+ while (! connection->outboundQueue.isEmpty()) {
+ DispatchEntry* dispatchEntry = connection->outboundQueue.dequeueAtHead();
+ mAllocator.releaseDispatchEntry(dispatchEntry);
+ }
+
+ // Outbound queue is empty, deactivate the connection.
+ deactivateConnectionLocked(connection);
+
+ // Handle the case where the connection appears to be unrecoverably broken.
+ if (broken) {
+ connection->status = Connection::STATUS_BROKEN;
+
+ // Notify other system components.
+ onDispatchCycleBrokenLocked(currentTime, connection);
+ }
+ return true; /*deactivated*/
+}
+
+bool 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 false; // remove the callback
+ }
+
+ nsecs_t currentTime = systemTime(SYSTEM_TIME_MONOTONIC);
+
+ sp<Connection> connection = d->mConnectionsByReceiveFd.valueAt(connectionIndex);
+ if (events & (POLLERR | POLLHUP | POLLNVAL)) {
+ LOGE("channel '%s' ~ Consumer closed input channel or an error occurred. "
+ "events=0x%x", connection->getInputChannelName(), events);
+ d->abortDispatchCycleLocked(currentTime, connection.get(), true /*broken*/);
+ return false; // remove the callback
+ }
+
+ if (! (events & POLLIN)) {
+ LOGW("channel '%s' ~ Received spurious callback for unhandled poll event. "
+ "events=0x%x", connection->getInputChannelName(), events);
+ return true;
+ }
+
+ status_t status = connection->inputPublisher.receiveFinishedSignal();
+ if (status) {
+ LOGE("channel '%s' ~ Failed to receive finished signal. status=%d",
+ connection->getInputChannelName(), status);
+ d->abortDispatchCycleLocked(currentTime, connection.get(), true /*broken*/);
+ return false; // remove the callback
+ }
+
+ d->finishDispatchCycleLocked(currentTime, connection.get());
+ return true;
+ } // release lock
+}
+
+void InputDispatcher::notifyConfigurationChanged(nsecs_t eventTime, int32_t touchScreenConfig,
+ int32_t keyboardConfig, int32_t navigationConfig) {
+#if DEBUG_INBOUND_EVENT_DETAILS
+ LOGD("notifyConfigurationChanged - eventTime=%lld, touchScreenConfig=%d, "
+ "keyboardConfig=%d, navigationConfig=%d", eventTime,
+ touchScreenConfig, keyboardConfig, navigationConfig);
+#endif
+
+ bool wasEmpty;
+ { // acquire lock
+ AutoMutex _l(mLock);
+
+ ConfigurationChangedEntry* newEntry = mAllocator.obtainConfigurationChangedEntry();
+ newEntry->eventTime = eventTime;
+ newEntry->touchScreenConfig = touchScreenConfig;
+ newEntry->keyboardConfig = keyboardConfig;
+ newEntry->navigationConfig = navigationConfig;
+
+ wasEmpty = mInboundQueue.isEmpty();
+ mInboundQueue.enqueueAtTail(newEntry);
+ } // release lock
+
+ if (wasEmpty) {
+ mPollLoop->wake();
+ }
+}
+
+void InputDispatcher::notifyLidSwitchChanged(nsecs_t eventTime, bool lidOpen) {
+#if DEBUG_INBOUND_EVENT_DETAILS
+ LOGD("notifyLidSwitchChanged - eventTime=%lld, open=%s", eventTime,
+ lidOpen ? "true" : "false");
+#endif
+
+ // Send lid switch notification immediately and synchronously.
+ mPolicy->notifyLidSwitchChanged(eventTime, lidOpen);
+}
+
+void InputDispatcher::notifyAppSwitchComing(nsecs_t eventTime) {
+#if DEBUG_INBOUND_EVENT_DETAILS
+ LOGD("notifyAppSwitchComing - eventTime=%lld", eventTime);
+#endif
+
+ // Remove movement keys from the queue from most recent to least recent, stopping at the
+ // first non-movement key.
+ // TODO: Include a detailed description of why we do this...
+
+ { // acquire lock
+ AutoMutex _l(mLock);
+
+ for (EventEntry* entry = mInboundQueue.tail.prev; entry != & mInboundQueue.head; ) {
+ EventEntry* prev = entry->prev;
+
+ if (entry->type == EventEntry::TYPE_KEY) {
+ KeyEntry* keyEntry = static_cast<KeyEntry*>(entry);
+ if (isMovementKey(keyEntry->keyCode)) {
+ LOGV("Dropping movement key during app switch: keyCode=%d, action=%d",
+ keyEntry->keyCode, keyEntry->action);
+ mInboundQueue.dequeue(keyEntry);
+ mAllocator.releaseKeyEntry(keyEntry);
+ } else {
+ // stop at last non-movement key
+ break;
+ }
+ }
+
+ entry = prev;
+ }
+ } // release lock
+}
+
+void InputDispatcher::notifyKey(nsecs_t eventTime, int32_t deviceId, int32_t nature,
+ 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=0x%x, nature=0x%x, policyFlags=0x%x, action=0x%x, "
+ "flags=0x%x, keyCode=0x%x, scanCode=0x%x, metaState=0x%x, downTime=%lld",
+ eventTime, deviceId, nature, policyFlags, action, flags,
+ keyCode, scanCode, metaState, downTime);
+#endif
+
+ bool wasEmpty;
+ { // acquire lock
+ AutoMutex _l(mLock);
+
+ KeyEntry* newEntry = mAllocator.obtainKeyEntry();
+ newEntry->eventTime = eventTime;
+ newEntry->deviceId = deviceId;
+ newEntry->nature = nature;
+ newEntry->policyFlags = policyFlags;
+ newEntry->action = action;
+ newEntry->flags = flags;
+ newEntry->keyCode = keyCode;
+ newEntry->scanCode = scanCode;
+ newEntry->metaState = metaState;
+ newEntry->repeatCount = 0;
+ newEntry->downTime = downTime;
+
+ wasEmpty = mInboundQueue.isEmpty();
+ mInboundQueue.enqueueAtTail(newEntry);
+ } // release lock
+
+ if (wasEmpty) {
+ mPollLoop->wake();
+ }
+}
+
+void InputDispatcher::notifyMotion(nsecs_t eventTime, int32_t deviceId, int32_t nature,
+ uint32_t policyFlags, int32_t action, 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=0x%x, nature=0x%x, policyFlags=0x%x, "
+ "action=0x%x, metaState=0x%x, edgeFlags=0x%x, xPrecision=%f, yPrecision=%f, "
+ "downTime=%lld",
+ eventTime, deviceId, nature, policyFlags, action, 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",
+ i, pointerIds[i], pointerCoords[i].x, pointerCoords[i].y,
+ pointerCoords[i].pressure, pointerCoords[i].size);
+ }
+#endif
+
+ bool wasEmpty;
+ { // acquire lock
+ AutoMutex _l(mLock);
+
+ // Attempt batching and streaming of move events.
+ if (action == MOTION_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.tail.prev;
+ entry != & mInboundQueue.head; 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 != MOTION_EVENT_ACTION_MOVE
+ || motionEntry->pointerCount != pointerCount) {
+ // 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 and exit.
+ mAllocator.appendMotionSample(motionEntry, eventTime, pointerCount, 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 queues for a synchronously dispatched motion event for this
+ // device. If found, then we append the new sample to that event and then try to
+ // push it out to all current targets. It is possible that some targets will already
+ // have consumed the motion event. This case is automatically handled by the
+ // logic in prepareDispatchCycleLocked by tracking where resumption takes place.
+ //
+ // The reason we look for a synchronously dispatched motion event is because we
+ // want to be sure that no other motion events have been dispatched since the move.
+ // It's also convenient because it means that the input targets are still valid.
+ // This code could be improved to support streaming of asynchronously dispatched
+ // motion events (which might be significantly more efficient) but it may become
+ // a little more complicated as a result.
+ //
+ // Note: This code crucially depends on the invariant that an outbound queue always
+ // contains at most one synchronous event and it is always last (but it might
+ // not be first!).
+ for (size_t i = 0; i < mActiveConnections.size(); i++) {
+ Connection* connection = mActiveConnections.itemAt(i);
+ if (! connection->outboundQueue.isEmpty()) {
+ DispatchEntry* dispatchEntry = connection->outboundQueue.tail.prev;
+ if (dispatchEntry->targetFlags & InputTarget::FLAG_SYNC) {
+ if (dispatchEntry->eventEntry->type != EventEntry::TYPE_MOTION) {
+ goto NoBatchingOrStreaming;
+ }
+
+ MotionEntry* syncedMotionEntry = static_cast<MotionEntry*>(
+ dispatchEntry->eventEntry);
+ if (syncedMotionEntry->action != MOTION_EVENT_ACTION_MOVE
+ || syncedMotionEntry->deviceId != deviceId
+ || syncedMotionEntry->pointerCount != pointerCount) {
+ goto NoBatchingOrStreaming;
+ }
+
+ // Found synced move entry. Append sample and resume dispatch.
+ mAllocator.appendMotionSample(syncedMotionEntry, eventTime,
+ pointerCount, pointerCoords);
+#if DEBUG_BATCHING
+ LOGD("Appended motion sample onto batch for most recent synchronously "
+ "dispatched motion event for this device in the outbound queues.");
+#endif
+ nsecs_t currentTime = systemTime(SYSTEM_TIME_MONOTONIC);
+ dispatchEventToCurrentInputTargetsLocked(currentTime, syncedMotionEntry,
+ true /*resumeWithAppendedMotionSample*/);
+ return; // done!
+ }
+ }
+ }
+
+NoBatchingOrStreaming:;
+ }
+
+ // Just enqueue a new motion event.
+ MotionEntry* newEntry = mAllocator.obtainMotionEntry();
+ newEntry->eventTime = eventTime;
+ newEntry->deviceId = deviceId;
+ newEntry->nature = nature;
+ newEntry->policyFlags = policyFlags;
+ newEntry->action = action;
+ newEntry->metaState = metaState;
+ newEntry->edgeFlags = edgeFlags;
+ newEntry->xPrecision = xPrecision;
+ newEntry->yPrecision = yPrecision;
+ newEntry->downTime = downTime;
+ newEntry->pointerCount = pointerCount;
+ newEntry->firstSample.eventTime = eventTime;
+ newEntry->lastSample = & newEntry->firstSample;
+ for (uint32_t i = 0; i < pointerCount; i++) {
+ newEntry->pointerIds[i] = pointerIds[i];
+ newEntry->firstSample.pointerCoords[i] = pointerCoords[i];
+ }
+
+ wasEmpty = mInboundQueue.isEmpty();
+ mInboundQueue.enqueueAtTail(newEntry);
+ } // release lock
+
+ if (wasEmpty) {
+ mPollLoop->wake();
+ }
+}
+
+void InputDispatcher::resetKeyRepeatLocked() {
+ if (mKeyRepeatState.lastKeyEntry) {
+ mAllocator.releaseKeyEntry(mKeyRepeatState.lastKeyEntry);
+ mKeyRepeatState.lastKeyEntry = NULL;
+ }
+}
+
+status_t InputDispatcher::registerInputChannel(const sp<InputChannel>& inputChannel) {
+ int receiveFd;
+ { // acquire lock
+ AutoMutex _l(mLock);
+
+ receiveFd = inputChannel->getReceivePipeFd();
+ if (mConnectionsByReceiveFd.indexOfKey(receiveFd) >= 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;
+ }
+
+ mConnectionsByReceiveFd.add(receiveFd, connection);
+ } // release lock
+
+ mPollLoop->setCallback(receiveFd, POLLIN, handleReceiveCallback, this);
+ return OK;
+}
+
+status_t InputDispatcher::unregisterInputChannel(const sp<InputChannel>& inputChannel) {
+ int32_t receiveFd;
+ { // acquire lock
+ AutoMutex _l(mLock);
+
+ receiveFd = inputChannel->getReceivePipeFd();
+ ssize_t connectionIndex = mConnectionsByReceiveFd.indexOfKey(receiveFd);
+ 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;
+
+ nsecs_t currentTime = systemTime(SYSTEM_TIME_MONOTONIC);
+ abortDispatchCycleLocked(currentTime, connection.get(), true /*broken*/);
+ } // release lock
+
+ mPollLoop->removeCallback(receiveFd);
+
+ // Wake the poll loop because removing the connection may have changed the current
+ // synchronization state.
+ mPollLoop->wake();
+ return OK;
+}
+
+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, Connection* connection) {
+}
+
+void InputDispatcher::onDispatchCycleFinishedLocked(nsecs_t currentTime,
+ Connection* connection, bool recoveredFromANR) {
+ if (recoveredFromANR) {
+ LOGI("channel '%s' ~ Recovered from ANR. %01.1fms since event, "
+ "%01.1fms since dispatch, %01.1fms since ANR",
+ connection->getInputChannelName(),
+ connection->getEventLatencyMillis(currentTime),
+ connection->getDispatchLatencyMillis(currentTime),
+ connection->getANRLatencyMillis(currentTime));
+
+ // TODO tell framework
+ }
+}
+
+void InputDispatcher::onDispatchCycleANRLocked(nsecs_t currentTime, Connection* connection) {
+ LOGI("channel '%s' ~ Not responding! %01.1fms since event, %01.1fms since dispatch",
+ connection->getInputChannelName(),
+ connection->getEventLatencyMillis(currentTime),
+ connection->getDispatchLatencyMillis(currentTime));
+
+ // TODO tell framework
+}
+
+void InputDispatcher::onDispatchCycleBrokenLocked(nsecs_t currentTime, Connection* connection) {
+ LOGE("channel '%s' ~ Channel is unrecoverably broken and will be disposed!",
+ connection->getInputChannelName());
+
+ // TODO tell framework
+}
+
+// --- InputDispatcher::Allocator ---
+
+InputDispatcher::Allocator::Allocator() {
+}
+
+InputDispatcher::ConfigurationChangedEntry*
+InputDispatcher::Allocator::obtainConfigurationChangedEntry() {
+ ConfigurationChangedEntry* entry = mConfigurationChangeEntryPool.alloc();
+ entry->refCount = 1;
+ entry->type = EventEntry::TYPE_CONFIGURATION_CHANGED;
+ return entry;
+}
+
+InputDispatcher::KeyEntry* InputDispatcher::Allocator::obtainKeyEntry() {
+ KeyEntry* entry = mKeyEntryPool.alloc();
+ entry->refCount = 1;
+ entry->type = EventEntry::TYPE_KEY;
+ return entry;
+}
+
+InputDispatcher::MotionEntry* InputDispatcher::Allocator::obtainMotionEntry() {
+ MotionEntry* entry = mMotionEntryPool.alloc();
+ entry->refCount = 1;
+ entry->type = EventEntry::TYPE_MOTION;
+ entry->firstSample.next = NULL;
+ return entry;
+}
+
+InputDispatcher::DispatchEntry* InputDispatcher::Allocator::obtainDispatchEntry(
+ EventEntry* eventEntry) {
+ DispatchEntry* entry = mDispatchEntryPool.alloc();
+ entry->eventEntry = eventEntry;
+ eventEntry->refCount += 1;
+ return entry;
+}
+
+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) {
+ mConfigurationChangeEntryPool.free(entry);
+ } else {
+ assert(entry->refCount > 0);
+ }
+}
+
+void InputDispatcher::Allocator::releaseKeyEntry(KeyEntry* entry) {
+ entry->refCount -= 1;
+ if (entry->refCount == 0) {
+ mKeyEntryPool.free(entry);
+ } else {
+ assert(entry->refCount > 0);
+ }
+}
+
+void InputDispatcher::Allocator::releaseMotionEntry(MotionEntry* entry) {
+ entry->refCount -= 1;
+ if (entry->refCount == 0) {
+ freeMotionSampleList(entry->firstSample.next);
+ mMotionEntryPool.free(entry);
+ } else {
+ assert(entry->refCount > 0);
+ }
+}
+
+void InputDispatcher::Allocator::releaseDispatchEntry(DispatchEntry* entry) {
+ releaseEventEntry(entry->eventEntry);
+ mDispatchEntryPool.free(entry);
+}
+
+void InputDispatcher::Allocator::appendMotionSample(MotionEntry* motionEntry,
+ nsecs_t eventTime, int32_t pointerCount, const PointerCoords* pointerCoords) {
+ MotionSample* sample = mMotionSamplePool.alloc();
+ sample->eventTime = eventTime;
+ for (int32_t i = 0; i < pointerCount; i++) {
+ sample->pointerCoords[i] = pointerCoords[i];
+ }
+
+ sample->next = NULL;
+ motionEntry->lastSample->next = sample;
+ motionEntry->lastSample = sample;
+}
+
+void InputDispatcher::Allocator::freeMotionSample(MotionSample* sample) {
+ mMotionSamplePool.free(sample);
+}
+
+void InputDispatcher::Allocator::freeMotionSampleList(MotionSample* head) {
+ while (head) {
+ MotionSample* next = head->next;
+ mMotionSamplePool.free(head);
+ head = next;
+ }
+}
+
+// --- InputDispatcher::Connection ---
+
+InputDispatcher::Connection::Connection(const sp<InputChannel>& inputChannel) :
+ status(STATUS_NORMAL), inputChannel(inputChannel), inputPublisher(inputChannel),
+ nextTimeoutTime(LONG_LONG_MAX),
+ lastEventTime(LONG_LONG_MAX), lastDispatchTime(LONG_LONG_MAX),
+ lastANRTime(LONG_LONG_MAX) {
+}
+
+InputDispatcher::Connection::~Connection() {
+}
+
+status_t InputDispatcher::Connection::initialize() {
+ return inputPublisher.initialize();
+}
+
+InputDispatcher::DispatchEntry* InputDispatcher::Connection::findQueuedDispatchEntryForEvent(
+ const EventEntry* eventEntry) const {
+ for (DispatchEntry* dispatchEntry = outboundQueue.tail.prev;
+ dispatchEntry != & outboundQueue.head; dispatchEntry = dispatchEntry->prev) {
+ if (dispatchEntry->eventEntry == eventEntry) {
+ return dispatchEntry;
+ }
+ }
+ 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
new file mode 100644
index 0000000..ab354a5
--- /dev/null
+++ b/libs/ui/InputManager.cpp
@@ -0,0 +1,114 @@
+//
+// 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<InputDispatchPolicyInterface>& policy) :
+ mEventHub(eventHub), mPolicy(policy) {
+ mDispatcher = new InputDispatcher(policy);
+ mReader = new InputReader(eventHub, policy, mDispatcher);
+
+ mDispatcherThread = new InputDispatcherThread(mDispatcher);
+ mReaderThread = new InputReaderThread(mReader);
+
+ configureExcludedDevices();
+}
+
+InputManager::~InputManager() {
+ stop();
+}
+
+void InputManager::configureExcludedDevices() {
+ Vector<String8> excludedDeviceNames;
+ mPolicy->getExcludedDeviceNames(excludedDeviceNames);
+
+ for (size_t i = 0; i < excludedDeviceNames.size(); i++) {
+ mEventHub->addExcludedDevice(excludedDeviceNames[i]);
+ }
+}
+
+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;
+}
+
+status_t InputManager::registerInputChannel(const sp<InputChannel>& inputChannel) {
+ return mDispatcher->registerInputChannel(inputChannel);
+}
+
+status_t InputManager::unregisterInputChannel(const sp<InputChannel>& inputChannel) {
+ return mDispatcher->unregisterInputChannel(inputChannel);
+}
+
+int32_t InputManager::getScanCodeState(int32_t deviceId, int32_t deviceClasses, int32_t scanCode)
+ const {
+ int32_t vkKeyCode, vkScanCode;
+ if (mReader->getCurrentVirtualKey(& vkKeyCode, & vkScanCode)) {
+ if (vkScanCode == scanCode) {
+ return KEY_STATE_VIRTUAL;
+ }
+ }
+
+ return mEventHub->getScanCodeState(deviceId, deviceClasses, scanCode);
+}
+
+int32_t InputManager::getKeyCodeState(int32_t deviceId, int32_t deviceClasses, int32_t keyCode)
+ const {
+ int32_t vkKeyCode, vkScanCode;
+ if (mReader->getCurrentVirtualKey(& vkKeyCode, & vkScanCode)) {
+ if (vkKeyCode == keyCode) {
+ return KEY_STATE_VIRTUAL;
+ }
+ }
+
+ return mEventHub->getKeyCodeState(deviceId, deviceClasses, keyCode);
+}
+
+int32_t InputManager::getSwitchState(int32_t deviceId, int32_t deviceClasses, int32_t sw) const {
+ return mEventHub->getSwitchState(deviceId, deviceClasses, sw);
+}
+
+bool InputManager::hasKeys(size_t numCodes, const int32_t* keyCodes, uint8_t* outFlags) const {
+ return mEventHub->hasKeys(numCodes, keyCodes, outFlags);
+}
+
+} // namespace android
diff --git a/libs/ui/InputReader.cpp b/libs/ui/InputReader.cpp
new file mode 100644
index 0000000..796abd0
--- /dev/null
+++ b/libs/ui/InputReader.cpp
@@ -0,0 +1,1843 @@
+//
+// 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 1
+
+// Log debug messages about virtual key processing.
+#define DEBUG_VIRTUAL_KEYS 1
+
+// Log debug messages about pointers.
+#define DEBUG_POINTERS 1
+
+#include <cutils/log.h>
+#include <ui/InputReader.h>
+
+#include <stddef.h>
+#include <unistd.h>
+#include <errno.h>
+#include <limits.h>
+
+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;
+}
+
+int32_t updateMetaState(int32_t keyCode, bool down, int32_t oldMetaState) {
+ int32_t mask;
+ switch (keyCode) {
+ case KEYCODE_ALT_LEFT:
+ mask = META_ALT_LEFT_ON;
+ break;
+ case KEYCODE_ALT_RIGHT:
+ mask = META_ALT_RIGHT_ON;
+ break;
+ case KEYCODE_SHIFT_LEFT:
+ mask = META_SHIFT_LEFT_ON;
+ break;
+ case KEYCODE_SHIFT_RIGHT:
+ mask = META_SHIFT_RIGHT_ON;
+ break;
+ case KEYCODE_SYM:
+ mask = META_SYM_ON;
+ break;
+ default:
+ return oldMetaState;
+ }
+
+ int32_t newMetaState = down ? oldMetaState | mask : oldMetaState & ~ mask
+ & ~ (META_ALT_ON | META_SHIFT_ON);
+
+ if (newMetaState & (META_ALT_LEFT_ON | META_ALT_RIGHT_ON)) {
+ newMetaState |= META_ALT_ON;
+ }
+
+ if (newMetaState & (META_SHIFT_LEFT_ON | META_SHIFT_RIGHT_ON)) {
+ newMetaState |= META_SHIFT_ON;
+ }
+
+ return newMetaState;
+}
+
+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
+ { KEYCODE_DPAD_DOWN, KEYCODE_DPAD_RIGHT, KEYCODE_DPAD_UP, KEYCODE_DPAD_LEFT },
+ { KEYCODE_DPAD_RIGHT, KEYCODE_DPAD_UP, KEYCODE_DPAD_LEFT, KEYCODE_DPAD_DOWN },
+ { KEYCODE_DPAD_UP, KEYCODE_DPAD_LEFT, KEYCODE_DPAD_DOWN, KEYCODE_DPAD_RIGHT },
+ { KEYCODE_DPAD_LEFT, KEYCODE_DPAD_DOWN, KEYCODE_DPAD_RIGHT, KEYCODE_DPAD_UP },
+};
+static const int keyCodeRotationMapSize =
+ sizeof(keyCodeRotationMap) / sizeof(keyCodeRotationMap[0]);
+
+int32_t rotateKeyCode(int32_t keyCode, int32_t orientation) {
+ if (orientation != InputDispatchPolicyInterface::ROTATION_0) {
+ for (int i = 0; i < keyCodeRotationMapSize; i++) {
+ if (keyCode == keyCodeRotationMap[i][0]) {
+ return keyCodeRotationMap[i][orientation];
+ }
+ }
+ }
+ return keyCode;
+}
+
+
+// --- InputDevice ---
+
+InputDevice::InputDevice(int32_t id, uint32_t classes, String8 name) :
+ id(id), classes(classes), name(name), ignored(false) {
+}
+
+void InputDevice::reset() {
+ if (isKeyboard()) {
+ keyboard.reset();
+ }
+
+ if (isTrackball()) {
+ trackball.reset();
+ }
+
+ if (isMultiTouchScreen()) {
+ multiTouchScreen.reset();
+ } else if (isSingleTouchScreen()) {
+ singleTouchScreen.reset();
+ }
+
+ if (isTouchScreen()) {
+ touchScreen.reset();
+ }
+}
+
+
+// --- InputDevice::TouchData ---
+
+void InputDevice::TouchData::copyFrom(const TouchData& other) {
+ pointerCount = other.pointerCount;
+ idBits = other.idBits;
+
+ for (uint32_t i = 0; i < pointerCount; i++) {
+ pointers[i] = other.pointers[i];
+ idToIndex[i] = other.idToIndex[i];
+ }
+}
+
+
+// --- InputDevice::KeyboardState ---
+
+void InputDevice::KeyboardState::reset() {
+ current.metaState = META_NONE;
+ current.downTime = 0;
+}
+
+
+// --- InputDevice::TrackballState ---
+
+void InputDevice::TrackballState::reset() {
+ accumulator.clear();
+ current.down = false;
+ current.downTime = 0;
+}
+
+
+// --- InputDevice::TouchScreenState ---
+
+void InputDevice::TouchScreenState::reset() {
+ lastTouch.clear();
+ downTime = 0;
+ currentVirtualKey.down = false;
+
+ for (uint32_t i = 0; i < MAX_POINTERS; i++) {
+ averagingTouchFilter.historyStart[i] = 0;
+ averagingTouchFilter.historyEnd[i] = 0;
+ }
+
+ jumpyTouchFilter.jumpyPointsDropped = 0;
+}
+
+void InputDevice::TouchScreenState::calculatePointerIds() {
+ uint32_t currentPointerCount = currentTouch.pointerCount;
+ uint32_t lastPointerCount = lastTouch.pointerCount;
+
+ if (currentPointerCount == 0) {
+ // No pointers to assign.
+ currentTouch.idBits.clear();
+ } else if (lastPointerCount == 0) {
+ // All pointers are new.
+ currentTouch.idBits.clear();
+ for (uint32_t i = 0; i < currentPointerCount; i++) {
+ currentTouch.pointers[i].id = i;
+ currentTouch.idToIndex[i] = i;
+ currentTouch.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 = lastTouch.pointers[0].id;
+ currentTouch.pointers[0].id = id;
+ currentTouch.idToIndex[id] = 0;
+ currentTouch.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.
+ struct {
+ uint32_t currentPointerIndex : 8;
+ uint32_t lastPointerIndex : 8;
+ uint64_t distance : 48; // squared distance
+ } 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 = currentTouch.pointers[currentPointerIndex].x
+ - lastTouch.pointers[lastPointerIndex].x;
+ int64_t deltaY = currentTouch.pointers[currentPointerIndex].y
+ - lastTouch.pointers[lastPointerIndex].y;
+
+ uint64_t distance = uint64_t(deltaX * deltaX + deltaY * deltaY);
+
+ // Insert new element into the heap (sift up).
+ heapSize += 1;
+ uint32_t insertionIndex = heapSize;
+ while (insertionIndex > 1) {
+ uint32_t parentIndex = (insertionIndex - 1) / 2;
+ if (distance < heap[parentIndex].distance) {
+ heap[insertionIndex] = heap[parentIndex];
+ insertionIndex = parentIndex;
+ } else {
+ break;
+ }
+ }
+ heap[insertionIndex].currentPointerIndex = currentPointerIndex;
+ heap[insertionIndex].lastPointerIndex = lastPointerIndex;
+ heap[insertionIndex].distance = distance;
+ }
+ }
+
+ // 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 smalled 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 to find where the element at index heapSize needs to be moved.
+ uint32_t rootIndex = 0;
+ for (;;) {
+ uint32_t childIndex = rootIndex * 2 + 1;
+ if (childIndex >= heapSize) {
+ break;
+ }
+
+ if (childIndex + 1 < heapSize
+ && heap[childIndex + 1].distance < heap[childIndex].distance) {
+ childIndex += 1;
+ }
+
+ if (heap[heapSize].distance < heap[childIndex].distance) {
+ break;
+ }
+
+ heap[rootIndex] = heap[childIndex];
+ rootIndex = childIndex;
+ }
+ heap[rootIndex] = heap[heapSize];
+ }
+
+ 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 = lastTouch.pointers[lastPointerIndex].id;
+ currentTouch.pointers[currentPointerIndex].id = id;
+ currentTouch.idToIndex[id] = currentPointerIndex;
+ usedIdBits.markBit(id);
+ 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();
+
+ currentTouch.pointers[currentPointerIndex].id = id;
+ currentTouch.idToIndex[id] = currentPointerIndex;
+ usedIdBits.markBit(id);
+
+ if (--i == 0) break; // done
+ matchedCurrentBits.markBit(currentPointerIndex);
+ }
+ }
+
+ // Fix id bits.
+ currentTouch.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 InputDevice::TouchScreenState::applyBadTouchFilter() {
+ uint32_t pointerCount = currentTouch.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 != lastTouch.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 = parameters.yAxis.range * 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 = currentTouch.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 = lastTouch.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
+
+ currentTouch.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 InputDevice::TouchScreenState::applyJumpyTouchFilter() {
+ uint32_t pointerCount = currentTouch.pointerCount;
+ if (lastTouch.pointerCount != pointerCount) {
+#if DEBUG_HACKS
+ LOGD("JumpyTouchFilter: Different pointer count %d -> %d",
+ lastTouch.pointerCount, pointerCount);
+ for (uint32_t i = 0; i < pointerCount; i++) {
+ LOGD(" Pointer %d (%d, %d)", i,
+ currentTouch.pointers[i].x, currentTouch.pointers[i].y);
+ }
+#endif
+
+ if (jumpyTouchFilter.jumpyPointsDropped < JUMPY_TRANSITION_DROPS) {
+ if (lastTouch.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.
+ currentTouch.pointerCount = 1;
+ jumpyTouchFilter.jumpyPointsDropped += 1;
+
+#if DEBUG_HACKS
+ LOGD("JumpyTouchFilter: Pointer 2 dropped");
+#endif
+ return true;
+ } else if (lastTouch.pointerCount == 2 && pointerCount == 1) {
+ // The event when we go from 2 -> 1 tends to be messed up too
+ currentTouch.pointerCount = 2;
+ currentTouch.pointers[0] = lastTouch.pointers[0];
+ currentTouch.pointers[1] = lastTouch.pointers[1];
+ jumpyTouchFilter.jumpyPointsDropped += 1;
+
+#if DEBUG_HACKS
+ for (int32_t i = 0; i < 2; i++) {
+ LOGD("JumpyTouchFilter: Pointer %d replaced (%d, %d)", i,
+ currentTouch.pointers[i].x, currentTouch.pointers[i].y);
+ }
+#endif
+ return true;
+ }
+ }
+ // Reset jumpy points dropped on other transitions or if limit exceeded.
+ jumpyTouchFilter.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 (jumpyTouchFilter.jumpyPointsDropped < JUMPY_DROP_LIMIT) {
+ int jumpyEpsilon = parameters.yAxis.range / 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 = currentTouch.pointers[i].x;
+ int32_t y = currentTouch.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 - currentTouch.pointers[j].x) <= jumpyEpsilon) {
+ dropX = true;
+ break;
+ }
+
+ if (abs(y - currentTouch.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 - lastTouch.pointers[j].y);
+ if (deltaY < smallestDeltaY) {
+ smallestDeltaY = deltaY;
+ replacementIndex = j;
+ }
+ }
+ distance = abs(x - lastTouch.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 - lastTouch.pointers[j].x);
+ if (deltaX < smallestDeltaX) {
+ smallestDeltaX = deltaX;
+ replacementIndex = j;
+ }
+ }
+ distance = abs(y - lastTouch.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,
+ lastTouch.pointers[badPointerReplacementIndex].x,
+ lastTouch.pointers[badPointerReplacementIndex].y);
+#endif
+
+ currentTouch.pointers[badPointerIndex].x =
+ lastTouch.pointers[badPointerReplacementIndex].x;
+ currentTouch.pointers[badPointerIndex].y =
+ lastTouch.pointers[badPointerReplacementIndex].y;
+ jumpyTouchFilter.jumpyPointsDropped += 1;
+ return true;
+ }
+ }
+
+ jumpyTouchFilter.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 InputDevice::TouchScreenState::applyAveragingTouchFilter() {
+ for (uint32_t currentIndex = 0; currentIndex < currentTouch.pointerCount; currentIndex++) {
+ uint32_t id = currentTouch.pointers[currentIndex].id;
+ int32_t x = currentTouch.pointers[currentIndex].x;
+ int32_t y = currentTouch.pointers[currentIndex].y;
+ int32_t pressure = currentTouch.pointers[currentIndex].pressure;
+
+ if (lastTouch.idBits.hasBit(id)) {
+ // Pointer still down compute average.
+ uint32_t start = averagingTouchFilter.historyStart[id];
+ uint32_t end = averagingTouchFilter.historyEnd[id];
+
+ int64_t deltaX = x - averagingTouchFilter.historyData[end].pointers[id].x;
+ int64_t deltaY = y - averagingTouchFilter.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) {
+ end += 1;
+ if (end > AVERAGING_HISTORY_SIZE) {
+ end = 0;
+ }
+
+ if (end == start) {
+ start += 1;
+ if (start > AVERAGING_HISTORY_SIZE) {
+ start = 0;
+ }
+ }
+
+ averagingTouchFilter.historyStart[id] = start;
+ averagingTouchFilter.historyEnd[id] = end;
+ averagingTouchFilter.historyData[end].pointers[id].x = x;
+ averagingTouchFilter.historyData[end].pointers[id].y = y;
+ averagingTouchFilter.historyData[end].pointers[id].pressure = pressure;
+
+ int32_t averagedX = 0;
+ int32_t averagedY = 0;
+ int32_t totalPressure = 0;
+ for (;;) {
+ int32_t historicalX = averagingTouchFilter.historyData[start].pointers[id].x;
+ int32_t historicalY = averagingTouchFilter.historyData[start].pointers[id].x;
+ int32_t historicalPressure = averagingTouchFilter.historyData[start]
+ .pointers[id].pressure;
+
+ averagedX += historicalX;
+ averagedY += historicalY;
+ totalPressure += historicalPressure;
+
+ if (start == end) {
+ break;
+ }
+
+ start += 1;
+ if (start > AVERAGING_HISTORY_SIZE) {
+ start = 0;
+ }
+ }
+
+ averagedX /= totalPressure;
+ averagedY /= totalPressure;
+
+#if DEBUG_HACKS
+ LOGD("AveragingTouchFilter: Pointer id %d - "
+ "totalPressure=%d, averagedX=%d, averagedY=%d", id, totalPressure,
+ averagedX, averagedY);
+#endif
+
+ currentTouch.pointers[currentIndex].x = averagedX;
+ currentTouch.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.
+ averagingTouchFilter.historyStart[id] = 0;
+ averagingTouchFilter.historyEnd[id] = 0;
+ averagingTouchFilter.historyData[0].pointers[id].x = x;
+ averagingTouchFilter.historyData[0].pointers[id].y = y;
+ averagingTouchFilter.historyData[0].pointers[id].pressure = pressure;
+ }
+}
+
+bool InputDevice::TouchScreenState::isPointInsideDisplay(int32_t x, int32_t y) const {
+ return x >= parameters.xAxis.minValue
+ && x <= parameters.xAxis.maxValue
+ && y >= parameters.yAxis.minValue
+ && y <= parameters.yAxis.maxValue;
+}
+
+
+// --- InputDevice::SingleTouchScreenState ---
+
+void InputDevice::SingleTouchScreenState::reset() {
+ accumulator.clear();
+ current.down = false;
+ current.x = 0;
+ current.y = 0;
+ current.pressure = 0;
+ current.size = 0;
+}
+
+
+// --- InputDevice::MultiTouchScreenState ---
+
+void InputDevice::MultiTouchScreenState::reset() {
+ accumulator.clear();
+}
+
+
+// --- InputReader ---
+
+InputReader::InputReader(const sp<EventHubInterface>& eventHub,
+ const sp<InputDispatchPolicyInterface>& policy,
+ const sp<InputDispatcherInterface>& dispatcher) :
+ mEventHub(eventHub), mPolicy(policy), mDispatcher(dispatcher) {
+ resetGlobalMetaState();
+ resetDisplayProperties();
+ updateGlobalVirtualKeyState();
+}
+
+InputReader::~InputReader() {
+ for (size_t i = 0; i < mDevices.size(); i++) {
+ delete mDevices.valueAt(i);
+ }
+}
+
+void InputReader::loopOnce() {
+ RawEvent rawEvent;
+ mEventHub->getEvent(& rawEvent.deviceId, & rawEvent.type, & rawEvent.scanCode,
+ & rawEvent.keyCode, & rawEvent.flags, & rawEvent.value, & rawEvent.when);
+
+ // Replace the event timestamp so it is in same timebase as java.lang.System.nanoTime()
+ // and android.os.SystemClock.uptimeMillis() as expected by the rest of the system.
+ rawEvent.when = systemTime(SYSTEM_TIME_MONOTONIC);
+
+#if DEBUG_RAW_EVENTS
+ LOGD("Input event: device=0x%x 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:
+ handleDeviceAdded(rawEvent);
+ break;
+
+ case EventHubInterface::DEVICE_REMOVED:
+ handleDeviceRemoved(rawEvent);
+ break;
+
+ case EV_SYN:
+ handleSync(rawEvent);
+ break;
+
+ case EV_KEY:
+ handleKey(rawEvent);
+ break;
+
+ case EV_REL:
+ handleRelativeMotion(rawEvent);
+ break;
+
+ case EV_ABS:
+ handleAbsoluteMotion(rawEvent);
+ break;
+
+ case EV_SW:
+ handleSwitch(rawEvent);
+ break;
+ }
+}
+
+void InputReader::handleDeviceAdded(const RawEvent* rawEvent) {
+ InputDevice* device = getDevice(rawEvent->deviceId);
+ if (device) {
+ LOGW("Ignoring spurious device added event for deviceId %d.", rawEvent->deviceId);
+ return;
+ }
+
+ addDevice(rawEvent->when, rawEvent->deviceId);
+}
+
+void InputReader::handleDeviceRemoved(const RawEvent* rawEvent) {
+ InputDevice* device = getDevice(rawEvent->deviceId);
+ if (! device) {
+ LOGW("Ignoring spurious device removed event for deviceId %d.", rawEvent->deviceId);
+ return;
+ }
+
+ removeDevice(rawEvent->when, device);
+}
+
+void InputReader::handleSync(const RawEvent* rawEvent) {
+ InputDevice* device = getNonIgnoredDevice(rawEvent->deviceId);
+ if (! device) return;
+
+ if (rawEvent->scanCode == SYN_MT_REPORT) {
+ // MultiTouch Sync: The driver has returned all data for *one* of the pointers.
+ // We drop pointers with pressure <= 0 since that indicates they are not down.
+ if (device->isMultiTouchScreen()) {
+ uint32_t pointerIndex = device->multiTouchScreen.accumulator.pointerCount;
+
+ if (device->multiTouchScreen.accumulator.pointers[pointerIndex].fields) {
+ if (pointerIndex == MAX_POINTERS) {
+ LOGW("MultiTouch device driver returned more than maximum of %d pointers.",
+ MAX_POINTERS);
+ } else {
+ pointerIndex += 1;
+ device->multiTouchScreen.accumulator.pointerCount = pointerIndex;
+ }
+ }
+
+ device->multiTouchScreen.accumulator.pointers[pointerIndex].clear();
+ }
+ } else if (rawEvent->scanCode == SYN_REPORT) {
+ // General Sync: The driver has returned all data for the current event update.
+ if (device->isMultiTouchScreen()) {
+ if (device->multiTouchScreen.accumulator.isDirty()) {
+ onMultiTouchScreenStateChanged(rawEvent->when, device);
+ device->multiTouchScreen.accumulator.clear();
+ }
+ } else if (device->isSingleTouchScreen()) {
+ if (device->singleTouchScreen.accumulator.isDirty()) {
+ onSingleTouchScreenStateChanged(rawEvent->when, device);
+ device->singleTouchScreen.accumulator.clear();
+ }
+ }
+
+ if (device->trackball.accumulator.isDirty()) {
+ onTrackballStateChanged(rawEvent->when, device);
+ device->trackball.accumulator.clear();
+ }
+ }
+}
+
+void InputReader::handleKey(const RawEvent* rawEvent) {
+ InputDevice* device = getNonIgnoredDevice(rawEvent->deviceId);
+ if (! device) return;
+
+ bool down = rawEvent->value != 0;
+ int32_t scanCode = rawEvent->scanCode;
+
+ if (device->isKeyboard() && (scanCode < BTN_FIRST || scanCode > BTN_LAST)) {
+ int32_t keyCode = rawEvent->keyCode;
+ onKey(rawEvent->when, device, down, keyCode, scanCode, rawEvent->flags);
+ } else if (device->isSingleTouchScreen()) {
+ switch (rawEvent->scanCode) {
+ case BTN_TOUCH:
+ device->singleTouchScreen.accumulator.fields |=
+ InputDevice::SingleTouchScreenState::Accumulator::FIELD_BTN_TOUCH;
+ device->singleTouchScreen.accumulator.btnTouch = down;
+ break;
+ }
+ } else if (device->isTrackball()) {
+ switch (rawEvent->scanCode) {
+ case BTN_MOUSE:
+ device->trackball.accumulator.fields |=
+ InputDevice::TrackballState::Accumulator::FIELD_BTN_MOUSE;
+ device->trackball.accumulator.btnMouse = down;
+
+ // send the down immediately
+ // XXX this emulates the old behavior of KeyInputQueue, unclear whether it is
+ // necessary or if we can wait until the next sync
+ onTrackballStateChanged(rawEvent->when, device);
+ device->trackball.accumulator.clear();
+ break;
+ }
+ }
+}
+
+void InputReader::handleRelativeMotion(const RawEvent* rawEvent) {
+ InputDevice* device = getNonIgnoredDevice(rawEvent->deviceId);
+ if (! device) return;
+
+ if (device->isTrackball()) {
+ switch (rawEvent->scanCode) {
+ case REL_X:
+ device->trackball.accumulator.fields |=
+ InputDevice::TrackballState::Accumulator::FIELD_REL_X;
+ device->trackball.accumulator.relX = rawEvent->value;
+ break;
+ case REL_Y:
+ device->trackball.accumulator.fields |=
+ InputDevice::TrackballState::Accumulator::FIELD_REL_Y;
+ device->trackball.accumulator.relY = rawEvent->value;
+ break;
+ }
+ }
+}
+
+void InputReader::handleAbsoluteMotion(const RawEvent* rawEvent) {
+ InputDevice* device = getNonIgnoredDevice(rawEvent->deviceId);
+ if (! device) return;
+
+ if (device->isMultiTouchScreen()) {
+ uint32_t pointerIndex = device->multiTouchScreen.accumulator.pointerCount;
+ InputDevice::MultiTouchScreenState::Accumulator::Pointer* pointer =
+ & device->multiTouchScreen.accumulator.pointers[pointerIndex];
+
+ switch (rawEvent->scanCode) {
+ case ABS_MT_POSITION_X:
+ pointer->fields |=
+ InputDevice::MultiTouchScreenState::Accumulator::FIELD_ABS_MT_POSITION_X;
+ pointer->absMTPositionX = rawEvent->value;
+ break;
+ case ABS_MT_POSITION_Y:
+ pointer->fields |=
+ InputDevice::MultiTouchScreenState::Accumulator::FIELD_ABS_MT_POSITION_Y;
+ pointer->absMTPositionY = rawEvent->value;
+ break;
+ case ABS_MT_TOUCH_MAJOR:
+ pointer->fields |=
+ InputDevice::MultiTouchScreenState::Accumulator::FIELD_ABS_MT_TOUCH_MAJOR;
+ pointer->absMTTouchMajor = rawEvent->value;
+ break;
+ case ABS_MT_WIDTH_MAJOR:
+ pointer->fields |=
+ InputDevice::MultiTouchScreenState::Accumulator::FIELD_ABS_MT_WIDTH_MAJOR;
+ pointer->absMTWidthMajor = rawEvent->value;
+ break;
+ case ABS_MT_TRACKING_ID:
+ pointer->fields |=
+ InputDevice::MultiTouchScreenState::Accumulator::FIELD_ABS_MT_TRACKING_ID;
+ pointer->absMTTrackingId = rawEvent->value;
+ break;
+ }
+ } else if (device->isSingleTouchScreen()) {
+ switch (rawEvent->scanCode) {
+ case ABS_X:
+ device->singleTouchScreen.accumulator.fields |=
+ InputDevice::SingleTouchScreenState::Accumulator::FIELD_ABS_X;
+ device->singleTouchScreen.accumulator.absX = rawEvent->value;
+ break;
+ case ABS_Y:
+ device->singleTouchScreen.accumulator.fields |=
+ InputDevice::SingleTouchScreenState::Accumulator::FIELD_ABS_Y;
+ device->singleTouchScreen.accumulator.absY = rawEvent->value;
+ break;
+ case ABS_PRESSURE:
+ device->singleTouchScreen.accumulator.fields |=
+ InputDevice::SingleTouchScreenState::Accumulator::FIELD_ABS_PRESSURE;
+ device->singleTouchScreen.accumulator.absPressure = rawEvent->value;
+ break;
+ case ABS_TOOL_WIDTH:
+ device->singleTouchScreen.accumulator.fields |=
+ InputDevice::SingleTouchScreenState::Accumulator::FIELD_ABS_TOOL_WIDTH;
+ device->singleTouchScreen.accumulator.absToolWidth = rawEvent->value;
+ break;
+ }
+ }
+}
+
+void InputReader::handleSwitch(const RawEvent* rawEvent) {
+ InputDevice* device = getNonIgnoredDevice(rawEvent->deviceId);
+ if (! device) return;
+
+ onSwitch(rawEvent->when, device, rawEvent->value != 0, rawEvent->scanCode);
+}
+
+void InputReader::onKey(nsecs_t when, InputDevice* device,
+ bool down, int32_t keyCode, int32_t scanCode, uint32_t policyFlags) {
+ /* Refresh display properties so we can rotate key codes according to display orientation */
+
+ if (! refreshDisplayProperties()) {
+ return;
+ }
+
+ /* Update device state */
+
+ int32_t oldMetaState = device->keyboard.current.metaState;
+ int32_t newMetaState = updateMetaState(keyCode, down, oldMetaState);
+ if (oldMetaState != newMetaState) {
+ device->keyboard.current.metaState = newMetaState;
+ resetGlobalMetaState();
+ }
+
+ // FIXME if we send a down event about a rotated key press we should ensure that we send
+ // a corresponding up event about the rotated key press even if the orientation
+ // has changed in the meantime
+ keyCode = rotateKeyCode(keyCode, mDisplayOrientation);
+
+ if (down) {
+ device->keyboard.current.downTime = when;
+ }
+
+ /* Apply policy */
+
+ int32_t policyActions = mPolicy->interceptKey(when, device->id,
+ down, keyCode, scanCode, policyFlags);
+
+ if (! applyStandardInputDispatchPolicyActions(when, policyActions, & policyFlags)) {
+ return; // event dropped
+ }
+
+ /* Enqueue key event for dispatch */
+
+ int32_t keyEventAction;
+ if (down) {
+ device->keyboard.current.downTime = when;
+ keyEventAction = KEY_EVENT_ACTION_DOWN;
+ } else {
+ keyEventAction = KEY_EVENT_ACTION_UP;
+ }
+
+ int32_t keyEventFlags = KEY_EVENT_FLAG_FROM_SYSTEM;
+ if (policyActions & InputDispatchPolicyInterface::ACTION_WOKE_HERE) {
+ keyEventFlags = keyEventFlags | KEY_EVENT_FLAG_WOKE_HERE;
+ }
+
+ mDispatcher->notifyKey(when, device->id, INPUT_EVENT_NATURE_KEY, policyFlags,
+ keyEventAction, keyEventFlags, keyCode, scanCode,
+ device->keyboard.current.metaState,
+ device->keyboard.current.downTime);
+}
+
+void InputReader::onSwitch(nsecs_t when, InputDevice* device, bool down,
+ int32_t code) {
+ switch (code) {
+ case SW_LID:
+ mDispatcher->notifyLidSwitchChanged(when, ! down);
+ }
+}
+
+void InputReader::onMultiTouchScreenStateChanged(nsecs_t when,
+ InputDevice* device) {
+ static const uint32_t REQUIRED_FIELDS =
+ InputDevice::MultiTouchScreenState::Accumulator::FIELD_ABS_MT_POSITION_X
+ | InputDevice::MultiTouchScreenState::Accumulator::FIELD_ABS_MT_POSITION_Y
+ | InputDevice::MultiTouchScreenState::Accumulator::FIELD_ABS_MT_TOUCH_MAJOR
+ | InputDevice::MultiTouchScreenState::Accumulator::FIELD_ABS_MT_WIDTH_MAJOR;
+
+ /* Refresh display properties so we can map touch screen coords into display coords */
+
+ if (! refreshDisplayProperties()) {
+ return;
+ }
+
+ /* Update device state */
+
+ InputDevice::MultiTouchScreenState* in = & device->multiTouchScreen;
+ InputDevice::TouchData* out = & device->touchScreen.currentTouch;
+
+ uint32_t inCount = in->accumulator.pointerCount;
+ uint32_t outCount = 0;
+ bool havePointerIds = true;
+
+ out->clear();
+
+ for (uint32_t inIndex = 0; inIndex < inCount; inIndex++) {
+ uint32_t fields = in->accumulator.pointers[inIndex].fields;
+
+ if ((fields & REQUIRED_FIELDS) != REQUIRED_FIELDS) {
+#if DEBUG_POINTERS
+ LOGD("Pointers: Missing required multitouch pointer fields: index=%d, fields=%d",
+ inIndex, fields);
+ continue;
+#endif
+ }
+
+ if (in->accumulator.pointers[inIndex].absMTTouchMajor <= 0) {
+ // Pointer is not down. Drop it.
+ continue;
+ }
+
+ // FIXME assignment of pressure may be incorrect, probably better to let
+ // pressure = touch / width. Later on we pass width to MotionEvent as a size, which
+ // isn't quite right either. Should be using touch for that.
+ out->pointers[outCount].x = in->accumulator.pointers[inIndex].absMTPositionX;
+ out->pointers[outCount].y = in->accumulator.pointers[inIndex].absMTPositionY;
+ out->pointers[outCount].pressure = in->accumulator.pointers[inIndex].absMTTouchMajor;
+ out->pointers[outCount].size = in->accumulator.pointers[inIndex].absMTWidthMajor;
+
+ if (havePointerIds) {
+ if (fields & InputDevice::MultiTouchScreenState::Accumulator::
+ FIELD_ABS_MT_TRACKING_ID) {
+ uint32_t id = uint32_t(in->accumulator.pointers[inIndex].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 for optimizations",
+ id, MAX_POINTER_ID);
+#endif
+ havePointerIds = false;
+ }
+ else {
+ out->pointers[outCount].id = id;
+ out->idToIndex[id] = outCount;
+ out->idBits.markBit(id);
+ }
+ } else {
+ havePointerIds = false;
+ }
+ }
+
+ outCount += 1;
+ }
+
+ out->pointerCount = outCount;
+
+ onTouchScreenChanged(when, device, havePointerIds);
+}
+
+void InputReader::onSingleTouchScreenStateChanged(nsecs_t when,
+ InputDevice* device) {
+ static const uint32_t POSITION_FIELDS =
+ InputDevice::SingleTouchScreenState::Accumulator::FIELD_ABS_X
+ | InputDevice::SingleTouchScreenState::Accumulator::FIELD_ABS_Y
+ | InputDevice::SingleTouchScreenState::Accumulator::FIELD_ABS_PRESSURE
+ | InputDevice::SingleTouchScreenState::Accumulator::FIELD_ABS_TOOL_WIDTH;
+
+ /* Refresh display properties so we can map touch screen coords into display coords */
+
+ if (! refreshDisplayProperties()) {
+ return;
+ }
+
+ /* Update device state */
+
+ InputDevice::SingleTouchScreenState* in = & device->singleTouchScreen;
+ InputDevice::TouchData* out = & device->touchScreen.currentTouch;
+
+ uint32_t fields = in->accumulator.fields;
+
+ if (fields & InputDevice::SingleTouchScreenState::Accumulator::FIELD_BTN_TOUCH) {
+ in->current.down = in->accumulator.btnTouch;
+ }
+
+ if ((fields & POSITION_FIELDS) == POSITION_FIELDS) {
+ in->current.x = in->accumulator.absX;
+ in->current.y = in->accumulator.absY;
+ in->current.pressure = in->accumulator.absPressure;
+ in->current.size = in->accumulator.absToolWidth;
+ }
+
+ out->clear();
+
+ if (in->current.down) {
+ out->pointerCount = 1;
+ out->pointers[0].id = 0;
+ out->pointers[0].x = in->current.x;
+ out->pointers[0].y = in->current.y;
+ out->pointers[0].pressure = in->current.pressure;
+ out->pointers[0].size = in->current.size;
+ out->idToIndex[0] = 0;
+ out->idBits.markBit(0);
+ }
+
+ onTouchScreenChanged(when, device, true);
+}
+
+void InputReader::onTouchScreenChanged(nsecs_t when,
+ InputDevice* device, bool havePointerIds) {
+ /* Apply policy */
+
+ int32_t policyActions = mPolicy->interceptTouch(when);
+
+ uint32_t policyFlags = 0;
+ if (! applyStandardInputDispatchPolicyActions(when, policyActions, & policyFlags)) {
+ device->touchScreen.lastTouch.clear();
+ return; // event dropped
+ }
+
+ /* Preprocess pointer data */
+
+ if (device->touchScreen.parameters.useBadTouchFilter) {
+ if (device->touchScreen.applyBadTouchFilter()) {
+ havePointerIds = false;
+ }
+ }
+
+ if (device->touchScreen.parameters.useJumpyTouchFilter) {
+ if (device->touchScreen.applyJumpyTouchFilter()) {
+ havePointerIds = false;
+ }
+ }
+
+ if (! havePointerIds) {
+ device->touchScreen.calculatePointerIds();
+ }
+
+ InputDevice::TouchData temp;
+ InputDevice::TouchData* savedTouch;
+ if (device->touchScreen.parameters.useAveragingTouchFilter) {
+ temp.copyFrom(device->touchScreen.currentTouch);
+ savedTouch = & temp;
+
+ device->touchScreen.applyAveragingTouchFilter();
+ } else {
+ savedTouch = & device->touchScreen.currentTouch;
+ }
+
+ /* Process virtual keys or touches */
+
+ if (! consumeVirtualKeyTouches(when, device, policyFlags)) {
+ dispatchTouches(when, device, policyFlags);
+ }
+
+ // Copy current touch to last touch in preparation for the next cycle.
+ device->touchScreen.lastTouch.copyFrom(*savedTouch);
+}
+
+bool InputReader::consumeVirtualKeyTouches(nsecs_t when,
+ InputDevice* device, uint32_t policyFlags) {
+ if (device->touchScreen.currentVirtualKey.down) {
+ if (device->touchScreen.currentTouch.pointerCount == 0) {
+ // Pointer went up while virtual key was down. Send key up event.
+ device->touchScreen.currentVirtualKey.down = false;
+
+#if DEBUG_VIRTUAL_KEYS
+ LOGD("VirtualKeys: Generating key up: keyCode=%d, scanCode=%d",
+ device->touchScreen.currentVirtualKey.keyCode,
+ device->touchScreen.currentVirtualKey.scanCode);
+#endif
+
+ dispatchVirtualKey(when, device, policyFlags, KEY_EVENT_ACTION_UP,
+ KEY_EVENT_FLAG_FROM_SYSTEM | KEY_EVENT_FLAG_VIRTUAL_HARD_KEY);
+ return true; // consumed
+ }
+
+ int32_t x = device->touchScreen.currentTouch.pointers[0].x;
+ int32_t y = device->touchScreen.currentTouch.pointers[0].y;
+ if (device->touchScreen.isPointInsideDisplay(x, y)) {
+ // Pointer moved inside the display area. Send key cancellation.
+ device->touchScreen.currentVirtualKey.down = false;
+
+#if DEBUG_VIRTUAL_KEYS
+ LOGD("VirtualKeys: Canceling key: keyCode=%d, scanCode=%d",
+ device->touchScreen.currentVirtualKey.keyCode,
+ device->touchScreen.currentVirtualKey.scanCode);
+#endif
+
+ dispatchVirtualKey(when, device, policyFlags, KEY_EVENT_ACTION_UP,
+ KEY_EVENT_FLAG_FROM_SYSTEM | KEY_EVENT_FLAG_VIRTUAL_HARD_KEY
+ | KEY_EVENT_FLAG_CANCELED);
+
+ // Clear the last touch data so we will consider the pointer as having just been
+ // pressed down when generating subsequent motion events.
+ device->touchScreen.lastTouch.clear();
+ return false; // not consumed
+ }
+ } else if (device->touchScreen.currentTouch.pointerCount > 0
+ && device->touchScreen.lastTouch.pointerCount == 0) {
+ int32_t x = device->touchScreen.currentTouch.pointers[0].x;
+ int32_t y = device->touchScreen.currentTouch.pointers[0].y;
+ for (size_t i = 0; i < device->touchScreen.virtualKeys.size(); i++) {
+ const InputDevice::VirtualKey& virtualKey = device->touchScreen.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)) {
+ device->touchScreen.currentVirtualKey.down = true;
+ device->touchScreen.currentVirtualKey.downTime = when;
+ device->touchScreen.currentVirtualKey.keyCode = virtualKey.keyCode;
+ device->touchScreen.currentVirtualKey.scanCode = virtualKey.scanCode;
+
+#if DEBUG_VIRTUAL_KEYS
+ LOGD("VirtualKeys: Generating key down: keyCode=%d, scanCode=%d",
+ device->touchScreen.currentVirtualKey.keyCode,
+ device->touchScreen.currentVirtualKey.scanCode);
+#endif
+
+ dispatchVirtualKey(when, device, policyFlags, KEY_EVENT_ACTION_DOWN,
+ KEY_EVENT_FLAG_FROM_SYSTEM | KEY_EVENT_FLAG_VIRTUAL_HARD_KEY);
+ return true; // consumed
+ }
+ }
+ }
+
+ return false; // not consumed
+}
+
+void InputReader::dispatchVirtualKey(nsecs_t when,
+ InputDevice* device, uint32_t policyFlags,
+ int32_t keyEventAction, int32_t keyEventFlags) {
+ int32_t keyCode = device->touchScreen.currentVirtualKey.keyCode;
+ int32_t scanCode = device->touchScreen.currentVirtualKey.scanCode;
+ nsecs_t downTime = device->touchScreen.currentVirtualKey.downTime;
+ int32_t metaState = globalMetaState();
+
+ updateGlobalVirtualKeyState();
+
+ mPolicy->virtualKeyFeedback(when, device->id, keyEventAction, keyEventFlags,
+ keyCode, scanCode, metaState, downTime);
+
+ mDispatcher->notifyKey(when, device->id, INPUT_EVENT_NATURE_KEY, policyFlags,
+ keyEventAction, keyEventFlags, keyCode, scanCode, metaState, downTime);
+}
+
+void InputReader::dispatchTouches(nsecs_t when,
+ InputDevice* device, uint32_t policyFlags) {
+ uint32_t currentPointerCount = device->touchScreen.currentTouch.pointerCount;
+ uint32_t lastPointerCount = device->touchScreen.lastTouch.pointerCount;
+ if (currentPointerCount == 0 && lastPointerCount == 0) {
+ return; // nothing to do!
+ }
+
+ BitSet32 currentIdBits = device->touchScreen.currentTouch.idBits;
+ BitSet32 lastIdBits = device->touchScreen.lastTouch.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 = MOTION_EVENT_ACTION_MOVE;
+ dispatchTouch(when, device, policyFlags, & device->touchScreen.currentTouch,
+ currentIdBits, motionEventAction);
+ } else {
+ // There may be pointers going up and pointers going down at the same time when pointer
+ // ids are reported by the device driver.
+ BitSet32 upIdBits(lastIdBits.value & ~ currentIdBits.value);
+ BitSet32 downIdBits(currentIdBits.value & ~ lastIdBits.value);
+ BitSet32 activeIdBits(lastIdBits.value);
+
+ while (! upIdBits.isEmpty()) {
+ uint32_t upId = upIdBits.firstMarkedBit();
+ upIdBits.clearBit(upId);
+ BitSet32 oldActiveIdBits = activeIdBits;
+ activeIdBits.clearBit(upId);
+
+ int32_t motionEventAction;
+ if (activeIdBits.isEmpty()) {
+ motionEventAction = MOTION_EVENT_ACTION_UP;
+ } else {
+ motionEventAction = MOTION_EVENT_ACTION_POINTER_UP
+ | (upId << MOTION_EVENT_ACTION_POINTER_INDEX_SHIFT);
+ }
+
+ dispatchTouch(when, device, policyFlags, & device->touchScreen.lastTouch,
+ oldActiveIdBits, motionEventAction);
+ }
+
+ while (! downIdBits.isEmpty()) {
+ uint32_t downId = downIdBits.firstMarkedBit();
+ downIdBits.clearBit(downId);
+ BitSet32 oldActiveIdBits = activeIdBits;
+ activeIdBits.markBit(downId);
+
+ int32_t motionEventAction;
+ if (oldActiveIdBits.isEmpty()) {
+ motionEventAction = MOTION_EVENT_ACTION_DOWN;
+ device->touchScreen.downTime = when;
+ } else {
+ motionEventAction = MOTION_EVENT_ACTION_POINTER_DOWN
+ | (downId << MOTION_EVENT_ACTION_POINTER_INDEX_SHIFT);
+ }
+
+ dispatchTouch(when, device, policyFlags, & device->touchScreen.currentTouch,
+ activeIdBits, motionEventAction);
+ }
+ }
+}
+
+void InputReader::dispatchTouch(nsecs_t when, InputDevice* device, uint32_t policyFlags,
+ InputDevice::TouchData* touch, BitSet32 idBits,
+ int32_t motionEventAction) {
+ int32_t orientedWidth, orientedHeight;
+ switch (mDisplayOrientation) {
+ case InputDispatchPolicyInterface::ROTATION_90:
+ case InputDispatchPolicyInterface::ROTATION_270:
+ orientedWidth = mDisplayHeight;
+ orientedHeight = mDisplayWidth;
+ break;
+ default:
+ orientedWidth = mDisplayWidth;
+ orientedHeight = mDisplayHeight;
+ break;
+ }
+
+ uint32_t pointerCount = 0;
+ int32_t pointerIds[MAX_POINTERS];
+ PointerCoords pointerCoords[MAX_POINTERS];
+
+ // Walk through the the active pointers and map touch screen coordinates (TouchData) into
+ // display coordinates (PointerCoords) and adjust for display orientation.
+ while (! idBits.isEmpty()) {
+ uint32_t id = idBits.firstMarkedBit();
+ idBits.clearBit(id);
+ uint32_t index = touch->idToIndex[id];
+
+ float x = (float(touch->pointers[index].x)
+ - device->touchScreen.parameters.xAxis.minValue)
+ * device->touchScreen.precalculated.xScale;
+ float y = (float(touch->pointers[index].y)
+ - device->touchScreen.parameters.yAxis.minValue)
+ * device->touchScreen.precalculated.yScale;
+ float pressure = (float(touch->pointers[index].pressure)
+ - device->touchScreen.parameters.pressureAxis.minValue)
+ * device->touchScreen.precalculated.pressureScale;
+ float size = (float(touch->pointers[index].size)
+ - device->touchScreen.parameters.sizeAxis.minValue)
+ * device->touchScreen.precalculated.sizeScale;
+
+ switch (mDisplayOrientation) {
+ case InputDispatchPolicyInterface::ROTATION_90: {
+ float xTemp = x;
+ x = y;
+ y = mDisplayHeight - xTemp;
+ break;
+ }
+ case InputDispatchPolicyInterface::ROTATION_180: {
+ x = mDisplayWidth - x;
+ y = mDisplayHeight - y;
+ break;
+ }
+ case InputDispatchPolicyInterface::ROTATION_270: {
+ float xTemp = x;
+ x = mDisplayWidth - y;
+ y = xTemp;
+ break;
+ }
+ }
+
+ pointerIds[pointerCount] = int32_t(id);
+
+ pointerCoords[pointerCount].x = x;
+ pointerCoords[pointerCount].y = y;
+ pointerCoords[pointerCount].pressure = pressure;
+ pointerCoords[pointerCount].size = size;
+
+ pointerCount += 1;
+ }
+
+ // Check edge flags by looking only at the first pointer since the flags are
+ // global to the event.
+ // XXX Maybe we should revise the edge flags API to work on a per-pointer basis.
+ int32_t motionEventEdgeFlags = 0;
+ if (motionEventAction == MOTION_EVENT_ACTION_DOWN) {
+ if (pointerCoords[0].x <= 0) {
+ motionEventEdgeFlags |= MOTION_EVENT_EDGE_FLAG_LEFT;
+ } else if (pointerCoords[0].x >= orientedWidth) {
+ motionEventEdgeFlags |= MOTION_EVENT_EDGE_FLAG_RIGHT;
+ }
+ if (pointerCoords[0].y <= 0) {
+ motionEventEdgeFlags |= MOTION_EVENT_EDGE_FLAG_TOP;
+ } else if (pointerCoords[0].y >= orientedHeight) {
+ motionEventEdgeFlags |= MOTION_EVENT_EDGE_FLAG_BOTTOM;
+ }
+ }
+
+ nsecs_t downTime = device->touchScreen.downTime;
+ mDispatcher->notifyMotion(when, device->id, INPUT_EVENT_NATURE_TOUCH, policyFlags,
+ motionEventAction, globalMetaState(), motionEventEdgeFlags,
+ pointerCount, pointerIds, pointerCoords,
+ 0, 0, downTime);
+}
+
+void InputReader::onTrackballStateChanged(nsecs_t when,
+ InputDevice* device) {
+ static const uint32_t DELTA_FIELDS =
+ InputDevice::TrackballState::Accumulator::FIELD_REL_X
+ | InputDevice::TrackballState::Accumulator::FIELD_REL_Y;
+
+ /* Refresh display properties so we can trackball moves according to display orientation */
+
+ if (! refreshDisplayProperties()) {
+ return;
+ }
+
+ /* Update device state */
+
+ uint32_t fields = device->trackball.accumulator.fields;
+ bool downChanged = fields & InputDevice::TrackballState::Accumulator::FIELD_BTN_MOUSE;
+ bool deltaChanged = (fields & DELTA_FIELDS) == DELTA_FIELDS;
+
+ bool down;
+ if (downChanged) {
+ if (device->trackball.accumulator.btnMouse) {
+ device->trackball.current.down = true;
+ device->trackball.current.downTime = when;
+ down = true;
+ } else {
+ device->trackball.current.down = false;
+ down = false;
+ }
+ } else {
+ down = device->trackball.current.down;
+ }
+
+ /* Apply policy */
+
+ int32_t policyActions = mPolicy->interceptTrackball(when, downChanged, down, deltaChanged);
+
+ uint32_t policyFlags = 0;
+ if (! applyStandardInputDispatchPolicyActions(when, policyActions, & policyFlags)) {
+ return; // event dropped
+ }
+
+ /* Enqueue motion event for dispatch */
+
+ int32_t motionEventAction;
+ if (downChanged) {
+ motionEventAction = down ? MOTION_EVENT_ACTION_DOWN : MOTION_EVENT_ACTION_UP;
+ } else {
+ motionEventAction = MOTION_EVENT_ACTION_MOVE;
+ }
+
+ int32_t pointerId = 0;
+ PointerCoords pointerCoords;
+ pointerCoords.x = device->trackball.accumulator.relX
+ * device->trackball.precalculated.xScale;
+ pointerCoords.y = device->trackball.accumulator.relY
+ * device->trackball.precalculated.yScale;
+ pointerCoords.pressure = 1.0f; // XXX Consider making this 1.0f if down, 0 otherwise.
+ pointerCoords.size = 0;
+
+ float temp;
+ switch (mDisplayOrientation) {
+ case InputDispatchPolicyInterface::ROTATION_90:
+ temp = pointerCoords.x;
+ pointerCoords.x = pointerCoords.y;
+ pointerCoords.y = - temp;
+ break;
+
+ case InputDispatchPolicyInterface::ROTATION_180:
+ pointerCoords.x = - pointerCoords.x;
+ pointerCoords.y = - pointerCoords.y;
+ break;
+
+ case InputDispatchPolicyInterface::ROTATION_270:
+ temp = pointerCoords.x;
+ pointerCoords.x = - pointerCoords.y;
+ pointerCoords.y = temp;
+ break;
+ }
+
+ mDispatcher->notifyMotion(when, device->id, INPUT_EVENT_NATURE_TRACKBALL, policyFlags,
+ motionEventAction, globalMetaState(), MOTION_EVENT_EDGE_FLAG_NONE,
+ 1, & pointerId, & pointerCoords,
+ device->trackball.precalculated.xPrecision,
+ device->trackball.precalculated.yPrecision,
+ device->trackball.current.downTime);
+}
+
+void InputReader::onConfigurationChanged(nsecs_t when) {
+ // Reset global meta state because it depends on the list of all configured devices.
+ resetGlobalMetaState();
+
+ // Reset virtual keys, just in case.
+ updateGlobalVirtualKeyState();
+
+ // Enqueue configuration changed.
+ // XXX This stuff probably needs to be tracked elsewhere in an input device registry
+ // of some kind that can be asynchronously updated and queried. (Same as above?)
+ int32_t touchScreenConfig = InputDispatchPolicyInterface::TOUCHSCREEN_NOTOUCH;
+ int32_t keyboardConfig = InputDispatchPolicyInterface::KEYBOARD_NOKEYS;
+ int32_t navigationConfig = InputDispatchPolicyInterface::NAVIGATION_NONAV;
+
+ for (size_t i = 0; i < mDevices.size(); i++) {
+ InputDevice* device = mDevices.valueAt(i);
+ int32_t deviceClasses = device->classes;
+
+ if (deviceClasses & INPUT_DEVICE_CLASS_TOUCHSCREEN) {
+ touchScreenConfig = InputDispatchPolicyInterface::TOUCHSCREEN_FINGER;
+ }
+ if (deviceClasses & INPUT_DEVICE_CLASS_ALPHAKEY) {
+ keyboardConfig = InputDispatchPolicyInterface::KEYBOARD_QWERTY;
+ }
+ if (deviceClasses & INPUT_DEVICE_CLASS_TRACKBALL) {
+ navigationConfig = InputDispatchPolicyInterface::NAVIGATION_TRACKBALL;
+ } else if (deviceClasses & INPUT_DEVICE_CLASS_DPAD) {
+ navigationConfig = InputDispatchPolicyInterface::NAVIGATION_DPAD;
+ }
+ }
+
+ mDispatcher->notifyConfigurationChanged(when, touchScreenConfig,
+ keyboardConfig, navigationConfig);
+}
+
+bool InputReader::applyStandardInputDispatchPolicyActions(nsecs_t when,
+ int32_t policyActions, uint32_t* policyFlags) {
+ if (policyActions & InputDispatchPolicyInterface::ACTION_APP_SWITCH_COMING) {
+ mDispatcher->notifyAppSwitchComing(when);
+ }
+
+ if (policyActions & InputDispatchPolicyInterface::ACTION_WOKE_HERE) {
+ *policyFlags |= POLICY_FLAG_WOKE_HERE;
+ }
+
+ if (policyActions & InputDispatchPolicyInterface::ACTION_BRIGHT_HERE) {
+ *policyFlags |= POLICY_FLAG_BRIGHT_HERE;
+ }
+
+ return policyActions & InputDispatchPolicyInterface::ACTION_DISPATCH;
+}
+
+void InputReader::resetDisplayProperties() {
+ mDisplayWidth = mDisplayHeight = -1;
+ mDisplayOrientation = -1;
+}
+
+bool InputReader::refreshDisplayProperties() {
+ int32_t newWidth, newHeight, newOrientation;
+ if (mPolicy->getDisplayInfo(0, & newWidth, & newHeight, & newOrientation)) {
+ if (newWidth != mDisplayWidth || newHeight != mDisplayHeight) {
+ LOGD("Display size changed from %dx%d to %dx%d, updating device configuration",
+ mDisplayWidth, mDisplayHeight, newWidth, newHeight);
+
+ mDisplayWidth = newWidth;
+ mDisplayHeight = newHeight;
+
+ for (size_t i = 0; i < mDevices.size(); i++) {
+ configureDeviceForCurrentDisplaySize(mDevices.valueAt(i));
+ }
+ }
+
+ mDisplayOrientation = newOrientation;
+ return true;
+ } else {
+ resetDisplayProperties();
+ return false;
+ }
+}
+
+InputDevice* InputReader::getDevice(int32_t deviceId) {
+ ssize_t index = mDevices.indexOfKey(deviceId);
+ return index >= 0 ? mDevices.valueAt((size_t) index) : NULL;
+}
+
+InputDevice* InputReader::getNonIgnoredDevice(int32_t deviceId) {
+ InputDevice* device = getDevice(deviceId);
+ return device && ! device->ignored ? device : NULL;
+}
+
+void InputReader::addDevice(nsecs_t when, int32_t deviceId) {
+ uint32_t classes = mEventHub->getDeviceClasses(deviceId);
+ String8 name = mEventHub->getDeviceName(deviceId);
+ InputDevice* device = new InputDevice(deviceId, classes, name);
+
+ if (classes != 0) {
+ LOGI("Device added: id=0x%x, name=%s, classes=%02x", device->id,
+ device->name.string(), device->classes);
+
+ configureDevice(device);
+ } else {
+ LOGI("Device added: id=0x%x, name=%s (ignored non-input device)", device->id,
+ device->name.string());
+
+ device->ignored = true;
+ }
+
+ device->reset();
+
+ mDevices.add(deviceId, device);
+
+ if (! device->ignored) {
+ onConfigurationChanged(when);
+ }
+}
+
+void InputReader::removeDevice(nsecs_t when, InputDevice* device) {
+ mDevices.removeItem(device->id);
+
+ if (! device->ignored) {
+ LOGI("Device removed: id=0x%x, name=%s, classes=%02x", device->id,
+ device->name.string(), device->classes);
+
+ onConfigurationChanged(when);
+ } else {
+ LOGI("Device removed: id=0x%x, name=%s (ignored non-input device)", device->id,
+ device->name.string());
+ }
+
+ delete device;
+}
+
+void InputReader::configureDevice(InputDevice* device) {
+ if (device->isMultiTouchScreen()) {
+ configureAbsoluteAxisInfo(device, ABS_MT_POSITION_X, "X",
+ & device->touchScreen.parameters.xAxis);
+ configureAbsoluteAxisInfo(device, ABS_MT_POSITION_Y, "Y",
+ & device->touchScreen.parameters.yAxis);
+ configureAbsoluteAxisInfo(device, ABS_MT_TOUCH_MAJOR, "Pressure",
+ & device->touchScreen.parameters.pressureAxis);
+ configureAbsoluteAxisInfo(device, ABS_MT_WIDTH_MAJOR, "Size",
+ & device->touchScreen.parameters.sizeAxis);
+ } else if (device->isSingleTouchScreen()) {
+ configureAbsoluteAxisInfo(device, ABS_X, "X",
+ & device->touchScreen.parameters.xAxis);
+ configureAbsoluteAxisInfo(device, ABS_Y, "Y",
+ & device->touchScreen.parameters.yAxis);
+ configureAbsoluteAxisInfo(device, ABS_PRESSURE, "Pressure",
+ & device->touchScreen.parameters.pressureAxis);
+ configureAbsoluteAxisInfo(device, ABS_TOOL_WIDTH, "Size",
+ & device->touchScreen.parameters.sizeAxis);
+ }
+
+ if (device->isTouchScreen()) {
+ device->touchScreen.parameters.useBadTouchFilter =
+ mPolicy->filterTouchEvents();
+ device->touchScreen.parameters.useAveragingTouchFilter =
+ mPolicy->filterTouchEvents();
+ device->touchScreen.parameters.useJumpyTouchFilter =
+ mPolicy->filterJumpyTouchEvents();
+
+ device->touchScreen.precalculated.pressureScale =
+ 1.0f / device->touchScreen.parameters.pressureAxis.range;
+ device->touchScreen.precalculated.sizeScale =
+ 1.0f / device->touchScreen.parameters.sizeAxis.range;
+ }
+
+ if (device->isTrackball()) {
+ device->trackball.precalculated.xPrecision = TRACKBALL_MOVEMENT_THRESHOLD;
+ device->trackball.precalculated.yPrecision = TRACKBALL_MOVEMENT_THRESHOLD;
+ device->trackball.precalculated.xScale = 1.0f / TRACKBALL_MOVEMENT_THRESHOLD;
+ device->trackball.precalculated.yScale = 1.0f / TRACKBALL_MOVEMENT_THRESHOLD;
+ }
+
+ configureDeviceForCurrentDisplaySize(device);
+}
+
+void InputReader::configureDeviceForCurrentDisplaySize(InputDevice* device) {
+ if (device->isTouchScreen()) {
+ if (mDisplayWidth < 0) {
+ LOGD("Skipping part of touch screen configuration since display size is unknown.");
+ } else {
+ LOGI("Device configured: id=0x%x, name=%s (display size was changed)", device->id,
+ device->name.string());
+ configureVirtualKeys(device);
+
+ device->touchScreen.precalculated.xScale =
+ float(mDisplayWidth) / device->touchScreen.parameters.xAxis.range;
+ device->touchScreen.precalculated.yScale =
+ float(mDisplayHeight) / device->touchScreen.parameters.yAxis.range;
+ }
+ }
+}
+
+void InputReader::configureVirtualKeys(InputDevice* device) {
+ device->touchScreen.virtualKeys.clear();
+
+ Vector<InputDispatchPolicyInterface::VirtualKeyDefinition> virtualKeyDefinitions;
+ mPolicy->getVirtualKeyDefinitions(device->name, virtualKeyDefinitions);
+ if (virtualKeyDefinitions.size() == 0) {
+ return;
+ }
+
+ device->touchScreen.virtualKeys.setCapacity(virtualKeyDefinitions.size());
+
+ int32_t touchScreenLeft = device->touchScreen.parameters.xAxis.minValue;
+ int32_t touchScreenTop = device->touchScreen.parameters.yAxis.minValue;
+ int32_t touchScreenWidth = device->touchScreen.parameters.xAxis.range;
+ int32_t touchScreenHeight = device->touchScreen.parameters.yAxis.range;
+
+ for (size_t i = 0; i < virtualKeyDefinitions.size(); i++) {
+ const InputDispatchPolicyInterface::VirtualKeyDefinition& virtualKeyDefinition =
+ virtualKeyDefinitions[i];
+
+ device->touchScreen.virtualKeys.add();
+ InputDevice::VirtualKey& virtualKey =
+ device->touchScreen.virtualKeys.editTop();
+
+ virtualKey.scanCode = virtualKeyDefinition.scanCode;
+ int32_t keyCode;
+ uint32_t flags;
+ if (mEventHub->scancodeToKeycode(device->id, virtualKey.scanCode,
+ & keyCode, & flags)) {
+ LOGI(" VirtualKey %d: could not obtain key code, ignoring", virtualKey.scanCode);
+ device->touchScreen.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 / mDisplayWidth + touchScreenLeft;
+ virtualKey.hitRight= (virtualKeyDefinition.centerX + halfWidth)
+ * touchScreenWidth / mDisplayWidth + touchScreenLeft;
+ virtualKey.hitTop = (virtualKeyDefinition.centerY - halfHeight)
+ * touchScreenHeight / mDisplayHeight + touchScreenTop;
+ virtualKey.hitBottom = (virtualKeyDefinition.centerY + halfHeight)
+ * touchScreenHeight / mDisplayHeight + touchScreenTop;
+
+ LOGI(" VirtualKey %d: keyCode=%d hitLeft=%d hitRight=%d hitTop=%d hitBottom=%d",
+ virtualKey.scanCode, virtualKey.keyCode,
+ virtualKey.hitLeft, virtualKey.hitRight, virtualKey.hitTop, virtualKey.hitBottom);
+ }
+}
+
+void InputReader::configureAbsoluteAxisInfo(InputDevice* device,
+ int axis, const char* name, InputDevice::AbsoluteAxisInfo* out) {
+ if (! mEventHub->getAbsoluteInfo(device->id, axis,
+ & out->minValue, & out->maxValue, & out->flat, &out->fuzz)) {
+ out->range = out->maxValue - out->minValue;
+ if (out->range != 0) {
+ LOGI(" %s: min=%d max=%d flat=%d fuzz=%d",
+ name, out->minValue, out->maxValue, out->flat, out->fuzz);
+ return;
+ }
+ }
+
+ out->minValue = 0;
+ out->maxValue = 0;
+ out->flat = 0;
+ out->fuzz = 0;
+ out->range = 0;
+ LOGI(" %s: unknown axis values, setting to zero", name);
+}
+
+void InputReader::resetGlobalMetaState() {
+ mGlobalMetaState = -1;
+}
+
+int32_t InputReader::globalMetaState() {
+ if (mGlobalMetaState == -1) {
+ mGlobalMetaState = 0;
+ for (size_t i = 0; i < mDevices.size(); i++) {
+ InputDevice* device = mDevices.valueAt(i);
+ if (device->isKeyboard()) {
+ mGlobalMetaState |= device->keyboard.current.metaState;
+ }
+ }
+ }
+ return mGlobalMetaState;
+}
+
+void InputReader::updateGlobalVirtualKeyState() {
+ int32_t keyCode = -1, scanCode = -1;
+
+ for (size_t i = 0; i < mDevices.size(); i++) {
+ InputDevice* device = mDevices.valueAt(i);
+ if (device->isTouchScreen()) {
+ if (device->touchScreen.currentVirtualKey.down) {
+ keyCode = device->touchScreen.currentVirtualKey.keyCode;
+ scanCode = device->touchScreen.currentVirtualKey.scanCode;
+ }
+ }
+ }
+
+ {
+ AutoMutex _l(mExportedStateLock);
+
+ mGlobalVirtualKeyCode = keyCode;
+ mGlobalVirtualScanCode = scanCode;
+ }
+}
+
+bool InputReader::getCurrentVirtualKey(int32_t* outKeyCode, int32_t* outScanCode) const {
+ AutoMutex _l(mExportedStateLock);
+
+ *outKeyCode = mGlobalVirtualKeyCode;
+ *outScanCode = mGlobalVirtualScanCode;
+ return mGlobalVirtualKeyCode != -1;
+}
+
+
+// --- InputReaderThread ---
+
+InputReaderThread::InputReaderThread(const sp<InputReaderInterface>& reader) :
+ Thread(/*canCallJava*/ true), mReader(reader) {
+}
+
+InputReaderThread::~InputReaderThread() {
+}
+
+bool InputReaderThread::threadLoop() {
+ mReader->loopOnce();
+ return true;
+}
+
+} // namespace android
diff --git a/libs/ui/InputTransport.cpp b/libs/ui/InputTransport.cpp
new file mode 100644
index 0000000..a24180f
--- /dev/null
+++ b/libs/ui/InputTransport.cpp
@@ -0,0 +1,684 @@
+//
+// Copyright 2010 The Android Open Source Project
+//
+// Provides a shared memory transport for input events.
+//
+#define LOG_TAG "InputTransport"
+
+//#define LOG_NDEBUG 0
+
+// Log debug messages about channel signalling (send signal, receive signal)
+#define DEBUG_CHANNEL_SIGNALS 1
+
+// Log debug messages whenever InputChannel objects are created/destroyed
+#define DEBUG_CHANNEL_LIFECYCLE 1
+
+// Log debug messages about transport actions (initialize, reset, publish, ...)
+#define DEBUG_TRANSPORT_ACTIONS 1
+
+
+#include <cutils/ashmem.h>
+#include <cutils/log.h>
+#include <errno.h>
+#include <fcntl.h>
+#include <sys/mman.h>
+#include <ui/InputTransport.h>
+#include <unistd.h>
+
+namespace android {
+
+// Must be at least sizeof(InputMessage) + sufficient space for pointer data
+static const int DEFAULT_MESSAGE_BUFFER_SIZE = 16384;
+
+// Signal sent by the producer to the consumer to inform it that a new message is
+// available to be consumed in the shared memory buffer.
+static const char INPUT_SIGNAL_DISPATCH = 'D';
+
+// Signal sent by the consumer to the producer to inform it that it has finished
+// consuming the most recent message.
+static const char INPUT_SIGNAL_FINISHED = 'f';
+
+
+// --- InputChannel ---
+
+InputChannel::InputChannel(const String8& name, int32_t ashmemFd, int32_t receivePipeFd,
+ int32_t sendPipeFd) :
+ mName(name), mAshmemFd(ashmemFd), mReceivePipeFd(receivePipeFd), mSendPipeFd(sendPipeFd) {
+#if DEBUG_CHANNEL_LIFECYCLE
+ LOGD("Input channel constructed: name='%s', ashmemFd=%d, receivePipeFd=%d, sendPipeFd=%d",
+ mName.string(), ashmemFd, receivePipeFd, sendPipeFd);
+#endif
+
+ int result = fcntl(mReceivePipeFd, F_SETFL, O_NONBLOCK);
+ LOG_ALWAYS_FATAL_IF(result != 0, "channel '%s' ~ Could not make receive pipe "
+ "non-blocking. errno=%d", mName.string(), errno);
+
+ result = fcntl(mSendPipeFd, F_SETFL, O_NONBLOCK);
+ LOG_ALWAYS_FATAL_IF(result != 0, "channel '%s' ~ Could not make send pipe "
+ "non-blocking. errno=%d", mName.string(), errno);
+}
+
+InputChannel::~InputChannel() {
+#if DEBUG_CHANNEL_LIFECYCLE
+ LOGD("Input channel destroyed: name='%s', ashmemFd=%d, receivePipeFd=%d, sendPipeFd=%d",
+ mName.string(), mAshmemFd, mReceivePipeFd, mSendPipeFd);
+#endif
+
+ ::close(mAshmemFd);
+ ::close(mReceivePipeFd);
+ ::close(mSendPipeFd);
+}
+
+status_t InputChannel::openInputChannelPair(const String8& name,
+ InputChannel** outServerChannel, InputChannel** outClientChannel) {
+ status_t result;
+
+ int serverAshmemFd = ashmem_create_region(name.string(), DEFAULT_MESSAGE_BUFFER_SIZE);
+ if (serverAshmemFd < 0) {
+ result = -errno;
+ LOGE("channel '%s' ~ Could not create shared memory region. errno=%d",
+ name.string(), errno);
+ } else {
+ result = ashmem_set_prot_region(serverAshmemFd, PROT_READ | PROT_WRITE);
+ if (result < 0) {
+ LOGE("channel '%s' ~ Error %d trying to set protection of ashmem fd %d.",
+ name.string(), result, serverAshmemFd);
+ } else {
+ // Dup the file descriptor because the server and client input channel objects that
+ // are returned may have different lifetimes but they share the same shared memory region.
+ int clientAshmemFd;
+ clientAshmemFd = dup(serverAshmemFd);
+ if (clientAshmemFd < 0) {
+ result = -errno;
+ LOGE("channel '%s' ~ Could not dup() shared memory region fd. errno=%d",
+ name.string(), errno);
+ } else {
+ int forward[2];
+ if (pipe(forward)) {
+ result = -errno;
+ LOGE("channel '%s' ~ Could not create forward pipe. errno=%d",
+ name.string(), errno);
+ } else {
+ int reverse[2];
+ if (pipe(reverse)) {
+ result = -errno;
+ LOGE("channel '%s' ~ Could not create reverse pipe. errno=%d",
+ name.string(), errno);
+ } else {
+ String8 serverChannelName = name;
+ serverChannelName.append(" (server)");
+ *outServerChannel = new InputChannel(serverChannelName,
+ serverAshmemFd, reverse[0], forward[1]);
+
+ String8 clientChannelName = name;
+ clientChannelName.append(" (client)");
+ *outClientChannel = new InputChannel(clientChannelName,
+ clientAshmemFd, forward[0], reverse[1]);
+ return OK;
+ }
+ ::close(forward[0]);
+ ::close(forward[1]);
+ }
+ ::close(clientAshmemFd);
+ }
+ }
+ ::close(serverAshmemFd);
+ }
+
+ *outServerChannel = NULL;
+ *outClientChannel = NULL;
+ return result;
+}
+
+status_t InputChannel::sendSignal(char signal) {
+ ssize_t nWrite = ::write(mSendPipeFd, & signal, 1);
+
+ if (nWrite == 1) {
+#if DEBUG_CHANNEL_SIGNALS
+ LOGD("channel '%s' ~ sent signal '%c'", mName.string(), signal);
+#endif
+ return OK;
+ }
+
+#if DEBUG_CHANNEL_SIGNALS
+ LOGD("channel '%s' ~ error sending signal '%c', errno=%d", mName.string(), signal, errno);
+#endif
+ return -errno;
+}
+
+status_t InputChannel::receiveSignal(char* outSignal) {
+ ssize_t nRead = ::read(mReceivePipeFd, outSignal, 1);
+ if (nRead == 1) {
+#if DEBUG_CHANNEL_SIGNALS
+ LOGD("channel '%s' ~ received signal '%c'", mName.string(), *outSignal);
+#endif
+ return OK;
+ }
+
+ if (errno == EAGAIN) {
+#if DEBUG_CHANNEL_SIGNALS
+ LOGD("channel '%s' ~ receive signal failed because no signal available", mName.string());
+#endif
+ return WOULD_BLOCK;
+ }
+
+#if DEBUG_CHANNEL_SIGNALS
+ LOGD("channel '%s' ~ receive signal failed, errno=%d", mName.string(), errno);
+#endif
+ return -errno;
+}
+
+
+// --- InputPublisher ---
+
+InputPublisher::InputPublisher(const sp<InputChannel>& channel) :
+ mChannel(channel), mSharedMessage(NULL),
+ mPinned(false), mSemaphoreInitialized(false), mWasDispatched(false),
+ mMotionEventSampleDataTail(NULL) {
+}
+
+InputPublisher::~InputPublisher() {
+ reset();
+
+ if (mSharedMessage) {
+ munmap(mSharedMessage, mAshmemSize);
+ }
+}
+
+status_t InputPublisher::initialize() {
+#if DEBUG_TRANSPORT_ACTIONS
+ LOGD("channel '%s' publisher ~ initialize",
+ mChannel->getName().string());
+#endif
+
+ int ashmemFd = mChannel->getAshmemFd();
+ int result = ashmem_get_size_region(ashmemFd);
+ if (result < 0) {
+ LOGE("channel '%s' publisher ~ Error %d getting size of ashmem fd %d.",
+ mChannel->getName().string(), result, ashmemFd);
+ return UNKNOWN_ERROR;
+ }
+ mAshmemSize = (size_t) result;
+
+ mSharedMessage = static_cast<InputMessage*>(mmap(NULL, mAshmemSize,
+ PROT_READ | PROT_WRITE, MAP_SHARED, ashmemFd, 0));
+ if (! mSharedMessage) {
+ LOGE("channel '%s' publisher ~ mmap failed on ashmem fd %d.",
+ mChannel->getName().string(), ashmemFd);
+ return NO_MEMORY;
+ }
+
+ mPinned = true;
+ mSharedMessage->consumed = false;
+
+ return reset();
+}
+
+status_t InputPublisher::reset() {
+#if DEBUG_TRANSPORT_ACTIONS
+ LOGD("channel '%s' publisher ~ reset",
+ mChannel->getName().string());
+#endif
+
+ if (mPinned) {
+ // Destroy the semaphore since we are about to unpin the memory region that contains it.
+ int result;
+ if (mSemaphoreInitialized) {
+ if (mSharedMessage->consumed) {
+ result = sem_post(& mSharedMessage->semaphore);
+ if (result < 0) {
+ LOGE("channel '%s' publisher ~ Error %d in sem_post.",
+ mChannel->getName().string(), errno);
+ return UNKNOWN_ERROR;
+ }
+ }
+
+ result = sem_destroy(& mSharedMessage->semaphore);
+ if (result < 0) {
+ LOGE("channel '%s' publisher ~ Error %d in sem_destroy.",
+ mChannel->getName().string(), errno);
+ return UNKNOWN_ERROR;
+ }
+
+ mSemaphoreInitialized = false;
+ }
+
+ // Unpin the region since we no longer care about its contents.
+ int ashmemFd = mChannel->getAshmemFd();
+ result = ashmem_unpin_region(ashmemFd, 0, 0);
+ if (result < 0) {
+ LOGE("channel '%s' publisher ~ Error %d unpinning ashmem fd %d.",
+ mChannel->getName().string(), result, ashmemFd);
+ return UNKNOWN_ERROR;
+ }
+
+ mPinned = false;
+ }
+
+ mMotionEventSampleDataTail = NULL;
+ mWasDispatched = false;
+ return OK;
+}
+
+status_t InputPublisher::publishInputEvent(
+ int32_t type,
+ int32_t deviceId,
+ int32_t nature) {
+ if (mPinned) {
+ LOGE("channel '%s' publisher ~ Attempted to publish a new event but publisher has "
+ "not yet been reset.", mChannel->getName().string());
+ return INVALID_OPERATION;
+ }
+
+ // Pin the region.
+ // We do not check for ASHMEM_NOT_PURGED because we don't care about the previous
+ // contents of the buffer so it does not matter whether it was purged in the meantime.
+ int ashmemFd = mChannel->getAshmemFd();
+ int result = ashmem_pin_region(ashmemFd, 0, 0);
+ if (result < 0) {
+ LOGE("channel '%s' publisher ~ Error %d pinning ashmem fd %d.",
+ mChannel->getName().string(), result, ashmemFd);
+ return UNKNOWN_ERROR;
+ }
+
+ mPinned = true;
+
+ result = sem_init(& mSharedMessage->semaphore, 1, 1);
+ if (result < 0) {
+ LOGE("channel '%s' publisher ~ Error %d in sem_init.",
+ mChannel->getName().string(), errno);
+ return UNKNOWN_ERROR;
+ }
+
+ mSemaphoreInitialized = true;
+
+ mSharedMessage->consumed = false;
+ mSharedMessage->type = type;
+ mSharedMessage->deviceId = deviceId;
+ mSharedMessage->nature = nature;
+ return OK;
+}
+
+status_t InputPublisher::publishKeyEvent(
+ int32_t deviceId,
+ int32_t nature,
+ int32_t action,
+ int32_t flags,
+ int32_t keyCode,
+ int32_t scanCode,
+ int32_t metaState,
+ int32_t repeatCount,
+ nsecs_t downTime,
+ nsecs_t eventTime) {
+#if DEBUG_TRANSPORT_ACTIONS
+ LOGD("channel '%s' publisher ~ publishKeyEvent: deviceId=%d, nature=%d, "
+ "action=%d, flags=%d, keyCode=%d, scanCode=%d, metaState=%d, repeatCount=%d,"
+ "downTime=%lld, eventTime=%lld",
+ mChannel->getName().string(),
+ deviceId, nature, action, flags, keyCode, scanCode, metaState, repeatCount,
+ downTime, eventTime);
+#endif
+
+ status_t result = publishInputEvent(INPUT_EVENT_TYPE_KEY, deviceId, nature);
+ if (result < 0) {
+ return result;
+ }
+
+ mSharedMessage->key.action = action;
+ mSharedMessage->key.flags = flags;
+ mSharedMessage->key.keyCode = keyCode;
+ mSharedMessage->key.scanCode = scanCode;
+ mSharedMessage->key.metaState = metaState;
+ mSharedMessage->key.repeatCount = repeatCount;
+ mSharedMessage->key.downTime = downTime;
+ mSharedMessage->key.eventTime = eventTime;
+ return OK;
+}
+
+status_t InputPublisher::publishMotionEvent(
+ int32_t deviceId,
+ int32_t nature,
+ int32_t action,
+ int32_t edgeFlags,
+ int32_t metaState,
+ float xOffset,
+ float yOffset,
+ float xPrecision,
+ float yPrecision,
+ nsecs_t downTime,
+ nsecs_t eventTime,
+ size_t pointerCount,
+ const int32_t* pointerIds,
+ const PointerCoords* pointerCoords) {
+#if DEBUG_TRANSPORT_ACTIONS
+ LOGD("channel '%s' publisher ~ publishMotionEvent: deviceId=%d, nature=%d, "
+ "action=%d, edgeFlags=%d, metaState=%d, xOffset=%f, yOffset=%f, "
+ "xPrecision=%f, yPrecision=%f, downTime=%lld, eventTime=%lld, "
+ "pointerCount=%d",
+ mChannel->getName().string(),
+ deviceId, nature, action, edgeFlags, metaState, xOffset, yOffset,
+ xPrecision, yPrecision, downTime, eventTime, pointerCount);
+#endif
+
+ if (pointerCount > MAX_POINTERS || pointerCount < 1) {
+ LOGE("channel '%s' publisher ~ Invalid number of pointers provided: %d.",
+ mChannel->getName().string(), pointerCount);
+ return BAD_VALUE;
+ }
+
+ status_t result = publishInputEvent(INPUT_EVENT_TYPE_MOTION, deviceId, nature);
+ if (result < 0) {
+ return result;
+ }
+
+ mSharedMessage->motion.action = action;
+ mSharedMessage->motion.edgeFlags = edgeFlags;
+ mSharedMessage->motion.metaState = metaState;
+ mSharedMessage->motion.xOffset = xOffset;
+ mSharedMessage->motion.yOffset = yOffset;
+ mSharedMessage->motion.xPrecision = xPrecision;
+ mSharedMessage->motion.yPrecision = yPrecision;
+ mSharedMessage->motion.downTime = downTime;
+ mSharedMessage->motion.pointerCount = pointerCount;
+
+ mSharedMessage->motion.sampleCount = 1;
+ mSharedMessage->motion.sampleData[0].eventTime = eventTime;
+
+ for (size_t i = 0; i < pointerCount; i++) {
+ mSharedMessage->motion.pointerIds[i] = pointerIds[i];
+ mSharedMessage->motion.sampleData[0].coords[i] = pointerCoords[i];
+ }
+
+ // Cache essential information about the motion event to ensure that a malicious consumer
+ // cannot confuse the publisher by modifying the contents of the shared memory buffer while
+ // it is being updated.
+ if (action == MOTION_EVENT_ACTION_MOVE) {
+ mMotionEventPointerCount = pointerCount;
+ mMotionEventSampleDataStride = InputMessage::sampleDataStride(pointerCount);
+ mMotionEventSampleDataTail = InputMessage::sampleDataPtrIncrement(
+ mSharedMessage->motion.sampleData, mMotionEventSampleDataStride);
+ } else {
+ mMotionEventSampleDataTail = NULL;
+ }
+ return OK;
+}
+
+status_t InputPublisher::appendMotionSample(
+ nsecs_t eventTime,
+ const PointerCoords* pointerCoords) {
+#if DEBUG_TRANSPORT_ACTIONS
+ LOGD("channel '%s' publisher ~ appendMotionSample: eventTime=%lld",
+ mChannel->getName().string(), eventTime);
+#endif
+
+ if (! mPinned || ! mMotionEventSampleDataTail) {
+ LOGE("channel '%s' publisher ~ Cannot append motion sample because there is no current "
+ "MOTION_EVENT_ACTION_MOVE event.", mChannel->getName().string());
+ return INVALID_OPERATION;
+ }
+
+ InputMessage::SampleData* newTail = InputMessage::sampleDataPtrIncrement(
+ mMotionEventSampleDataTail, mMotionEventSampleDataStride);
+ size_t newBytesUsed = reinterpret_cast<char*>(newTail) -
+ reinterpret_cast<char*>(mSharedMessage);
+
+ if (newBytesUsed > mAshmemSize) {
+ LOGD("channel '%s' publisher ~ Cannot append motion sample because the shared memory "
+ "buffer is full. Buffer size: %d bytes, pointers: %d, samples: %d",
+ mChannel->getName().string(),
+ mAshmemSize, mMotionEventPointerCount, mSharedMessage->motion.sampleCount);
+ return NO_MEMORY;
+ }
+
+ int result;
+ if (mWasDispatched) {
+ result = sem_trywait(& mSharedMessage->semaphore);
+ if (result < 0) {
+ if (errno == EAGAIN) {
+ // Only possible source of contention is the consumer having consumed (or being in the
+ // process of consuming) the message and left the semaphore count at 0.
+ LOGD("channel '%s' publisher ~ Cannot append motion sample because the message has "
+ "already been consumed.", mChannel->getName().string());
+ return FAILED_TRANSACTION;
+ } else {
+ LOGE("channel '%s' publisher ~ Error %d in sem_trywait.",
+ mChannel->getName().string(), errno);
+ return UNKNOWN_ERROR;
+ }
+ }
+ }
+
+ mMotionEventSampleDataTail->eventTime = eventTime;
+ for (size_t i = 0; i < mMotionEventPointerCount; i++) {
+ mMotionEventSampleDataTail->coords[i] = pointerCoords[i];
+ }
+ mMotionEventSampleDataTail = newTail;
+
+ mSharedMessage->motion.sampleCount += 1;
+
+ if (mWasDispatched) {
+ result = sem_post(& mSharedMessage->semaphore);
+ if (result < 0) {
+ LOGE("channel '%s' publisher ~ Error %d in sem_post.",
+ mChannel->getName().string(), errno);
+ return UNKNOWN_ERROR;
+ }
+ }
+ return OK;
+}
+
+status_t InputPublisher::sendDispatchSignal() {
+#if DEBUG_TRANSPORT_ACTIONS
+ LOGD("channel '%s' publisher ~ sendDispatchSignal",
+ mChannel->getName().string());
+#endif
+
+ mWasDispatched = true;
+ return mChannel->sendSignal(INPUT_SIGNAL_DISPATCH);
+}
+
+status_t InputPublisher::receiveFinishedSignal() {
+#if DEBUG_TRANSPORT_ACTIONS
+ LOGD("channel '%s' publisher ~ receiveFinishedSignal",
+ mChannel->getName().string());
+#endif
+
+ char signal;
+ status_t result = mChannel->receiveSignal(& signal);
+ if (result) {
+ return result;
+ }
+ if (signal != INPUT_SIGNAL_FINISHED) {
+ LOGE("channel '%s' publisher ~ Received unexpected signal '%c' from consumer",
+ mChannel->getName().string(), signal);
+ return UNKNOWN_ERROR;
+ }
+ return OK;
+}
+
+// --- InputConsumer ---
+
+InputConsumer::InputConsumer(const sp<InputChannel>& channel) :
+ mChannel(channel), mSharedMessage(NULL) {
+}
+
+InputConsumer::~InputConsumer() {
+ if (mSharedMessage) {
+ munmap(mSharedMessage, mAshmemSize);
+ }
+}
+
+status_t InputConsumer::initialize() {
+#if DEBUG_TRANSPORT_ACTIONS
+ LOGD("channel '%s' consumer ~ initialize",
+ mChannel->getName().string());
+#endif
+
+ int ashmemFd = mChannel->getAshmemFd();
+ int result = ashmem_get_size_region(ashmemFd);
+ if (result < 0) {
+ LOGE("channel '%s' consumer ~ Error %d getting size of ashmem fd %d.",
+ mChannel->getName().string(), result, ashmemFd);
+ return UNKNOWN_ERROR;
+ }
+
+ mAshmemSize = (size_t) result;
+
+ mSharedMessage = static_cast<InputMessage*>(mmap(NULL, mAshmemSize,
+ PROT_READ | PROT_WRITE, MAP_SHARED, ashmemFd, 0));
+ if (! mSharedMessage) {
+ LOGE("channel '%s' consumer ~ mmap failed on ashmem fd %d.",
+ mChannel->getName().string(), ashmemFd);
+ return NO_MEMORY;
+ }
+
+ return OK;
+}
+
+status_t InputConsumer::consume(InputEventFactoryInterface* factory, InputEvent** event) {
+#if DEBUG_TRANSPORT_ACTIONS
+ LOGD("channel '%s' consumer ~ consume",
+ mChannel->getName().string());
+#endif
+
+ *event = NULL;
+
+ int ashmemFd = mChannel->getAshmemFd();
+ int result = ashmem_pin_region(ashmemFd, 0, 0);
+ if (result != ASHMEM_NOT_PURGED) {
+ if (result == ASHMEM_WAS_PURGED) {
+ LOGE("channel '%s' consumer ~ Error %d pinning ashmem fd %d because it was purged "
+ "which probably indicates that the publisher and consumer are out of sync.",
+ mChannel->getName().string(), result, ashmemFd);
+ return INVALID_OPERATION;
+ }
+
+ LOGE("channel '%s' consumer ~ Error %d pinning ashmem fd %d.",
+ mChannel->getName().string(), result, ashmemFd);
+ return UNKNOWN_ERROR;
+ }
+
+ if (mSharedMessage->consumed) {
+ LOGE("channel '%s' consumer ~ The current message has already been consumed.",
+ mChannel->getName().string());
+ return INVALID_OPERATION;
+ }
+
+ // Acquire but *never release* the semaphore. Contention on the semaphore is used to signal
+ // to the publisher that the message has been consumed (or is in the process of being
+ // consumed). Eventually the publisher will reinitialize the semaphore for the next message.
+ result = sem_wait(& mSharedMessage->semaphore);
+ if (result < 0) {
+ LOGE("channel '%s' consumer ~ Error %d in sem_wait.",
+ mChannel->getName().string(), errno);
+ return UNKNOWN_ERROR;
+ }
+
+ mSharedMessage->consumed = true;
+
+ switch (mSharedMessage->type) {
+ case INPUT_EVENT_TYPE_KEY: {
+ KeyEvent* keyEvent = factory->createKeyEvent();
+ if (! keyEvent) return NO_MEMORY;
+
+ populateKeyEvent(keyEvent);
+
+ *event = keyEvent;
+ break;
+ }
+
+ case INPUT_EVENT_TYPE_MOTION: {
+ MotionEvent* motionEvent = factory->createMotionEvent();
+ if (! motionEvent) return NO_MEMORY;
+
+ populateMotionEvent(motionEvent);
+
+ *event = motionEvent;
+ break;
+ }
+
+ default:
+ LOGE("channel '%s' consumer ~ Received message of unknown type %d",
+ mChannel->getName().string(), mSharedMessage->type);
+ return UNKNOWN_ERROR;
+ }
+
+ return OK;
+}
+
+status_t InputConsumer::sendFinishedSignal() {
+#if DEBUG_TRANSPORT_ACTIONS
+ LOGD("channel '%s' consumer ~ sendFinishedSignal",
+ mChannel->getName().string());
+#endif
+
+ return mChannel->sendSignal(INPUT_SIGNAL_FINISHED);
+}
+
+status_t InputConsumer::receiveDispatchSignal() {
+#if DEBUG_TRANSPORT_ACTIONS
+ LOGD("channel '%s' consumer ~ receiveDispatchSignal",
+ mChannel->getName().string());
+#endif
+
+ char signal;
+ status_t result = mChannel->receiveSignal(& signal);
+ if (result) {
+ return result;
+ }
+ if (signal != INPUT_SIGNAL_DISPATCH) {
+ LOGE("channel '%s' consumer ~ Received unexpected signal '%c' from publisher",
+ mChannel->getName().string(), signal);
+ return UNKNOWN_ERROR;
+ }
+ return OK;
+}
+
+void InputConsumer::populateKeyEvent(KeyEvent* keyEvent) const {
+ keyEvent->initialize(
+ mSharedMessage->deviceId,
+ mSharedMessage->nature,
+ mSharedMessage->key.action,
+ mSharedMessage->key.flags,
+ mSharedMessage->key.keyCode,
+ mSharedMessage->key.scanCode,
+ mSharedMessage->key.metaState,
+ mSharedMessage->key.repeatCount,
+ mSharedMessage->key.downTime,
+ mSharedMessage->key.eventTime);
+}
+
+void InputConsumer::populateMotionEvent(MotionEvent* motionEvent) const {
+ motionEvent->initialize(
+ mSharedMessage->deviceId,
+ mSharedMessage->nature,
+ mSharedMessage->motion.action,
+ mSharedMessage->motion.edgeFlags,
+ mSharedMessage->motion.metaState,
+ mSharedMessage->motion.sampleData[0].coords[0].x,
+ mSharedMessage->motion.sampleData[0].coords[0].y,
+ mSharedMessage->motion.xPrecision,
+ mSharedMessage->motion.yPrecision,
+ mSharedMessage->motion.downTime,
+ mSharedMessage->motion.sampleData[0].eventTime,
+ mSharedMessage->motion.pointerCount,
+ mSharedMessage->motion.pointerIds,
+ mSharedMessage->motion.sampleData[0].coords);
+
+ size_t sampleCount = mSharedMessage->motion.sampleCount;
+ if (sampleCount > 1) {
+ InputMessage::SampleData* sampleData = mSharedMessage->motion.sampleData;
+ size_t sampleDataStride = InputMessage::sampleDataStride(
+ mSharedMessage->motion.pointerCount);
+
+ while (--sampleCount > 0) {
+ sampleData = InputMessage::sampleDataPtrIncrement(sampleData, sampleDataStride);
+ motionEvent->addSample(sampleData->eventTime, sampleData->coords);
+ }
+ }
+
+ motionEvent->offsetLocation(mSharedMessage->motion.xOffset,
+ mSharedMessage->motion.yOffset);
+}
+
+} // namespace android
diff --git a/libs/ui/tests/Android.mk b/libs/ui/tests/Android.mk
index 6cc4a5a..018f18d 100644
--- a/libs/ui/tests/Android.mk
+++ b/libs/ui/tests/Android.mk
@@ -1,16 +1,38 @@
+# Build the unit tests.
LOCAL_PATH:= $(call my-dir)
include $(CLEAR_VARS)
-LOCAL_SRC_FILES:= \
- region.cpp
+test_src_files := \
+ InputDispatcher_test.cpp
LOCAL_SHARED_LIBRARIES := \
libcutils \
libutils \
- libui
+ libEGL \
+ libbinder \
+ libpixelflinger \
+ libhardware \
+ libhardware_legacy \
+ libui \
+ libstlport
-LOCAL_MODULE:= test-region
+LOCAL_STATIC_LIBRARIES := \
+ libgtest \
+ libgtest_main
-LOCAL_MODULE_TAGS := tests
+LOCAL_C_INCLUDES := \
+ bionic \
+ bionic/libstdc++/include \
+ external/gtest/include \
+ external/stlport/stlport
-include $(BUILD_EXECUTABLE)
+LOCAL_MODULE_TAGS := eng tests
+
+$(foreach file,$(test_src_files), \
+ $(eval LOCAL_SRC_FILES := $(file)) \
+ $(eval LOCAL_MODULE := $(notdir $(file:%.cpp=%))) \
+ $(eval include $(BUILD_EXECUTABLE)) \
+)
+
+# Build the manual test programs.
+include $(call all-subdir-makefiles)
diff --git a/libs/ui/tests/InputDispatcher_test.cpp b/libs/ui/tests/InputDispatcher_test.cpp
new file mode 100644
index 0000000..3d92043
--- /dev/null
+++ b/libs/ui/tests/InputDispatcher_test.cpp
@@ -0,0 +1,19 @@
+//
+// Copyright 2010 The Android Open Source Project
+//
+
+#include <ui/InputDispatcher.h>
+#include <gtest/gtest.h>
+
+namespace android {
+
+class InputDispatcherTest : public testing::Test {
+public:
+};
+
+TEST_F(InputDispatcherTest, Dummy) {
+ SCOPED_TRACE("Trace");
+ ASSERT_FALSE(true);
+}
+
+} // namespace android
diff --git a/libs/ui/tests/region/Android.mk b/libs/ui/tests/region/Android.mk
new file mode 100644
index 0000000..6cc4a5a
--- /dev/null
+++ b/libs/ui/tests/region/Android.mk
@@ -0,0 +1,16 @@
+LOCAL_PATH:= $(call my-dir)
+include $(CLEAR_VARS)
+
+LOCAL_SRC_FILES:= \
+ region.cpp
+
+LOCAL_SHARED_LIBRARIES := \
+ libcutils \
+ libutils \
+ libui
+
+LOCAL_MODULE:= test-region
+
+LOCAL_MODULE_TAGS := tests
+
+include $(BUILD_EXECUTABLE)
diff --git a/libs/ui/tests/region.cpp b/libs/ui/tests/region/region.cpp
index ef15de9..ef15de9 100644
--- a/libs/ui/tests/region.cpp
+++ b/libs/ui/tests/region/region.cpp
diff --git a/libs/utils/Android.mk b/libs/utils/Android.mk
index afecdcb..7d4524a 100644
--- a/libs/utils/Android.mk
+++ b/libs/utils/Android.mk
@@ -26,6 +26,7 @@ commonSources:= \
Debug.cpp \
FileMap.cpp \
Flattenable.cpp \
+ Pool.cpp \
RefBase.cpp \
ResourceTypes.cpp \
SharedBuffer.cpp \
@@ -39,7 +40,7 @@ commonSources:= \
Threads.cpp \
Timers.cpp \
VectorImpl.cpp \
- ZipFileCRO.cpp \
+ ZipFileCRO.cpp \
ZipFileRO.cpp \
ZipUtils.cpp \
misc.cpp
@@ -76,8 +77,9 @@ include $(CLEAR_VARS)
# we have the common sources, plus some device-specific stuff
LOCAL_SRC_FILES:= \
$(commonSources) \
- BackupData.cpp \
- BackupHelpers.cpp
+ BackupData.cpp \
+ BackupHelpers.cpp \
+ PollLoop.cpp
ifeq ($(TARGET_OS),linux)
LOCAL_LDLIBS += -lrt -ldl
diff --git a/libs/utils/PollLoop.cpp b/libs/utils/PollLoop.cpp
new file mode 100644
index 0000000..90a3e8b
--- /dev/null
+++ b/libs/utils/PollLoop.cpp
@@ -0,0 +1,267 @@
+//
+// Copyright 2010 The Android Open Source Project
+//
+// A select loop implementation.
+//
+#define LOG_TAG "PollLoop"
+
+//#define LOG_NDEBUG 0
+
+// Debugs poll and wake interactions.
+#define DEBUG_POLL_AND_WAKE 0
+
+// Debugs callback registration and invocation.
+#define DEBUG_CALLBACKS 1
+
+#include <cutils/log.h>
+#include <utils/PollLoop.h>
+
+#include <unistd.h>
+#include <fcntl.h>
+
+namespace android {
+
+PollLoop::PollLoop() :
+ mPolling(false) {
+ openWakePipe();
+}
+
+PollLoop::~PollLoop() {
+ closeWakePipe();
+}
+
+void PollLoop::openWakePipe() {
+ int wakeFds[2];
+ int result = pipe(wakeFds);
+ LOG_ALWAYS_FATAL_IF(result != 0, "Could not create wake pipe. errno=%d", errno);
+
+ mWakeReadPipeFd = wakeFds[0];
+ mWakeWritePipeFd = wakeFds[1];
+
+ result = fcntl(mWakeReadPipeFd, F_SETFL, O_NONBLOCK);
+ LOG_ALWAYS_FATAL_IF(result != 0, "Could not make wake read pipe non-blocking. errno=%d",
+ errno);
+
+ result = fcntl(mWakeWritePipeFd, F_SETFL, O_NONBLOCK);
+ LOG_ALWAYS_FATAL_IF(result != 0, "Could not make wake write pipe non-blocking. errno=%d",
+ errno);
+
+ // Add the wake pipe to the head of the request list with a null callback.
+ struct pollfd requestedFd;
+ requestedFd.fd = mWakeReadPipeFd;
+ requestedFd.events = POLLIN;
+ mRequestedFds.insertAt(requestedFd, 0);
+
+ RequestedCallback requestedCallback;
+ requestedCallback.callback = NULL;
+ requestedCallback.data = NULL;
+ mRequestedCallbacks.insertAt(requestedCallback, 0);
+}
+
+void PollLoop::closeWakePipe() {
+ close(mWakeReadPipeFd);
+ close(mWakeWritePipeFd);
+
+ // Note: We don't need to remove the poll structure or callback entry because this
+ // method is currently only called by the destructor.
+}
+
+bool PollLoop::pollOnce(int timeoutMillis) {
+ mLock.lock();
+ mPolling = true;
+ mLock.unlock();
+
+ bool result;
+ size_t requestedCount = mRequestedFds.size();
+
+#if DEBUG_POLL_AND_WAKE
+ LOGD("%p ~ pollOnce - waiting on %d fds", this, requestedCount);
+ for (size_t i = 0; i < requestedCount; i++) {
+ LOGD(" fd %d - events %d", mRequestedFds[i].fd, mRequestedFds[i].events);
+ }
+#endif
+
+ int respondedCount = poll(mRequestedFds.editArray(), requestedCount, timeoutMillis);
+
+ if (respondedCount == 0) {
+ // Timeout
+#if DEBUG_POLL_AND_WAKE
+ LOGD("%p ~ pollOnce - timeout", this);
+#endif
+ result = false;
+ goto Done;
+ }
+
+ if (respondedCount < 0) {
+ // Error
+#if DEBUG_POLL_AND_WAKE
+ LOGD("%p ~ pollOnce - error, errno=%d", this, errno);
+#endif
+ if (errno != EINTR) {
+ LOGW("Poll failed with an unexpected error, errno=%d", errno);
+ }
+ result = false;
+ goto Done;
+ }
+
+#if DEBUG_POLL_AND_WAKE
+ LOGD("%p ~ pollOnce - handling responses from %d fds", this, respondedCount);
+ for (size_t i = 0; i < requestedCount; i++) {
+ LOGD(" fd %d - events %d, revents %d", mRequestedFds[i].fd, mRequestedFds[i].events,
+ mRequestedFds[i].revents);
+ }
+#endif
+
+ mPendingCallbacks.clear();
+ for (size_t i = 0; i < requestedCount; i++) {
+ const struct pollfd& requestedFd = mRequestedFds.itemAt(i);
+
+ short revents = requestedFd.revents;
+ if (revents) {
+ const RequestedCallback& requestedCallback = mRequestedCallbacks.itemAt(i);
+ Callback callback = requestedCallback.callback;
+
+ if (callback) {
+ PendingCallback pendingCallback;
+ pendingCallback.fd = requestedFd.fd;
+ pendingCallback.events = requestedFd.revents;
+ pendingCallback.callback = callback;
+ pendingCallback.data = requestedCallback.data;
+ mPendingCallbacks.push(pendingCallback);
+ } else {
+ if (requestedFd.fd == mWakeReadPipeFd) {
+#if DEBUG_POLL_AND_WAKE
+ LOGD("%p ~ pollOnce - awoken", this);
+#endif
+ char buffer[16];
+ ssize_t nRead;
+ do {
+ nRead = read(mWakeReadPipeFd, buffer, sizeof(buffer));
+ } while (nRead == sizeof(buffer));
+ } else {
+#if DEBUG_POLL_AND_WAKE || DEBUG_CALLBACKS
+ LOGD("%p ~ pollOnce - fd %d has no callback!", this, requestedFd.fd);
+#endif
+ }
+ }
+
+ respondedCount -= 1;
+ if (respondedCount == 0) {
+ break;
+ }
+ }
+ }
+ result = true;
+
+Done:
+ mLock.lock();
+ mPolling = false;
+ mAwake.broadcast();
+ mLock.unlock();
+
+ if (result) {
+ size_t pendingCount = mPendingCallbacks.size();
+ for (size_t i = 0; i < pendingCount; i++) {
+ const PendingCallback& pendingCallback = mPendingCallbacks.itemAt(i);
+#if DEBUG_POLL_AND_WAKE || DEBUG_CALLBACKS
+ LOGD("%p ~ pollOnce - invoking callback for fd %d", this, pendingCallback.fd);
+#endif
+
+ bool keep = pendingCallback.callback(pendingCallback.fd, pendingCallback.events,
+ pendingCallback.data);
+ if (! keep) {
+ removeCallback(pendingCallback.fd);
+ }
+ }
+ }
+
+#if DEBUG_POLL_AND_WAKE
+ LOGD("%p ~ pollOnce - done", this);
+#endif
+ return result;
+}
+
+void PollLoop::wake() {
+#if DEBUG_POLL_AND_WAKE
+ LOGD("%p ~ wake", this);
+#endif
+
+ ssize_t nWrite = write(mWakeWritePipeFd, "W", 1);
+ if (nWrite != 1) {
+ if (errno != EAGAIN) {
+ LOGW("Could not write wake signal, errno=%d", errno);
+ }
+ }
+}
+
+void PollLoop::setCallback(int fd, int events, Callback callback, void* data) {
+#if DEBUG_CALLBACKS
+ LOGD("%p ~ setCallback - fd=%d, events=%d", this, fd, events);
+#endif
+
+ if (! events || ! callback) {
+ LOGE("Invalid attempt to set a callback with no selected poll events or no callback.");
+ removeCallback(fd);
+ return;
+ }
+
+ wakeAndLock();
+
+ struct pollfd requestedFd;
+ requestedFd.fd = fd;
+ requestedFd.events = events;
+
+ RequestedCallback requestedCallback;
+ requestedCallback.callback = callback;
+ requestedCallback.data = data;
+
+ ssize_t index = getRequestIndexLocked(fd);
+ if (index < 0) {
+ mRequestedFds.push(requestedFd);
+ mRequestedCallbacks.push(requestedCallback);
+ } else {
+ mRequestedFds.replaceAt(requestedFd, size_t(index));
+ mRequestedCallbacks.replaceAt(requestedCallback, size_t(index));
+ }
+
+ mLock.unlock();
+}
+
+bool PollLoop::removeCallback(int fd) {
+#if DEBUG_CALLBACKS
+ LOGD("%p ~ removeCallback - fd=%d", this, fd);
+#endif
+
+ wakeAndLock();
+
+ ssize_t index = getRequestIndexLocked(fd);
+ if (index >= 0) {
+ mRequestedFds.removeAt(size_t(index));
+ mRequestedCallbacks.removeAt(size_t(index));
+ }
+
+ mLock.unlock();
+ return index >= 0;
+}
+
+ssize_t PollLoop::getRequestIndexLocked(int fd) {
+ size_t requestCount = mRequestedFds.size();
+
+ for (size_t i = 0; i < requestCount; i++) {
+ if (mRequestedFds.itemAt(i).fd == fd) {
+ return i;
+ }
+ }
+
+ return -1;
+}
+
+void PollLoop::wakeAndLock() {
+ mLock.lock();
+ while (mPolling) {
+ wake();
+ mAwake.wait(mLock);
+ }
+}
+
+} // namespace android
diff --git a/libs/utils/Pool.cpp b/libs/utils/Pool.cpp
new file mode 100644
index 0000000..8f18cb9
--- /dev/null
+++ b/libs/utils/Pool.cpp
@@ -0,0 +1,37 @@
+//
+// Copyright 2010 The Android Open Source Project
+//
+// A simple memory pool.
+//
+#define LOG_TAG "Pool"
+
+//#define LOG_NDEBUG 0
+
+#include <cutils/log.h>
+#include <utils/Pool.h>
+
+#include <stdlib.h>
+
+namespace android {
+
+// TODO Provide a real implementation of a pool. This is just a stub for initial development.
+
+PoolImpl::PoolImpl(size_t objSize) :
+ mObjSize(objSize) {
+}
+
+PoolImpl::~PoolImpl() {
+}
+
+void* PoolImpl::allocImpl() {
+ void* ptr = malloc(mObjSize);
+ LOG_ALWAYS_FATAL_IF(ptr == NULL, "Cannot allocate new pool object.");
+ return ptr;
+}
+
+void PoolImpl::freeImpl(void* obj) {
+ LOG_ALWAYS_FATAL_IF(obj == NULL, "Caller attempted to free NULL pool object.");
+ return free(obj);
+}
+
+} // namespace android
diff --git a/libs/utils/StopWatch.cpp b/libs/utils/StopWatch.cpp
index 68a1c52..b5dda2f 100644
--- a/libs/utils/StopWatch.cpp
+++ b/libs/utils/StopWatch.cpp
@@ -30,10 +30,9 @@ namespace android {
StopWatch::StopWatch(const char *name, int clock, uint32_t flags)
- : mName(name), mClock(clock), mFlags(flags),
- mStartTime(0), mNumLaps(0)
+ : mName(name), mClock(clock), mFlags(flags)
{
- mStartTime = systemTime(mClock);
+ reset();
}
StopWatch::~StopWatch()
@@ -72,6 +71,12 @@ nsecs_t StopWatch::elapsedTime() const
return systemTime(mClock) - mStartTime;
}
+void StopWatch::reset()
+{
+ mNumLaps = 0;
+ mStartTime = systemTime(mClock);
+}
+
/*****************************************************************************/
diff --git a/libs/utils/String8.cpp b/libs/utils/String8.cpp
index 636cd83..82776f4 100644
--- a/libs/utils/String8.cpp
+++ b/libs/utils/String8.cpp
@@ -301,8 +301,9 @@ void String8::setTo(const String8& other)
status_t String8::setTo(const char* other)
{
+ const char *newString = allocFromUTF8(other, strlen(other));
SharedBuffer::bufferFromData(mString)->release();
- mString = allocFromUTF8(other, strlen(other));
+ mString = newString;
if (mString) return NO_ERROR;
mString = getEmptyString();
@@ -311,8 +312,9 @@ status_t String8::setTo(const char* other)
status_t String8::setTo(const char* other, size_t len)
{
+ const char *newString = allocFromUTF8(other, len);
SharedBuffer::bufferFromData(mString)->release();
- mString = allocFromUTF8(other, len);
+ mString = newString;
if (mString) return NO_ERROR;
mString = getEmptyString();
@@ -321,8 +323,9 @@ status_t String8::setTo(const char* other, size_t len)
status_t String8::setTo(const char16_t* other, size_t len)
{
+ const char *newString = allocFromUTF16(other, len);
SharedBuffer::bufferFromData(mString)->release();
- mString = allocFromUTF16(other, len);
+ mString = newString;
if (mString) return NO_ERROR;
mString = getEmptyString();
@@ -331,8 +334,9 @@ status_t String8::setTo(const char16_t* other, size_t len)
status_t String8::setTo(const char32_t* other, size_t len)
{
+ const char *newString = allocFromUTF32(other, len);
SharedBuffer::bufferFromData(mString)->release();
- mString = allocFromUTF32(other, len);
+ mString = newString;
if (mString) return NO_ERROR;
mString = getEmptyString();
diff --git a/libs/utils/VectorImpl.cpp b/libs/utils/VectorImpl.cpp
index 0322af7..b09c6ca 100644
--- a/libs/utils/VectorImpl.cpp
+++ b/libs/utils/VectorImpl.cpp
@@ -108,13 +108,7 @@ size_t VectorImpl::capacity() const
ssize_t VectorImpl::insertVectorAt(const VectorImpl& vector, size_t index)
{
- if (index > size())
- return BAD_INDEX;
- void* where = _grow(index, vector.size());
- if (where) {
- _do_copy(where, vector.arrayImpl(), vector.size());
- }
- return where ? index : (ssize_t)NO_MEMORY;
+ return insertAt(vector.arrayImpl(), index, vector.size());
}
ssize_t VectorImpl::appendVector(const VectorImpl& vector)
@@ -226,9 +220,9 @@ ssize_t VectorImpl::add()
return add(0);
}
-ssize_t VectorImpl::add(const void* item)
+ssize_t VectorImpl::add(const void* item, size_t numItems)
{
- return insertAt(item, size());
+ return insertAt(item, size(), numItems);
}
ssize_t VectorImpl::replaceAt(size_t index)
diff --git a/libs/utils/tests/Android.mk b/libs/utils/tests/Android.mk
new file mode 100644
index 0000000..45e8061
--- /dev/null
+++ b/libs/utils/tests/Android.mk
@@ -0,0 +1,33 @@
+# Build the unit tests.
+LOCAL_PATH := $(call my-dir)
+include $(CLEAR_VARS)
+
+test_src_files := \
+ PollLoop_test.cpp
+
+LOCAL_SHARED_LIBRARIES := \
+ libz \
+ liblog \
+ libcutils \
+ libutils \
+ libstlport
+
+LOCAL_STATIC_LIBRARIES := \
+ libgtest \
+ libgtest_main
+
+LOCAL_C_INCLUDES := \
+ external/zlib \
+ external/icu4c/common \
+ bionic \
+ bionic/libstdc++/include \
+ external/gtest/include \
+ external/stlport/stlport
+
+LOCAL_MODULE_TAGS := eng tests
+
+$(foreach file,$(test_src_files), \
+ $(eval LOCAL_SRC_FILES := $(file)) \
+ $(eval LOCAL_MODULE := $(notdir $(file:%.cpp=%))) \
+ $(eval include $(BUILD_EXECUTABLE)) \
+)
diff --git a/libs/utils/tests/PollLoop_test.cpp b/libs/utils/tests/PollLoop_test.cpp
new file mode 100644
index 0000000..6c719c8
--- /dev/null
+++ b/libs/utils/tests/PollLoop_test.cpp
@@ -0,0 +1,398 @@
+//
+// Copyright 2010 The Android Open Source Project
+//
+
+#include <utils/PollLoop.h>
+#include <utils/Timers.h>
+#include <utils/StopWatch.h>
+#include <gtest/gtest.h>
+#include <unistd.h>
+#include <time.h>
+
+#include "TestHelpers.h"
+
+// # of milliseconds to fudge stopwatch measurements
+#define TIMING_TOLERANCE_MS 25
+
+namespace android {
+
+class Pipe {
+public:
+ int sendFd;
+ int receiveFd;
+
+ Pipe() {
+ int fds[2];
+ ::pipe(fds);
+
+ receiveFd = fds[0];
+ sendFd = fds[1];
+ }
+
+ ~Pipe() {
+ ::close(sendFd);
+ ::close(receiveFd);
+ }
+
+ bool writeSignal() {
+ return ::write(sendFd, "*", 1) == 1;
+ }
+
+ bool readSignal() {
+ char buf[1];
+ return ::read(receiveFd, buf, 1) == 1;
+ }
+};
+
+class DelayedWake : public DelayedTask {
+ sp<PollLoop> mPollLoop;
+
+public:
+ DelayedWake(int delayMillis, const sp<PollLoop> pollLoop) :
+ DelayedTask(delayMillis), mPollLoop(pollLoop) {
+ }
+
+protected:
+ virtual void doTask() {
+ mPollLoop->wake();
+ }
+};
+
+class DelayedWriteSignal : public DelayedTask {
+ Pipe* mPipe;
+
+public:
+ DelayedWriteSignal(int delayMillis, Pipe* pipe) :
+ DelayedTask(delayMillis), mPipe(pipe) {
+ }
+
+protected:
+ virtual void doTask() {
+ mPipe->writeSignal();
+ }
+};
+
+class CallbackHandler {
+public:
+ void setCallback(const sp<PollLoop>& pollLoop, int fd, int events) {
+ pollLoop->setCallback(fd, events, staticHandler, this);
+ }
+
+protected:
+ virtual ~CallbackHandler() { }
+
+ virtual bool handler(int fd, int events) = 0;
+
+private:
+ static bool staticHandler(int fd, int events, void* data) {
+ return static_cast<CallbackHandler*>(data)->handler(fd, events);
+ }
+};
+
+class StubCallbackHandler : public CallbackHandler {
+public:
+ bool nextResult;
+ int callbackCount;
+
+ int fd;
+ int events;
+
+ StubCallbackHandler(bool nextResult) : nextResult(nextResult),
+ callbackCount(0), fd(-1), events(-1) {
+ }
+
+protected:
+ virtual bool handler(int fd, int events) {
+ callbackCount += 1;
+ this->fd = fd;
+ this->events = events;
+ return nextResult;
+ }
+};
+
+class PollLoopTest : public testing::Test {
+protected:
+ sp<PollLoop> mPollLoop;
+
+ virtual void SetUp() {
+ mPollLoop = new PollLoop();
+ }
+
+ virtual void TearDown() {
+ mPollLoop.clear();
+ }
+};
+
+
+TEST_F(PollLoopTest, PollOnce_WhenNonZeroTimeoutAndNotAwoken_WaitsForTimeoutAndReturnsFalse) {
+ StopWatch stopWatch("pollOnce");
+ bool result = mPollLoop->pollOnce(100);
+ int32_t elapsedMillis = ns2ms(stopWatch.elapsedTime());
+
+ EXPECT_NEAR(100, elapsedMillis, TIMING_TOLERANCE_MS)
+ << "elapsed time should approx. equal timeout";
+ EXPECT_FALSE(result)
+ << "pollOnce result should be false because timeout occurred";
+}
+
+TEST_F(PollLoopTest, PollOnce_WhenNonZeroTimeoutAndAwokenBeforeWaiting_ImmediatelyReturnsTrue) {
+ mPollLoop->wake();
+
+ StopWatch stopWatch("pollOnce");
+ bool result = mPollLoop->pollOnce(1000);
+ int32_t elapsedMillis = ns2ms(stopWatch.elapsedTime());
+
+ EXPECT_NEAR(0, elapsedMillis, TIMING_TOLERANCE_MS)
+ << "elapsed time should approx. zero because wake() was called before waiting";
+ EXPECT_TRUE(result)
+ << "pollOnce result should be true because loop was awoken";
+}
+
+TEST_F(PollLoopTest, PollOnce_WhenNonZeroTimeoutAndAwokenWhileWaiting_PromptlyReturnsTrue) {
+ sp<DelayedWake> delayedWake = new DelayedWake(100, mPollLoop);
+ delayedWake->run();
+
+ StopWatch stopWatch("pollOnce");
+ bool result = mPollLoop->pollOnce(1000);
+ int32_t elapsedMillis = ns2ms(stopWatch.elapsedTime());
+
+ EXPECT_NEAR(100, elapsedMillis, TIMING_TOLERANCE_MS)
+ << "elapsed time should approx. equal wake delay";
+ EXPECT_TRUE(result)
+ << "pollOnce result should be true because loop was awoken";
+}
+
+TEST_F(PollLoopTest, PollOnce_WhenZeroTimeoutAndNoRegisteredFDs_ImmediatelyReturnsFalse) {
+ StopWatch stopWatch("pollOnce");
+ bool result = mPollLoop->pollOnce(0);
+ int32_t elapsedMillis = ns2ms(stopWatch.elapsedTime());
+
+ EXPECT_NEAR(0, elapsedMillis, TIMING_TOLERANCE_MS)
+ << "elapsed time should be approx. zero";
+ EXPECT_FALSE(result)
+ << "pollOnce result should be false because timeout occurred";
+}
+
+TEST_F(PollLoopTest, PollOnce_WhenZeroTimeoutAndNoSignalledFDs_ImmediatelyReturnsFalse) {
+ Pipe pipe;
+ StubCallbackHandler handler(true);
+
+ handler.setCallback(mPollLoop, pipe.receiveFd, POLL_IN);
+
+ StopWatch stopWatch("pollOnce");
+ bool result = mPollLoop->pollOnce(0);
+ int32_t elapsedMillis = ns2ms(stopWatch.elapsedTime());
+
+ EXPECT_NEAR(0, elapsedMillis, TIMING_TOLERANCE_MS)
+ << "elapsed time should be approx. zero";
+ EXPECT_FALSE(result)
+ << "pollOnce result should be false because timeout occurred";
+ EXPECT_EQ(0, handler.callbackCount)
+ << "callback should not have been invoked because FD was not signalled";
+}
+
+TEST_F(PollLoopTest, PollOnce_WhenZeroTimeoutAndSignalledFD_ImmediatelyInvokesCallbackAndReturnsTrue) {
+ Pipe pipe;
+ StubCallbackHandler handler(true);
+
+ ASSERT_TRUE(pipe.writeSignal());
+ handler.setCallback(mPollLoop, pipe.receiveFd, POLL_IN);
+
+ StopWatch stopWatch("pollOnce");
+ bool result = mPollLoop->pollOnce(0);
+ int32_t elapsedMillis = ns2ms(stopWatch.elapsedTime());
+
+ EXPECT_NEAR(0, elapsedMillis, TIMING_TOLERANCE_MS)
+ << "elapsed time should be approx. zero";
+ EXPECT_TRUE(result)
+ << "pollOnce result should be true because FD was signalled";
+ EXPECT_EQ(1, handler.callbackCount)
+ << "callback should be invoked exactly once";
+ EXPECT_EQ(pipe.receiveFd, handler.fd)
+ << "callback should have received pipe fd as parameter";
+ EXPECT_EQ(POLL_IN, handler.events)
+ << "callback should have received POLL_IN as events";
+}
+
+TEST_F(PollLoopTest, PollOnce_WhenNonZeroTimeoutAndNoSignalledFDs_WaitsForTimeoutAndReturnsFalse) {
+ Pipe pipe;
+ StubCallbackHandler handler(true);
+
+ handler.setCallback(mPollLoop, pipe.receiveFd, POLL_IN);
+
+ StopWatch stopWatch("pollOnce");
+ bool result = mPollLoop->pollOnce(100);
+ int32_t elapsedMillis = ns2ms(stopWatch.elapsedTime());
+
+ EXPECT_NEAR(100, elapsedMillis, TIMING_TOLERANCE_MS)
+ << "elapsed time should approx. equal timeout";
+ EXPECT_FALSE(result)
+ << "pollOnce result should be false because timeout occurred";
+ EXPECT_EQ(0, handler.callbackCount)
+ << "callback should not have been invoked because FD was not signalled";
+}
+
+TEST_F(PollLoopTest, PollOnce_WhenNonZeroTimeoutAndSignalledFDBeforeWaiting_ImmediatelyInvokesCallbackAndReturnsTrue) {
+ Pipe pipe;
+ StubCallbackHandler handler(true);
+
+ pipe.writeSignal();
+ handler.setCallback(mPollLoop, pipe.receiveFd, POLL_IN);
+
+ StopWatch stopWatch("pollOnce");
+ bool result = mPollLoop->pollOnce(100);
+ int32_t elapsedMillis = ns2ms(stopWatch.elapsedTime());
+
+ ASSERT_TRUE(pipe.readSignal())
+ << "signal should actually have been written";
+ EXPECT_NEAR(0, elapsedMillis, TIMING_TOLERANCE_MS)
+ << "elapsed time should be approx. zero";
+ EXPECT_TRUE(result)
+ << "pollOnce result should be true because FD was signalled";
+ EXPECT_EQ(1, handler.callbackCount)
+ << "callback should be invoked exactly once";
+ EXPECT_EQ(pipe.receiveFd, handler.fd)
+ << "callback should have received pipe fd as parameter";
+ EXPECT_EQ(POLL_IN, handler.events)
+ << "callback should have received POLL_IN as events";
+}
+
+TEST_F(PollLoopTest, PollOnce_WhenNonZeroTimeoutAndSignalledFDWhileWaiting_PromptlyInvokesCallbackAndReturnsTrue) {
+ Pipe pipe;
+ StubCallbackHandler handler(true);
+ sp<DelayedWriteSignal> delayedWriteSignal = new DelayedWriteSignal(100, & pipe);
+
+ handler.setCallback(mPollLoop, pipe.receiveFd, POLL_IN);
+ delayedWriteSignal->run();
+
+ StopWatch stopWatch("pollOnce");
+ bool result = mPollLoop->pollOnce(1000);
+ int32_t elapsedMillis = ns2ms(stopWatch.elapsedTime());
+
+ ASSERT_TRUE(pipe.readSignal())
+ << "signal should actually have been written";
+ EXPECT_NEAR(100, elapsedMillis, TIMING_TOLERANCE_MS)
+ << "elapsed time should approx. equal signal delay";
+ EXPECT_TRUE(result)
+ << "pollOnce result should be true because FD was signalled";
+ EXPECT_EQ(1, handler.callbackCount)
+ << "callback should be invoked exactly once";
+ EXPECT_EQ(pipe.receiveFd, handler.fd)
+ << "callback should have received pipe fd as parameter";
+ EXPECT_EQ(POLL_IN, handler.events)
+ << "callback should have received POLL_IN as events";
+}
+
+TEST_F(PollLoopTest, PollOnce_WhenCallbackAddedThenRemoved_CallbackShouldNotBeInvoked) {
+ Pipe pipe;
+ StubCallbackHandler handler(true);
+
+ handler.setCallback(mPollLoop, pipe.receiveFd, POLL_IN);
+ pipe.writeSignal(); // would cause FD to be considered signalled
+ mPollLoop->removeCallback(pipe.receiveFd);
+
+ StopWatch stopWatch("pollOnce");
+ bool result = mPollLoop->pollOnce(100);
+ int32_t elapsedMillis = ns2ms(stopWatch.elapsedTime());
+
+ ASSERT_TRUE(pipe.readSignal())
+ << "signal should actually have been written";
+ EXPECT_NEAR(100, elapsedMillis, TIMING_TOLERANCE_MS)
+ << "elapsed time should approx. equal timeout because FD was no longer registered";
+ EXPECT_FALSE(result)
+ << "pollOnce result should be false because timeout occurred";
+ EXPECT_EQ(0, handler.callbackCount)
+ << "callback should not be invoked";
+}
+
+TEST_F(PollLoopTest, PollOnce_WhenCallbackReturnsFalse_CallbackShouldNotBeInvokedAgainLater) {
+ Pipe pipe;
+ StubCallbackHandler handler(false);
+
+ handler.setCallback(mPollLoop, pipe.receiveFd, POLL_IN);
+
+ // First loop: Callback is registered and FD is signalled.
+ pipe.writeSignal();
+
+ StopWatch stopWatch("pollOnce");
+ bool result = mPollLoop->pollOnce(0);
+ int32_t elapsedMillis = ns2ms(stopWatch.elapsedTime());
+
+ ASSERT_TRUE(pipe.readSignal())
+ << "signal should actually have been written";
+ EXPECT_NEAR(0, elapsedMillis, TIMING_TOLERANCE_MS)
+ << "elapsed time should approx. equal zero because FD was already signalled";
+ EXPECT_TRUE(result)
+ << "pollOnce result should be true because FD was signalled";
+ EXPECT_EQ(1, handler.callbackCount)
+ << "callback should be invoked";
+
+ // Second loop: Callback is no longer registered and FD is signalled.
+ pipe.writeSignal();
+
+ stopWatch.reset();
+ result = mPollLoop->pollOnce(0);
+ elapsedMillis = ns2ms(stopWatch.elapsedTime());
+
+ ASSERT_TRUE(pipe.readSignal())
+ << "signal should actually have been written";
+ EXPECT_NEAR(0, elapsedMillis, TIMING_TOLERANCE_MS)
+ << "elapsed time should approx. equal zero because timeout was zero";
+ EXPECT_FALSE(result)
+ << "pollOnce result should be false because timeout occurred";
+ EXPECT_EQ(1, handler.callbackCount)
+ << "callback should not be invoked this time";
+}
+
+TEST_F(PollLoopTest, RemoveCallback_WhenCallbackNotAdded_ReturnsFalse) {
+ bool result = mPollLoop->removeCallback(1);
+
+ EXPECT_FALSE(result)
+ << "removeCallback should return false because FD not registered";
+}
+
+TEST_F(PollLoopTest, RemoveCallback_WhenCallbackAddedThenRemovedTwice_ReturnsTrueFirstTimeAndReturnsFalseSecondTime) {
+ Pipe pipe;
+ StubCallbackHandler handler(false);
+ handler.setCallback(mPollLoop, pipe.receiveFd, POLL_IN);
+
+ // First time.
+ bool result = mPollLoop->removeCallback(pipe.receiveFd);
+
+ EXPECT_TRUE(result)
+ << "removeCallback should return true first time because FD was registered";
+
+ // Second time.
+ result = mPollLoop->removeCallback(pipe.receiveFd);
+
+ EXPECT_FALSE(result)
+ << "removeCallback should return false second time because FD was no longer registered";
+}
+
+TEST_F(PollLoopTest, PollOnce_WhenCallbackAddedTwice_OnlySecondCallbackShouldBeInvoked) {
+ Pipe pipe;
+ StubCallbackHandler handler1(true);
+ StubCallbackHandler handler2(true);
+
+ handler1.setCallback(mPollLoop, pipe.receiveFd, POLL_IN);
+ handler2.setCallback(mPollLoop, pipe.receiveFd, POLL_IN); // replace it
+ pipe.writeSignal(); // would cause FD to be considered signalled
+
+ StopWatch stopWatch("pollOnce");
+ bool result = mPollLoop->pollOnce(100);
+ int32_t elapsedMillis = ns2ms(stopWatch.elapsedTime());
+
+ ASSERT_TRUE(pipe.readSignal())
+ << "signal should actually have been written";
+ EXPECT_NEAR(0, elapsedMillis, TIMING_TOLERANCE_MS)
+ << "elapsed time should approx. zero because FD was already signalled";
+ EXPECT_TRUE(result)
+ << "pollOnce result should be true because FD was signalled";
+ EXPECT_EQ(0, handler1.callbackCount)
+ << "original handler callback should not be invoked because it was replaced";
+ EXPECT_EQ(1, handler2.callbackCount)
+ << "replacement handler callback should be invoked";
+}
+
+
+} // namespace android
diff --git a/libs/utils/tests/TestHelpers.h b/libs/utils/tests/TestHelpers.h
new file mode 100644
index 0000000..e55af3c
--- /dev/null
+++ b/libs/utils/tests/TestHelpers.h
@@ -0,0 +1,44 @@
+/*
+ * 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 TESTHELPERS_H
+#define TESTHELPERS_H
+
+#include <utils/threads.h>
+
+namespace android {
+
+class DelayedTask : public Thread {
+ int mDelayMillis;
+
+public:
+ DelayedTask(int delayMillis) : mDelayMillis(delayMillis) { }
+
+protected:
+ virtual ~DelayedTask() { }
+
+ virtual void doTask() = 0;
+
+ virtual bool threadLoop() {
+ usleep(mDelayMillis * 1000);
+ doTask();
+ return false;
+ }
+};
+
+} // namespace android
+
+#endif // TESTHELPERS_H
diff --git a/opengl/include/EGL/egl.h b/opengl/include/EGL/egl.h
index c269976..99ea342 100644
--- a/opengl/include/EGL/egl.h
+++ b/opengl/include/EGL/egl.h
@@ -1,7 +1,7 @@
/* -*- mode: c; tab-width: 8; -*- */
/* vi: set sw=4 ts=8: */
/* Reference version of egl.h for EGL 1.4.
- * $Revision: 7244 $ on $Date: 2009-01-20 17:06:59 -0800 (Tue, 20 Jan 2009) $
+ * $Revision: 9356 $ on $Date: 2009-10-21 02:52:25 -0700 (Wed, 21 Oct 2009) $
*/
/*
@@ -109,7 +109,6 @@ typedef void *EGLClientBuffer;
#define EGL_NATIVE_RENDERABLE 0x302D
#define EGL_NATIVE_VISUAL_ID 0x302E
#define EGL_NATIVE_VISUAL_TYPE 0x302F
-#define EGL_PRESERVED_RESOURCES 0x3030
#define EGL_SAMPLES 0x3031
#define EGL_SAMPLE_BUFFERS 0x3032
#define EGL_SURFACE_TYPE 0x3033
diff --git a/opengl/include/EGL/eglext.h b/opengl/include/EGL/eglext.h
index 545fd0e..b121158 100644
--- a/opengl/include/EGL/eglext.h
+++ b/opengl/include/EGL/eglext.h
@@ -6,7 +6,7 @@ extern "C" {
#endif
/*
-** Copyright (c) 2007-2009 The Khronos Group Inc.
+** Copyright (c) 2007-2010 The Khronos Group Inc.
**
** Permission is hereby granted, free of charge, to any person obtaining a
** copy of this software and/or associated documentation files (the
@@ -34,8 +34,8 @@ extern "C" {
/* Header file version number */
/* Current version at http://www.khronos.org/registry/egl/ */
-/* $Revision: 7244 $ on $Date: 2009-01-20 17:06:59 -0800 (Tue, 20 Jan 2009) $ */
-#define EGL_EGLEXT_VERSION 3
+/* $Revision: 11249 $ on $Date: 2010-05-05 09:54:28 -0700 (Wed, 05 May 2010) $ */
+#define EGL_EGLEXT_VERSION 5
#ifndef EGL_KHR_config_attribs
#define EGL_KHR_config_attribs 1
@@ -120,6 +120,36 @@ typedef EGLBoolean (EGLAPIENTRYP PFNEGLDESTROYIMAGEKHRPROC) (EGLDisplay dpy, EGL
#define EGL_GL_RENDERBUFFER_KHR 0x30B9 /* eglCreateImageKHR target */
#endif
+#ifndef EGL_KHR_reusable_sync
+#define EGL_KHR_reusable_sync 1
+
+typedef void* EGLSyncKHR;
+typedef khronos_utime_nanoseconds_t EGLTimeKHR;
+
+#define EGL_SYNC_STATUS_KHR 0x30F1
+#define EGL_SIGNALED_KHR 0x30F2
+#define EGL_UNSIGNALED_KHR 0x30F3
+#define EGL_TIMEOUT_EXPIRED_KHR 0x30F5
+#define EGL_CONDITION_SATISFIED_KHR 0x30F6
+#define EGL_SYNC_TYPE_KHR 0x30F7
+#define EGL_SYNC_REUSABLE_KHR 0x30FA
+#define EGL_SYNC_FLUSH_COMMANDS_BIT_KHR 0x0001 /* eglClientWaitSyncKHR <flags> bitfield */
+#define EGL_FOREVER_KHR 0xFFFFFFFFFFFFFFFFull
+#define EGL_NO_SYNC_KHR ((EGLSyncKHR)0)
+#ifdef EGL_EGLEXT_PROTOTYPES
+EGLAPI EGLSyncKHR EGLAPIENTRY eglCreateSyncKHR(EGLDisplay dpy, EGLenum type, const EGLint *attrib_list);
+EGLAPI EGLBoolean EGLAPIENTRY eglDestroySyncKHR(EGLDisplay dpy, EGLSyncKHR sync);
+EGLAPI EGLint EGLAPIENTRY eglClientWaitSyncKHR(EGLDisplay dpy, EGLSyncKHR sync, EGLint flags, EGLTimeKHR timeout);
+EGLAPI EGLBoolean EGLAPIENTRY eglSignalSyncKHR(EGLDisplay dpy, EGLSyncKHR sync, EGLenum mode);
+EGLAPI EGLBoolean EGLAPIENTRY eglGetSyncAttribKHR(EGLDisplay dpy, EGLSyncKHR sync, EGLint attribute, EGLint *value);
+#endif /* EGL_EGLEXT_PROTOTYPES */
+typedef EGLSyncKHR (EGLAPIENTRYP PFNEGLCREATESYNCKHRPROC) (EGLDisplay dpy, EGLenum type, const EGLint *attrib_list);
+typedef EGLBoolean (EGLAPIENTRYP PFNEGLDESTROYSYNCKHRPROC) (EGLDisplay dpy, EGLSyncKHR sync);
+typedef EGLint (EGLAPIENTRYP PFNEGLCLIENTWAITSYNCKHRPROC) (EGLDisplay dpy, EGLSyncKHR sync, EGLint flags, EGLTimeKHR timeout);
+typedef EGLBoolean (EGLAPIENTRYP PFNEGLSIGNALSYNCKHRPROC) (EGLDisplay dpy, EGLSyncKHR sync, EGLenum mode);
+typedef EGLBoolean (EGLAPIENTRYP PFNEGLGETSYNCATTRIBKHRPROC) (EGLDisplay dpy, EGLSyncKHR sync, EGLint attribute, EGLint *value);
+#endif
+
#ifndef EGL_KHR_image_base
#define EGL_KHR_image_base 1
/* Most interfaces defined by EGL_KHR_image_pixmap above */
@@ -131,6 +161,67 @@ typedef EGLBoolean (EGLAPIENTRYP PFNEGLDESTROYIMAGEKHRPROC) (EGLDisplay dpy, EGL
/* Interfaces defined by EGL_KHR_image above */
#endif
+#ifndef EGL_IMG_context_priority
+#define EGL_IMG_context_priority 1
+#define EGL_CONTEXT_PRIORITY_LEVEL_IMG 0x3100
+#define EGL_CONTEXT_PRIORITY_HIGH_IMG 0x3101
+#define EGL_CONTEXT_PRIORITY_MEDIUM_IMG 0x3102
+#define EGL_CONTEXT_PRIORITY_LOW_IMG 0x3103
+#endif
+
+#ifndef EGL_NV_coverage_sample
+#define EGL_NV_coverage_sample 1
+#define EGL_COVERAGE_BUFFERS_NV 0x30E0
+#define EGL_COVERAGE_SAMPLES_NV 0x30E1
+#endif
+
+#ifndef EGL_NV_depth_nonlinear
+#define EGL_NV_depth_nonlinear 1
+#define EGL_DEPTH_ENCODING_NV 0x30E2
+#define EGL_DEPTH_ENCODING_NONE_NV 0
+#define EGL_DEPTH_ENCODING_NONLINEAR_NV 0x30E3
+#endif
+
+#ifndef EGL_NV_sync
+#define EGL_NV_sync 1
+#define EGL_SYNC_PRIOR_COMMANDS_COMPLETE_NV 0x30E6
+#define EGL_SYNC_STATUS_NV 0x30E7
+#define EGL_SIGNALED_NV 0x30E8
+#define EGL_UNSIGNALED_NV 0x30E9
+#define EGL_SYNC_FLUSH_COMMANDS_BIT_NV 0x0001
+#define EGL_FOREVER_NV 0xFFFFFFFFFFFFFFFFull
+#define EGL_ALREADY_SIGNALED_NV 0x30EA
+#define EGL_TIMEOUT_EXPIRED_NV 0x30EB
+#define EGL_CONDITION_SATISFIED_NV 0x30EC
+#define EGL_SYNC_TYPE_NV 0x30ED
+#define EGL_SYNC_CONDITION_NV 0x30EE
+#define EGL_SYNC_FENCE_NV 0x30EF
+#define EGL_NO_SYNC_NV ((EGLSyncNV)0)
+typedef void* EGLSyncNV;
+typedef unsigned long long EGLTimeNV;
+#ifdef EGL_EGLEXT_PROTOTYPES
+EGLSyncNV eglCreateFenceSyncNV (EGLDisplay dpy, EGLenum condition, const EGLint *attrib_list);
+EGLBoolean eglDestroySyncNV (EGLSyncNV sync);
+EGLBoolean eglFenceNV (EGLSyncNV sync);
+EGLint eglClientWaitSyncNV (EGLSyncNV sync, EGLint flags, EGLTimeNV timeout);
+EGLBoolean eglSignalSyncNV (EGLSyncNV sync, EGLenum mode);
+EGLBoolean eglGetSyncAttribNV (EGLSyncNV sync, EGLint attribute, EGLint *value);
+#endif /* EGL_EGLEXT_PROTOTYPES */
+typedef EGLSyncNV (EGLAPIENTRYP PFNEGLCREATEFENCESYNCNVPROC) (EGLDisplay dpy, EGLenum condition, const EGLint *attrib_list);
+typedef EGLBoolean (EGLAPIENTRYP PFNEGLDESTROYSYNCNVPROC) (EGLSyncNV sync);
+typedef EGLBoolean (EGLAPIENTRYP PFNEGLFENCENVPROC) (EGLSyncNV sync);
+typedef EGLint (EGLAPIENTRYP PFNEGLCLIENTWAITSYNCNVPROC) (EGLSyncNV sync, EGLint flags, EGLTimeNV timeout);
+typedef EGLBoolean (EGLAPIENTRYP PFNEGLSIGNALSYNCNVPROC) (EGLSyncNV sync, EGLenum mode);
+typedef EGLBoolean (EGLAPIENTRYP PFNEGLGETSYNCATTRIBNVPROC) (EGLSyncNV sync, EGLint attribute, EGLint *value);
+#endif
+
+#ifndef EGL_KHR_fence_sync
+#define EGL_KHR_fence_sync 1
+/* Reuses most tokens and entry points from EGL_KHR_reusable_sync */
+#define EGL_SYNC_PRIOR_COMMANDS_COMPLETE_KHR 0x30F0
+#define EGL_SYNC_CONDITION_KHR 0x30F8
+#define EGL_SYNC_FENCE_KHR 0x30F9
+#endif
#ifndef EGL_ANDROID_image_native_buffer
#define EGL_ANDROID_image_native_buffer 1
@@ -154,7 +245,6 @@ EGLAPI EGLBoolean EGLAPIENTRY eglSetSwapRectangleANDROID (EGLDisplay dpy, EGLSur
typedef EGLBoolean (EGLAPIENTRYP PFNEGLSETSWAPRECTANGLEANDROIDPROC) (EGLDisplay dpy, EGLSurface draw, EGLint left, EGLint top, EGLint width, EGLint height);
#endif
-
#ifdef __cplusplus
}
#endif
diff --git a/opengl/include/EGL/eglplatform.h b/opengl/include/EGL/eglplatform.h
index 53e9e61..a2c6a7d 100644
--- a/opengl/include/EGL/eglplatform.h
+++ b/opengl/include/EGL/eglplatform.h
@@ -25,7 +25,7 @@
*/
/* Platform-specific types and definitions for egl.h
- * $Revision: 7244 $ on $Date: 2009-01-20 17:06:59 -0800 (Tue, 20 Jan 2009) $
+ * $Revision: 9724 $ on $Date: 2009-12-02 02:05:33 -0800 (Wed, 02 Dec 2009) $
*
* Adopters may modify khrplatform.h and this file to suit their platform.
* You are encouraged to submit all modifications to the Khronos group so that
@@ -50,8 +50,10 @@
#define EGLAPI KHRONOS_APICALL
#endif
+#ifndef EGLAPIENTRY
#define EGLAPIENTRY KHRONOS_APIENTRY
-#define EGLAPIENTRYP KHRONOS_APIENTRY*
+#endif
+#define EGLAPIENTRYP EGLAPIENTRY*
/* The types NativeDisplayType, NativeWindowType, and NativePixmapType
* are aliases of window-system-dependent types, such as X Display * or
diff --git a/opengl/include/GLES/gl.h b/opengl/include/GLES/gl.h
index 2e8b971..5b8d85a 100644
--- a/opengl/include/GLES/gl.h
+++ b/opengl/include/GLES/gl.h
@@ -1,7 +1,7 @@
#ifndef __gl_h_
#define __gl_h_
-/* $Revision: 7172 $ on $Date:: 2009-01-09 11:17:41 -0800 #$ */
+/* $Revision: 10601 $ on $Date:: 2010-03-04 22:15:27 -0800 #$ */
#include <GLES/glplatform.h>
@@ -15,6 +15,7 @@ extern "C" {
*/
typedef void GLvoid;
+typedef char GLchar;
typedef unsigned int GLenum;
typedef unsigned char GLboolean;
typedef unsigned int GLbitfield;
@@ -678,7 +679,7 @@ GL_API void GL_APIENTRY glGetFixedv (GLenum pname, GLfixed *params);
GL_API void GL_APIENTRY glGetIntegerv (GLenum pname, GLint *params);
GL_API void GL_APIENTRY glGetLightxv (GLenum light, GLenum pname, GLfixed *params);
GL_API void GL_APIENTRY glGetMaterialxv (GLenum face, GLenum pname, GLfixed *params);
-GL_API void GL_APIENTRY glGetPointerv (GLenum pname, void **params);
+GL_API void GL_APIENTRY glGetPointerv (GLenum pname, GLvoid **params);
GL_API const GLubyte * GL_APIENTRY glGetString (GLenum name);
GL_API void GL_APIENTRY glGetTexEnviv (GLenum env, GLenum pname, GLint *params);
GL_API void GL_APIENTRY glGetTexEnvxv (GLenum env, GLenum pname, GLfixed *params);
diff --git a/opengl/include/GLES/glext.h b/opengl/include/GLES/glext.h
index a8fe2e9..9596148 100644
--- a/opengl/include/GLES/glext.h
+++ b/opengl/include/GLES/glext.h
@@ -1,7 +1,7 @@
#ifndef __glext_h_
#define __glext_h_
-/* $Revision: 7172 $ on $Date:: 2009-01-09 11:17:41 -0800 #$ */
+/* $Revision: 10965 $ on $Date:: 2010-04-09 02:11:29 -0700 #$ */
#ifdef __cplusplus
extern "C" {
@@ -68,6 +68,11 @@ extern "C" {
typedef void* GLeglImageOES;
#endif
+/* GL_OES_element_index_uint */
+#ifndef GL_OES_element_index_uint
+#define GL_UNSIGNED_INT 0x1405
+#endif
+
/* GL_OES_fixed_point */
#ifndef GL_OES_fixed_point
#define GL_FIXED_OES 0x140C
@@ -201,6 +206,11 @@ typedef void* GLeglImageOES;
#define GL_MIRRORED_REPEAT_OES 0x8370
#endif
+/* GL_OES_vertex_array_object */
+#ifndef GL_OES_vertex_array_object
+#define GL_VERTEX_ARRAY_BINDING_OES 0x85B5
+#endif
+
/*------------------------------------------------------------------------*
* AMD extension tokens
*------------------------------------------------------------------------*/
@@ -219,15 +229,191 @@ typedef void* GLeglImageOES;
#endif
/*------------------------------------------------------------------------*
+ * APPLE extension tokens
+ *------------------------------------------------------------------------*/
+
+/* GL_APPLE_texture_2D_limited_npot */
+/* No new tokens introduced by this extension. */
+
+/*------------------------------------------------------------------------*
* EXT extension tokens
*------------------------------------------------------------------------*/
+/* GL_EXT_blend_minmax */
+#ifndef GL_EXT_blend_minmax
+#define GL_MIN_EXT 0x8007
+#define GL_MAX_EXT 0x8008
+#endif
+
+/* GL_EXT_discard_framebuffer */
+#ifndef GL_EXT_discard_framebuffer
+#define GL_COLOR_EXT 0x1800
+#define GL_DEPTH_EXT 0x1801
+#define GL_STENCIL_EXT 0x1802
+#endif
+
+/* GL_EXT_multi_draw_arrays */
+/* No new tokens introduced by this extension. */
+
+/* GL_EXT_read_format_bgra */
+#ifndef GL_EXT_read_format_bgra
+#define GL_BGRA_EXT 0x80E1
+#define GL_UNSIGNED_SHORT_4_4_4_4_REV_EXT 0x8365
+#define GL_UNSIGNED_SHORT_1_5_5_5_REV_EXT 0x8366
+#endif
+
/* GL_EXT_texture_filter_anisotropic */
#ifndef GL_EXT_texture_filter_anisotropic
#define GL_TEXTURE_MAX_ANISOTROPY_EXT 0x84FE
#define GL_MAX_TEXTURE_MAX_ANISOTROPY_EXT 0x84FF
#endif
+/* GL_EXT_texture_format_BGRA8888 */
+#ifndef GL_EXT_texture_format_BGRA8888
+#define GL_BGRA_EXT 0x80E1
+#endif
+
+/* GL_EXT_texture_lod_bias */
+#ifndef GL_EXT_texture_lod_bias
+#define GL_MAX_TEXTURE_LOD_BIAS_EXT 0x84FD
+#define GL_TEXTURE_FILTER_CONTROL_EXT 0x8500
+#define GL_TEXTURE_LOD_BIAS_EXT 0x8501
+#endif
+
+/*------------------------------------------------------------------------*
+ * IMG extension tokens
+ *------------------------------------------------------------------------*/
+
+/* GL_IMG_read_format */
+#ifndef GL_IMG_read_format
+#define GL_BGRA_IMG 0x80E1
+#define GL_UNSIGNED_SHORT_4_4_4_4_REV_IMG 0x8365
+#endif
+
+/* GL_IMG_texture_compression_pvrtc */
+#ifndef GL_IMG_texture_compression_pvrtc
+#define GL_COMPRESSED_RGB_PVRTC_4BPPV1_IMG 0x8C00
+#define GL_COMPRESSED_RGB_PVRTC_2BPPV1_IMG 0x8C01
+#define GL_COMPRESSED_RGBA_PVRTC_4BPPV1_IMG 0x8C02
+#define GL_COMPRESSED_RGBA_PVRTC_2BPPV1_IMG 0x8C03
+#endif
+
+/* GL_IMG_texture_env_enhanced_fixed_function */
+#ifndef GL_IMG_texture_env_enhanced_fixed_function
+#define GL_MODULATE_COLOR_IMG 0x8C04
+#define GL_RECIP_ADD_SIGNED_ALPHA_IMG 0x8C05
+#define GL_TEXTURE_ALPHA_MODULATE_IMG 0x8C06
+#define GL_FACTOR_ALPHA_MODULATE_IMG 0x8C07
+#define GL_FRAGMENT_ALPHA_MODULATE_IMG 0x8C08
+#define GL_ADD_BLEND_IMG 0x8C09
+#define GL_DOT3_RGBA_IMG 0x86AF
+#endif
+
+/* GL_IMG_user_clip_plane */
+#ifndef GL_IMG_user_clip_plane
+#define GL_CLIP_PLANE0_IMG 0x3000
+#define GL_CLIP_PLANE1_IMG 0x3001
+#define GL_CLIP_PLANE2_IMG 0x3002
+#define GL_CLIP_PLANE3_IMG 0x3003
+#define GL_CLIP_PLANE4_IMG 0x3004
+#define GL_CLIP_PLANE5_IMG 0x3005
+#define GL_MAX_CLIP_PLANES_IMG 0x0D32
+#endif
+
+/* GL_IMG_multisampled_render_to_texture */
+#ifndef GL_IMG_multisampled_render_to_texture
+#define GL_RENDERBUFFER_SAMPLES_IMG 0x9133
+#define GL_FRAMEBUFFER_INCOMPLETE_MULTISAMPLE_IMG 0x9134
+#define GL_MAX_SAMPLES_IMG 0x9135
+#define GL_TEXTURE_SAMPLES_IMG 0x9136
+#endif
+
+/*------------------------------------------------------------------------*
+ * NV extension tokens
+ *------------------------------------------------------------------------*/
+
+/* GL_NV_fence */
+#ifndef GL_NV_fence
+#define GL_ALL_COMPLETED_NV 0x84F2
+#define GL_FENCE_STATUS_NV 0x84F3
+#define GL_FENCE_CONDITION_NV 0x84F4
+#endif
+
+/*------------------------------------------------------------------------*
+ * QCOM extension tokens
+ *------------------------------------------------------------------------*/
+
+/* GL_QCOM_driver_control */
+/* No new tokens introduced by this extension. */
+
+/* GL_QCOM_extended_get */
+#ifndef GL_QCOM_extended_get
+#define GL_TEXTURE_WIDTH_QCOM 0x8BD2
+#define GL_TEXTURE_HEIGHT_QCOM 0x8BD3
+#define GL_TEXTURE_DEPTH_QCOM 0x8BD4
+#define GL_TEXTURE_INTERNAL_FORMAT_QCOM 0x8BD5
+#define GL_TEXTURE_FORMAT_QCOM 0x8BD6
+#define GL_TEXTURE_TYPE_QCOM 0x8BD7
+#define GL_TEXTURE_IMAGE_VALID_QCOM 0x8BD8
+#define GL_TEXTURE_NUM_LEVELS_QCOM 0x8BD9
+#define GL_TEXTURE_TARGET_QCOM 0x8BDA
+#define GL_TEXTURE_OBJECT_VALID_QCOM 0x8BDB
+#define GL_STATE_RESTORE 0x8BDC
+#endif
+
+/* GL_QCOM_extended_get2 */
+/* No new tokens introduced by this extension. */
+
+/* GL_QCOM_perfmon_global_mode */
+#ifndef GL_QCOM_perfmon_global_mode
+#define GL_PERFMON_GLOBAL_MODE_QCOM 0x8FA0
+#endif
+
+/* GL_QCOM_writeonly_rendering */
+#ifndef GL_QCOM_writeonly_rendering
+#define GL_WRITEONLY_RENDERING_QCOM 0x8823
+#endif
+
+/* GL_QCOM_tiled_rendering */
+#ifndef GL_QCOM_tiled_rendering
+#define GL_COLOR_BUFFER_BIT0_QCOM 0x00000001
+#define GL_COLOR_BUFFER_BIT1_QCOM 0x00000002
+#define GL_COLOR_BUFFER_BIT2_QCOM 0x00000004
+#define GL_COLOR_BUFFER_BIT3_QCOM 0x00000008
+#define GL_COLOR_BUFFER_BIT4_QCOM 0x00000010
+#define GL_COLOR_BUFFER_BIT5_QCOM 0x00000020
+#define GL_COLOR_BUFFER_BIT6_QCOM 0x00000040
+#define GL_COLOR_BUFFER_BIT7_QCOM 0x00000080
+#define GL_DEPTH_BUFFER_BIT0_QCOM 0x00000100
+#define GL_DEPTH_BUFFER_BIT1_QCOM 0x00000200
+#define GL_DEPTH_BUFFER_BIT2_QCOM 0x00000400
+#define GL_DEPTH_BUFFER_BIT3_QCOM 0x00000800
+#define GL_DEPTH_BUFFER_BIT4_QCOM 0x00001000
+#define GL_DEPTH_BUFFER_BIT5_QCOM 0x00002000
+#define GL_DEPTH_BUFFER_BIT6_QCOM 0x00004000
+#define GL_DEPTH_BUFFER_BIT7_QCOM 0x00008000
+#define GL_STENCIL_BUFFER_BIT0_QCOM 0x00010000
+#define GL_STENCIL_BUFFER_BIT1_QCOM 0x00020000
+#define GL_STENCIL_BUFFER_BIT2_QCOM 0x00040000
+#define GL_STENCIL_BUFFER_BIT3_QCOM 0x00080000
+#define GL_STENCIL_BUFFER_BIT4_QCOM 0x00100000
+#define GL_STENCIL_BUFFER_BIT5_QCOM 0x00200000
+#define GL_STENCIL_BUFFER_BIT6_QCOM 0x00400000
+#define GL_STENCIL_BUFFER_BIT7_QCOM 0x00800000
+#define GL_MULTISAMPLE_BUFFER_BIT0_QCOM 0x01000000
+#define GL_MULTISAMPLE_BUFFER_BIT1_QCOM 0x02000000
+#define GL_MULTISAMPLE_BUFFER_BIT2_QCOM 0x04000000
+#define GL_MULTISAMPLE_BUFFER_BIT3_QCOM 0x08000000
+#define GL_MULTISAMPLE_BUFFER_BIT4_QCOM 0x10000000
+#define GL_MULTISAMPLE_BUFFER_BIT5_QCOM 0x20000000
+#define GL_MULTISAMPLE_BUFFER_BIT6_QCOM 0x40000000
+#define GL_MULTISAMPLE_BUFFER_BIT7_QCOM 0x80000000
+#endif
+
+/*------------------------------------------------------------------------*
+ * End of extension tokens, start of corresponding extension functions
+ *------------------------------------------------------------------------*/
+
/*------------------------------------------------------------------------*
* OES extension functions
*------------------------------------------------------------------------*/
@@ -456,11 +642,11 @@ typedef void (GL_APIENTRYP PFNGLGENERATEMIPMAPOESPROC) (GLenum target);
#ifdef GL_GLEXT_PROTOTYPES
GL_API void* GL_APIENTRY glMapBufferOES (GLenum target, GLenum access);
GL_API GLboolean GL_APIENTRY glUnmapBufferOES (GLenum target);
-GL_API void GL_APIENTRY glGetBufferPointervOES (GLenum target, GLenum pname, void** params);
+GL_API void GL_APIENTRY glGetBufferPointervOES (GLenum target, GLenum pname, GLvoid ** params);
#endif
typedef void* (GL_APIENTRYP PFNGLMAPBUFFEROESPROC) (GLenum target, GLenum access);
typedef GLboolean (GL_APIENTRYP PFNGLUNMAPBUFFEROESPROC) (GLenum target);
-typedef void (GL_APIENTRYP PFNGLGETBUFFERPOINTERVOESPROC) (GLenum target, GLenum pname, void** params);
+typedef void (GL_APIENTRYP PFNGLGETBUFFERPOINTERVOESPROC) (GLenum target, GLenum pname, GLvoid ** params);
#endif
/* GL_OES_matrix_get */
@@ -576,6 +762,21 @@ typedef void (GL_APIENTRYP PFNGLGETTEXGENXVOESPROC) (GLenum coord, GLenum pname,
#define GL_OES_texture_mirrored_repeat 1
#endif
+/* GL_OES_vertex_array_object */
+#ifndef GL_OES_vertex_array_object
+#define GL_OES_vertex_array_object 1
+#ifdef GL_GLEXT_PROTOTYPES
+GL_API void GL_APIENTRY glBindVertexArrayOES (GLuint array);
+GL_API void GL_APIENTRY glDeleteVertexArraysOES (GLsizei n, const GLuint *arrays);
+GL_API void GL_APIENTRY glGenVertexArraysOES (GLsizei n, GLuint *arrays);
+GL_API GLboolean GL_APIENTRY glIsVertexArrayOES (GLuint array);
+#endif
+typedef void (GL_APIENTRYP PFNGLBINDVERTEXARRAYOESPROC) (GLuint array);
+typedef void (GL_APIENTRYP PFNGLDELETEVERTEXARRAYSOESPROC) (GLsizei n, const GLuint *arrays);
+typedef void (GL_APIENTRYP PFNGLGENVERTEXARRAYSOESPROC) (GLsizei n, GLuint *arrays);
+typedef GLboolean (GL_APIENTRYP PFNGLISVERTEXARRAYOESPROC) (GLuint array);
+#endif
+
/*------------------------------------------------------------------------*
* AMD extension functions
*------------------------------------------------------------------------*/
@@ -591,14 +792,207 @@ typedef void (GL_APIENTRYP PFNGLGETTEXGENXVOESPROC) (GLenum coord, GLenum pname,
#endif
/*------------------------------------------------------------------------*
+ * APPLE extension functions
+ *------------------------------------------------------------------------*/
+
+/* GL_APPLE_texture_2D_limited_npot */
+#ifndef GL_APPLE_texture_2D_limited_npot
+#define GL_APPLE_texture_2D_limited_npot 1
+#endif
+
+/*------------------------------------------------------------------------*
* EXT extension functions
*------------------------------------------------------------------------*/
+/* GL_EXT_blend_minmax */
+#ifndef GL_EXT_blend_minmax
+#define GL_EXT_blend_minmax 1
+#endif
+
+/* GL_EXT_discard_framebuffer */
+#ifndef GL_EXT_discard_framebuffer
+#define GL_EXT_discard_framebuffer 1
+#ifdef GL_GLEXT_PROTOTYPES
+GL_API void GL_APIENTRY glDiscardFramebufferEXT (GLenum target, GLsizei numAttachments, const GLenum *attachments);
+#endif
+typedef void (GL_APIENTRYP PFNGLDISCARDFRAMEBUFFEREXTPROC) (GLenum target, GLsizei numAttachments, const GLenum *attachments);
+#endif
+
+/* GL_EXT_multi_draw_arrays */
+#ifndef GL_EXT_multi_draw_arrays
+#define GL_EXT_multi_draw_arrays 1
+#ifdef GL_GLEXT_PROTOTYPES
+GL_API void GL_APIENTRY glMultiDrawArraysEXT (GLenum mode, GLint *first, GLsizei *count, GLsizei primcount);
+GL_API void GL_APIENTRY glMultiDrawElementsEXT (GLenum mode, const GLsizei *count, GLenum type, const GLvoid* *indices, GLsizei primcount);
+#endif /* GL_GLEXT_PROTOTYPES */
+typedef void (GL_APIENTRYP PFNGLMULTIDRAWARRAYSEXTPROC) (GLenum mode, GLint *first, GLsizei *count, GLsizei primcount);
+typedef void (GL_APIENTRYP PFNGLMULTIDRAWELEMENTSEXTPROC) (GLenum mode, const GLsizei *count, GLenum type, const GLvoid* *indices, GLsizei primcount);
+#endif
+
+/* GL_EXT_read_format_bgra */
+#ifndef GL_EXT_read_format_bgra
+#define GL_EXT_read_format_bgra 1
+#endif
+
/* GL_EXT_texture_filter_anisotropic */
#ifndef GL_EXT_texture_filter_anisotropic
#define GL_EXT_texture_filter_anisotropic 1
#endif
+/* GL_EXT_texture_format_BGRA8888 */
+#ifndef GL_EXT_texture_format_BGRA8888
+#define GL_EXT_texture_format_BGRA8888 1
+#endif
+
+/* GL_EXT_texture_lod_bias */
+#ifndef GL_EXT_texture_lod_bias
+#define GL_EXT_texture_lod_bias 1
+#endif
+
+/*------------------------------------------------------------------------*
+ * IMG extension functions
+ *------------------------------------------------------------------------*/
+
+/* GL_IMG_read_format */
+#ifndef GL_IMG_read_format
+#define GL_IMG_read_format 1
+#endif
+
+/* GL_IMG_texture_compression_pvrtc */
+#ifndef GL_IMG_texture_compression_pvrtc
+#define GL_IMG_texture_compression_pvrtc 1
+#endif
+
+/* GL_IMG_texture_env_enhanced_fixed_function */
+#ifndef GL_IMG_texture_env_enhanced_fixed_function
+#define GL_IMG_texture_env_enhanced_fixed_function 1
+#endif
+
+/* GL_IMG_user_clip_plane */
+#ifndef GL_IMG_user_clip_plane
+#define GL_IMG_user_clip_plane 1
+#ifdef GL_GLEXT_PROTOTYPES
+GL_API void GL_APIENTRY glClipPlanefIMG (GLenum p, const GLfloat *eqn);
+GL_API void GL_APIENTRY glClipPlanexIMG (GLenum p, const GLfixed *eqn);
+#endif
+typedef void (GL_APIENTRYP PFNGLCLIPPLANEFIMGPROC) (GLenum p, const GLfloat *eqn);
+typedef void (GL_APIENTRYP PFNGLCLIPPLANEXIMGPROC) (GLenum p, const GLfixed *eqn);
+#endif
+
+/* GL_IMG_multisampled_render_to_texture */
+#ifndef GL_IMG_multisampled_render_to_texture
+#define GL_IMG_multisampled_render_to_texture 1
+#ifdef GL_GLEXT_PROTOTYPES
+GL_API void GL_APIENTRY glRenderbufferStorageMultisampleIMG (GLenum target, GLsizei samples, GLenum internalformat, GLsizei width, GLsizei height);
+GL_API void GL_APIENTRY glFramebufferTexture2DMultisampleIMG (GLenum target, GLenum attachment, GLenum textarget, GLuint texture, GLint level, GLsizei samples);
+#endif
+typedef void (GL_APIENTRYP PFNGLRENDERBUFFERSTORAGEMULTISAMPLEIMG) (GLenum target, GLsizei samples, GLenum internalformat, GLsizei width, GLsizei height);
+typedef void (GL_APIENTRYP PFNGLFRAMEBUFFERTEXTURE2DMULTISAMPLEIMG) (GLenum target, GLenum attachment, GLenum textarget, GLuint texture, GLint level, GLsizei samples);
+#endif
+
+/*------------------------------------------------------------------------*
+ * NV extension functions
+ *------------------------------------------------------------------------*/
+
+/* NV_fence */
+#ifndef GL_NV_fence
+#define GL_NV_fence 1
+#ifdef GL_GLEXT_PROTOTYPES
+GL_API void GL_APIENTRY glDeleteFencesNV (GLsizei n, const GLuint *fences);
+GL_API void GL_APIENTRY glGenFencesNV (GLsizei n, GLuint *fences);
+GL_API GLboolean GL_APIENTRY glIsFenceNV (GLuint fence);
+GL_API GLboolean GL_APIENTRY glTestFenceNV (GLuint fence);
+GL_API void GL_APIENTRY glGetFenceivNV (GLuint fence, GLenum pname, GLint *params);
+GL_API void GL_APIENTRY glFinishFenceNV (GLuint fence);
+GL_API void GL_APIENTRY glSetFenceNV (GLuint fence, GLenum condition);
+#endif
+typedef void (GL_APIENTRYP PFNGLDELETEFENCESNVPROC) (GLsizei n, const GLuint *fences);
+typedef void (GL_APIENTRYP PFNGLGENFENCESNVPROC) (GLsizei n, GLuint *fences);
+typedef GLboolean (GL_APIENTRYP PFNGLISFENCENVPROC) (GLuint fence);
+typedef GLboolean (GL_APIENTRYP PFNGLTESTFENCENVPROC) (GLuint fence);
+typedef void (GL_APIENTRYP PFNGLGETFENCEIVNVPROC) (GLuint fence, GLenum pname, GLint *params);
+typedef void (GL_APIENTRYP PFNGLFINISHFENCENVPROC) (GLuint fence);
+typedef void (GL_APIENTRYP PFNGLSETFENCENVPROC) (GLuint fence, GLenum condition);
+#endif
+
+/*------------------------------------------------------------------------*
+ * QCOM extension functions
+ *------------------------------------------------------------------------*/
+
+/* GL_QCOM_driver_control */
+#ifndef GL_QCOM_driver_control
+#define GL_QCOM_driver_control 1
+#ifdef GL_GLEXT_PROTOTYPES
+GL_API void GL_APIENTRY glGetDriverControlsQCOM (GLint *num, GLsizei size, GLuint *driverControls);
+GL_API void GL_APIENTRY glGetDriverControlStringQCOM (GLuint driverControl, GLsizei bufSize, GLsizei *length, GLchar *driverControlString);
+GL_API void GL_APIENTRY glEnableDriverControlQCOM (GLuint driverControl);
+GL_API void GL_APIENTRY glDisableDriverControlQCOM (GLuint driverControl);
+#endif
+typedef void (GL_APIENTRYP PFNGLGETDRIVERCONTROLSQCOMPROC) (GLint *num, GLsizei size, GLuint *driverControls);
+typedef void (GL_APIENTRYP PFNGLGETDRIVERCONTROLSTRINGQCOMPROC) (GLuint driverControl, GLsizei bufSize, GLsizei *length, GLchar *driverControlString);
+typedef void (GL_APIENTRYP PFNGLENABLEDRIVERCONTROLQCOMPROC) (GLuint driverControl);
+typedef void (GL_APIENTRYP PFNGLDISABLEDRIVERCONTROLQCOMPROC) (GLuint driverControl);
+#endif
+
+/* GL_QCOM_extended_get */
+#ifndef GL_QCOM_extended_get
+#define GL_QCOM_extended_get 1
+#ifdef GL_GLEXT_PROTOTYPES
+GL_API void GL_APIENTRY glExtGetTexturesQCOM (GLuint *textures, GLint maxTextures, GLint *numTextures);
+GL_API void GL_APIENTRY glExtGetBuffersQCOM (GLuint *buffers, GLint maxBuffers, GLint *numBuffers);
+GL_API void GL_APIENTRY glExtGetRenderbuffersQCOM (GLuint *renderbuffers, GLint maxRenderbuffers, GLint *numRenderbuffers);
+GL_API void GL_APIENTRY glExtGetFramebuffersQCOM (GLuint *framebuffers, GLint maxFramebuffers, GLint *numFramebuffers);
+GL_API void GL_APIENTRY glExtGetTexLevelParameterivQCOM (GLuint texture, GLenum face, GLint level, GLenum pname, GLint *params);
+GL_API void GL_APIENTRY glExtTexObjectStateOverrideiQCOM (GLenum target, GLenum pname, GLint param);
+GL_API void GL_APIENTRY glExtGetTexSubImageQCOM (GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint zoffset, GLsizei width, GLsizei height, GLsizei depth, GLenum format, GLenum type, GLvoid *texels);
+GL_API void GL_APIENTRY glExtGetBufferPointervQCOM (GLenum target, GLvoid **params);
+#endif
+typedef void (GL_APIENTRYP PFNGLEXTGETTEXTURESQCOMPROC) (GLuint *textures, GLint maxTextures, GLint *numTextures);
+typedef void (GL_APIENTRYP PFNGLEXTGETBUFFERSQCOMPROC) (GLuint *buffers, GLint maxBuffers, GLint *numBuffers);
+typedef void (GL_APIENTRYP PFNGLEXTGETRENDERBUFFERSQCOMPROC) (GLuint *renderbuffers, GLint maxRenderbuffers, GLint *numRenderbuffers);
+typedef void (GL_APIENTRYP PFNGLEXTGETFRAMEBUFFERSQCOMPROC) (GLuint *framebuffers, GLint maxFramebuffers, GLint *numFramebuffers);
+typedef void (GL_APIENTRYP PFNGLEXTGETTEXLEVELPARAMETERIVQCOMPROC) (GLuint texture, GLenum face, GLint level, GLenum pname, GLint *params);
+typedef void (GL_APIENTRYP PFNGLEXTTEXOBJECTSTATEOVERRIDEIQCOMPROC) (GLenum target, GLenum pname, GLint param);
+typedef void (GL_APIENTRYP PFNGLEXTGETTEXSUBIMAGEQCOMPROC) (GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint zoffset, GLsizei width, GLsizei height, GLsizei depth, GLenum format, GLenum type, GLvoid *texels);
+typedef void (GL_APIENTRYP PFNGLEXTGETBUFFERPOINTERVQCOMPROC) (GLenum target, GLvoid **params);
+#endif
+
+/* GL_QCOM_extended_get2 */
+#ifndef GL_QCOM_extended_get2
+#define GL_QCOM_extended_get2 1
+#ifdef GL_GLEXT_PROTOTYPES
+GL_API void GL_APIENTRY glExtGetShadersQCOM (GLuint *shaders, GLint maxShaders, GLint *numShaders);
+GL_API void GL_APIENTRY glExtGetProgramsQCOM (GLuint *programs, GLint maxPrograms, GLint *numPrograms);
+GL_API GLboolean GL_APIENTRY glExtIsProgramBinaryQCOM (GLuint program);
+GL_API void GL_APIENTRY glExtGetProgramBinarySourceQCOM (GLuint program, GLenum shadertype, GLchar *source, GLint *length);
+#endif
+typedef void (GL_APIENTRYP PFNGLEXTGETSHADERSQCOMPROC) (GLuint *shaders, GLint maxShaders, GLint *numShaders);
+typedef void (GL_APIENTRYP PFNGLEXTGETPROGRAMSQCOMPROC) (GLuint *programs, GLint maxPrograms, GLint *numPrograms);
+typedef GLboolean (GL_APIENTRYP PFNGLEXTISPROGRAMBINARYQCOMPROC) (GLuint program);
+typedef void (GL_APIENTRYP PFNGLEXTGETPROGRAMBINARYSOURCEQCOMPROC) (GLuint program, GLenum shadertype, GLchar *source, GLint *length);
+#endif
+
+/* GL_QCOM_perfmon_global_mode */
+#ifndef GL_QCOM_perfmon_global_mode
+#define GL_QCOM_perfmon_global_mode 1
+#endif
+
+/* GL_QCOM_writeonly_rendering */
+#ifndef GL_QCOM_writeonly_rendering
+#define GL_QCOM_writeonly_rendering 1
+#endif
+
+/* GL_QCOM_tiled_rendering */
+#ifndef GL_QCOM_tiled_rendering
+#define GL_QCOM_tiled_rendering 1
+#ifdef GL_GLEXT_PROTOTYPES
+GL_API void GL_APIENTRY glStartTilingQCOM (GLuint x, GLuint y, GLuint width, GLuint height, GLbitfield preserveMask);
+GL_API void GL_APIENTRY glEndTilingQCOM (GLbitfield preserveMask);
+#endif
+typedef void (GL_APIENTRYP PFNGLSTARTTILINGQCOMPROC) (GLuint x, GLuint y, GLuint width, GLuint height, GLbitfield preserveMask);
+typedef void (GL_APIENTRYP PFNGLENDTILINGQCOMPROC) (GLbitfield preserveMask);
+#endif
+
#ifdef __cplusplus
}
#endif
diff --git a/opengl/include/GLES/glplatform.h b/opengl/include/GLES/glplatform.h
index 198e679..2db6ee2 100644
--- a/opengl/include/GLES/glplatform.h
+++ b/opengl/include/GLES/glplatform.h
@@ -1,7 +1,7 @@
#ifndef __glplatform_h_
#define __glplatform_h_
-/* $Revision: 7172 $ on $Date:: 2009-01-09 11:17:41 -0800 #$ */
+/* $Revision: 10601 $ on $Date:: 2010-03-04 22:15:27 -0800 #$ */
/*
* This document is licensed under the SGI Free Software B License Version
@@ -9,7 +9,6 @@
*/
/* Platform-specific types and definitions for OpenGL ES 1.X gl.h
- * Last modified on 2008/12/19
*
* Adopters may modify khrplatform.h and this file to suit their platform.
* You are encouraged to submit all modifications to the Khronos group so that
@@ -24,10 +23,8 @@
#define GL_API KHRONOS_APICALL
#endif
-#if defined(ANDROID)
-
+#ifndef GL_APIENTRY
#define GL_APIENTRY KHRONOS_APIENTRY
-
#endif
#endif /* __glplatform_h_ */
diff --git a/opengl/include/GLES2/gl2.h b/opengl/include/GLES2/gl2.h
index 0182a67..e1d3b87 100644
--- a/opengl/include/GLES2/gl2.h
+++ b/opengl/include/GLES2/gl2.h
@@ -1,7 +1,7 @@
#ifndef __gl2_h_
#define __gl2_h_
-/* $Revision: 7173 $ on $Date:: 2009-01-09 11:18:21 -0800 #$ */
+/* $Revision: 10602 $ on $Date:: 2010-03-04 22:35:34 -0800 #$ */
#include <GLES2/gl2platform.h>
@@ -19,6 +19,7 @@ extern "C" {
*-----------------------------------------------------------------------*/
typedef void GLvoid;
+typedef char GLchar;
typedef unsigned int GLenum;
typedef unsigned char GLboolean;
typedef unsigned int GLbitfield;
@@ -472,7 +473,7 @@ typedef khronos_ssize_t GLsizeiptr;
GL_APICALL void GL_APIENTRY glActiveTexture (GLenum texture);
GL_APICALL void GL_APIENTRY glAttachShader (GLuint program, GLuint shader);
-GL_APICALL void GL_APIENTRY glBindAttribLocation (GLuint program, GLuint index, const char* name);
+GL_APICALL void GL_APIENTRY glBindAttribLocation (GLuint program, GLuint index, const GLchar* name);
GL_APICALL void GL_APIENTRY glBindBuffer (GLenum target, GLuint buffer);
GL_APICALL void GL_APIENTRY glBindFramebuffer (GLenum target, GLuint framebuffer);
GL_APICALL void GL_APIENTRY glBindRenderbuffer (GLenum target, GLuint renderbuffer);
@@ -482,8 +483,8 @@ GL_APICALL void GL_APIENTRY glBlendEquation ( GLenum mode );
GL_APICALL void GL_APIENTRY glBlendEquationSeparate (GLenum modeRGB, GLenum modeAlpha);
GL_APICALL void GL_APIENTRY glBlendFunc (GLenum sfactor, GLenum dfactor);
GL_APICALL void GL_APIENTRY glBlendFuncSeparate (GLenum srcRGB, GLenum dstRGB, GLenum srcAlpha, GLenum dstAlpha);
-GL_APICALL void GL_APIENTRY glBufferData (GLenum target, GLsizeiptr size, const void* data, GLenum usage);
-GL_APICALL void GL_APIENTRY glBufferSubData (GLenum target, GLintptr offset, GLsizeiptr size, const void* data);
+GL_APICALL void GL_APIENTRY glBufferData (GLenum target, GLsizeiptr size, const GLvoid* data, GLenum usage);
+GL_APICALL void GL_APIENTRY glBufferSubData (GLenum target, GLintptr offset, GLsizeiptr size, const GLvoid* data);
GL_APICALL GLenum GL_APIENTRY glCheckFramebufferStatus (GLenum target);
GL_APICALL void GL_APIENTRY glClear (GLbitfield mask);
GL_APICALL void GL_APIENTRY glClearColor (GLclampf red, GLclampf green, GLclampf blue, GLclampf alpha);
@@ -491,8 +492,8 @@ GL_APICALL void GL_APIENTRY glClearDepthf (GLclampf depth);
GL_APICALL void GL_APIENTRY glClearStencil (GLint s);
GL_APICALL void GL_APIENTRY glColorMask (GLboolean red, GLboolean green, GLboolean blue, GLboolean alpha);
GL_APICALL void GL_APIENTRY glCompileShader (GLuint shader);
-GL_APICALL void GL_APIENTRY glCompressedTexImage2D (GLenum target, GLint level, GLenum internalformat, GLsizei width, GLsizei height, GLint border, GLsizei imageSize, const void* data);
-GL_APICALL void GL_APIENTRY glCompressedTexSubImage2D (GLenum target, GLint level, GLint xoffset, GLint yoffset, GLsizei width, GLsizei height, GLenum format, GLsizei imageSize, const void* data);
+GL_APICALL void GL_APIENTRY glCompressedTexImage2D (GLenum target, GLint level, GLenum internalformat, GLsizei width, GLsizei height, GLint border, GLsizei imageSize, const GLvoid* data);
+GL_APICALL void GL_APIENTRY glCompressedTexSubImage2D (GLenum target, GLint level, GLint xoffset, GLint yoffset, GLsizei width, GLsizei height, GLenum format, GLsizei imageSize, const GLvoid* data);
GL_APICALL void GL_APIENTRY glCopyTexImage2D (GLenum target, GLint level, GLenum internalformat, GLint x, GLint y, GLsizei width, GLsizei height, GLint border);
GL_APICALL void GL_APIENTRY glCopyTexSubImage2D (GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint x, GLint y, GLsizei width, GLsizei height);
GL_APICALL GLuint GL_APIENTRY glCreateProgram (void);
@@ -511,7 +512,7 @@ GL_APICALL void GL_APIENTRY glDetachShader (GLuint program, GLuint shade
GL_APICALL void GL_APIENTRY glDisable (GLenum cap);
GL_APICALL void GL_APIENTRY glDisableVertexAttribArray (GLuint index);
GL_APICALL void GL_APIENTRY glDrawArrays (GLenum mode, GLint first, GLsizei count);
-GL_APICALL void GL_APIENTRY glDrawElements (GLenum mode, GLsizei count, GLenum type, const void* indices);
+GL_APICALL void GL_APIENTRY glDrawElements (GLenum mode, GLsizei count, GLenum type, const GLvoid* indices);
GL_APICALL void GL_APIENTRY glEnable (GLenum cap);
GL_APICALL void GL_APIENTRY glEnableVertexAttribArray (GLuint index);
GL_APICALL void GL_APIENTRY glFinish (void);
@@ -524,10 +525,10 @@ GL_APICALL void GL_APIENTRY glGenerateMipmap (GLenum target);
GL_APICALL void GL_APIENTRY glGenFramebuffers (GLsizei n, GLuint* framebuffers);
GL_APICALL void GL_APIENTRY glGenRenderbuffers (GLsizei n, GLuint* renderbuffers);
GL_APICALL void GL_APIENTRY glGenTextures (GLsizei n, GLuint* textures);
-GL_APICALL void GL_APIENTRY glGetActiveAttrib (GLuint program, GLuint index, GLsizei bufsize, GLsizei* length, GLint* size, GLenum* type, char* name);
-GL_APICALL void GL_APIENTRY glGetActiveUniform (GLuint program, GLuint index, GLsizei bufsize, GLsizei* length, GLint* size, GLenum* type, char* name);
+GL_APICALL void GL_APIENTRY glGetActiveAttrib (GLuint program, GLuint index, GLsizei bufsize, GLsizei* length, GLint* size, GLenum* type, GLchar* name);
+GL_APICALL void GL_APIENTRY glGetActiveUniform (GLuint program, GLuint index, GLsizei bufsize, GLsizei* length, GLint* size, GLenum* type, GLchar* name);
GL_APICALL void GL_APIENTRY glGetAttachedShaders (GLuint program, GLsizei maxcount, GLsizei* count, GLuint* shaders);
-GL_APICALL int GL_APIENTRY glGetAttribLocation (GLuint program, const char* name);
+GL_APICALL int GL_APIENTRY glGetAttribLocation (GLuint program, const GLchar* name);
GL_APICALL void GL_APIENTRY glGetBooleanv (GLenum pname, GLboolean* params);
GL_APICALL void GL_APIENTRY glGetBufferParameteriv (GLenum target, GLenum pname, GLint* params);
GL_APICALL GLenum GL_APIENTRY glGetError (void);
@@ -535,21 +536,21 @@ GL_APICALL void GL_APIENTRY glGetFloatv (GLenum pname, GLfloat* params);
GL_APICALL void GL_APIENTRY glGetFramebufferAttachmentParameteriv (GLenum target, GLenum attachment, GLenum pname, GLint* params);
GL_APICALL void GL_APIENTRY glGetIntegerv (GLenum pname, GLint* params);
GL_APICALL void GL_APIENTRY glGetProgramiv (GLuint program, GLenum pname, GLint* params);
-GL_APICALL void GL_APIENTRY glGetProgramInfoLog (GLuint program, GLsizei bufsize, GLsizei* length, char* infolog);
+GL_APICALL void GL_APIENTRY glGetProgramInfoLog (GLuint program, GLsizei bufsize, GLsizei* length, GLchar* infolog);
GL_APICALL void GL_APIENTRY glGetRenderbufferParameteriv (GLenum target, GLenum pname, GLint* params);
GL_APICALL void GL_APIENTRY glGetShaderiv (GLuint shader, GLenum pname, GLint* params);
-GL_APICALL void GL_APIENTRY glGetShaderInfoLog (GLuint shader, GLsizei bufsize, GLsizei* length, char* infolog);
+GL_APICALL void GL_APIENTRY glGetShaderInfoLog (GLuint shader, GLsizei bufsize, GLsizei* length, GLchar* infolog);
GL_APICALL void GL_APIENTRY glGetShaderPrecisionFormat (GLenum shadertype, GLenum precisiontype, GLint* range, GLint* precision);
-GL_APICALL void GL_APIENTRY glGetShaderSource (GLuint shader, GLsizei bufsize, GLsizei* length, char* source);
+GL_APICALL void GL_APIENTRY glGetShaderSource (GLuint shader, GLsizei bufsize, GLsizei* length, GLchar* source);
GL_APICALL const GLubyte* GL_APIENTRY glGetString (GLenum name);
GL_APICALL void GL_APIENTRY glGetTexParameterfv (GLenum target, GLenum pname, GLfloat* params);
GL_APICALL void GL_APIENTRY glGetTexParameteriv (GLenum target, GLenum pname, GLint* params);
GL_APICALL void GL_APIENTRY glGetUniformfv (GLuint program, GLint location, GLfloat* params);
GL_APICALL void GL_APIENTRY glGetUniformiv (GLuint program, GLint location, GLint* params);
-GL_APICALL int GL_APIENTRY glGetUniformLocation (GLuint program, const char* name);
+GL_APICALL int GL_APIENTRY glGetUniformLocation (GLuint program, const GLchar* name);
GL_APICALL void GL_APIENTRY glGetVertexAttribfv (GLuint index, GLenum pname, GLfloat* params);
GL_APICALL void GL_APIENTRY glGetVertexAttribiv (GLuint index, GLenum pname, GLint* params);
-GL_APICALL void GL_APIENTRY glGetVertexAttribPointerv (GLuint index, GLenum pname, void** pointer);
+GL_APICALL void GL_APIENTRY glGetVertexAttribPointerv (GLuint index, GLenum pname, GLvoid** pointer);
GL_APICALL void GL_APIENTRY glHint (GLenum target, GLenum mode);
GL_APICALL GLboolean GL_APIENTRY glIsBuffer (GLuint buffer);
GL_APICALL GLboolean GL_APIENTRY glIsEnabled (GLenum cap);
@@ -562,25 +563,25 @@ GL_APICALL void GL_APIENTRY glLineWidth (GLfloat width);
GL_APICALL void GL_APIENTRY glLinkProgram (GLuint program);
GL_APICALL void GL_APIENTRY glPixelStorei (GLenum pname, GLint param);
GL_APICALL void GL_APIENTRY glPolygonOffset (GLfloat factor, GLfloat units);
-GL_APICALL void GL_APIENTRY glReadPixels (GLint x, GLint y, GLsizei width, GLsizei height, GLenum format, GLenum type, void* pixels);
+GL_APICALL void GL_APIENTRY glReadPixels (GLint x, GLint y, GLsizei width, GLsizei height, GLenum format, GLenum type, GLvoid* pixels);
GL_APICALL void GL_APIENTRY glReleaseShaderCompiler (void);
GL_APICALL void GL_APIENTRY glRenderbufferStorage (GLenum target, GLenum internalformat, GLsizei width, GLsizei height);
GL_APICALL void GL_APIENTRY glSampleCoverage (GLclampf value, GLboolean invert);
GL_APICALL void GL_APIENTRY glScissor (GLint x, GLint y, GLsizei width, GLsizei height);
-GL_APICALL void GL_APIENTRY glShaderBinary (GLsizei n, const GLuint* shaders, GLenum binaryformat, const void* binary, GLsizei length);
-GL_APICALL void GL_APIENTRY glShaderSource (GLuint shader, GLsizei count, const char** string, const GLint* length);
+GL_APICALL void GL_APIENTRY glShaderBinary (GLsizei n, const GLuint* shaders, GLenum binaryformat, const GLvoid* binary, GLsizei length);
+GL_APICALL void GL_APIENTRY glShaderSource (GLuint shader, GLsizei count, const GLchar** string, const GLint* length);
GL_APICALL void GL_APIENTRY glStencilFunc (GLenum func, GLint ref, GLuint mask);
GL_APICALL void GL_APIENTRY glStencilFuncSeparate (GLenum face, GLenum func, GLint ref, GLuint mask);
GL_APICALL void GL_APIENTRY glStencilMask (GLuint mask);
GL_APICALL void GL_APIENTRY glStencilMaskSeparate (GLenum face, GLuint mask);
GL_APICALL void GL_APIENTRY glStencilOp (GLenum fail, GLenum zfail, GLenum zpass);
GL_APICALL void GL_APIENTRY glStencilOpSeparate (GLenum face, GLenum fail, GLenum zfail, GLenum zpass);
-GL_APICALL void GL_APIENTRY glTexImage2D (GLenum target, GLint level, GLint internalformat, GLsizei width, GLsizei height, GLint border, GLenum format, GLenum type, const GLvoid* pixels);
+GL_APICALL void GL_APIENTRY glTexImage2D (GLenum target, GLint level, GLint internalformat, GLsizei width, GLsizei height, GLint border, GLenum format, GLenum type, const GLvoid* pixels);
GL_APICALL void GL_APIENTRY glTexParameterf (GLenum target, GLenum pname, GLfloat param);
GL_APICALL void GL_APIENTRY glTexParameterfv (GLenum target, GLenum pname, const GLfloat* params);
GL_APICALL void GL_APIENTRY glTexParameteri (GLenum target, GLenum pname, GLint param);
GL_APICALL void GL_APIENTRY glTexParameteriv (GLenum target, GLenum pname, const GLint* params);
-GL_APICALL void GL_APIENTRY glTexSubImage2D (GLenum target, GLint level, GLint xoffset, GLint yoffset, GLsizei width, GLsizei height, GLenum format, GLenum type, const void* pixels);
+GL_APICALL void GL_APIENTRY glTexSubImage2D (GLenum target, GLint level, GLint xoffset, GLint yoffset, GLsizei width, GLsizei height, GLenum format, GLenum type, const GLvoid* pixels);
GL_APICALL void GL_APIENTRY glUniform1f (GLint location, GLfloat x);
GL_APICALL void GL_APIENTRY glUniform1fv (GLint location, GLsizei count, const GLfloat* v);
GL_APICALL void GL_APIENTRY glUniform1i (GLint location, GLint x);
@@ -610,7 +611,7 @@ GL_APICALL void GL_APIENTRY glVertexAttrib3f (GLuint indx, GLfloat x, GL
GL_APICALL void GL_APIENTRY glVertexAttrib3fv (GLuint indx, const GLfloat* values);
GL_APICALL void GL_APIENTRY glVertexAttrib4f (GLuint indx, GLfloat x, GLfloat y, GLfloat z, GLfloat w);
GL_APICALL void GL_APIENTRY glVertexAttrib4fv (GLuint indx, const GLfloat* values);
-GL_APICALL void GL_APIENTRY glVertexAttribPointer (GLuint indx, GLint size, GLenum type, GLboolean normalized, GLsizei stride, const void* ptr);
+GL_APICALL void GL_APIENTRY glVertexAttribPointer (GLuint indx, GLint size, GLenum type, GLboolean normalized, GLsizei stride, const GLvoid* ptr);
GL_APICALL void GL_APIENTRY glViewport (GLint x, GLint y, GLsizei width, GLsizei height);
#ifdef __cplusplus
diff --git a/opengl/include/GLES2/gl2ext.h b/opengl/include/GLES2/gl2ext.h
index 72f1ae7..d8c9f41 100644
--- a/opengl/include/GLES2/gl2ext.h
+++ b/opengl/include/GLES2/gl2ext.h
@@ -1,7 +1,7 @@
#ifndef __gl2ext_h_
#define __gl2ext_h_
-/* $Revision: 8271 $ on $Date:: 2009-05-21 09:33:40 -0700 #$ */
+/* $Revision: 10969 $ on $Date:: 2010-04-09 02:27:15 -0700 #$ */
#ifdef __cplusplus
extern "C" {
@@ -57,6 +57,11 @@ extern "C" {
typedef void* GLeglImageOES;
#endif
+/* GL_OES_element_index_uint */
+#ifndef GL_OES_element_index_uint
+#define GL_UNSIGNED_INT 0x1405
+#endif
+
/* GL_OES_get_program_binary */
#ifndef GL_OES_get_program_binary
#define GL_PROGRAM_BINARY_LENGTH_OES 0x8741
@@ -100,8 +105,8 @@ typedef void* GLeglImageOES;
#define GL_STENCIL_INDEX4_OES 0x8D47
#endif
-/* GL_OES_texture3D */
-#ifndef GL_OES_texture3D
+/* GL_OES_texture_3D */
+#ifndef GL_OES_texture_3D
#define GL_TEXTURE_WRAP_R_OES 0x8072
#define GL_TEXTURE_3D_OES 0x806F
#define GL_TEXTURE_BINDING_3D_OES 0x806A
@@ -110,11 +115,28 @@ typedef void* GLeglImageOES;
#define GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_3D_ZOFFSET_OES 0x8CD4
#endif
+/* GL_OES_texture_float */
+/* No new tokens introduced by this extension. */
+
+/* GL_OES_texture_float_linear */
+/* No new tokens introduced by this extension. */
+
/* GL_OES_texture_half_float */
#ifndef GL_OES_texture_half_float
#define GL_HALF_FLOAT_OES 0x8D61
#endif
+/* GL_OES_texture_half_float_linear */
+/* No new tokens introduced by this extension. */
+
+/* GL_OES_texture_npot */
+/* No new tokens introduced by this extension. */
+
+/* GL_OES_vertex_array_object */
+#ifndef GL_OES_vertex_array_object
+#define GL_VERTEX_ARRAY_BINDING_OES 0x85B5
+#endif
+
/* GL_OES_vertex_half_float */
/* GL_HALF_FLOAT_OES defined in GL_OES_texture_half_float already. */
@@ -141,11 +163,6 @@ typedef void* GLeglImageOES;
#define GL_ATC_RGBA_INTERPOLATED_ALPHA_AMD 0x87EE
#endif
-/* GL_AMD_program_binary_Z400 */
-#ifndef GL_AMD_program_binary_Z400
-#define GL_Z400_BINARY_AMD 0x8740
-#endif
-
/* GL_AMD_performance_monitor */
#ifndef GL_AMD_performance_monitor
#define GL_COUNTER_TYPE_AMD 0x8BC0
@@ -157,35 +174,78 @@ typedef void* GLeglImageOES;
#define GL_PERFMON_RESULT_AMD 0x8BC6
#endif
+/* GL_AMD_program_binary_Z400 */
+#ifndef GL_AMD_program_binary_Z400
+#define GL_Z400_BINARY_AMD 0x8740
+#endif
+
/*------------------------------------------------------------------------*
* EXT extension tokens
*------------------------------------------------------------------------*/
+/* GL_EXT_blend_minmax */
+#ifndef GL_EXT_blend_minmax
+#define GL_MIN_EXT 0x8007
+#define GL_MAX_EXT 0x8008
+#endif
+
+/* GL_EXT_discard_framebuffer */
+#ifndef GL_EXT_discard_framebuffer
+#define GL_COLOR_EXT 0x1800
+#define GL_DEPTH_EXT 0x1801
+#define GL_STENCIL_EXT 0x1802
+#endif
+
+/* GL_EXT_multi_draw_arrays */
+/* No new tokens introduced by this extension. */
+
+/* GL_EXT_read_format_bgra */
+#ifndef GL_EXT_read_format_bgra
+#define GL_BGRA_EXT 0x80E1
+#define GL_UNSIGNED_SHORT_4_4_4_4_REV_EXT 0x8365
+#define GL_UNSIGNED_SHORT_1_5_5_5_REV_EXT 0x8366
+#endif
+
/* GL_EXT_texture_filter_anisotropic */
#ifndef GL_EXT_texture_filter_anisotropic
#define GL_TEXTURE_MAX_ANISOTROPY_EXT 0x84FE
#define GL_MAX_TEXTURE_MAX_ANISOTROPY_EXT 0x84FF
#endif
+/* GL_EXT_texture_format_BGRA8888 */
+#ifndef GL_EXT_texture_format_BGRA8888
+#define GL_BGRA_EXT 0x80E1
+#endif
+
/* GL_EXT_texture_type_2_10_10_10_REV */
#ifndef GL_EXT_texture_type_2_10_10_10_REV
#define GL_UNSIGNED_INT_2_10_10_10_REV_EXT 0x8368
#endif
-/* GL_EXT_texture_format_BGRA8888 */
-#ifndef GL_EXT_texture_format_BGRA8888
-#define GL_BGRA 0x80E1
+/* GL_EXT_texture_compression_dxt1 */
+#ifndef GL_EXT_texture_compression_dxt1
+#define GL_COMPRESSED_RGB_S3TC_DXT1_EXT 0x83F0
+#define GL_COMPRESSED_RGBA_S3TC_DXT1_EXT 0x83F1
#endif
/*------------------------------------------------------------------------*
* IMG extension tokens
*------------------------------------------------------------------------*/
+/* GL_IMG_program_binary */
+#ifndef GL_IMG_program_binary
+#define GL_SGX_PROGRAM_BINARY_IMG 0x9130
+#endif
+
/* GL_IMG_read_format */
#ifndef GL_IMG_read_format
-#define GL_BGRA 0x80E1
-#define GL_UNSIGNED_SHORT_4_4_4_4_REV 0x8365
-#define GL_UNSIGNED_SHORT_1_5_5_5_REV 0x8366
+#define GL_BGRA_IMG 0x80E1
+#define GL_UNSIGNED_SHORT_4_4_4_4_REV_IMG 0x8365
+#endif
+
+/* GL_IMG_shader_binary */
+#ifndef GL_IMG_shader_binary
+#define GL_SGX_BINARY_IMG 0x8C0A
#endif
/* GL_IMG_texture_compression_pvrtc */
@@ -196,6 +256,14 @@ typedef void* GLeglImageOES;
#define GL_COMPRESSED_RGBA_PVRTC_2BPPV1_IMG 0x8C03
#endif
+/* GL_IMG_multisampled_render_to_texture */
+#ifndef GL_IMG_multisampled_render_to_texture
+#define GL_RENDERBUFFER_SAMPLES_IMG 0x9133
+#define GL_FRAMEBUFFER_INCOMPLETE_MULTISAMPLE_IMG 0x9134
+#define GL_MAX_SAMPLES_IMG 0x9135
+#define GL_TEXTURE_SAMPLES_IMG 0x9136
+#endif
+
/*------------------------------------------------------------------------*
* NV extension tokens
*------------------------------------------------------------------------*/
@@ -207,6 +275,24 @@ typedef void* GLeglImageOES;
#define GL_FENCE_CONDITION_NV 0x84F4
#endif
+/* GL_NV_coverage_sample */
+#ifndef GL_NV_coverage_sample
+#define GL_COVERAGE_COMPONENT_NV 0x8ED0
+#define GL_COVERAGE_COMPONENT4_NV 0x8ED1
+#define GL_COVERAGE_ATTACHMENT_NV 0x8ED2
+#define GL_COVERAGE_BUFFERS_NV 0x8ED3
+#define GL_COVERAGE_SAMPLES_NV 0x8ED4
+#define GL_COVERAGE_ALL_FRAGMENTS_NV 0x8ED5
+#define GL_COVERAGE_EDGE_FRAGMENTS_NV 0x8ED6
+#define GL_COVERAGE_AUTOMATIC_NV 0x8ED7
+#define GL_COVERAGE_BUFFER_BIT_NV 0x8000
+#endif
+
+/* GL_NV_depth_nonlinear */
+#ifndef GL_NV_depth_nonlinear
+#define GL_DEPTH_COMPONENT16_NONLINEAR_NV 0x8E2C
+#endif
+
/*------------------------------------------------------------------------*
* QCOM extension tokens
*------------------------------------------------------------------------*/
@@ -214,11 +300,70 @@ typedef void* GLeglImageOES;
/* GL_QCOM_driver_control */
/* No new tokens introduced by this extension. */
+/* GL_QCOM_extended_get */
+#ifndef GL_QCOM_extended_get
+#define GL_TEXTURE_WIDTH_QCOM 0x8BD2
+#define GL_TEXTURE_HEIGHT_QCOM 0x8BD3
+#define GL_TEXTURE_DEPTH_QCOM 0x8BD4
+#define GL_TEXTURE_INTERNAL_FORMAT_QCOM 0x8BD5
+#define GL_TEXTURE_FORMAT_QCOM 0x8BD6
+#define GL_TEXTURE_TYPE_QCOM 0x8BD7
+#define GL_TEXTURE_IMAGE_VALID_QCOM 0x8BD8
+#define GL_TEXTURE_NUM_LEVELS_QCOM 0x8BD9
+#define GL_TEXTURE_TARGET_QCOM 0x8BDA
+#define GL_TEXTURE_OBJECT_VALID_QCOM 0x8BDB
+#define GL_STATE_RESTORE 0x8BDC
+#endif
+
+/* GL_QCOM_extended_get2 */
+/* No new tokens introduced by this extension. */
+
/* GL_QCOM_perfmon_global_mode */
#ifndef GL_QCOM_perfmon_global_mode
#define GL_PERFMON_GLOBAL_MODE_QCOM 0x8FA0
#endif
+/* GL_QCOM_writeonly_rendering */
+#ifndef GL_QCOM_writeonly_rendering
+#define GL_WRITEONLY_RENDERING_QCOM 0x8823
+#endif
+
+/* GL_QCOM_tiled_rendering */
+#ifndef GL_QCOM_tiled_rendering
+#define GL_COLOR_BUFFER_BIT0_QCOM 0x00000001
+#define GL_COLOR_BUFFER_BIT1_QCOM 0x00000002
+#define GL_COLOR_BUFFER_BIT2_QCOM 0x00000004
+#define GL_COLOR_BUFFER_BIT3_QCOM 0x00000008
+#define GL_COLOR_BUFFER_BIT4_QCOM 0x00000010
+#define GL_COLOR_BUFFER_BIT5_QCOM 0x00000020
+#define GL_COLOR_BUFFER_BIT6_QCOM 0x00000040
+#define GL_COLOR_BUFFER_BIT7_QCOM 0x00000080
+#define GL_DEPTH_BUFFER_BIT0_QCOM 0x00000100
+#define GL_DEPTH_BUFFER_BIT1_QCOM 0x00000200
+#define GL_DEPTH_BUFFER_BIT2_QCOM 0x00000400
+#define GL_DEPTH_BUFFER_BIT3_QCOM 0x00000800
+#define GL_DEPTH_BUFFER_BIT4_QCOM 0x00001000
+#define GL_DEPTH_BUFFER_BIT5_QCOM 0x00002000
+#define GL_DEPTH_BUFFER_BIT6_QCOM 0x00004000
+#define GL_DEPTH_BUFFER_BIT7_QCOM 0x00008000
+#define GL_STENCIL_BUFFER_BIT0_QCOM 0x00010000
+#define GL_STENCIL_BUFFER_BIT1_QCOM 0x00020000
+#define GL_STENCIL_BUFFER_BIT2_QCOM 0x00040000
+#define GL_STENCIL_BUFFER_BIT3_QCOM 0x00080000
+#define GL_STENCIL_BUFFER_BIT4_QCOM 0x00100000
+#define GL_STENCIL_BUFFER_BIT5_QCOM 0x00200000
+#define GL_STENCIL_BUFFER_BIT6_QCOM 0x00400000
+#define GL_STENCIL_BUFFER_BIT7_QCOM 0x00800000
+#define GL_MULTISAMPLE_BUFFER_BIT0_QCOM 0x01000000
+#define GL_MULTISAMPLE_BUFFER_BIT1_QCOM 0x02000000
+#define GL_MULTISAMPLE_BUFFER_BIT2_QCOM 0x04000000
+#define GL_MULTISAMPLE_BUFFER_BIT3_QCOM 0x08000000
+#define GL_MULTISAMPLE_BUFFER_BIT4_QCOM 0x10000000
+#define GL_MULTISAMPLE_BUFFER_BIT5_QCOM 0x20000000
+#define GL_MULTISAMPLE_BUFFER_BIT6_QCOM 0x40000000
+#define GL_MULTISAMPLE_BUFFER_BIT7_QCOM 0x80000000
+#endif
+
/*------------------------------------------------------------------------*
* End of extension tokens, start of corresponding extension functions
*------------------------------------------------------------------------*/
@@ -237,17 +382,6 @@ typedef void* GLeglImageOES;
#define GL_OES_compressed_paletted_texture 1
#endif
-/* GL_OES_EGL_image */
-#ifndef GL_OES_EGL_image
-#define GL_OES_EGL_image 1
-#ifdef GL_GLEXT_PROTOTYPES
-GL_APICALL void GL_APIENTRY glEGLImageTargetTexture2DOES (GLenum target, GLeglImageOES image);
-GL_APICALL void GL_APIENTRY glEGLImageTargetRenderbufferStorageOES (GLenum target, GLeglImageOES image);
-#endif
-typedef void (GL_APIENTRYP PFNGLEGLIMAGETARGETTEXTURE2DOESPROC) (GLenum target, GLeglImageOES image);
-typedef void (GL_APIENTRYP PFNGLEGLIMAGETARGETRENDERBUFFERSTORAGEOESPROC) (GLenum target, GLeglImageOES image);
-#endif
-
/* GL_OES_depth24 */
#ifndef GL_OES_depth24
#define GL_OES_depth24 1
@@ -263,6 +397,17 @@ typedef void (GL_APIENTRYP PFNGLEGLIMAGETARGETRENDERBUFFERSTORAGEOESPROC) (GLenu
#define GL_OES_depth_texture 1
#endif
+/* GL_OES_EGL_image */
+#ifndef GL_OES_EGL_image
+#define GL_OES_EGL_image 1
+#ifdef GL_GLEXT_PROTOTYPES
+GL_APICALL void GL_APIENTRY glEGLImageTargetTexture2DOES (GLenum target, GLeglImageOES image);
+GL_APICALL void GL_APIENTRY glEGLImageTargetRenderbufferStorageOES (GLenum target, GLeglImageOES image);
+#endif
+typedef void (GL_APIENTRYP PFNGLEGLIMAGETARGETTEXTURE2DOESPROC) (GLenum target, GLeglImageOES image);
+typedef void (GL_APIENTRYP PFNGLEGLIMAGETARGETRENDERBUFFERSTORAGEOESPROC) (GLenum target, GLeglImageOES image);
+#endif
+
/* GL_OES_element_index_uint */
#ifndef GL_OES_element_index_uint
#define GL_OES_element_index_uint 1
@@ -282,11 +427,11 @@ typedef void (GL_APIENTRYP PFNGLEGLIMAGETARGETRENDERBUFFERSTORAGEOESPROC) (GLenu
#ifndef GL_OES_get_program_binary
#define GL_OES_get_program_binary 1
#ifdef GL_GLEXT_PROTOTYPES
-GL_APICALL void GL_APIENTRY glGetProgramBinaryOES (GLuint program, GLsizei bufSize, GLsizei *length, GLenum *binaryFormat, void *binary);
-GL_APICALL void GL_APIENTRY glProgramBinaryOES (GLuint program, GLenum binaryFormat, const void *binary, GLint length);
+GL_APICALL void GL_APIENTRY glGetProgramBinaryOES (GLuint program, GLsizei bufSize, GLsizei *length, GLenum *binaryFormat, GLvoid *binary);
+GL_APICALL void GL_APIENTRY glProgramBinaryOES (GLuint program, GLenum binaryFormat, const GLvoid *binary, GLint length);
#endif
-typedef void (GL_APIENTRYP PFNGLGETPROGRAMBINARYOESPROC) (GLuint program, GLsizei bufSize, GLsizei *length, GLenum *binaryFormat, void *binary);
-typedef void (GL_APIENTRYP PFNGLPROGRAMBINARYOESPROC) (GLuint program, GLenum binaryFormat, const void *binary, GLint length);
+typedef void (GL_APIENTRYP PFNGLGETPROGRAMBINARYOESPROC) (GLuint program, GLsizei bufSize, GLsizei *length, GLenum *binaryFormat, GLvoid *binary);
+typedef void (GL_APIENTRYP PFNGLPROGRAMBINARYOESPROC) (GLuint program, GLenum binaryFormat, const GLvoid *binary, GLint length);
#endif
/* GL_OES_mapbuffer */
@@ -295,11 +440,11 @@ typedef void (GL_APIENTRYP PFNGLPROGRAMBINARYOESPROC) (GLuint program, GLenum bi
#ifdef GL_GLEXT_PROTOTYPES
GL_APICALL void* GL_APIENTRY glMapBufferOES (GLenum target, GLenum access);
GL_APICALL GLboolean GL_APIENTRY glUnmapBufferOES (GLenum target);
-GL_APICALL void GL_APIENTRY glGetBufferPointervOES (GLenum target, GLenum pname, void** params);
+GL_APICALL void GL_APIENTRY glGetBufferPointervOES (GLenum target, GLenum pname, GLvoid** params);
#endif
typedef void* (GL_APIENTRYP PFNGLMAPBUFFEROESPROC) (GLenum target, GLenum access);
typedef GLboolean (GL_APIENTRYP PFNGLUNMAPBUFFEROESPROC) (GLenum target);
-typedef void (GL_APIENTRYP PFNGLGETBUFFERPOINTERVOESPROC) (GLenum target, GLenum pname, void** params);
+typedef void (GL_APIENTRYP PFNGLGETBUFFERPOINTERVOESPROC) (GLenum target, GLenum pname, GLvoid** params);
#endif
/* GL_OES_packed_depth_stencil */
@@ -331,46 +476,61 @@ typedef void (GL_APIENTRYP PFNGLGETBUFFERPOINTERVOESPROC) (GLenum target, GLenum
#ifndef GL_OES_texture_3D
#define GL_OES_texture_3D 1
#ifdef GL_GLEXT_PROTOTYPES
-GL_APICALL void GL_APIENTRY glTexImage3DOES (GLenum target, GLint level, GLenum internalformat, GLsizei width, GLsizei height, GLsizei depth, GLint border, GLenum format, GLenum type, const void* pixels);
-GL_APICALL void GL_APIENTRY glTexSubImage3DOES (GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint zoffset, GLsizei width, GLsizei height, GLsizei depth, GLenum format, GLenum type, const void* pixels);
+GL_APICALL void GL_APIENTRY glTexImage3DOES (GLenum target, GLint level, GLenum internalformat, GLsizei width, GLsizei height, GLsizei depth, GLint border, GLenum format, GLenum type, const GLvoid* pixels);
+GL_APICALL void GL_APIENTRY glTexSubImage3DOES (GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint zoffset, GLsizei width, GLsizei height, GLsizei depth, GLenum format, GLenum type, const GLvoid* pixels);
GL_APICALL void GL_APIENTRY glCopyTexSubImage3DOES (GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint zoffset, GLint x, GLint y, GLsizei width, GLsizei height);
-GL_APICALL void GL_APIENTRY glCompressedTexImage3DOES (GLenum target, GLint level, GLenum internalformat, GLsizei width, GLsizei height, GLsizei depth, GLint border, GLsizei imageSize, const void* data);
-GL_APICALL void GL_APIENTRY glCompressedTexSubImage3DOES (GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint zoffset, GLsizei width, GLsizei height, GLsizei depth, GLenum format, GLsizei imageSize, const void* data);
+GL_APICALL void GL_APIENTRY glCompressedTexImage3DOES (GLenum target, GLint level, GLenum internalformat, GLsizei width, GLsizei height, GLsizei depth, GLint border, GLsizei imageSize, const GLvoid* data);
+GL_APICALL void GL_APIENTRY glCompressedTexSubImage3DOES (GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint zoffset, GLsizei width, GLsizei height, GLsizei depth, GLenum format, GLsizei imageSize, const GLvoid* data);
GL_APICALL void GL_APIENTRY glFramebufferTexture3DOES (GLenum target, GLenum attachment, GLenum textarget, GLuint texture, GLint level, GLint zoffset);
#endif
typedef void (GL_APIENTRYP PFNGLTEXIMAGE3DOESPROC) (GLenum target, GLint level, GLenum internalformat, GLsizei width, GLsizei height, GLsizei depth, GLint border, GLenum format, GLenum type, const GLvoid* pixels);
-typedef void (GL_APIENTRYP PFNGLTEXSUBIMAGE3DOESPROC) (GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint zoffset, GLsizei width, GLsizei height, GLsizei depth, GLenum format, GLenum type, const void* pixels);
+typedef void (GL_APIENTRYP PFNGLTEXSUBIMAGE3DOESPROC) (GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint zoffset, GLsizei width, GLsizei height, GLsizei depth, GLenum format, GLenum type, const GLvoid* pixels);
typedef void (GL_APIENTRYP PFNGLCOPYTEXSUBIMAGE3DOESPROC) (GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint zoffset, GLint x, GLint y, GLsizei width, GLsizei height);
-typedef void (GL_APIENTRYP PFNGLCOMPRESSEDTEXIMAGE3DOESPROC) (GLenum target, GLint level, GLenum internalformat, GLsizei width, GLsizei height, GLsizei depth, GLint border, GLsizei imageSize, const void* data);
-typedef void (GL_APIENTRYP PFNGLCOMPRESSEDTEXSUBIMAGE3DOESPROC) (GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint zoffset, GLsizei width, GLsizei height, GLsizei depth, GLenum format, GLsizei imageSize, const void* data);
+typedef void (GL_APIENTRYP PFNGLCOMPRESSEDTEXIMAGE3DOESPROC) (GLenum target, GLint level, GLenum internalformat, GLsizei width, GLsizei height, GLsizei depth, GLint border, GLsizei imageSize, const GLvoid* data);
+typedef void (GL_APIENTRYP PFNGLCOMPRESSEDTEXSUBIMAGE3DOESPROC) (GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint zoffset, GLsizei width, GLsizei height, GLsizei depth, GLenum format, GLsizei imageSize, const GLvoid* data);
typedef void (GL_APIENTRYP PFNGLFRAMEBUFFERTEXTURE3DOES) (GLenum target, GLenum attachment, GLenum textarget, GLuint texture, GLint level, GLint zoffset);
#endif
-/* GL_OES_texture_float_linear */
-#ifndef GL_OES_texture_float_linear
-#define GL_OES_texture_float_linear 1
-#endif
-
-/* GL_OES_texture_half_float_linear */
-#ifndef GL_OES_texture_half_float_linear
-#define GL_OES_texture_half_float_linear 1
-#endif
-
/* GL_OES_texture_float */
#ifndef GL_OES_texture_float
#define GL_OES_texture_float 1
#endif
+/* GL_OES_texture_float_linear */
+#ifndef GL_OES_texture_float_linear
+#define GL_OES_texture_float_linear 1
+#endif
+
/* GL_OES_texture_half_float */
#ifndef GL_OES_texture_half_float
#define GL_OES_texture_half_float 1
#endif
+/* GL_OES_texture_half_float_linear */
+#ifndef GL_OES_texture_half_float_linear
+#define GL_OES_texture_half_float_linear 1
+#endif
+
/* GL_OES_texture_npot */
#ifndef GL_OES_texture_npot
#define GL_OES_texture_npot 1
#endif
+/* GL_OES_vertex_array_object */
+#ifndef GL_OES_vertex_array_object
+#define GL_OES_vertex_array_object 1
+#ifdef GL_GLEXT_PROTOTYPES
+GL_APICALL void GL_APIENTRY glBindVertexArrayOES (GLuint array);
+GL_APICALL void GL_APIENTRY glDeleteVertexArraysOES (GLsizei n, const GLuint *arrays);
+GL_APICALL void GL_APIENTRY glGenVertexArraysOES (GLsizei n, GLuint *arrays);
+GL_APICALL GLboolean GL_APIENTRY glIsVertexArrayOES (GLuint array);
+#endif
+typedef void (GL_APIENTRYP PFNGLBINDVERTEXARRAYOESPROC) (GLuint array);
+typedef void (GL_APIENTRYP PFNGLDELETEVERTEXARRAYSOESPROC) (GLsizei n, const GLuint *arrays);
+typedef void (GL_APIENTRYP PFNGLGENVERTEXARRAYSOESPROC) (GLsizei n, GLuint *arrays);
+typedef GLboolean (GL_APIENTRYP PFNGLISVERTEXARRAYOESPROC) (GLuint array);
+#endif
+
/* GL_OES_vertex_half_float */
#ifndef GL_OES_vertex_half_float
#define GL_OES_vertex_half_float 1
@@ -395,20 +555,15 @@ typedef void (GL_APIENTRYP PFNGLFRAMEBUFFERTEXTURE3DOES) (GLenum target, GLenum
#define GL_AMD_compressed_ATC_texture 1
#endif
-/* GL_AMD_program_binary_Z400 */
-#ifndef GL_AMD_program_binary_Z400
-#define GL_AMD_program_binary_Z400 1
-#endif
-
/* AMD_performance_monitor */
#ifndef GL_AMD_performance_monitor
#define GL_AMD_performance_monitor 1
#ifdef GL_GLEXT_PROTOTYPES
GL_APICALL void GL_APIENTRY glGetPerfMonitorGroupsAMD (GLint *numGroups, GLsizei groupsSize, GLuint *groups);
GL_APICALL void GL_APIENTRY glGetPerfMonitorCountersAMD (GLuint group, GLint *numCounters, GLint *maxActiveCounters, GLsizei counterSize, GLuint *counters);
-GL_APICALL void GL_APIENTRY glGetPerfMonitorGroupStringAMD (GLuint group, GLsizei bufSize, GLsizei *length, char *groupString);
-GL_APICALL void GL_APIENTRY glGetPerfMonitorCounterStringAMD (GLuint group, GLuint counter, GLsizei bufSize, GLsizei *length, char *counterString);
-GL_APICALL void GL_APIENTRY glGetPerfMonitorCounterInfoAMD (GLuint group, GLuint counter, GLenum pname, void *data);
+GL_APICALL void GL_APIENTRY glGetPerfMonitorGroupStringAMD (GLuint group, GLsizei bufSize, GLsizei *length, GLchar *groupString);
+GL_APICALL void GL_APIENTRY glGetPerfMonitorCounterStringAMD (GLuint group, GLuint counter, GLsizei bufSize, GLsizei *length, GLchar *counterString);
+GL_APICALL void GL_APIENTRY glGetPerfMonitorCounterInfoAMD (GLuint group, GLuint counter, GLenum pname, GLvoid *data);
GL_APICALL void GL_APIENTRY glGenPerfMonitorsAMD (GLsizei n, GLuint *monitors);
GL_APICALL void GL_APIENTRY glDeletePerfMonitorsAMD (GLsizei n, GLuint *monitors);
GL_APICALL void GL_APIENTRY glSelectPerfMonitorCountersAMD (GLuint monitor, GLboolean enable, GLuint group, GLint numCounters, GLuint *countersList);
@@ -418,9 +573,9 @@ GL_APICALL void GL_APIENTRY glGetPerfMonitorCounterDataAMD (GLuint monitor, GLen
#endif
typedef void (GL_APIENTRYP PFNGLGETPERFMONITORGROUPSAMDPROC) (GLint *numGroups, GLsizei groupsSize, GLuint *groups);
typedef void (GL_APIENTRYP PFNGLGETPERFMONITORCOUNTERSAMDPROC) (GLuint group, GLint *numCounters, GLint *maxActiveCounters, GLsizei counterSize, GLuint *counters);
-typedef void (GL_APIENTRYP PFNGLGETPERFMONITORGROUPSTRINGAMDPROC) (GLuint group, GLsizei bufSize, GLsizei *length, char *groupString);
-typedef void (GL_APIENTRYP PFNGLGETPERFMONITORCOUNTERSTRINGAMDPROC) (GLuint group, GLuint counter, GLsizei bufSize, GLsizei *length, char *counterString);
-typedef void (GL_APIENTRYP PFNGLGETPERFMONITORCOUNTERINFOAMDPROC) (GLuint group, GLuint counter, GLenum pname, void *data);
+typedef void (GL_APIENTRYP PFNGLGETPERFMONITORGROUPSTRINGAMDPROC) (GLuint group, GLsizei bufSize, GLsizei *length, GLchar *groupString);
+typedef void (GL_APIENTRYP PFNGLGETPERFMONITORCOUNTERSTRINGAMDPROC) (GLuint group, GLuint counter, GLsizei bufSize, GLsizei *length, GLchar *counterString);
+typedef void (GL_APIENTRYP PFNGLGETPERFMONITORCOUNTERINFOAMDPROC) (GLuint group, GLuint counter, GLenum pname, GLvoid *data);
typedef void (GL_APIENTRYP PFNGLGENPERFMONITORSAMDPROC) (GLsizei n, GLuint *monitors);
typedef void (GL_APIENTRYP PFNGLDELETEPERFMONITORSAMDPROC) (GLsizei n, GLuint *monitors);
typedef void (GL_APIENTRYP PFNGLSELECTPERFMONITORCOUNTERSAMDPROC) (GLuint monitor, GLboolean enable, GLuint group, GLint numCounters, GLuint *countersList);
@@ -429,39 +584,99 @@ typedef void (GL_APIENTRYP PFNGLENDPERFMONITORAMDPROC) (GLuint monitor);
typedef void (GL_APIENTRYP PFNGLGETPERFMONITORCOUNTERDATAAMDPROC) (GLuint monitor, GLenum pname, GLsizei dataSize, GLuint *data, GLint *bytesWritten);
#endif
+/* GL_AMD_program_binary_Z400 */
+#ifndef GL_AMD_program_binary_Z400
+#define GL_AMD_program_binary_Z400 1
+#endif
+
/*------------------------------------------------------------------------*
* EXT extension functions
*------------------------------------------------------------------------*/
+/* GL_EXT_blend_minmax */
+#ifndef GL_EXT_blend_minmax
+#define GL_EXT_blend_minmax 1
+#endif
+
+/* GL_EXT_discard_framebuffer */
+#ifndef GL_EXT_discard_framebuffer
+#define GL_EXT_discard_framebuffer 1
+#ifdef GL_GLEXT_PROTOTYPES
+GL_APICALL void GL_APIENTRY glDiscardFramebufferEXT (GLenum target, GLsizei numAttachments, const GLenum *attachments);
+#endif
+typedef void (GL_APIENTRYP PFNGLDISCARDFRAMEBUFFEREXTPROC) (GLenum target, GLsizei numAttachments, const GLenum *attachments);
+#endif
+
+#ifndef GL_EXT_multi_draw_arrays
+#define GL_EXT_multi_draw_arrays 1
+#ifdef GL_GLEXT_PROTOTYPES
+GL_APICALL void GL_APIENTRY glMultiDrawArraysEXT (GLenum mode, GLint *first, GLsizei *count, GLsizei primcount);
+GL_APICALL void GL_APIENTRY glMultiDrawElementsEXT (GLenum mode, const GLsizei *count, GLenum type, const GLvoid* *indices, GLsizei primcount);
+#endif /* GL_GLEXT_PROTOTYPES */
+typedef void (GL_APIENTRYP PFNGLMULTIDRAWARRAYSEXTPROC) (GLenum mode, GLint *first, GLsizei *count, GLsizei primcount);
+typedef void (GL_APIENTRYP PFNGLMULTIDRAWELEMENTSEXTPROC) (GLenum mode, const GLsizei *count, GLenum type, const GLvoid* *indices, GLsizei primcount);
+#endif
+
+/* GL_EXT_read_format_bgra */
+#ifndef GL_EXT_read_format_bgra
+#define GL_EXT_read_format_bgra 1
+#endif
+
/* GL_EXT_texture_filter_anisotropic */
#ifndef GL_EXT_texture_filter_anisotropic
#define GL_EXT_texture_filter_anisotropic 1
#endif
+/* GL_EXT_texture_format_BGRA8888 */
+#ifndef GL_EXT_texture_format_BGRA8888
+#define GL_EXT_texture_format_BGRA8888 1
+#endif
+
/* GL_EXT_texture_type_2_10_10_10_REV */
#ifndef GL_EXT_texture_type_2_10_10_10_REV
#define GL_EXT_texture_type_2_10_10_10_REV 1
#endif
-/* GL_EXT_texture_format_BGRA8888 */
-#ifndef GL_EXT_texture_format_BGRA8888
-#define GL_EXT_texture_format_BGRA8888 1
+/* GL_EXT_texture_compression_dxt1 */
+#ifndef GL_EXT_texture_compression_dxt1
+#define GL_EXT_texture_compression_dxt1 1
#endif
/*------------------------------------------------------------------------*
* IMG extension functions
*------------------------------------------------------------------------*/
+/* GL_IMG_program_binary */
+#ifndef GL_IMG_program_binary
+#define GL_IMG_program_binary 1
+#endif
+
/* GL_IMG_read_format */
#ifndef GL_IMG_read_format
#define GL_IMG_read_format 1
#endif
+/* GL_IMG_shader_binary */
+#ifndef GL_IMG_shader_binary
+#define GL_IMG_shader_binary 1
+#endif
+
/* GL_IMG_texture_compression_pvrtc */
#ifndef GL_IMG_texture_compression_pvrtc
#define GL_IMG_texture_compression_pvrtc 1
#endif
+/* GL_IMG_multisampled_render_to_texture */
+#ifndef GL_IMG_multisampled_render_to_texture
+#define GL_IMG_multisampled_render_to_texture 1
+#ifdef GL_GLEXT_PROTOTYPES
+GL_APICALL void GL_APIENTRY glRenderbufferStorageMultisampleIMG (GLenum target, GLsizei samples, GLenum internalformat, GLsizei width, GLsizei height);
+GL_APICALL void GL_APIENTRY glFramebufferTexture2DMultisampleIMG (GLenum target, GLenum attachment, GLenum textarget, GLuint texture, GLint level, GLsizei samples);
+#endif
+typedef void (GL_APIENTRYP PFNGLRENDERBUFFERSTORAGEMULTISAMPLEIMG) (GLenum target, GLsizei samples, GLenum internalformat, GLsizei width, GLsizei height);
+typedef void (GL_APIENTRYP PFNGLFRAMEBUFFERTEXTURE2DMULTISAMPLEIMG) (GLenum target, GLenum attachment, GLenum textarget, GLuint texture, GLint level, GLsizei samples);
+#endif
+
/*------------------------------------------------------------------------*
* NV extension functions
*------------------------------------------------------------------------*/
@@ -487,6 +702,22 @@ typedef void (GL_APIENTRYP PFNGLFINISHFENCENVPROC) (GLuint fence);
typedef void (GL_APIENTRYP PFNGLSETFENCENVPROC) (GLuint fence, GLenum condition);
#endif
+/* GL_NV_coverage_sample */
+#ifndef GL_NV_coverage_sample
+#define GL_NV_coverage_sample 1
+#ifdef GL_GLEXT_PROTOTYPES
+GL_APICALL void GL_APIENTRY glCoverageMaskNV (GLboolean mask);
+GL_APICALL void GL_APIENTRY glCoverageOperationNV (GLenum operation);
+#endif
+typedef void (GL_APIENTRYP PFNGLCOVERAGEMASKNVPROC) (GLboolean mask);
+typedef void (GL_APIENTRYP PFNGLCOVERAGEOPERATIONNVPROC) (GLenum operation);
+#endif
+
+/* GL_NV_depth_nonlinear */
+#ifndef GL_NV_depth_nonlinear
+#define GL_NV_depth_nonlinear 1
+#endif
+
/*------------------------------------------------------------------------*
* QCOM extension functions
*------------------------------------------------------------------------*/
@@ -496,21 +727,75 @@ typedef void (GL_APIENTRYP PFNGLSETFENCENVPROC) (GLuint fence, GLenum condition)
#define GL_QCOM_driver_control 1
#ifdef GL_GLEXT_PROTOTYPES
GL_APICALL void GL_APIENTRY glGetDriverControlsQCOM (GLint *num, GLsizei size, GLuint *driverControls);
-GL_APICALL void GL_APIENTRY glGetDriverControlStringQCOM (GLuint driverControl, GLsizei bufSize, GLsizei *length, char *driverControlString);
+GL_APICALL void GL_APIENTRY glGetDriverControlStringQCOM (GLuint driverControl, GLsizei bufSize, GLsizei *length, GLchar *driverControlString);
GL_APICALL void GL_APIENTRY glEnableDriverControlQCOM (GLuint driverControl);
GL_APICALL void GL_APIENTRY glDisableDriverControlQCOM (GLuint driverControl);
#endif
typedef void (GL_APIENTRYP PFNGLGETDRIVERCONTROLSQCOMPROC) (GLint *num, GLsizei size, GLuint *driverControls);
-typedef void (GL_APIENTRYP PFNGLGETDRIVERCONTROLSTRINGQCOMPROC) (GLuint driverControl, GLsizei bufSize, GLsizei *length, char *driverControlString);
+typedef void (GL_APIENTRYP PFNGLGETDRIVERCONTROLSTRINGQCOMPROC) (GLuint driverControl, GLsizei bufSize, GLsizei *length, GLchar *driverControlString);
typedef void (GL_APIENTRYP PFNGLENABLEDRIVERCONTROLQCOMPROC) (GLuint driverControl);
typedef void (GL_APIENTRYP PFNGLDISABLEDRIVERCONTROLQCOMPROC) (GLuint driverControl);
#endif
+/* GL_QCOM_extended_get */
+#ifndef GL_QCOM_extended_get
+#define GL_QCOM_extended_get 1
+#ifdef GL_GLEXT_PROTOTYPES
+GL_APICALL void GL_APIENTRY glExtGetTexturesQCOM (GLuint *textures, GLint maxTextures, GLint *numTextures);
+GL_APICALL void GL_APIENTRY glExtGetBuffersQCOM (GLuint *buffers, GLint maxBuffers, GLint *numBuffers);
+GL_APICALL void GL_APIENTRY glExtGetRenderbuffersQCOM (GLuint *renderbuffers, GLint maxRenderbuffers, GLint *numRenderbuffers);
+GL_APICALL void GL_APIENTRY glExtGetFramebuffersQCOM (GLuint *framebuffers, GLint maxFramebuffers, GLint *numFramebuffers);
+GL_APICALL void GL_APIENTRY glExtGetTexLevelParameterivQCOM (GLuint texture, GLenum face, GLint level, GLenum pname, GLint *params);
+GL_APICALL void GL_APIENTRY glExtTexObjectStateOverrideiQCOM (GLenum target, GLenum pname, GLint param);
+GL_APICALL void GL_APIENTRY glExtGetTexSubImageQCOM (GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint zoffset, GLsizei width, GLsizei height, GLsizei depth, GLenum format, GLenum type, GLvoid *texels);
+GL_APICALL void GL_APIENTRY glExtGetBufferPointervQCOM (GLenum target, GLvoid **params);
+#endif
+typedef void (GL_APIENTRYP PFNGLEXTGETTEXTURESQCOMPROC) (GLuint *textures, GLint maxTextures, GLint *numTextures);
+typedef void (GL_APIENTRYP PFNGLEXTGETBUFFERSQCOMPROC) (GLuint *buffers, GLint maxBuffers, GLint *numBuffers);
+typedef void (GL_APIENTRYP PFNGLEXTGETRENDERBUFFERSQCOMPROC) (GLuint *renderbuffers, GLint maxRenderbuffers, GLint *numRenderbuffers);
+typedef void (GL_APIENTRYP PFNGLEXTGETFRAMEBUFFERSQCOMPROC) (GLuint *framebuffers, GLint maxFramebuffers, GLint *numFramebuffers);
+typedef void (GL_APIENTRYP PFNGLEXTGETTEXLEVELPARAMETERIVQCOMPROC) (GLuint texture, GLenum face, GLint level, GLenum pname, GLint *params);
+typedef void (GL_APIENTRYP PFNGLEXTTEXOBJECTSTATEOVERRIDEIQCOMPROC) (GLenum target, GLenum pname, GLint param);
+typedef void (GL_APIENTRYP PFNGLEXTGETTEXSUBIMAGEQCOMPROC) (GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint zoffset, GLsizei width, GLsizei height, GLsizei depth, GLenum format, GLenum type, GLvoid *texels);
+typedef void (GL_APIENTRYP PFNGLEXTGETBUFFERPOINTERVQCOMPROC) (GLenum target, GLvoid **params);
+#endif
+
+/* GL_QCOM_extended_get2 */
+#ifndef GL_QCOM_extended_get2
+#define GL_QCOM_extended_get2 1
+#ifdef GL_GLEXT_PROTOTYPES
+GL_APICALL void GL_APIENTRY glExtGetShadersQCOM (GLuint *shaders, GLint maxShaders, GLint *numShaders);
+GL_APICALL void GL_APIENTRY glExtGetProgramsQCOM (GLuint *programs, GLint maxPrograms, GLint *numPrograms);
+GL_APICALL GLboolean GL_APIENTRY glExtIsProgramBinaryQCOM (GLuint program);
+GL_APICALL void GL_APIENTRY glExtGetProgramBinarySourceQCOM (GLuint program, GLenum shadertype, GLchar *source, GLint *length);
+#endif
+typedef void (GL_APIENTRYP PFNGLEXTGETSHADERSQCOMPROC) (GLuint *shaders, GLint maxShaders, GLint *numShaders);
+typedef void (GL_APIENTRYP PFNGLEXTGETPROGRAMSQCOMPROC) (GLuint *programs, GLint maxPrograms, GLint *numPrograms);
+typedef GLboolean (GL_APIENTRYP PFNGLEXTISPROGRAMBINARYQCOMPROC) (GLuint program);
+typedef void (GL_APIENTRYP PFNGLEXTGETPROGRAMBINARYSOURCEQCOMPROC) (GLuint program, GLenum shadertype, GLchar *source, GLint *length);
+#endif
+
/* GL_QCOM_perfmon_global_mode */
#ifndef GL_QCOM_perfmon_global_mode
#define GL_QCOM_perfmon_global_mode 1
#endif
+/* GL_QCOM_writeonly_rendering */
+#ifndef GL_QCOM_writeonly_rendering
+#define GL_QCOM_writeonly_rendering 1
+#endif
+
+/* GL_QCOM_tiled_rendering */
+#ifndef GL_QCOM_tiled_rendering
+#define GL_QCOM_tiled_rendering 1
+#ifdef GL_GLEXT_PROTOTYPES
+GL_APICALL void GL_APIENTRY glStartTilingQCOM (GLuint x, GLuint y, GLuint width, GLuint height, GLbitfield preserveMask);
+GL_APICALL void GL_APIENTRY glEndTilingQCOM (GLbitfield preserveMask);
+#endif
+typedef void (GL_APIENTRYP PFNGLSTARTTILINGQCOMPROC) (GLuint x, GLuint y, GLuint width, GLuint height, GLbitfield preserveMask);
+typedef void (GL_APIENTRYP PFNGLENDTILINGQCOMPROC) (GLbitfield preserveMask);
+#endif
+
#ifdef __cplusplus
}
#endif
diff --git a/opengl/include/GLES2/gl2platform.h b/opengl/include/GLES2/gl2platform.h
index 3e9036c..c9fa3c4 100644
--- a/opengl/include/GLES2/gl2platform.h
+++ b/opengl/include/GLES2/gl2platform.h
@@ -1,7 +1,7 @@
#ifndef __gl2platform_h_
#define __gl2platform_h_
-/* $Revision: 7173 $ on $Date:: 2009-01-09 11:18:21 -0800 #$ */
+/* $Revision: 10602 $ on $Date:: 2010-03-04 22:35:34 -0800 #$ */
/*
* This document is licensed under the SGI Free Software B License Version
@@ -9,7 +9,6 @@
*/
/* Platform-specific types and definitions for OpenGL ES 2.X gl2.h
- * Last modified on 2008/12/19
*
* Adopters may modify khrplatform.h and this file to suit their platform.
* You are encouraged to submit all modifications to the Khronos group so that
@@ -24,6 +23,8 @@
#define GL_APICALL KHRONOS_APICALL
#endif
+#ifndef GL_APIENTRY
#define GL_APIENTRY KHRONOS_APIENTRY
+#endif
#endif /* __gl2platform_h_ */
diff --git a/opengl/libs/GLES2/gl2_api.in b/opengl/libs/GLES2/gl2_api.in
index 9c2e69a..5164450 100644
--- a/opengl/libs/GLES2/gl2_api.in
+++ b/opengl/libs/GLES2/gl2_api.in
@@ -4,7 +4,7 @@ void API_ENTRY(glActiveTexture)(GLenum texture) {
void API_ENTRY(glAttachShader)(GLuint program, GLuint shader) {
CALL_GL_API(glAttachShader, program, shader);
}
-void API_ENTRY(glBindAttribLocation)(GLuint program, GLuint index, const char* name) {
+void API_ENTRY(glBindAttribLocation)(GLuint program, GLuint index, const GLchar* name) {
CALL_GL_API(glBindAttribLocation, program, index, name);
}
void API_ENTRY(glBindBuffer)(GLenum target, GLuint buffer) {
@@ -34,10 +34,10 @@ void API_ENTRY(glBlendFunc)(GLenum sfactor, GLenum dfactor) {
void API_ENTRY(glBlendFuncSeparate)(GLenum srcRGB, GLenum dstRGB, GLenum srcAlpha, GLenum dstAlpha) {
CALL_GL_API(glBlendFuncSeparate, srcRGB, dstRGB, srcAlpha, dstAlpha);
}
-void API_ENTRY(glBufferData)(GLenum target, GLsizeiptr size, const void* data, GLenum usage) {
+void API_ENTRY(glBufferData)(GLenum target, GLsizeiptr size, const GLvoid* data, GLenum usage) {
CALL_GL_API(glBufferData, target, size, data, usage);
}
-void API_ENTRY(glBufferSubData)(GLenum target, GLintptr offset, GLsizeiptr size, const void* data) {
+void API_ENTRY(glBufferSubData)(GLenum target, GLintptr offset, GLsizeiptr size, const GLvoid* data) {
CALL_GL_API(glBufferSubData, target, offset, size, data);
}
GLenum API_ENTRY(glCheckFramebufferStatus)(GLenum target) {
@@ -61,10 +61,10 @@ void API_ENTRY(glColorMask)(GLboolean red, GLboolean green, GLboolean blue, GLbo
void API_ENTRY(glCompileShader)(GLuint shader) {
CALL_GL_API(glCompileShader, shader);
}
-void API_ENTRY(glCompressedTexImage2D)(GLenum target, GLint level, GLenum internalformat, GLsizei width, GLsizei height, GLint border, GLsizei imageSize, const void* data) {
+void API_ENTRY(glCompressedTexImage2D)(GLenum target, GLint level, GLenum internalformat, GLsizei width, GLsizei height, GLint border, GLsizei imageSize, const GLvoid* data) {
CALL_GL_API(glCompressedTexImage2D, target, level, internalformat, width, height, border, imageSize, data);
}
-void API_ENTRY(glCompressedTexSubImage2D)(GLenum target, GLint level, GLint xoffset, GLint yoffset, GLsizei width, GLsizei height, GLenum format, GLsizei imageSize, const void* data) {
+void API_ENTRY(glCompressedTexSubImage2D)(GLenum target, GLint level, GLint xoffset, GLint yoffset, GLsizei width, GLsizei height, GLenum format, GLsizei imageSize, const GLvoid* data) {
CALL_GL_API(glCompressedTexSubImage2D, target, level, xoffset, yoffset, width, height, format, imageSize, data);
}
void API_ENTRY(glCopyTexImage2D)(GLenum target, GLint level, GLenum internalformat, GLint x, GLint y, GLsizei width, GLsizei height, GLint border) {
@@ -121,7 +121,7 @@ void API_ENTRY(glDisableVertexAttribArray)(GLuint index) {
void API_ENTRY(glDrawArrays)(GLenum mode, GLint first, GLsizei count) {
CALL_GL_API(glDrawArrays, mode, first, count);
}
-void API_ENTRY(glDrawElements)(GLenum mode, GLsizei count, GLenum type, const void* indices) {
+void API_ENTRY(glDrawElements)(GLenum mode, GLsizei count, GLenum type, const GLvoid* indices) {
CALL_GL_API(glDrawElements, mode, count, type, indices);
}
void API_ENTRY(glEnable)(GLenum cap) {
@@ -160,16 +160,16 @@ void API_ENTRY(glGenRenderbuffers)(GLsizei n, GLuint* renderbuffers) {
void API_ENTRY(glGenTextures)(GLsizei n, GLuint* textures) {
CALL_GL_API(glGenTextures, n, textures);
}
-void API_ENTRY(glGetActiveAttrib)(GLuint program, GLuint index, GLsizei bufsize, GLsizei* length, GLint* size, GLenum* type, char* name) {
+void API_ENTRY(glGetActiveAttrib)(GLuint program, GLuint index, GLsizei bufsize, GLsizei* length, GLint* size, GLenum* type, GLchar* name) {
CALL_GL_API(glGetActiveAttrib, program, index, bufsize, length, size, type, name);
}
-void API_ENTRY(glGetActiveUniform)(GLuint program, GLuint index, GLsizei bufsize, GLsizei* length, GLint* size, GLenum* type, char* name) {
+void API_ENTRY(glGetActiveUniform)(GLuint program, GLuint index, GLsizei bufsize, GLsizei* length, GLint* size, GLenum* type, GLchar* name) {
CALL_GL_API(glGetActiveUniform, program, index, bufsize, length, size, type, name);
}
void API_ENTRY(glGetAttachedShaders)(GLuint program, GLsizei maxcount, GLsizei* count, GLuint* shaders) {
CALL_GL_API(glGetAttachedShaders, program, maxcount, count, shaders);
}
-int API_ENTRY(glGetAttribLocation)(GLuint program, const char* name) {
+int API_ENTRY(glGetAttribLocation)(GLuint program, const GLchar* name) {
CALL_GL_API_RETURN(glGetAttribLocation, program, name);
}
void API_ENTRY(glGetBooleanv)(GLenum pname, GLboolean* params) {
@@ -193,7 +193,7 @@ void API_ENTRY(glGetIntegerv)(GLenum pname, GLint* params) {
void API_ENTRY(glGetProgramiv)(GLuint program, GLenum pname, GLint* params) {
CALL_GL_API(glGetProgramiv, program, pname, params);
}
-void API_ENTRY(glGetProgramInfoLog)(GLuint program, GLsizei bufsize, GLsizei* length, char* infolog) {
+void API_ENTRY(glGetProgramInfoLog)(GLuint program, GLsizei bufsize, GLsizei* length, GLchar* infolog) {
CALL_GL_API(glGetProgramInfoLog, program, bufsize, length, infolog);
}
void API_ENTRY(glGetRenderbufferParameteriv)(GLenum target, GLenum pname, GLint* params) {
@@ -202,13 +202,13 @@ void API_ENTRY(glGetRenderbufferParameteriv)(GLenum target, GLenum pname, GLint*
void API_ENTRY(glGetShaderiv)(GLuint shader, GLenum pname, GLint* params) {
CALL_GL_API(glGetShaderiv, shader, pname, params);
}
-void API_ENTRY(glGetShaderInfoLog)(GLuint shader, GLsizei bufsize, GLsizei* length, char* infolog) {
+void API_ENTRY(glGetShaderInfoLog)(GLuint shader, GLsizei bufsize, GLsizei* length, GLchar* infolog) {
CALL_GL_API(glGetShaderInfoLog, shader, bufsize, length, infolog);
}
void API_ENTRY(glGetShaderPrecisionFormat)(GLenum shadertype, GLenum precisiontype, GLint* range, GLint* precision) {
CALL_GL_API(glGetShaderPrecisionFormat, shadertype, precisiontype, range, precision);
}
-void API_ENTRY(glGetShaderSource)(GLuint shader, GLsizei bufsize, GLsizei* length, char* source) {
+void API_ENTRY(glGetShaderSource)(GLuint shader, GLsizei bufsize, GLsizei* length, GLchar* source) {
CALL_GL_API(glGetShaderSource, shader, bufsize, length, source);
}
const GLubyte* API_ENTRY(glGetString)(GLenum name) {
@@ -226,7 +226,7 @@ void API_ENTRY(glGetUniformfv)(GLuint program, GLint location, GLfloat* params)
void API_ENTRY(glGetUniformiv)(GLuint program, GLint location, GLint* params) {
CALL_GL_API(glGetUniformiv, program, location, params);
}
-int API_ENTRY(glGetUniformLocation)(GLuint program, const char* name) {
+int API_ENTRY(glGetUniformLocation)(GLuint program, const GLchar* name) {
CALL_GL_API_RETURN(glGetUniformLocation, program, name);
}
void API_ENTRY(glGetVertexAttribfv)(GLuint index, GLenum pname, GLfloat* params) {
@@ -235,7 +235,7 @@ void API_ENTRY(glGetVertexAttribfv)(GLuint index, GLenum pname, GLfloat* params)
void API_ENTRY(glGetVertexAttribiv)(GLuint index, GLenum pname, GLint* params) {
CALL_GL_API(glGetVertexAttribiv, index, pname, params);
}
-void API_ENTRY(glGetVertexAttribPointerv)(GLuint index, GLenum pname, void** pointer) {
+void API_ENTRY(glGetVertexAttribPointerv)(GLuint index, GLenum pname, GLvoid** pointer) {
CALL_GL_API(glGetVertexAttribPointerv, index, pname, pointer);
}
void API_ENTRY(glHint)(GLenum target, GLenum mode) {
@@ -274,7 +274,7 @@ void API_ENTRY(glPixelStorei)(GLenum pname, GLint param) {
void API_ENTRY(glPolygonOffset)(GLfloat factor, GLfloat units) {
CALL_GL_API(glPolygonOffset, factor, units);
}
-void API_ENTRY(glReadPixels)(GLint x, GLint y, GLsizei width, GLsizei height, GLenum format, GLenum type, void* pixels) {
+void API_ENTRY(glReadPixels)(GLint x, GLint y, GLsizei width, GLsizei height, GLenum format, GLenum type, GLvoid* pixels) {
CALL_GL_API(glReadPixels, x, y, width, height, format, type, pixels);
}
void API_ENTRY(glReleaseShaderCompiler)(void) {
@@ -289,10 +289,10 @@ void API_ENTRY(glSampleCoverage)(GLclampf value, GLboolean invert) {
void API_ENTRY(glScissor)(GLint x, GLint y, GLsizei width, GLsizei height) {
CALL_GL_API(glScissor, x, y, width, height);
}
-void API_ENTRY(glShaderBinary)(GLsizei n, const GLuint* shaders, GLenum binaryformat, const void* binary, GLsizei length) {
+void API_ENTRY(glShaderBinary)(GLsizei n, const GLuint* shaders, GLenum binaryformat, const GLvoid* binary, GLsizei length) {
CALL_GL_API(glShaderBinary, n, shaders, binaryformat, binary, length);
}
-void API_ENTRY(glShaderSource)(GLuint shader, GLsizei count, const char** string, const GLint* length) {
+void API_ENTRY(glShaderSource)(GLuint shader, GLsizei count, const GLchar** string, const GLint* length) {
CALL_GL_API(glShaderSource, shader, count, string, length);
}
void API_ENTRY(glStencilFunc)(GLenum func, GLint ref, GLuint mask) {
@@ -313,7 +313,7 @@ void API_ENTRY(glStencilOp)(GLenum fail, GLenum zfail, GLenum zpass) {
void API_ENTRY(glStencilOpSeparate)(GLenum face, GLenum fail, GLenum zfail, GLenum zpass) {
CALL_GL_API(glStencilOpSeparate, face, fail, zfail, zpass);
}
-void API_ENTRY(glTexImage2D)(GLenum target, GLint level, GLint internalformat, GLsizei width, GLsizei height, GLint border, GLenum format, GLenum type, const GLvoid* pixels) {
+void API_ENTRY(glTexImage2D)(GLenum target, GLint level, GLint internalformat, GLsizei width, GLsizei height, GLint border, GLenum format, GLenum type, const GLvoid* pixels) {
CALL_GL_API(glTexImage2D, target, level, internalformat, width, height, border, format, type, pixels);
}
void API_ENTRY(glTexParameterf)(GLenum target, GLenum pname, GLfloat param) {
@@ -328,7 +328,7 @@ void API_ENTRY(glTexParameteri)(GLenum target, GLenum pname, GLint param) {
void API_ENTRY(glTexParameteriv)(GLenum target, GLenum pname, const GLint* params) {
CALL_GL_API(glTexParameteriv, target, pname, params);
}
-void API_ENTRY(glTexSubImage2D)(GLenum target, GLint level, GLint xoffset, GLint yoffset, GLsizei width, GLsizei height, GLenum format, GLenum type, const void* pixels) {
+void API_ENTRY(glTexSubImage2D)(GLenum target, GLint level, GLint xoffset, GLint yoffset, GLsizei width, GLsizei height, GLenum format, GLenum type, const GLvoid* pixels) {
CALL_GL_API(glTexSubImage2D, target, level, xoffset, yoffset, width, height, format, type, pixels);
}
void API_ENTRY(glUniform1f)(GLint location, GLfloat x) {
@@ -418,7 +418,7 @@ void API_ENTRY(glVertexAttrib4f)(GLuint indx, GLfloat x, GLfloat y, GLfloat z, G
void API_ENTRY(glVertexAttrib4fv)(GLuint indx, const GLfloat* values) {
CALL_GL_API(glVertexAttrib4fv, indx, values);
}
-void API_ENTRY(glVertexAttribPointer)(GLuint indx, GLint size, GLenum type, GLboolean normalized, GLsizei stride, const void* ptr) {
+void API_ENTRY(glVertexAttribPointer)(GLuint indx, GLint size, GLenum type, GLboolean normalized, GLsizei stride, const GLvoid* ptr) {
CALL_GL_API(glVertexAttribPointer, indx, size, type, normalized, stride, ptr);
}
void API_ENTRY(glViewport)(GLint x, GLint y, GLsizei width, GLsizei height) {
diff --git a/opengl/libs/GLES2/gl2ext_api.in b/opengl/libs/GLES2/gl2ext_api.in
index 6eeecb3..e965625 100644
--- a/opengl/libs/GLES2/gl2ext_api.in
+++ b/opengl/libs/GLES2/gl2ext_api.in
@@ -4,10 +4,10 @@ void API_ENTRY(__glEGLImageTargetTexture2DOES)(GLenum target, GLeglImageOES imag
void API_ENTRY(__glEGLImageTargetRenderbufferStorageOES)(GLenum target, GLeglImageOES image) {
CALL_GL_API(glEGLImageTargetRenderbufferStorageOES, target, image);
}
-void API_ENTRY(glGetProgramBinaryOES)(GLuint program, GLsizei bufSize, GLsizei *length, GLenum *binaryFormat, void *binary) {
+void API_ENTRY(glGetProgramBinaryOES)(GLuint program, GLsizei bufSize, GLsizei *length, GLenum *binaryFormat, GLvoid *binary) {
CALL_GL_API(glGetProgramBinaryOES, program, bufSize, length, binaryFormat, binary);
}
-void API_ENTRY(glProgramBinaryOES)(GLuint program, GLenum binaryFormat, const void *binary, GLint length) {
+void API_ENTRY(glProgramBinaryOES)(GLuint program, GLenum binaryFormat, const GLvoid *binary, GLint length) {
CALL_GL_API(glProgramBinaryOES, program, binaryFormat, binary, length);
}
void* API_ENTRY(glMapBufferOES)(GLenum target, GLenum access) {
@@ -16,40 +16,52 @@ void* API_ENTRY(glMapBufferOES)(GLenum target, GLenum access) {
GLboolean API_ENTRY(glUnmapBufferOES)(GLenum target) {
CALL_GL_API_RETURN(glUnmapBufferOES, target);
}
-void API_ENTRY(glGetBufferPointervOES)(GLenum target, GLenum pname, void** params) {
+void API_ENTRY(glGetBufferPointervOES)(GLenum target, GLenum pname, GLvoid** params) {
CALL_GL_API(glGetBufferPointervOES, target, pname, params);
}
-void API_ENTRY(glTexImage3DOES)(GLenum target, GLint level, GLenum internalformat, GLsizei width, GLsizei height, GLsizei depth, GLint border, GLenum format, GLenum type, const void* pixels) {
+void API_ENTRY(glTexImage3DOES)(GLenum target, GLint level, GLenum internalformat, GLsizei width, GLsizei height, GLsizei depth, GLint border, GLenum format, GLenum type, const GLvoid* pixels) {
CALL_GL_API(glTexImage3DOES, target, level, internalformat, width, height, depth, border, format, type, pixels);
}
-void API_ENTRY(glTexSubImage3DOES)(GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint zoffset, GLsizei width, GLsizei height, GLsizei depth, GLenum format, GLenum type, const void* pixels) {
+void API_ENTRY(glTexSubImage3DOES)(GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint zoffset, GLsizei width, GLsizei height, GLsizei depth, GLenum format, GLenum type, const GLvoid* pixels) {
CALL_GL_API(glTexSubImage3DOES, target, level, xoffset, yoffset, zoffset, width, height, depth, format, type, pixels);
}
void API_ENTRY(glCopyTexSubImage3DOES)(GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint zoffset, GLint x, GLint y, GLsizei width, GLsizei height) {
CALL_GL_API(glCopyTexSubImage3DOES, target, level, xoffset, yoffset, zoffset, x, y, width, height);
}
-void API_ENTRY(glCompressedTexImage3DOES)(GLenum target, GLint level, GLenum internalformat, GLsizei width, GLsizei height, GLsizei depth, GLint border, GLsizei imageSize, const void* data) {
+void API_ENTRY(glCompressedTexImage3DOES)(GLenum target, GLint level, GLenum internalformat, GLsizei width, GLsizei height, GLsizei depth, GLint border, GLsizei imageSize, const GLvoid* data) {
CALL_GL_API(glCompressedTexImage3DOES, target, level, internalformat, width, height, depth, border, imageSize, data);
}
-void API_ENTRY(glCompressedTexSubImage3DOES)(GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint zoffset, GLsizei width, GLsizei height, GLsizei depth, GLenum format, GLsizei imageSize, const void* data) {
+void API_ENTRY(glCompressedTexSubImage3DOES)(GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint zoffset, GLsizei width, GLsizei height, GLsizei depth, GLenum format, GLsizei imageSize, const GLvoid* data) {
CALL_GL_API(glCompressedTexSubImage3DOES, target, level, xoffset, yoffset, zoffset, width, height, depth, format, imageSize, data);
}
void API_ENTRY(glFramebufferTexture3DOES)(GLenum target, GLenum attachment, GLenum textarget, GLuint texture, GLint level, GLint zoffset) {
CALL_GL_API(glFramebufferTexture3DOES, target, attachment, textarget, texture, level, zoffset);
}
+void API_ENTRY(glBindVertexArrayOES)(GLuint array) {
+ CALL_GL_API(glBindVertexArrayOES, array);
+}
+void API_ENTRY(glDeleteVertexArraysOES)(GLsizei n, const GLuint *arrays) {
+ CALL_GL_API(glDeleteVertexArraysOES, n, arrays);
+}
+void API_ENTRY(glGenVertexArraysOES)(GLsizei n, GLuint *arrays) {
+ CALL_GL_API(glGenVertexArraysOES, n, arrays);
+}
+GLboolean API_ENTRY(glIsVertexArrayOES)(GLuint array) {
+ CALL_GL_API_RETURN(glIsVertexArrayOES, array);
+}
void API_ENTRY(glGetPerfMonitorGroupsAMD)(GLint *numGroups, GLsizei groupsSize, GLuint *groups) {
CALL_GL_API(glGetPerfMonitorGroupsAMD, numGroups, groupsSize, groups);
}
void API_ENTRY(glGetPerfMonitorCountersAMD)(GLuint group, GLint *numCounters, GLint *maxActiveCounters, GLsizei counterSize, GLuint *counters) {
CALL_GL_API(glGetPerfMonitorCountersAMD, group, numCounters, maxActiveCounters, counterSize, counters);
}
-void API_ENTRY(glGetPerfMonitorGroupStringAMD)(GLuint group, GLsizei bufSize, GLsizei *length, char *groupString) {
+void API_ENTRY(glGetPerfMonitorGroupStringAMD)(GLuint group, GLsizei bufSize, GLsizei *length, GLchar *groupString) {
CALL_GL_API(glGetPerfMonitorGroupStringAMD, group, bufSize, length, groupString);
}
-void API_ENTRY(glGetPerfMonitorCounterStringAMD)(GLuint group, GLuint counter, GLsizei bufSize, GLsizei *length, char *counterString) {
+void API_ENTRY(glGetPerfMonitorCounterStringAMD)(GLuint group, GLuint counter, GLsizei bufSize, GLsizei *length, GLchar *counterString) {
CALL_GL_API(glGetPerfMonitorCounterStringAMD, group, counter, bufSize, length, counterString);
}
-void API_ENTRY(glGetPerfMonitorCounterInfoAMD)(GLuint group, GLuint counter, GLenum pname, void *data) {
+void API_ENTRY(glGetPerfMonitorCounterInfoAMD)(GLuint group, GLuint counter, GLenum pname, GLvoid *data) {
CALL_GL_API(glGetPerfMonitorCounterInfoAMD, group, counter, pname, data);
}
void API_ENTRY(glGenPerfMonitorsAMD)(GLsizei n, GLuint *monitors) {
@@ -70,6 +82,21 @@ void API_ENTRY(glEndPerfMonitorAMD)(GLuint monitor) {
void API_ENTRY(glGetPerfMonitorCounterDataAMD)(GLuint monitor, GLenum pname, GLsizei dataSize, GLuint *data, GLint *bytesWritten) {
CALL_GL_API(glGetPerfMonitorCounterDataAMD, monitor, pname, dataSize, data, bytesWritten);
}
+void API_ENTRY(glDiscardFramebufferEXT)(GLenum target, GLsizei numAttachments, const GLenum *attachments) {
+ CALL_GL_API(glDiscardFramebufferEXT, target, numAttachments, attachments);
+}
+void API_ENTRY(glMultiDrawArraysEXT)(GLenum mode, GLint *first, GLsizei *count, GLsizei primcount) {
+ CALL_GL_API(glMultiDrawArraysEXT, mode, first, count, primcount);
+}
+void API_ENTRY(glMultiDrawElementsEXT)(GLenum mode, const GLsizei *count, GLenum type, const GLvoid* *indices, GLsizei primcount) {
+ CALL_GL_API(glMultiDrawElementsEXT, mode, count, type, indices, primcount);
+}
+void API_ENTRY(glRenderbufferStorageMultisampleIMG)(GLenum target, GLsizei samples, GLenum internalformat, GLsizei width, GLsizei height) {
+ CALL_GL_API(glRenderbufferStorageMultisampleIMG, target, samples, internalformat, width, height);
+}
+void API_ENTRY(glFramebufferTexture2DMultisampleIMG)(GLenum target, GLenum attachment, GLenum textarget, GLuint texture, GLint level, GLsizei samples) {
+ CALL_GL_API(glFramebufferTexture2DMultisampleIMG, target, attachment, textarget, texture, level, samples);
+}
void API_ENTRY(glDeleteFencesNV)(GLsizei n, const GLuint *fences) {
CALL_GL_API(glDeleteFencesNV, n, fences);
}
@@ -91,10 +118,16 @@ void API_ENTRY(glFinishFenceNV)(GLuint fence) {
void API_ENTRY(glSetFenceNV)(GLuint fence, GLenum condition) {
CALL_GL_API(glSetFenceNV, fence, condition);
}
+void API_ENTRY(glCoverageMaskNV)(GLboolean mask) {
+ CALL_GL_API(glCoverageMaskNV, mask);
+}
+void API_ENTRY(glCoverageOperationNV)(GLenum operation) {
+ CALL_GL_API(glCoverageOperationNV, operation);
+}
void API_ENTRY(glGetDriverControlsQCOM)(GLint *num, GLsizei size, GLuint *driverControls) {
CALL_GL_API(glGetDriverControlsQCOM, num, size, driverControls);
}
-void API_ENTRY(glGetDriverControlStringQCOM)(GLuint driverControl, GLsizei bufSize, GLsizei *length, char *driverControlString) {
+void API_ENTRY(glGetDriverControlStringQCOM)(GLuint driverControl, GLsizei bufSize, GLsizei *length, GLchar *driverControlString) {
CALL_GL_API(glGetDriverControlStringQCOM, driverControl, bufSize, length, driverControlString);
}
void API_ENTRY(glEnableDriverControlQCOM)(GLuint driverControl) {
@@ -103,3 +136,45 @@ void API_ENTRY(glEnableDriverControlQCOM)(GLuint driverControl) {
void API_ENTRY(glDisableDriverControlQCOM)(GLuint driverControl) {
CALL_GL_API(glDisableDriverControlQCOM, driverControl);
}
+void API_ENTRY(glExtGetTexturesQCOM)(GLuint *textures, GLint maxTextures, GLint *numTextures) {
+ CALL_GL_API(glExtGetTexturesQCOM, textures, maxTextures, numTextures);
+}
+void API_ENTRY(glExtGetBuffersQCOM)(GLuint *buffers, GLint maxBuffers, GLint *numBuffers) {
+ CALL_GL_API(glExtGetBuffersQCOM, buffers, maxBuffers, numBuffers);
+}
+void API_ENTRY(glExtGetRenderbuffersQCOM)(GLuint *renderbuffers, GLint maxRenderbuffers, GLint *numRenderbuffers) {
+ CALL_GL_API(glExtGetRenderbuffersQCOM, renderbuffers, maxRenderbuffers, numRenderbuffers);
+}
+void API_ENTRY(glExtGetFramebuffersQCOM)(GLuint *framebuffers, GLint maxFramebuffers, GLint *numFramebuffers) {
+ CALL_GL_API(glExtGetFramebuffersQCOM, framebuffers, maxFramebuffers, numFramebuffers);
+}
+void API_ENTRY(glExtGetTexLevelParameterivQCOM)(GLuint texture, GLenum face, GLint level, GLenum pname, GLint *params) {
+ CALL_GL_API(glExtGetTexLevelParameterivQCOM, texture, face, level, pname, params);
+}
+void API_ENTRY(glExtTexObjectStateOverrideiQCOM)(GLenum target, GLenum pname, GLint param) {
+ CALL_GL_API(glExtTexObjectStateOverrideiQCOM, target, pname, param);
+}
+void API_ENTRY(glExtGetTexSubImageQCOM)(GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint zoffset, GLsizei width, GLsizei height, GLsizei depth, GLenum format, GLenum type, GLvoid *texels) {
+ CALL_GL_API(glExtGetTexSubImageQCOM, target, level, xoffset, yoffset, zoffset, width, height, depth, format, type, texels);
+}
+void API_ENTRY(glExtGetBufferPointervQCOM)(GLenum target, GLvoid **params) {
+ CALL_GL_API(glExtGetBufferPointervQCOM, target, params);
+}
+void API_ENTRY(glExtGetShadersQCOM)(GLuint *shaders, GLint maxShaders, GLint *numShaders) {
+ CALL_GL_API(glExtGetShadersQCOM, shaders, maxShaders, numShaders);
+}
+void API_ENTRY(glExtGetProgramsQCOM)(GLuint *programs, GLint maxPrograms, GLint *numPrograms) {
+ CALL_GL_API(glExtGetProgramsQCOM, programs, maxPrograms, numPrograms);
+}
+GLboolean API_ENTRY(glExtIsProgramBinaryQCOM)(GLuint program) {
+ CALL_GL_API_RETURN(glExtIsProgramBinaryQCOM, program);
+}
+void API_ENTRY(glExtGetProgramBinarySourceQCOM)(GLuint program, GLenum shadertype, GLchar *source, GLint *length) {
+ CALL_GL_API(glExtGetProgramBinarySourceQCOM, program, shadertype, source, length);
+}
+void API_ENTRY(glStartTilingQCOM)(GLuint x, GLuint y, GLuint width, GLuint height, GLbitfield preserveMask) {
+ CALL_GL_API(glStartTilingQCOM, x, y, width, height, preserveMask);
+}
+void API_ENTRY(glEndTilingQCOM)(GLbitfield preserveMask) {
+ CALL_GL_API(glEndTilingQCOM, preserveMask);
+}
diff --git a/opengl/libs/GLES_CM/gl_api.in b/opengl/libs/GLES_CM/gl_api.in
index 5437d47..7f20c4f 100644
--- a/opengl/libs/GLES_CM/gl_api.in
+++ b/opengl/libs/GLES_CM/gl_api.in
@@ -259,7 +259,7 @@ void API_ENTRY(glGetLightxv)(GLenum light, GLenum pname, GLfixed *params) {
void API_ENTRY(glGetMaterialxv)(GLenum face, GLenum pname, GLfixed *params) {
CALL_GL_API(glGetMaterialxv, face, pname, params);
}
-void API_ENTRY(glGetPointerv)(GLenum pname, void **params) {
+void API_ENTRY(glGetPointerv)(GLenum pname, GLvoid **params) {
CALL_GL_API(glGetPointerv, pname, params);
}
const GLubyte * API_ENTRY(glGetString)(GLenum name) {
diff --git a/opengl/libs/GLES_CM/glext_api.in b/opengl/libs/GLES_CM/glext_api.in
index 2c8648e..5393fa6 100644
--- a/opengl/libs/GLES_CM/glext_api.in
+++ b/opengl/libs/GLES_CM/glext_api.in
@@ -205,7 +205,7 @@ void* API_ENTRY(glMapBufferOES)(GLenum target, GLenum access) {
GLboolean API_ENTRY(glUnmapBufferOES)(GLenum target) {
CALL_GL_API_RETURN(glUnmapBufferOES, target);
}
-void API_ENTRY(glGetBufferPointervOES)(GLenum target, GLenum pname, void** params) {
+void API_ENTRY(glGetBufferPointervOES)(GLenum target, GLenum pname, GLvoid ** params) {
CALL_GL_API(glGetBufferPointervOES, target, pname, params);
}
void API_ENTRY(glCurrentPaletteMatrixOES)(GLuint matrixpaletteindex) {
@@ -268,3 +268,111 @@ void API_ENTRY(glGetTexGenivOES)(GLenum coord, GLenum pname, GLint *params) {
void API_ENTRY(glGetTexGenxvOES)(GLenum coord, GLenum pname, GLfixed *params) {
CALL_GL_API(glGetTexGenxvOES, coord, pname, params);
}
+void API_ENTRY(glBindVertexArrayOES)(GLuint array) {
+ CALL_GL_API(glBindVertexArrayOES, array);
+}
+void API_ENTRY(glDeleteVertexArraysOES)(GLsizei n, const GLuint *arrays) {
+ CALL_GL_API(glDeleteVertexArraysOES, n, arrays);
+}
+void API_ENTRY(glGenVertexArraysOES)(GLsizei n, GLuint *arrays) {
+ CALL_GL_API(glGenVertexArraysOES, n, arrays);
+}
+GLboolean API_ENTRY(glIsVertexArrayOES)(GLuint array) {
+ CALL_GL_API_RETURN(glIsVertexArrayOES, array);
+}
+void API_ENTRY(glDiscardFramebufferEXT)(GLenum target, GLsizei numAttachments, const GLenum *attachments) {
+ CALL_GL_API(glDiscardFramebufferEXT, target, numAttachments, attachments);
+}
+void API_ENTRY(glMultiDrawArraysEXT)(GLenum mode, GLint *first, GLsizei *count, GLsizei primcount) {
+ CALL_GL_API(glMultiDrawArraysEXT, mode, first, count, primcount);
+}
+void API_ENTRY(glMultiDrawElementsEXT)(GLenum mode, const GLsizei *count, GLenum type, const GLvoid* *indices, GLsizei primcount) {
+ CALL_GL_API(glMultiDrawElementsEXT, mode, count, type, indices, primcount);
+}
+void API_ENTRY(glClipPlanefIMG)(GLenum p, const GLfloat *eqn) {
+ CALL_GL_API(glClipPlanefIMG, p, eqn);
+}
+void API_ENTRY(glClipPlanexIMG)(GLenum p, const GLfixed *eqn) {
+ CALL_GL_API(glClipPlanexIMG, p, eqn);
+}
+void API_ENTRY(glRenderbufferStorageMultisampleIMG)(GLenum target, GLsizei samples, GLenum internalformat, GLsizei width, GLsizei height) {
+ CALL_GL_API(glRenderbufferStorageMultisampleIMG, target, samples, internalformat, width, height);
+}
+void API_ENTRY(glFramebufferTexture2DMultisampleIMG)(GLenum target, GLenum attachment, GLenum textarget, GLuint texture, GLint level, GLsizei samples) {
+ CALL_GL_API(glFramebufferTexture2DMultisampleIMG, target, attachment, textarget, texture, level, samples);
+}
+void API_ENTRY(glDeleteFencesNV)(GLsizei n, const GLuint *fences) {
+ CALL_GL_API(glDeleteFencesNV, n, fences);
+}
+void API_ENTRY(glGenFencesNV)(GLsizei n, GLuint *fences) {
+ CALL_GL_API(glGenFencesNV, n, fences);
+}
+GLboolean API_ENTRY(glIsFenceNV)(GLuint fence) {
+ CALL_GL_API_RETURN(glIsFenceNV, fence);
+}
+GLboolean API_ENTRY(glTestFenceNV)(GLuint fence) {
+ CALL_GL_API_RETURN(glTestFenceNV, fence);
+}
+void API_ENTRY(glGetFenceivNV)(GLuint fence, GLenum pname, GLint *params) {
+ CALL_GL_API(glGetFenceivNV, fence, pname, params);
+}
+void API_ENTRY(glFinishFenceNV)(GLuint fence) {
+ CALL_GL_API(glFinishFenceNV, fence);
+}
+void API_ENTRY(glSetFenceNV)(GLuint fence, GLenum condition) {
+ CALL_GL_API(glSetFenceNV, fence, condition);
+}
+void API_ENTRY(glGetDriverControlsQCOM)(GLint *num, GLsizei size, GLuint *driverControls) {
+ CALL_GL_API(glGetDriverControlsQCOM, num, size, driverControls);
+}
+void API_ENTRY(glGetDriverControlStringQCOM)(GLuint driverControl, GLsizei bufSize, GLsizei *length, GLchar *driverControlString) {
+ CALL_GL_API(glGetDriverControlStringQCOM, driverControl, bufSize, length, driverControlString);
+}
+void API_ENTRY(glEnableDriverControlQCOM)(GLuint driverControl) {
+ CALL_GL_API(glEnableDriverControlQCOM, driverControl);
+}
+void API_ENTRY(glDisableDriverControlQCOM)(GLuint driverControl) {
+ CALL_GL_API(glDisableDriverControlQCOM, driverControl);
+}
+void API_ENTRY(glExtGetTexturesQCOM)(GLuint *textures, GLint maxTextures, GLint *numTextures) {
+ CALL_GL_API(glExtGetTexturesQCOM, textures, maxTextures, numTextures);
+}
+void API_ENTRY(glExtGetBuffersQCOM)(GLuint *buffers, GLint maxBuffers, GLint *numBuffers) {
+ CALL_GL_API(glExtGetBuffersQCOM, buffers, maxBuffers, numBuffers);
+}
+void API_ENTRY(glExtGetRenderbuffersQCOM)(GLuint *renderbuffers, GLint maxRenderbuffers, GLint *numRenderbuffers) {
+ CALL_GL_API(glExtGetRenderbuffersQCOM, renderbuffers, maxRenderbuffers, numRenderbuffers);
+}
+void API_ENTRY(glExtGetFramebuffersQCOM)(GLuint *framebuffers, GLint maxFramebuffers, GLint *numFramebuffers) {
+ CALL_GL_API(glExtGetFramebuffersQCOM, framebuffers, maxFramebuffers, numFramebuffers);
+}
+void API_ENTRY(glExtGetTexLevelParameterivQCOM)(GLuint texture, GLenum face, GLint level, GLenum pname, GLint *params) {
+ CALL_GL_API(glExtGetTexLevelParameterivQCOM, texture, face, level, pname, params);
+}
+void API_ENTRY(glExtTexObjectStateOverrideiQCOM)(GLenum target, GLenum pname, GLint param) {
+ CALL_GL_API(glExtTexObjectStateOverrideiQCOM, target, pname, param);
+}
+void API_ENTRY(glExtGetTexSubImageQCOM)(GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint zoffset, GLsizei width, GLsizei height, GLsizei depth, GLenum format, GLenum type, GLvoid *texels) {
+ CALL_GL_API(glExtGetTexSubImageQCOM, target, level, xoffset, yoffset, zoffset, width, height, depth, format, type, texels);
+}
+void API_ENTRY(glExtGetBufferPointervQCOM)(GLenum target, GLvoid **params) {
+ CALL_GL_API(glExtGetBufferPointervQCOM, target, params);
+}
+void API_ENTRY(glExtGetShadersQCOM)(GLuint *shaders, GLint maxShaders, GLint *numShaders) {
+ CALL_GL_API(glExtGetShadersQCOM, shaders, maxShaders, numShaders);
+}
+void API_ENTRY(glExtGetProgramsQCOM)(GLuint *programs, GLint maxPrograms, GLint *numPrograms) {
+ CALL_GL_API(glExtGetProgramsQCOM, programs, maxPrograms, numPrograms);
+}
+GLboolean API_ENTRY(glExtIsProgramBinaryQCOM)(GLuint program) {
+ CALL_GL_API_RETURN(glExtIsProgramBinaryQCOM, program);
+}
+void API_ENTRY(glExtGetProgramBinarySourceQCOM)(GLuint program, GLenum shadertype, GLchar *source, GLint *length) {
+ CALL_GL_API(glExtGetProgramBinarySourceQCOM, program, shadertype, source, length);
+}
+void API_ENTRY(glStartTilingQCOM)(GLuint x, GLuint y, GLuint width, GLuint height, GLbitfield preserveMask) {
+ CALL_GL_API(glStartTilingQCOM, x, y, width, height, preserveMask);
+}
+void API_ENTRY(glEndTilingQCOM)(GLbitfield preserveMask) {
+ CALL_GL_API(glEndTilingQCOM, preserveMask);
+}
diff --git a/opengl/libs/entries.in b/opengl/libs/entries.in
index bbe3e23..61acb5f 100644
--- a/opengl/libs/entries.in
+++ b/opengl/libs/entries.in
@@ -4,13 +4,14 @@ GL_ENTRY(void, glAlphaFuncx, GLenum func, GLclampx ref)
GL_ENTRY(void, glAlphaFuncxOES, GLenum func, GLclampx ref)
GL_ENTRY(void, glAttachShader, GLuint program, GLuint shader)
GL_ENTRY(void, glBeginPerfMonitorAMD, GLuint monitor)
-GL_ENTRY(void, glBindAttribLocation, GLuint program, GLuint index, const char* name)
+GL_ENTRY(void, glBindAttribLocation, GLuint program, GLuint index, const GLchar* name)
GL_ENTRY(void, glBindBuffer, GLenum target, GLuint buffer)
GL_ENTRY(void, glBindFramebuffer, GLenum target, GLuint framebuffer)
GL_ENTRY(void, glBindFramebufferOES, GLenum target, GLuint framebuffer)
GL_ENTRY(void, glBindRenderbuffer, GLenum target, GLuint renderbuffer)
GL_ENTRY(void, glBindRenderbufferOES, GLenum target, GLuint renderbuffer)
GL_ENTRY(void, glBindTexture, GLenum target, GLuint texture)
+GL_ENTRY(void, glBindVertexArrayOES, GLuint array)
GL_ENTRY(void, glBlendColor, GLclampf red, GLclampf green, GLclampf blue, GLclampf alpha)
GL_ENTRY(void, glBlendEquation, GLenum mode )
GL_ENTRY(void, glBlendEquationOES, GLenum mode)
@@ -34,8 +35,10 @@ GL_ENTRY(void, glClearDepthxOES, GLclampx depth)
GL_ENTRY(void, glClearStencil, GLint s)
GL_ENTRY(void, glClientActiveTexture, GLenum texture)
GL_ENTRY(void, glClipPlanef, GLenum plane, const GLfloat *equation)
+GL_ENTRY(void, glClipPlanefIMG, GLenum p, const GLfloat *eqn)
GL_ENTRY(void, glClipPlanefOES, GLenum plane, const GLfloat *equation)
GL_ENTRY(void, glClipPlanex, GLenum plane, const GLfixed *equation)
+GL_ENTRY(void, glClipPlanexIMG, GLenum p, const GLfixed *eqn)
GL_ENTRY(void, glClipPlanexOES, GLenum plane, const GLfixed *equation)
GL_ENTRY(void, glColor4f, GLfloat red, GLfloat green, GLfloat blue, GLfloat alpha)
GL_ENTRY(void, glColor4ub, GLubyte red, GLubyte green, GLubyte blue, GLubyte alpha)
@@ -45,12 +48,14 @@ GL_ENTRY(void, glColorMask, GLboolean red, GLboolean green, GLboolean blue, GLbo
GL_ENTRY(void, glColorPointer, GLint size, GLenum type, GLsizei stride, const GLvoid *pointer)
GL_ENTRY(void, glCompileShader, GLuint shader)
GL_ENTRY(void, glCompressedTexImage2D, GLenum target, GLint level, GLenum internalformat, GLsizei width, GLsizei height, GLint border, GLsizei imageSize, const GLvoid *data)
-GL_ENTRY(void, glCompressedTexImage3DOES, GLenum target, GLint level, GLenum internalformat, GLsizei width, GLsizei height, GLsizei depth, GLint border, GLsizei imageSize, const void* data)
+GL_ENTRY(void, glCompressedTexImage3DOES, GLenum target, GLint level, GLenum internalformat, GLsizei width, GLsizei height, GLsizei depth, GLint border, GLsizei imageSize, const GLvoid* data)
GL_ENTRY(void, glCompressedTexSubImage2D, GLenum target, GLint level, GLint xoffset, GLint yoffset, GLsizei width, GLsizei height, GLenum format, GLsizei imageSize, const GLvoid *data)
-GL_ENTRY(void, glCompressedTexSubImage3DOES, GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint zoffset, GLsizei width, GLsizei height, GLsizei depth, GLenum format, GLsizei imageSize, const void* data)
+GL_ENTRY(void, glCompressedTexSubImage3DOES, GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint zoffset, GLsizei width, GLsizei height, GLsizei depth, GLenum format, GLsizei imageSize, const GLvoid* data)
GL_ENTRY(void, glCopyTexImage2D, GLenum target, GLint level, GLenum internalformat, GLint x, GLint y, GLsizei width, GLsizei height, GLint border)
GL_ENTRY(void, glCopyTexSubImage2D, GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint x, GLint y, GLsizei width, GLsizei height)
GL_ENTRY(void, glCopyTexSubImage3DOES, GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint zoffset, GLint x, GLint y, GLsizei width, GLsizei height)
+GL_ENTRY(void, glCoverageMaskNV, GLboolean mask)
+GL_ENTRY(void, glCoverageOperationNV, GLenum operation)
GL_ENTRY(GLuint, glCreateProgram, void)
GL_ENTRY(GLuint, glCreateShader, GLenum type)
GL_ENTRY(void, glCullFace, GLenum mode)
@@ -65,6 +70,7 @@ GL_ENTRY(void, glDeleteRenderbuffers, GLsizei n, const GLuint* renderbuffers)
GL_ENTRY(void, glDeleteRenderbuffersOES, GLsizei n, const GLuint* renderbuffers)
GL_ENTRY(void, glDeleteShader, GLuint shader)
GL_ENTRY(void, glDeleteTextures, GLsizei n, const GLuint *textures)
+GL_ENTRY(void, glDeleteVertexArraysOES, GLsizei n, const GLuint *arrays)
GL_ENTRY(void, glDepthFunc, GLenum func)
GL_ENTRY(void, glDepthMask, GLboolean flag)
GL_ENTRY(void, glDepthRangef, GLclampf zNear, GLclampf zFar)
@@ -76,6 +82,7 @@ GL_ENTRY(void, glDisable, GLenum cap)
GL_ENTRY(void, glDisableClientState, GLenum array)
GL_ENTRY(void, glDisableDriverControlQCOM, GLuint driverControl)
GL_ENTRY(void, glDisableVertexAttribArray, GLuint index)
+GL_ENTRY(void, glDiscardFramebufferEXT, GLenum target, GLsizei numAttachments, const GLenum *attachments)
GL_ENTRY(void, glDrawArrays, GLenum mode, GLint first, GLsizei count)
GL_ENTRY(void, glDrawElements, GLenum mode, GLsizei count, GLenum type, const GLvoid *indices)
GL_ENTRY(void, glDrawTexfOES, GLfloat x, GLfloat y, GLfloat z, GLfloat width, GLfloat height)
@@ -93,6 +100,19 @@ GL_ENTRY(void, glEnableClientState, GLenum array)
GL_ENTRY(void, glEnableDriverControlQCOM, GLuint driverControl)
GL_ENTRY(void, glEnableVertexAttribArray, GLuint index)
GL_ENTRY(void, glEndPerfMonitorAMD, GLuint monitor)
+GL_ENTRY(void, glEndTilingQCOM, GLbitfield preserveMask)
+GL_ENTRY(void, glExtGetBufferPointervQCOM, GLenum target, GLvoid **params)
+GL_ENTRY(void, glExtGetBuffersQCOM, GLuint *buffers, GLint maxBuffers, GLint *numBuffers)
+GL_ENTRY(void, glExtGetFramebuffersQCOM, GLuint *framebuffers, GLint maxFramebuffers, GLint *numFramebuffers)
+GL_ENTRY(void, glExtGetProgramBinarySourceQCOM, GLuint program, GLenum shadertype, GLchar *source, GLint *length)
+GL_ENTRY(void, glExtGetProgramsQCOM, GLuint *programs, GLint maxPrograms, GLint *numPrograms)
+GL_ENTRY(void, glExtGetRenderbuffersQCOM, GLuint *renderbuffers, GLint maxRenderbuffers, GLint *numRenderbuffers)
+GL_ENTRY(void, glExtGetShadersQCOM, GLuint *shaders, GLint maxShaders, GLint *numShaders)
+GL_ENTRY(void, glExtGetTexLevelParameterivQCOM, GLuint texture, GLenum face, GLint level, GLenum pname, GLint *params)
+GL_ENTRY(void, glExtGetTexSubImageQCOM, GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint zoffset, GLsizei width, GLsizei height, GLsizei depth, GLenum format, GLenum type, GLvoid *texels)
+GL_ENTRY(void, glExtGetTexturesQCOM, GLuint *textures, GLint maxTextures, GLint *numTextures)
+GL_ENTRY(GLboolean, glExtIsProgramBinaryQCOM, GLuint program)
+GL_ENTRY(void, glExtTexObjectStateOverrideiQCOM, GLenum target, GLenum pname, GLint param)
GL_ENTRY(void, glFinish, void)
GL_ENTRY(void, glFinishFenceNV, GLuint fence)
GL_ENTRY(void, glFlush, void)
@@ -105,6 +125,7 @@ GL_ENTRY(void, glFogxvOES, GLenum pname, const GLfixed *params)
GL_ENTRY(void, glFramebufferRenderbuffer, GLenum target, GLenum attachment, GLenum renderbuffertarget, GLuint renderbuffer)
GL_ENTRY(void, glFramebufferRenderbufferOES, GLenum target, GLenum attachment, GLenum renderbuffertarget, GLuint renderbuffer)
GL_ENTRY(void, glFramebufferTexture2D, GLenum target, GLenum attachment, GLenum textarget, GLuint texture, GLint level)
+GL_ENTRY(void, glFramebufferTexture2DMultisampleIMG, GLenum target, GLenum attachment, GLenum textarget, GLuint texture, GLint level, GLsizei samples)
GL_ENTRY(void, glFramebufferTexture2DOES, GLenum target, GLenum attachment, GLenum textarget, GLuint texture, GLint level)
GL_ENTRY(void, glFramebufferTexture3DOES, GLenum target, GLenum attachment, GLenum textarget, GLuint texture, GLint level, GLint zoffset)
GL_ENTRY(void, glFrontFace, GLenum mode)
@@ -120,20 +141,21 @@ GL_ENTRY(void, glGenPerfMonitorsAMD, GLsizei n, GLuint *monitors)
GL_ENTRY(void, glGenRenderbuffers, GLsizei n, GLuint* renderbuffers)
GL_ENTRY(void, glGenRenderbuffersOES, GLsizei n, GLuint* renderbuffers)
GL_ENTRY(void, glGenTextures, GLsizei n, GLuint *textures)
+GL_ENTRY(void, glGenVertexArraysOES, GLsizei n, GLuint *arrays)
GL_ENTRY(void, glGenerateMipmap, GLenum target)
GL_ENTRY(void, glGenerateMipmapOES, GLenum target)
-GL_ENTRY(void, glGetActiveAttrib, GLuint program, GLuint index, GLsizei bufsize, GLsizei* length, GLint* size, GLenum* type, char* name)
-GL_ENTRY(void, glGetActiveUniform, GLuint program, GLuint index, GLsizei bufsize, GLsizei* length, GLint* size, GLenum* type, char* name)
+GL_ENTRY(void, glGetActiveAttrib, GLuint program, GLuint index, GLsizei bufsize, GLsizei* length, GLint* size, GLenum* type, GLchar* name)
+GL_ENTRY(void, glGetActiveUniform, GLuint program, GLuint index, GLsizei bufsize, GLsizei* length, GLint* size, GLenum* type, GLchar* name)
GL_ENTRY(void, glGetAttachedShaders, GLuint program, GLsizei maxcount, GLsizei* count, GLuint* shaders)
-GL_ENTRY(int, glGetAttribLocation, GLuint program, const char* name)
+GL_ENTRY(int, glGetAttribLocation, GLuint program, const GLchar* name)
GL_ENTRY(void, glGetBooleanv, GLenum pname, GLboolean *params)
GL_ENTRY(void, glGetBufferParameteriv, GLenum target, GLenum pname, GLint *params)
-GL_ENTRY(void, glGetBufferPointervOES, GLenum target, GLenum pname, void** params)
+GL_ENTRY(void, glGetBufferPointervOES, GLenum target, GLenum pname, GLvoid ** params)
GL_ENTRY(void, glGetClipPlanef, GLenum pname, GLfloat eqn[4])
GL_ENTRY(void, glGetClipPlanefOES, GLenum pname, GLfloat eqn[4])
GL_ENTRY(void, glGetClipPlanex, GLenum pname, GLfixed eqn[4])
GL_ENTRY(void, glGetClipPlanexOES, GLenum pname, GLfixed eqn[4])
-GL_ENTRY(void, glGetDriverControlStringQCOM, GLuint driverControl, GLsizei bufSize, GLsizei *length, char *driverControlString)
+GL_ENTRY(void, glGetDriverControlStringQCOM, GLuint driverControl, GLsizei bufSize, GLsizei *length, GLchar *driverControlString)
GL_ENTRY(void, glGetDriverControlsQCOM, GLint *num, GLsizei size, GLuint *driverControls)
GL_ENTRY(GLenum, glGetError, void)
GL_ENTRY(void, glGetFenceivNV, GLuint fence, GLenum pname, GLint *params)
@@ -150,20 +172,20 @@ GL_ENTRY(void, glGetMaterialfv, GLenum face, GLenum pname, GLfloat *params)
GL_ENTRY(void, glGetMaterialxv, GLenum face, GLenum pname, GLfixed *params)
GL_ENTRY(void, glGetMaterialxvOES, GLenum face, GLenum pname, GLfixed *params)
GL_ENTRY(void, glGetPerfMonitorCounterDataAMD, GLuint monitor, GLenum pname, GLsizei dataSize, GLuint *data, GLint *bytesWritten)
-GL_ENTRY(void, glGetPerfMonitorCounterInfoAMD, GLuint group, GLuint counter, GLenum pname, void *data)
-GL_ENTRY(void, glGetPerfMonitorCounterStringAMD, GLuint group, GLuint counter, GLsizei bufSize, GLsizei *length, char *counterString)
+GL_ENTRY(void, glGetPerfMonitorCounterInfoAMD, GLuint group, GLuint counter, GLenum pname, GLvoid *data)
+GL_ENTRY(void, glGetPerfMonitorCounterStringAMD, GLuint group, GLuint counter, GLsizei bufSize, GLsizei *length, GLchar *counterString)
GL_ENTRY(void, glGetPerfMonitorCountersAMD, GLuint group, GLint *numCounters, GLint *maxActiveCounters, GLsizei counterSize, GLuint *counters)
-GL_ENTRY(void, glGetPerfMonitorGroupStringAMD, GLuint group, GLsizei bufSize, GLsizei *length, char *groupString)
+GL_ENTRY(void, glGetPerfMonitorGroupStringAMD, GLuint group, GLsizei bufSize, GLsizei *length, GLchar *groupString)
GL_ENTRY(void, glGetPerfMonitorGroupsAMD, GLint *numGroups, GLsizei groupsSize, GLuint *groups)
-GL_ENTRY(void, glGetPointerv, GLenum pname, void **params)
-GL_ENTRY(void, glGetProgramBinaryOES, GLuint program, GLsizei bufSize, GLsizei *length, GLenum *binaryFormat, void *binary)
-GL_ENTRY(void, glGetProgramInfoLog, GLuint program, GLsizei bufsize, GLsizei* length, char* infolog)
+GL_ENTRY(void, glGetPointerv, GLenum pname, GLvoid **params)
+GL_ENTRY(void, glGetProgramBinaryOES, GLuint program, GLsizei bufSize, GLsizei *length, GLenum *binaryFormat, GLvoid *binary)
+GL_ENTRY(void, glGetProgramInfoLog, GLuint program, GLsizei bufsize, GLsizei* length, GLchar* infolog)
GL_ENTRY(void, glGetProgramiv, GLuint program, GLenum pname, GLint* params)
GL_ENTRY(void, glGetRenderbufferParameteriv, GLenum target, GLenum pname, GLint* params)
GL_ENTRY(void, glGetRenderbufferParameterivOES, GLenum target, GLenum pname, GLint* params)
-GL_ENTRY(void, glGetShaderInfoLog, GLuint shader, GLsizei bufsize, GLsizei* length, char* infolog)
+GL_ENTRY(void, glGetShaderInfoLog, GLuint shader, GLsizei bufsize, GLsizei* length, GLchar* infolog)
GL_ENTRY(void, glGetShaderPrecisionFormat, GLenum shadertype, GLenum precisiontype, GLint* range, GLint* precision)
-GL_ENTRY(void, glGetShaderSource, GLuint shader, GLsizei bufsize, GLsizei* length, char* source)
+GL_ENTRY(void, glGetShaderSource, GLuint shader, GLsizei bufsize, GLsizei* length, GLchar* source)
GL_ENTRY(void, glGetShaderiv, GLuint shader, GLenum pname, GLint* params)
GL_ENTRY(const GLubyte *, glGetString, GLenum name)
GL_ENTRY(void, glGetTexEnvfv, GLenum env, GLenum pname, GLfloat *params)
@@ -177,10 +199,10 @@ GL_ENTRY(void, glGetTexParameterfv, GLenum target, GLenum pname, GLfloat *params
GL_ENTRY(void, glGetTexParameteriv, GLenum target, GLenum pname, GLint *params)
GL_ENTRY(void, glGetTexParameterxv, GLenum target, GLenum pname, GLfixed *params)
GL_ENTRY(void, glGetTexParameterxvOES, GLenum target, GLenum pname, GLfixed *params)
-GL_ENTRY(int, glGetUniformLocation, GLuint program, const char* name)
+GL_ENTRY(int, glGetUniformLocation, GLuint program, const GLchar* name)
GL_ENTRY(void, glGetUniformfv, GLuint program, GLint location, GLfloat* params)
GL_ENTRY(void, glGetUniformiv, GLuint program, GLint location, GLint* params)
-GL_ENTRY(void, glGetVertexAttribPointerv, GLuint index, GLenum pname, void** pointer)
+GL_ENTRY(void, glGetVertexAttribPointerv, GLuint index, GLenum pname, GLvoid** pointer)
GL_ENTRY(void, glGetVertexAttribfv, GLuint index, GLenum pname, GLfloat* params)
GL_ENTRY(void, glGetVertexAttribiv, GLuint index, GLenum pname, GLint* params)
GL_ENTRY(void, glHint, GLenum target, GLenum mode)
@@ -194,6 +216,7 @@ GL_ENTRY(GLboolean, glIsRenderbuffer, GLuint renderbuffer)
GL_ENTRY(GLboolean, glIsRenderbufferOES, GLuint renderbuffer)
GL_ENTRY(GLboolean, glIsShader, GLuint shader)
GL_ENTRY(GLboolean, glIsTexture, GLuint texture)
+GL_ENTRY(GLboolean, glIsVertexArrayOES, GLuint array)
GL_ENTRY(void, glLightModelf, GLenum pname, GLfloat param)
GL_ENTRY(void, glLightModelfv, GLenum pname, const GLfloat *params)
GL_ENTRY(void, glLightModelx, GLenum pname, GLfixed param)
@@ -228,6 +251,8 @@ GL_ENTRY(void, glMatrixMode, GLenum mode)
GL_ENTRY(void, glMultMatrixf, const GLfloat *m)
GL_ENTRY(void, glMultMatrixx, const GLfixed *m)
GL_ENTRY(void, glMultMatrixxOES, const GLfixed *m)
+GL_ENTRY(void, glMultiDrawArraysEXT, GLenum mode, GLint *first, GLsizei *count, GLsizei primcount)
+GL_ENTRY(void, glMultiDrawElementsEXT, GLenum mode, const GLsizei *count, GLenum type, const GLvoid* *indices, GLsizei primcount)
GL_ENTRY(void, glMultiTexCoord4f, GLenum target, GLfloat s, GLfloat t, GLfloat r, GLfloat q)
GL_ENTRY(void, glMultiTexCoord4x, GLenum target, GLfixed s, GLfixed t, GLfixed r, GLfixed q)
GL_ENTRY(void, glMultiTexCoord4xOES, GLenum target, GLfixed s, GLfixed t, GLfixed r, GLfixed q)
@@ -254,12 +279,13 @@ GL_ENTRY(void, glPolygonOffset, GLfloat factor, GLfloat units)
GL_ENTRY(void, glPolygonOffsetx, GLfixed factor, GLfixed units)
GL_ENTRY(void, glPolygonOffsetxOES, GLfixed factor, GLfixed units)
GL_ENTRY(void, glPopMatrix, void)
-GL_ENTRY(void, glProgramBinaryOES, GLuint program, GLenum binaryFormat, const void *binary, GLint length)
+GL_ENTRY(void, glProgramBinaryOES, GLuint program, GLenum binaryFormat, const GLvoid *binary, GLint length)
GL_ENTRY(void, glPushMatrix, void)
GL_ENTRY(GLbitfield, glQueryMatrixxOES, GLfixed mantissa[16], GLint exponent[16])
GL_ENTRY(void, glReadPixels, GLint x, GLint y, GLsizei width, GLsizei height, GLenum format, GLenum type, GLvoid *pixels)
GL_ENTRY(void, glReleaseShaderCompiler, void)
GL_ENTRY(void, glRenderbufferStorage, GLenum target, GLenum internalformat, GLsizei width, GLsizei height)
+GL_ENTRY(void, glRenderbufferStorageMultisampleIMG, GLenum target, GLsizei samples, GLenum internalformat, GLsizei width, GLsizei height)
GL_ENTRY(void, glRenderbufferStorageOES, GLenum target, GLenum internalformat, GLsizei width, GLsizei height)
GL_ENTRY(void, glRotatef, GLfloat angle, GLfloat x, GLfloat y, GLfloat z)
GL_ENTRY(void, glRotatex, GLfixed angle, GLfixed x, GLfixed y, GLfixed z)
@@ -274,8 +300,9 @@ GL_ENTRY(void, glScissor, GLint x, GLint y, GLsizei width, GLsizei height)
GL_ENTRY(void, glSelectPerfMonitorCountersAMD, GLuint monitor, GLboolean enable, GLuint group, GLint numCounters, GLuint *countersList)
GL_ENTRY(void, glSetFenceNV, GLuint fence, GLenum condition)
GL_ENTRY(void, glShadeModel, GLenum mode)
-GL_ENTRY(void, glShaderBinary, GLsizei n, const GLuint* shaders, GLenum binaryformat, const void* binary, GLsizei length)
-GL_ENTRY(void, glShaderSource, GLuint shader, GLsizei count, const char** string, const GLint* length)
+GL_ENTRY(void, glShaderBinary, GLsizei n, const GLuint* shaders, GLenum binaryformat, const GLvoid* binary, GLsizei length)
+GL_ENTRY(void, glShaderSource, GLuint shader, GLsizei count, const GLchar** string, const GLint* length)
+GL_ENTRY(void, glStartTilingQCOM, GLuint x, GLuint y, GLuint width, GLuint height, GLbitfield preserveMask)
GL_ENTRY(void, glStencilFunc, GLenum func, GLint ref, GLuint mask)
GL_ENTRY(void, glStencilFuncSeparate, GLenum face, GLenum func, GLint ref, GLuint mask)
GL_ENTRY(void, glStencilMask, GLuint mask)
@@ -298,8 +325,8 @@ GL_ENTRY(void, glTexGeniOES, GLenum coord, GLenum pname, GLint param)
GL_ENTRY(void, glTexGenivOES, GLenum coord, GLenum pname, const GLint *params)
GL_ENTRY(void, glTexGenxOES, GLenum coord, GLenum pname, GLfixed param)
GL_ENTRY(void, glTexGenxvOES, GLenum coord, GLenum pname, const GLfixed *params)
-GL_ENTRY(void, glTexImage2D, GLenum target, GLint level, GLint internalformat, GLsizei width, GLsizei height, GLint border, GLenum format, GLenum type, const GLvoid* pixels)
-GL_ENTRY(void, glTexImage3DOES, GLenum target, GLint level, GLenum internalformat, GLsizei width, GLsizei height, GLsizei depth, GLint border, GLenum format, GLenum type, const void* pixels)
+GL_ENTRY(void, glTexImage2D, GLenum target, GLint level, GLint internalformat, GLsizei width, GLsizei height, GLint border, GLenum format, GLenum type, const GLvoid *pixels)
+GL_ENTRY(void, glTexImage3DOES, GLenum target, GLint level, GLenum internalformat, GLsizei width, GLsizei height, GLsizei depth, GLint border, GLenum format, GLenum type, const GLvoid* pixels)
GL_ENTRY(void, glTexParameterf, GLenum target, GLenum pname, GLfloat param)
GL_ENTRY(void, glTexParameterfv, GLenum target, GLenum pname, const GLfloat *params)
GL_ENTRY(void, glTexParameteri, GLenum target, GLenum pname, GLint param)
@@ -309,7 +336,7 @@ GL_ENTRY(void, glTexParameterxOES, GLenum target, GLenum pname, GLfixed param)
GL_ENTRY(void, glTexParameterxv, GLenum target, GLenum pname, const GLfixed *params)
GL_ENTRY(void, glTexParameterxvOES, GLenum target, GLenum pname, const GLfixed *params)
GL_ENTRY(void, glTexSubImage2D, GLenum target, GLint level, GLint xoffset, GLint yoffset, GLsizei width, GLsizei height, GLenum format, GLenum type, const GLvoid *pixels)
-GL_ENTRY(void, glTexSubImage3DOES, GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint zoffset, GLsizei width, GLsizei height, GLsizei depth, GLenum format, GLenum type, const void* pixels)
+GL_ENTRY(void, glTexSubImage3DOES, GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint zoffset, GLsizei width, GLsizei height, GLsizei depth, GLenum format, GLenum type, const GLvoid* pixels)
GL_ENTRY(void, glTranslatef, GLfloat x, GLfloat y, GLfloat z)
GL_ENTRY(void, glTranslatex, GLfixed x, GLfixed y, GLfixed z)
GL_ENTRY(void, glTranslatexOES, GLfixed x, GLfixed y, GLfixed z)
@@ -343,7 +370,7 @@ GL_ENTRY(void, glVertexAttrib3f, GLuint indx, GLfloat x, GLfloat y, GLfloat z)
GL_ENTRY(void, glVertexAttrib3fv, GLuint indx, const GLfloat* values)
GL_ENTRY(void, glVertexAttrib4f, GLuint indx, GLfloat x, GLfloat y, GLfloat z, GLfloat w)
GL_ENTRY(void, glVertexAttrib4fv, GLuint indx, const GLfloat* values)
-GL_ENTRY(void, glVertexAttribPointer, GLuint indx, GLint size, GLenum type, GLboolean normalized, GLsizei stride, const void* ptr)
+GL_ENTRY(void, glVertexAttribPointer, GLuint indx, GLint size, GLenum type, GLboolean normalized, GLsizei stride, const GLvoid* ptr)
GL_ENTRY(void, glVertexPointer, GLint size, GLenum type, GLsizei stride, const GLvoid *pointer)
GL_ENTRY(void, glViewport, GLint x, GLint y, GLsizei width, GLsizei height)
GL_ENTRY(void, glWeightPointerOES, GLint size, GLenum type, GLsizei stride, const GLvoid *pointer)
diff --git a/opengl/tests/gl2_basic/gl2_basic.cpp b/opengl/tests/gl2_basic/gl2_basic.cpp
index 2361db5..f274c7c 100644
--- a/opengl/tests/gl2_basic/gl2_basic.cpp
+++ b/opengl/tests/gl2_basic/gl2_basic.cpp
@@ -195,7 +195,6 @@ void printEGLConfiguration(EGLDisplay dpy, EGLConfig config) {
X(EGL_NATIVE_RENDERABLE),
X(EGL_NATIVE_VISUAL_ID),
X(EGL_NATIVE_VISUAL_TYPE),
- X(EGL_PRESERVED_RESOURCES),
X(EGL_SAMPLES),
X(EGL_SAMPLE_BUFFERS),
X(EGL_SURFACE_TYPE),
diff --git a/opengl/tests/gl_basic/gl_basic.cpp b/opengl/tests/gl_basic/gl_basic.cpp
index feb964a..0cc8398 100644
--- a/opengl/tests/gl_basic/gl_basic.cpp
+++ b/opengl/tests/gl_basic/gl_basic.cpp
@@ -114,7 +114,6 @@ void printEGLConfiguration(EGLDisplay dpy, EGLConfig config) {
X(EGL_NATIVE_RENDERABLE),
X(EGL_NATIVE_VISUAL_ID),
X(EGL_NATIVE_VISUAL_TYPE),
- X(EGL_PRESERVED_RESOURCES),
X(EGL_SAMPLES),
X(EGL_SAMPLE_BUFFERS),
X(EGL_SURFACE_TYPE),