recovery: Move SwipeDetector into common location am: 9020e0f
am: 1500f11

* commit '1500f11e81584c105eb1f36439719629e2c39073':
  recovery: Move SwipeDetector into common location
diff --git a/Android.mk b/Android.mk
index fc981e1..c2f98c6 100644
--- a/Android.mk
+++ b/Android.mk
@@ -43,6 +43,7 @@
     ui.cpp \
     verifier.cpp \
     wear_ui.cpp \
+    wear_touch.cpp \
 
 LOCAL_MODULE := recovery
 
diff --git a/wear_touch.cpp b/wear_touch.cpp
new file mode 100644
index 0000000..f22d40b
--- /dev/null
+++ b/wear_touch.cpp
@@ -0,0 +1,177 @@
+/*
+ * Copyright (C) 2016 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include "common.h"
+#include "wear_touch.h"
+
+#include <dirent.h>
+#include <fcntl.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <unistd.h>
+#include <errno.h>
+#include <string.h>
+
+#include <linux/input.h>
+
+#define DEVICE_PATH "/dev/input"
+
+WearSwipeDetector::WearSwipeDetector(int low, int high, OnSwipeCallback callback, void* cookie):
+    mLowThreshold(low),
+    mHighThreshold(high),
+    mCallback(callback),
+    mCookie(cookie),
+    mCurrentSlot(-1) {
+    pthread_create(&mThread, NULL, touch_thread, this);
+}
+
+WearSwipeDetector::~WearSwipeDetector() {
+}
+
+void WearSwipeDetector::detect(int dx, int dy) {
+    enum SwipeDirection direction;
+
+    if (abs(dy) < mLowThreshold && abs(dx) > mHighThreshold) {
+        direction = dx < 0 ? LEFT : RIGHT;
+    } else if (abs(dx) < mLowThreshold && abs(dy) > mHighThreshold) {
+        direction = dy < 0 ? UP : DOWN;
+    } else {
+        LOGD("Ignore %d %d\n", dx, dy);
+        return;
+    }
+
+    LOGD("Swipe direction=%d\n", direction);
+    mCallback(mCookie, direction);
+}
+
+void WearSwipeDetector::process(struct input_event *event) {
+    if (mCurrentSlot < 0) {
+        mCallback(mCookie, UP);
+        mCurrentSlot = 0;
+    }
+
+    if (event->type == EV_ABS) {
+        if (event->code == ABS_MT_SLOT)
+            mCurrentSlot = event->value;
+
+        // Ignore other fingers
+        if (mCurrentSlot > 0) {
+            return;
+        }
+
+        switch (event->code) {
+        case ABS_MT_POSITION_X:
+            mX = event->value;
+            mFingerDown = true;
+            break;
+
+        case ABS_MT_POSITION_Y:
+            mY = event->value;
+            mFingerDown = true;
+            break;
+
+        case ABS_MT_TRACKING_ID:
+            if (event->value < 0)
+                mFingerDown = false;
+            break;
+        }
+    } else if (event->type == EV_SYN) {
+        if (event->code == SYN_REPORT) {
+            if (mFingerDown && !mSwiping) {
+                mStartX = mX;
+                mStartY = mY;
+                mSwiping = true;
+            } else if (!mFingerDown && mSwiping) {
+                mSwiping = false;
+                detect(mX - mStartX, mY - mStartY);
+            }
+        }
+    }
+}
+
+void WearSwipeDetector::run() {
+    int fd = findDevice(DEVICE_PATH);
+    if (fd < 0) {
+        LOGE("no input devices found\n");
+        return;
+    }
+
+    struct input_event event;
+    while (read(fd, &event, sizeof(event)) == sizeof(event)) {
+        process(&event);
+    }
+
+    close(fd);
+}
+
+void* WearSwipeDetector::touch_thread(void* cookie) {
+    ((WearSwipeDetector*)cookie)->run();
+    return NULL;
+}
+
+#define test_bit(bit, array)    (array[bit/8] & (1<<(bit%8)))
+
+int WearSwipeDetector::openDevice(const char *device) {
+    int fd = open(device, O_RDONLY);
+    if (fd < 0) {
+        LOGE("could not open %s, %s\n", device, strerror(errno));
+        return false;
+    }
+
+    char name[80];
+    name[sizeof(name) - 1] = '\0';
+    if (ioctl(fd, EVIOCGNAME(sizeof(name) - 1), &name) < 1) {
+        LOGE("could not get device name for %s, %s\n", device, strerror(errno));
+        name[0] = '\0';
+    }
+
+    uint8_t bits[512];
+    memset(bits, 0, sizeof(bits));
+    int ret = ioctl(fd, EVIOCGBIT(EV_ABS, sizeof(bits)), bits);
+    if (ret > 0) {
+        if (test_bit(ABS_MT_POSITION_X, bits) && test_bit(ABS_MT_POSITION_Y, bits)) {
+            LOGD("Found %s %s\n", device, name);
+            return fd;
+        }
+    }
+
+    close(fd);
+    return -1;
+}
+
+int WearSwipeDetector::findDevice(const char* path) {
+    DIR* dir = opendir(path);
+    if (dir == NULL) {
+        LOGE("Could not open directory %s", path);
+        return false;
+    }
+
+    struct dirent* entry;
+    int ret = -1;
+    while (ret < 0 && (entry = readdir(dir)) != NULL) {
+        if (entry->d_name[0] == '.') continue;
+
+        char device[PATH_MAX];
+        device[PATH_MAX-1] = '\0';
+        snprintf(device, PATH_MAX-1, "%s/%s", path, entry->d_name);
+
+        ret = openDevice(device);
+    }
+
+    closedir(dir);
+    return ret;
+}
+
diff --git a/wear_touch.h b/wear_touch.h
new file mode 100644
index 0000000..9a1d315
--- /dev/null
+++ b/wear_touch.h
@@ -0,0 +1,58 @@
+/*
+ * Copyright (C) 2016 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 __WEAR_TOUCH_H
+#define __WEAR_TOUCH_H
+
+#include <pthread.h>
+
+class WearSwipeDetector {
+
+public:
+    enum SwipeDirection { UP, DOWN, RIGHT, LEFT };
+    typedef void (*OnSwipeCallback)(void* cookie, enum SwipeDirection direction);
+
+    WearSwipeDetector(int low, int high, OnSwipeCallback cb, void* cookie);
+    ~WearSwipeDetector();
+
+private:
+    void run();
+    void process(struct input_event *event);
+    void detect(int dx, int dy);
+
+    pthread_t mThread;
+    static void* touch_thread(void* cookie);
+
+    int findDevice(const char* path);
+    int openDevice(const char* device);
+
+    int mLowThreshold;
+    int mHighThreshold;
+
+    OnSwipeCallback mCallback;
+    void *mCookie;
+
+    int mX;
+    int mY;
+    int mStartX;
+    int mStartY;
+
+    int mCurrentSlot;
+    bool mFingerDown;
+    bool mSwiping;
+};
+
+#endif // __WEAR_TOUCH_H