Merge "emugl: minor update of DESIGN document." into studio-1.3-dev
diff --git a/Makefile.common b/Makefile.common
index 28c87db..5a43aa5 100644
--- a/Makefile.common
+++ b/Makefile.common
@@ -519,6 +519,7 @@
     android/hw-lcd.c \
     android/hw-events.c \
     android/hw-control.c \
+    android/hw-fingerprint.c \
     android/hw-sensors.c \
     android/hw-qemud.c \
     android/looper-qemu.cpp \
diff --git a/android/console.c b/android/console.c
index 90ddbb0..f802064 100644
--- a/android/console.c
+++ b/android/console.c
@@ -51,6 +51,7 @@
 #include <fcntl.h>
 #include "android/hw-events.h"
 #include "android/user-events.h"
+#include "android/hw-fingerprint.h"
 #include "android/hw-sensors.h"
 #include "android/skin/charmap.h"
 #include "android/skin/keycode-buffer.h"
@@ -2597,6 +2598,49 @@
 /********************************************************************************************/
 /********************************************************************************************/
 /*****                                                                                 ******/
+/*****                        F I N G E R P R I N T  C O M M A N D S                   ******/
+/*****                                                                                 ******/
+/********************************************************************************************/
+/********************************************************************************************/
+
+static int
+do_fingerprint_touch(ControlClient client, char* args )
+{
+    if (args) {
+        char *endptr;
+        int fingerid = strtol(args, &endptr, 0);
+        if (endptr != args) {
+            android_hw_fingerprint_touch(fingerid);
+            return 0;
+        }
+        control_write(client, "KO: invalid fingerid\r\n");
+        return -1;
+    }
+    control_write(client, "KO: missing fingerid\r\n");
+    return -1;
+}
+
+static int
+do_fingerprint_remove(ControlClient client, char* args )
+{
+    android_hw_fingerprint_remove();
+    return 0;
+}
+
+static const CommandDefRec fingerprint_commands[] =
+{
+    { "touch", "touch finger print sensor with <fingerid>",
+      "'touch <fingerid>' touch finger print sensor with <fingerid>.\r\n",
+      NULL, do_fingerprint_touch, NULL },
+    { "remove", "remove finger from the fingerprint sensor",
+      "'remove' remove finger from the fingerprint sensor.\r\n",
+      NULL, do_fingerprint_remove, NULL },
+    { NULL, NULL, NULL, NULL, NULL, NULL }
+};
+
+/********************************************************************************************/
+/********************************************************************************************/
+/*****                                                                                 ******/
 /*****                           M A I N   C O M M A N D S                             ******/
 /*****                                                                                 ******/
 /********************************************************************************************/
@@ -2957,6 +3001,10 @@
       "allows you to request the emulator sensors\r\n", NULL,
       NULL, sensor_commands },
 
+    { "finger", "manage emulator finger print",
+      "allows you to touch the emulator finger print sensor\r\n", NULL,
+      NULL, fingerprint_commands},
+
     { NULL, NULL, NULL, NULL, NULL, NULL }
 };
 
