Merge "Add Python wrappers for bind and connect as well as sendmsg."
diff --git a/f2fs_utils/f2fs_utils.c b/f2fs_utils/f2fs_utils.c
index d42ccc1..4c92622 100644
--- a/f2fs_utils/f2fs_utils.c
+++ b/f2fs_utils/f2fs_utils.c
@@ -29,7 +29,7 @@
 #define _LARGEFILE64_SOURCE
 
 #include <fcntl.h>
-#include <dlfcn.h>
+#include <string.h>
 
 #include <f2fs_fs.h>
 #include <f2fs_format_utils.h>
diff --git a/slideshow/Android.mk b/slideshow/Android.mk
new file mode 100644
index 0000000..8c782c3
--- /dev/null
+++ b/slideshow/Android.mk
@@ -0,0 +1,16 @@
+# Copyright 2015 The Android Open Source Project
+
+LOCAL_PATH := $(call my-dir)
+
+include $(CLEAR_VARS)
+LOCAL_SRC_FILES := slideshow.cpp
+LOCAL_MODULE := slideshow
+LOCAL_MODULE_TAGS := optional
+LOCAL_FORCE_STATIC_EXECUTABLE := true
+LOCAL_MODULE_PATH := $(TARGET_ROOT_OUT_SBIN)
+LOCAL_UNSTRIPPED_PATH := $(TARGET_ROOT_OUT_SBIN_UNSTRIPPED)
+
+LOCAL_CFLAGS := -D__STDC_LIMIT_MACROS -Werror
+LOCAL_C_INCLUDES := bootable/recovery
+LOCAL_STATIC_LIBRARIES := libminui libpng libz libutils libstdc++ libcutils liblog libm libc
+include $(BUILD_EXECUTABLE)
diff --git a/slideshow/slideshow.cpp b/slideshow/slideshow.cpp
new file mode 100644
index 0000000..25a2206
--- /dev/null
+++ b/slideshow/slideshow.cpp
@@ -0,0 +1,154 @@
+/*
+ * Copyright (C) 2015 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 <unistd.h>
+#include <stdlib.h>
+#include <limits.h>
+#include <time.h>
+#include <linux/input.h>
+#include <cutils/klog.h>
+#include "minui/minui.h"
+
+#define NEXT_TIMEOUT_MS 5000
+#define LAST_TIMEOUT_S  30
+
+#define LOGE(x...) do { KLOG_ERROR("slideshow", x); } while (0)
+
+static int input_cb(int fd, unsigned int epevents, void *data)
+{
+    struct input_event ev;
+    int *key_code = (int *)data;
+
+    *key_code = -1;
+
+    if (ev_get_input(fd, epevents, &ev)) {
+        return -1;
+    }
+
+    if (ev.type == EV_KEY) {
+        *key_code = ev.code;
+    }
+
+    return 0;
+}
+
+static void clear()
+{
+    gr_color(0, 0, 0, 0);
+    gr_clear();
+    gr_flip();
+}
+
+static void draw(const char *resname)
+{
+    gr_surface surface;
+    int w, h, x, y;
+
+    if (res_create_display_surface(resname, &surface) < 0) {
+        LOGE("failed to create surface for %s\n", resname);
+        return;
+    }
+
+    w = gr_get_width(surface);
+    h = gr_get_height(surface);
+    x = (gr_fb_width() - w) / 2;
+    y = (gr_fb_height() - h) / 2;
+
+    gr_blit(surface, 0, 0, w, h, x, y);
+    gr_flip();
+
+    res_free_surface(surface);
+}
+
+int usage()
+{
+    LOGE("usage: slideshow [-t timeout] image.png [image2.png ...] last.png\n");
+    return EXIT_FAILURE;
+}
+
+int main(int argc, char **argv)
+{
+    int key_code = -1;
+    int input = false;
+    int opt;
+    long int timeout = NEXT_TIMEOUT_MS;
+    time_t start;
+
+    while ((opt = getopt(argc, argv, "t")) != -1) {
+        switch (opt) {
+        case 't':
+            timeout = strtol(optarg, NULL, 0);
+
+            if (timeout < 0 || timeout >= LONG_MAX) {
+                timeout = NEXT_TIMEOUT_MS;
+                LOGE("invalid timeout %s, defaulting to %u\n", optarg,
+                    timeout);
+            }
+            break;
+        default:
+            return usage();
+        }
+    }
+
+    if (optind >= argc) {
+        return usage();
+    }
+
+    if (gr_init() == -1 || ev_init(input_cb, &key_code) == -1) {
+        LOGE("failed to initialize minui\n");
+        return EXIT_FAILURE;
+    }
+
+    /* display all images except the last one, switch to next image after
+     * timeout or user input */
+
+    while (optind < argc - 1) {
+        draw(argv[optind++]);
+
+        if (ev_wait(timeout) == 0) {
+            ev_dispatch();
+
+            if (key_code != -1) {
+                input = true;
+            }
+        }
+    };
+
+    /* if there was user input while showing the images, display the last
+     * image and wait until the power button is pressed or LAST_TIMEOUT_S
+     * has elapsed */
+
+    if (input) {
+        start = time(NULL);
+        draw(argv[optind]);
+
+        do {
+            if (ev_wait(timeout) == 0) {
+                ev_dispatch();
+            }
+
+            if (time(NULL) - start >= LAST_TIMEOUT_S) {
+                break;
+            }
+        } while (key_code != KEY_POWER);
+    }
+
+    clear();
+    gr_exit();
+    ev_exit();
+
+    return EXIT_SUCCESS;
+}