Camera service skeleton

Skeleton that implements camera emulation service over QEMU pipe. More meat
will be added as the guest camera emulation develops.

This is a patch taken from approved AOSP commit that didn't go through
because of a merge conflict.

Change-Id: I6f0a2e42be4f5f0bd86d3dbf0c2a609e74b200c2
diff --git a/Makefile.common b/Makefile.common
index 0b9f954..ed3bd6e 100644
--- a/Makefile.common
+++ b/Makefile.common
@@ -424,7 +424,8 @@
     android/qemu-setup.c \
     android/snapshot.c \
     android/utils/timezone.c \
-    android/camera/camera-format-converters.c
+    android/camera/camera-format-converters.c \
+    android/camera/camera-service.c
 
 $(call gen-hw-config-defs)
 
diff --git a/android/camera/camera-service.c b/android/camera/camera-service.c
new file mode 100644
index 0000000..077809d
--- /dev/null
+++ b/android/camera/camera-service.c
@@ -0,0 +1,322 @@
+/*
+ * Copyright (C) 2011 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+/*
+ * Contains emulated camera service implementation.
+ */
+
+#include "qemu-common.h"
+#include "android/hw-qemud.h"
+#include "android/utils/misc.h"
+#include "android/utils/system.h"
+#include "android/utils/debug.h"
+#include "android/camera/camera-capture.h"
+#include "android/camera/camera-format-converters.h"
+#include "android/camera/camera-service.h"
+
+#define  D(...)    VERBOSE_PRINT(camera,__VA_ARGS__)
+#define  W(...)    VERBOSE_PRINT(camera,__VA_ARGS__)
+#define  E(...)    VERBOSE_PRINT(camera,__VA_ARGS__)
+#define  D_ACTIVE  VERBOSE_CHECK(camera)
+
+#define SERVICE_NAME  "camera"
+
+/* Camera sevice descriptor. */
+typedef struct CameraServiceDesc CameraServiceDesc;
+struct CameraServiceDesc {
+    /* Number of camera devices connected to the host. */
+    int camera_count;
+};
+
+/* One and only one camera service. */
+static CameraServiceDesc    _camera_service_desc;
+
+/********************************************************************************
+ * CameraServiceDesc API
+ *******************************************************************************/
+
+/* Initializes camera service descriptor.
+ */
+static void
+_csDesc_init(CameraServiceDesc* csd)
+{
+    csd->camera_count = 0;
+}
+
+/********************************************************************************
+ * Camera Factory API
+ *******************************************************************************/
+
+/* Handles a message received from the emulated camera factory client.
+ */
+static void
+_factory_client_recv(void*         opaque,
+                     uint8_t*      msg,
+                     int           msglen,
+                     QemudClient*  client)
+{
+    // TODO: implement.
+}
+
+/* Emulated camera factory client has been disconnected from the service.
+ */
+static void
+_factory_client_close(void*  opaque)
+{
+}
+
+/********************************************************************************
+ * Camera client API
+ *******************************************************************************/
+
+/* Describes an emulated camera client.
+ */
+typedef struct CameraClient CameraClient;
+struct CameraClient
+{
+    /* Client name.
+     *  On Linux this is the name of the camera device.
+     *  On Windows this is the name of capturing window.
+     */
+    char*   name;
+
+    /* Input channel to use to connect to the camera. */
+    int     inp_channel;
+
+    /* Extra parameters passed to the client. */
+    char*   remaining_param;
+};
+
+/* Frees emulated camera client descriptor.
+ */
+static void
+_camera_client_free(CameraClient* cc)
+{
+    if (cc->remaining_param != NULL) {
+        free(cc->remaining_param);
+    }
+    if (cc->name != NULL) {
+        free(cc->name);
+    }
+
+    AFREE(cc);
+}
+
+/* Parses emulated camera client parameters.
+ * Param:
+ *  param - Parameters to parse. This string contains multiple parameters,
+ *      separated by a ':' character. The format of the parameters string is as
+ *      follows:
+ *          <device name>[:<input channel #>][:<extra param>],
+ *      where 'device name' is a required parameter defining name of the camera
+ *      device, 'input channel' is an optional parameter (positive integer),
+ *      defining input channel to use on the camera device. Format of the
+ *      extra parameters is not defined at this point.
+ *  device_name - Upon success contains camera device name. The caller is
+ *      responsible for freeing string buffer returned here.
+ *  inp_channel - Upon success contains the input channel to use when connecting
+ *      to the device. If this parameter is missing, a 0 will be returned here.
+ *  remainder - Contains copy of the string containing remander of the parameters
+ *      following device name and input channel. If there are no remainding
+ *      parameters, a NULL will be returned here. The caller is responsible for
+ *      freeing string buffer returned here.
+ * Return:
+ *  0 on success, or !0 on failure.
+ */
+static int
+_parse_camera_client_param(const char* param,
+                           char** device_name,
+                           int* inp_channel,
+                           char** remainder)
+{
+    const char* wrk = param;
+    const char* sep;
+
+    *device_name = *remainder = NULL;
+    *inp_channel = 0;
+
+    /* Sanity check. */
+    if (param == NULL || *param == '\0') {
+        E("%s: Parameters must contain device name", __FUNCTION__);
+        return -1;
+    }
+
+    /* Must contain device name. */
+    sep = strchr(wrk, ':');
+    if (sep == NULL) {
+        /* Contains only device name. */
+        *device_name = ASTRDUP(param);
+        return 0;
+    }
+
+    /* Save device name. */
+    *device_name = (char*)malloc((sep - wrk) + 1);
+    if (*device_name == NULL) {
+        derror("%s: Not enough memory", __FUNCTION__);
+        return -1;
+    }
+    memcpy(*device_name, wrk, sep - wrk);
+    (*device_name)[sep - wrk] = '\0';
+
+    /* Move on to the the input channel. */
+    wrk = sep + 1;
+    if (*wrk == '\0') {
+        return 0;
+    }
+    sep = strchr(wrk, ':');
+    if (sep == NULL) {
+        sep = wrk + strlen(wrk);
+    }
+    errno = 0;  // strtol doesn't set it on success.
+    *inp_channel = strtol(wrk, (char**)&sep, 10);
+    if (errno != 0) {
+        E("%s: Parameters %s contain invalid input channel",
+          __FUNCTION__, param);
+        free(*device_name);
+        *device_name = NULL;
+        return -1;
+    }
+    if (*sep == '\0') {
+        return 0;
+    }
+
+    /* Move on to the the remaining string. */
+    wrk = sep + 1;
+    if (*wrk == '\0') {
+        return 0;
+    }
+    *remainder = ASTRDUP(wrk);
+
+    return 0;
+}
+
+/* Creates descriptor for a connecting emulated camera client.
+ * Param:
+ *  csd - Camera service descriptor.
+ *  param - Client parameters. Must be formatted as follows:
+ *      - Multiple parameters are separated by ':'
+ *      - Must begin with camera device name
+ *      - Can follow with an optional input channel number, wich must be an
+ *        integer value
+ * Return:
+ *  Emulated camera client descriptor on success, or NULL on failure.
+ */
+static CameraClient*
+_camera_client_create(CameraServiceDesc* csd, const char* param)
+{
+    CameraClient* cc;
+    int res;
+
+    ANEW0(cc);
+
+    /* Parse parameters, and save them to the client. */
+    res = _parse_camera_client_param(param, &cc->name, &cc->inp_channel,
+                                     &cc->remaining_param);
+    if (res) {
+        _camera_client_free(cc);
+        return NULL;
+    }
+
+    D("Camera client created: name=%s, inp_channel=%d",
+      cc->name, cc->inp_channel);
+    return cc;
+}
+
+/* Handles a message received from the emulated camera client.
+ */
+static void
+_camera_client_recv(void*         opaque,
+                    uint8_t*      msg,
+                    int           msglen,
+                    QemudClient*  client)
+{
+    CameraClient* cc = (CameraClient*)opaque;
+
+    // TODO: implement!
+}
+
+/* Emulated camera client has been disconnected from the service.
+ */
+static void
+_camera_client_close(void*  opaque)
+{
+    CameraClient* cc = (CameraClient*)opaque;
+
+    D("Camera client closed: name=%s, inp_channel=%d",
+      cc->name, cc->inp_channel);
+
+    _camera_client_free(cc);
+}
+
+/********************************************************************************
+ * Camera service API
+ *******************************************************************************/
+
+/* Connects a client to the camera service.
+ * There are two classes of the client that can connect to the service:
+ *  - Camera factory that is insterested only in listing camera devices attached
+ *    to the host.
+ *  - Camera device emulators that attach to the actual camera devices.
+ * The distinction between these two classes is made by looking at extra
+ * parameters passed in client_param variable. If it's NULL, or empty, the client
+ * connects to a camera factory. Otherwise, parameters describe the camera device
+ * the client wants to connect to.
+ */
+static QemudClient*
+_camera_service_connect(void*          opaque,
+                        QemudService*  serv,
+                        int            channel,
+                        const char*    client_param)
+{
+    QemudClient*  client = NULL;
+    CameraServiceDesc* csd = (CameraServiceDesc*)opaque;
+
+    if (client_param == NULL || *client_param == '\0') {
+        /* This is an emulated camera factory client. */
+        client = qemud_client_new(serv, channel, client_param, csd,
+                                  _factory_client_recv, _factory_client_close,
+                                  NULL, NULL);
+    } else {
+        /* This is an emulated camera client. */
+        CameraClient* cc = _camera_client_create(csd, client_param);
+        if (cc != NULL) {
+            client = qemud_client_new(serv, channel, client_param, cc,
+                                      _camera_client_recv, _camera_client_close,
+                                      NULL, NULL);
+        }
+    }
+
+    return client;
+}
+
+void
+android_camera_service_init(void)
+{
+    static int _inited = 0;
+
+    if (!_inited) {
+        _csDesc_init(&_camera_service_desc);
+        QemudService*  serv = qemud_service_register( SERVICE_NAME, 0,
+                                                      &_camera_service_desc,
+                                                      _camera_service_connect,
+                                                      NULL, NULL);
+        if (serv == NULL) {
+            derror("could not register '%s' service", SERVICE_NAME);
+            return;
+        }
+        D("registered '%s' qemud service", SERVICE_NAME);
+    }
+}
diff --git a/android/camera/camera-service.h b/android/camera/camera-service.h
new file mode 100644
index 0000000..6794187
--- /dev/null
+++ b/android/camera/camera-service.h
@@ -0,0 +1,27 @@
+/*
+ * Copyright (C) 2011 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef ANDROID_CAMERA_CAMERA_SERVICE_H_
+#define ANDROID_CAMERA_CAMERA_SERVICE_H_
+
+/*
+ * Contains public camera service API.
+ */
+
+/* Initializes camera emulation service over qemu pipe. */
+extern void android_camera_service_init(void);
+
+#endif  /* ANDROID_CAMERA_CAMERA_SERVICE_H_ */
diff --git a/vl-android.c b/vl-android.c
index 4c2a433..c02abd5 100644
--- a/vl-android.c
+++ b/vl-android.c
@@ -54,6 +54,7 @@
 #include "android/hw-kmsg.h"
 #include "android/hw-pipe-net.h"
 #include "android/hw-qemud.h"
+#include "android/camera/camera-service.h"
 #include "android/charmap.h"
 #include "android/globals.h"
 #include "android/utils/bufprint.h"
@@ -2618,6 +2619,7 @@
     boot_property_init_service();
     android_hw_control_init();
     android_net_pipes_init();
+    android_camera_service_init();
 
 #ifdef CONFIG_KVM
     /* By default, force auto-detection for kvm */