diff --git a/android/hw-fingerprint.c b/android/hw-fingerprint.c
new file mode 100644
index 0000000..7456602
--- /dev/null
+++ b/android/hw-fingerprint.c
@@ -0,0 +1,222 @@
+/* Copyright (C) 2015 The Android Open Source Project
+**
+** This software is licensed under the terms of the GNU General Public
+** License version 2, as published by the Free Software Foundation, and
+** may be copied, distributed, and modified under those terms.
+**
+** This program is distributed in the hope that it will be useful,
+** but WITHOUT ANY WARRANTY; without even the implied warranty of
+** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+** GNU General Public License for more details.
+*/
+
+#include "android/hw-fingerprint.h"
+#include "android/utils/debug.h"
+#include "android/utils/misc.h"
+#include "android/utils/system.h"
+#include "android/hw-qemud.h"
+#include "android/globals.h"
+#include "hw/hw.h"
+
+#include <math.h>
+
+#define  E(...)    derror(__VA_ARGS__)
+#define  W(...)    dwarning(__VA_ARGS__)
+#define  D(...)  VERBOSE_PRINT(init,__VA_ARGS__)
+#define  V(...)  VERBOSE_PRINT(init,__VA_ARGS__)
+
+/***********************************************************************************
+
+            All the declarations
+
+***********************************************************************************/
+
+typedef struct HwFingerprintClient   HwFingerprintClient;
+
+typedef struct {
+    QemudService*           qemu_listen_service;
+    HwFingerprintClient*    fp_clients;
+    int32_t     fingerid;
+    int32_t     finger_is_on_sensor;
+} HwFingerprintService;
+
+struct HwFingerprintClient {
+    HwFingerprintClient*    next;
+    HwFingerprintService*          fp;
+    QemudClient*            qemu_client;
+};
+
+static void
+_hwFingerprintClient_recv(void* opaque, uint8_t* msg, int msglen,
+                      QemudClient*  client );
+
+static void
+_hwFingerprintClient_close(void* opaque);
+
+static HwFingerprintClient*
+_hwFingerprintClient_new( HwFingerprintService*  fp);
+
+/* the only static variable */
+static HwFingerprintService _fingerprintState[1];
+
+static void _hwFingerprint_send();
+
+static QemudClient*
+_hwFingerprint_connect(void*  opaque,
+                    QemudService*  service,
+                    int  channel,
+                    const char* client_param);
+static void
+_hwFingerprintClient_removeFromList(HwFingerprintClient** phead,
+        HwFingerprintClient* target);
+
+static void
+_hwFingerprint_save(QEMUFile*  f, QemudService*  sv, void*  opaque);
+
+static int
+_hwFingerprint_load(QEMUFile*  f, QemudService*  sv, void*  opaque);
+/***********************************************************************************
+
+            All the public methods
+
+***********************************************************************************/
+
+void
+android_hw_fingerprint_init( void )
+{
+    HwFingerprintService*  fp = _fingerprintState;
+
+    if (fp->qemu_listen_service == NULL) {
+        fp->qemu_listen_service = qemud_service_register("fingerprintlisten", 0, fp,
+                _hwFingerprint_connect, _hwFingerprint_save, _hwFingerprint_load);
+        D("%s: fingerprint qemud listen service initialized\n", __FUNCTION__);
+    }
+}
+
+void
+android_hw_fingerprint_touch(int fingerid)
+{
+    HwFingerprintService*  fp = _fingerprintState;
+    D("touched fingerprint sensor with finger id %d\n", fingerid);
+    fp->fingerid = fingerid;
+    fp->finger_is_on_sensor = 1;
+    _hwFingerprint_send();
+}
+
+void
+android_hw_fingerprint_remove()
+{
+    HwFingerprintService*  fp = _fingerprintState;
+    D("finger removed from the fingerprint sensor\n");
+    fp->finger_is_on_sensor = 0;
+    _hwFingerprint_send();
+}
+
+/***********************************************************************************
+
+            All the static methods
+
+***********************************************************************************/
+
+static void
+_hwFingerprint_save(QEMUFile*  f, QemudService*  sv, void*  opaque)
+{
+    HwFingerprintService* fp = opaque;
+    qemu_put_be32(f, fp->fingerid);
+    qemu_put_be32(f, fp->finger_is_on_sensor);
+}
+
+static int
+_hwFingerprint_load(QEMUFile*  f, QemudService*  sv, void*  opaque)
+{
+    HwFingerprintService* fp = opaque;
+    fp->fingerid = qemu_get_be32(f);
+    fp->finger_is_on_sensor = qemu_get_be32(f);
+    return 0;
+}
+
+static void
+_hwFingerprint_send()
+{
+    HwFingerprintService*  fp = _fingerprintState;
+    HwFingerprintClient*    fp_client = fp->fp_clients;
+    if (!fp_client)
+        return;
+
+    char buffer[128];
+    if (fp->finger_is_on_sensor) {
+        /* send back the finger id that is on the finger print sensor */
+        snprintf(buffer, sizeof(buffer) - 1, "on:%d", fp_client->fp->fingerid);
+    } else {
+        snprintf(buffer, sizeof(buffer) - 1, "off");
+    }
+    qemud_client_send(fp_client->qemu_client, (const uint8_t*)buffer,
+            strlen(buffer)+1 /*add 1 for '\0'*/);
+}
+
+static QemudClient*
+_hwFingerprint_connect(void*  opaque,
+                    QemudService*  service,
+                    int  channel,
+                    const char* client_param)
+{
+    HwFingerprintService*  fp = opaque;
+    HwFingerprintClient*    fp_client = _hwFingerprintClient_new(fp);
+    QemudClient*    client  = qemud_client_new(service, channel, client_param, fp_client,
+                                                _hwFingerprintClient_recv,
+                                                _hwFingerprintClient_close,
+                                                NULL, /* no save */
+                                                NULL /* no load */ );
+    qemud_client_set_framing(client, 1);
+    fp_client->qemu_client = client;
+
+    D("%s: connect finger print listen is called\n", __FUNCTION__);
+    return client;
+}
+
+static void
+_hwFingerprintClient_recv(void* opaque, uint8_t* msg, int msglen,
+                      QemudClient*  client )
+{
+    /* HwFingerprintClient*       fp_client = opaque; */
+    D("got message from guest system fingerprint HAL\n");
+}
+
+static HwFingerprintClient*
+_hwFingerprintClient_new( HwFingerprintService*  fp)
+{
+    HwFingerprintClient*  fp_client;
+    ANEW0(fp_client);
+    fp_client->fp = fp;
+    fp_client->next = fp->fp_clients;
+    fp->fp_clients = fp_client;
+    return fp_client;
+}
+
+static void
+_hwFingerprintClient_close(void* opaque)
+{
+    HwFingerprintClient*       fp_client = opaque;
+    if (fp_client->fp) {
+        HwFingerprintClient** pnode = &fp_client->fp->fp_clients;
+        _hwFingerprintClient_removeFromList(pnode, fp_client);
+        fp_client->next = NULL;
+        fp_client->fp = NULL;
+    }
+    AFREE(fp_client);
+}
+
+static void
+_hwFingerprintClient_removeFromList(HwFingerprintClient** phead, HwFingerprintClient* target)
+{
+    for (;;) {
+        HwFingerprintClient* node = *phead;
+        if (node == NULL)
+            break;
+        if (node == target) {
+            *phead = target->next;
+            break;
+        }
+        phead = &node->next;
+    }
+}
diff --git a/android/hw-fingerprint.h b/android/hw-fingerprint.h
new file mode 100644
index 0000000..16806e9
--- /dev/null
+++ b/android/hw-fingerprint.h
@@ -0,0 +1,26 @@
+/* Copyright (C) 2015 The Android Open Source Project
+**
+** This software is licensed under the terms of the GNU General Public
+** License version 2, as published by the Free Software Foundation, and
+** may be copied, distributed, and modified under those terms.
+**
+** This program is distributed in the hope that it will be useful,
+** but WITHOUT ANY WARRANTY; without even the implied warranty of
+** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+** GNU General Public License for more details.
+*/
+#ifndef _android_fingerprint_h
+#define _android_fingerprint_h
+
+#include "qemu-common.h"
+
+/* initialize */
+extern void  android_hw_fingerprint_init( void );
+
+/* touch fingerprint sensor with fingerid*/
+void android_hw_fingerprint_touch(int fingerid);
+
+/* take finger off the fingerprint sensor */
+void android_hw_fingerprint_remove();
+
+#endif /* _android_fingerprint_h */
diff --git a/android/qemu-setup.c b/android/qemu-setup.c
index 7985246..36cbca9 100644
--- a/android/qemu-setup.c
+++ b/android/qemu-setup.c
@@ -19,6 +19,7 @@
 #include "android/android.h"
 #include "android/globals.h"
 #include "android/hw-sensors.h"
+#include "android/hw-fingerprint.h"
 #include "android/utils/debug.h"
 #include "android/utils/path.h"
 #include "android/utils/system.h"
@@ -468,6 +469,9 @@
     /* initialize sensors, this must be done here due to timer issues */
     android_hw_sensors_init();
 
+    /* initilize fingperprint here */
+    android_hw_fingerprint_init();
+
    /* cool, now try to run the "ddms ping" command, which will take care of pinging usage
     * if the user agreed for it. the emulator itself never sends anything to any outside
     * machine