Merge "Introduce mksquashfsimage.sh"
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;
+}
diff --git a/tests/net_test/sendmsg.py b/tests/net_test/csocket.py
similarity index 88%
rename from tests/net_test/sendmsg.py
rename to tests/net_test/csocket.py
index 422a16a..4b268e9 100644
--- a/tests/net_test/sendmsg.py
+++ b/tests/net_test/csocket.py
@@ -12,7 +12,7 @@
# See the License for the specific language governing permissions and
# limitations under the License.
-"""Python wrapper for sendmsg."""
+"""Python wrapper for C socket calls and data structures."""
import ctypes
import ctypes.util
@@ -23,7 +23,7 @@
import cstruct
-# Data structures used by sendmsg.
+# Data structures.
CMsgHdr = cstruct.Struct("cmsghdr", "@Lii", "len level type")
Iovec = cstruct.Struct("iovec", "@LL", "base len")
MsgHdr = cstruct.Struct("msghdr", "@LLLLLLi",
@@ -44,6 +44,12 @@
return CMSG_ALIGNTO * ((length / CMSG_ALIGNTO) + (length % CMSG_ALIGNTO != 0))
+def MaybeRaiseSocketError(ret):
+ if ret < 0:
+ errno = ctypes.get_errno()
+ raise socket.error(errno, os.strerror(errno))
+
+
def Sockaddr(addr):
if ":" in addr[0]:
family = socket.AF_INET6
@@ -100,12 +106,25 @@
return msg_control
+def Bind(s, to):
+ """Python wrapper for connect."""
+ ret = libc.bind(s.fileno(), to.CPointer(), len(to))
+ MaybeRaiseSocketError(ret)
+ return ret
+
+def Connect(s, to):
+ """Python wrapper for connect."""
+ ret = libc.connect(s.fileno(), to.CPointer(), len(to))
+ MaybeRaiseSocketError(ret)
+ return ret
+
+
def Sendmsg(s, to, data, control, flags):
"""Python wrapper for sendmsg.
Args:
s: A Python socket object. Becomes sockfd.
- to: A Python socket address tuple. Becomes msg->msg_name.
+ to: An address tuple, or a SockaddrIn[6] struct. Becomes msg->msg_name.
data: A string, the data to write. Goes into msg->msg_iov.
control: A list of cmsg options. Becomes msg->msg_control.
flags: An integer. Becomes msg->msg_flags.
@@ -122,9 +141,10 @@
# Convert the destination address into a struct sockaddr.
if to:
- name = Sockaddr(to)
- msg_name = name.CPointer()
- msg_namelen = len(name)
+ if isinstance(to, tuple):
+ to = Sockaddr(to)
+ msg_name = to.CPointer()
+ msg_namelen = len(to)
else:
msg_name = 0
msg_namelen = 0
@@ -155,9 +175,6 @@
# Call sendmsg.
ret = libc.sendmsg(s.fileno(), msghdr, 0)
-
- if ret < 0:
- errno = ctypes.get_errno()
- raise socket.error(errno, os.strerror(errno))
+ MaybeRaiseSocketError(ret)
return ret
diff --git a/tests/net_test/iproute.py b/tests/net_test/iproute.py
index 1060fb7..cde1803 100644
--- a/tests/net_test/iproute.py
+++ b/tests/net_test/iproute.py
@@ -150,6 +150,7 @@
### FIB rule constants. See include/uapi/linux/fib_rules.h.
+FRA_IIFNAME = 3
FRA_PRIORITY = 6
FRA_FWMARK = 10
FRA_SUPPRESS_PREFIXLEN = 14
@@ -225,6 +226,9 @@
def _NlAttrIPAddress(self, nla_type, family, address):
return self._NlAttr(nla_type, socket.inet_pton(family, address))
+ def _NlAttrInterfaceName(self, nla_type, interface):
+ return self._NlAttr(nla_type, interface + "\x00")
+
def _GetConstantName(self, value, prefix):
thismodule = sys.modules[__name__]
for name in dir(thismodule):
@@ -462,11 +466,12 @@
return self._Rule(version, is_add, RTN_UNICAST, table, nlattr, priority)
def OifRule(self, version, is_add, oif, table, priority):
- nlattr = self._NlAttr(FRA_OIFNAME, oif + "\x00")
+ nlattr = self._NlAttrInterfaceName(FRA_OIFNAME, oif)
return self._Rule(version, is_add, RTN_UNICAST, table, nlattr, priority)
def UidRangeRule(self, version, is_add, start, end, table, priority):
- nlattr = (self._NlAttrU32(FRA_UID_START, start) +
+ nlattr = (self._NlAttrInterfaceName(FRA_IIFNAME, "lo") +
+ self._NlAttrU32(FRA_UID_START, start) +
self._NlAttrU32(FRA_UID_END, end))
return self._Rule(version, is_add, RTN_UNICAST, table, nlattr, priority)
diff --git a/tests/net_test/multinetwork_base.py b/tests/net_test/multinetwork_base.py
index e3cda7a..8940258 100644
--- a/tests/net_test/multinetwork_base.py
+++ b/tests/net_test/multinetwork_base.py
@@ -27,10 +27,10 @@
from scapy import all as scapy
+import csocket
import cstruct
import iproute
import net_test
-import sendmsg
IFF_TUN = 1
@@ -447,7 +447,7 @@
4: (net_test.SOL_IP, IP_PKTINFO),
6: (net_test.SOL_IPV6, IPV6_PKTINFO)}[version]
cmsgs.append((cmsg_level, cmsg_name, pktinfo))
- sendmsg.Sendmsg(s, (dstaddr, dstport), payload, cmsgs, sendmsg.MSG_CONFIRM)
+ csocket.Sendmsg(s, (dstaddr, dstport), payload, cmsgs, csocket.MSG_CONFIRM)
def ReceiveEtherPacketOn(self, netid, packet):
posix.write(self.tuns[netid].fileno(), str(packet))
diff --git a/tests/net_test/srcaddr_selection_test.py b/tests/net_test/srcaddr_selection_test.py
index 323c7da..eb09b7f 100755
--- a/tests/net_test/srcaddr_selection_test.py
+++ b/tests/net_test/srcaddr_selection_test.py
@@ -23,11 +23,11 @@
from scapy import all as scapy
+import csocket
import iproute
import multinetwork_base
import multinetwork_test
import net_test
-import sendmsg
# Setsockopt values.
IPV6_ADDR_PREFERENCES = 72
@@ -88,7 +88,7 @@
pktinfo = multinetwork_base.MakePktInfo(6, address, 0)
cmsgs = [(net_test.SOL_IPV6, IPV6_PKTINFO, pktinfo)]
s = self.BuildSocket(6, net_test.UDPSocket, netid, "mark")
- return sendmsg.Sendmsg(s, (dest, 53), "Hello", cmsgs, 0)
+ return csocket.Sendmsg(s, (dest, 53), "Hello", cmsgs, 0)
def assertAddressUsable(self, address, netid):
self.BindToAddress(address)