Just linking with libandroid-shmem doesn't work for libcairo for some reason.

diff -uNr cairo-1.16.0/src/android-shmem.c cairo-1.16.0.mod/src/android-shmem.c
--- cairo-1.16.0/src/android-shmem.c	1970-01-01 03:00:00.000000000 +0300
+++ cairo-1.16.0.mod/src/android-shmem.c	2019-08-16 20:37:14.952643714 +0300
@@ -0,0 +1,549 @@
+#include <android/log.h>
+#include <errno.h>
+#include <pthread.h>
+#include <stdbool.h>
+#include <stdint.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <sys/mman.h>
+#include <sys/socket.h>
+#include <sys/un.h>
+#include <unistd.h>
+#include <paths.h>
+
+#define __u32 uint32_t
+#include <linux/ashmem.h>
+
+#include "android-shmem.h"
+
+#define DBG(...) __android_log_print(ANDROID_LOG_INFO, "shmem", __VA_ARGS__)
+#define ASHV_KEY_SYMLINK_PATH _PATH_TMP "ashv_key_%d"
+#define ANDROID_SHMEM_SOCKNAME "/dev/shm/%08x"
+#define ROUND_UP(N, S) ((((N) + (S) - 1) / (S)) * (S))
+
+static pthread_mutex_t mutex = PTHREAD_MUTEX_INITIALIZER;
+
+typedef struct {
+	// The shmid (shared memory id) contains the socket address (16 bits)
+	// and a local id (15 bits).
+	int id;
+	void *addr;
+	int descriptor;
+	size_t size;
+	bool markedForDeletion;
+	key_t key;
+} shmem_t;
+
+static shmem_t* shmem = NULL;
+static size_t shmem_amount = 0;
+
+// The lower 16 bits of (getpid() + i), where i is a sequence number.
+// It is unique among processes as it's only set when bound.
+static int ashv_local_socket_id = 0;
+// To handle forks we store which pid the ashv_local_socket_id was
+// created for.
+static int ashv_pid_setup = 0;
+static pthread_t ashv_listening_thread_id = 0;
+
+static int ancil_send_fd(int sock, int fd)
+{
+	char nothing = '!';
+	struct iovec nothing_ptr = { .iov_base = &nothing, .iov_len = 1 };
+
+	struct {
+		struct cmsghdr align;
+		int fd[1];
+	} ancillary_data_buffer;
+
+	struct msghdr message_header = {
+		.msg_name = NULL,
+		.msg_namelen = 0,
+		.msg_iov = &nothing_ptr,
+		.msg_iovlen = 1,
+		.msg_flags = 0,
+		.msg_control = &ancillary_data_buffer,
+		.msg_controllen = sizeof(struct cmsghdr) + sizeof(int)
+	};
+
+	struct cmsghdr* cmsg = CMSG_FIRSTHDR(&message_header);
+	cmsg->cmsg_len = message_header.msg_controllen; // sizeof(int);
+	cmsg->cmsg_level = SOL_SOCKET;
+	cmsg->cmsg_type = SCM_RIGHTS;
+	((int*) CMSG_DATA(cmsg))[0] = fd;
+
+	return sendmsg(sock, &message_header, 0) >= 0 ? 0 : -1;
+}
+
+static int ancil_recv_fd(int sock)
+{
+	char nothing = '!';
+	struct iovec nothing_ptr = { .iov_base = &nothing, .iov_len = 1 };
+
+	struct {
+		struct cmsghdr align;
+		int fd[1];
+	} ancillary_data_buffer;
+
+	struct msghdr message_header = {
+		.msg_name = NULL,
+		.msg_namelen = 0,
+		.msg_iov = &nothing_ptr,
+		.msg_iovlen = 1,
+		.msg_flags = 0,
+		.msg_control = &ancillary_data_buffer,
+		.msg_controllen = sizeof(struct cmsghdr) + sizeof(int)
+	};
+
+	struct cmsghdr* cmsg = CMSG_FIRSTHDR(&message_header);
+	cmsg->cmsg_len = message_header.msg_controllen;
+	cmsg->cmsg_level = SOL_SOCKET;
+	cmsg->cmsg_type = SCM_RIGHTS;
+	((int*) CMSG_DATA(cmsg))[0] = -1;
+
+	if (recvmsg(sock, &message_header, 0) < 0) return -1;
+
+	return ((int*) CMSG_DATA(cmsg))[0];
+}
+
+static int ashmem_get_size_region(int fd)
+{
+	//int ret = __ashmem_is_ashmem(fd, 1);
+	//if (ret < 0) return ret;
+	return TEMP_FAILURE_RETRY(ioctl(fd, ASHMEM_GET_SIZE, NULL));
+}
+
+/*
+ * From https://android.googlesource.com/platform/system/core/+/master/libcutils/ashmem-dev.c
+ *
+ * ashmem_create_region - creates a new named ashmem region and returns the file
+ * descriptor, or <0 on error.
+ *
+ * `name' is the label to give the region (visible in /proc/pid/maps)
+ * `size' is the size of the region, in page-aligned bytes
+ */
+static int ashmem_create_region(char const* name, size_t size)
+{
+	int fd = open("/dev/ashmem", O_RDWR);
+	if (fd < 0) return fd;
+
+	char name_buffer[ASHMEM_NAME_LEN] = {0};
+	strncpy(name_buffer, name, sizeof(name_buffer));
+	name_buffer[sizeof(name_buffer)-1] = 0;
+
+	int ret = ioctl(fd, ASHMEM_SET_NAME, name_buffer);
+	if (ret < 0) goto error;
+
+	ret = ioctl(fd, ASHMEM_SET_SIZE, size);
+	if (ret < 0) goto error;
+
+	return fd;
+error:
+	close(fd);
+	return ret;
+}
+
+static void ashv_check_pid()
+{
+	pid_t mypid = getpid();
+	if (ashv_pid_setup == 0) {
+		ashv_pid_setup = mypid;
+	} else if (ashv_pid_setup != mypid) {
+		DBG("%s: Cleaning to new pid=%d from oldpid=%d", __PRETTY_FUNCTION__, mypid, ashv_pid_setup);
+		// We inherited old state across a fork.
+		ashv_pid_setup = mypid;
+		ashv_local_socket_id = 0;
+		ashv_listening_thread_id = 0;
+		shmem_amount = 0;
+		// Unlock if fork left us with held lock from parent thread.
+		pthread_mutex_unlock(&mutex);
+		if (shmem != NULL) free(shmem);
+		shmem = NULL;
+	}
+}
+
+
+// Store index in the lower 15 bits and the socket id in the
+// higher 16 bits.
+static int ashv_shmid_from_counter(unsigned int counter)
+{
+	return ashv_local_socket_id * 0x10000 + counter;
+}
+
+static int ashv_socket_id_from_shmid(int shmid)
+{
+	return shmid / 0x10000;
+}
+
+static int ashv_find_local_index(int shmid)
+{
+	for (size_t i = 0; i < shmem_amount; i++)
+		if (shmem[i].id == shmid)
+			return i;
+	return -1;
+}
+
+static void* ashv_thread_function(void* arg)
+{
+	int sock = *(int*)arg;
+	free(arg);
+	struct sockaddr_un addr;
+	socklen_t len = sizeof(addr);
+	int sendsock;
+	//DBG("%s: thread started", __PRETTY_FUNCTION__);
+	while ((sendsock = accept(sock, (struct sockaddr *)&addr, &len)) != -1) {
+		int shmid;
+		if (recv(sendsock, &shmid, sizeof(shmid), 0) != sizeof(shmid)) {
+			DBG("%s: ERROR: recv() returned not %zu bytes", __PRETTY_FUNCTION__, sizeof(shmid));
+			close(sendsock);
+			continue;
+		}
+		pthread_mutex_lock(&mutex);
+		int idx = ashv_find_local_index(shmid);
+		if (idx != -1) {
+			if (write(sendsock, &shmem[idx].key, sizeof(key_t)) != sizeof(key_t)) {
+				DBG("%s: ERROR: write failed: %s", __PRETTY_FUNCTION__, strerror(errno));
+			}
+			if (ancil_send_fd(sendsock, shmem[idx].descriptor) != 0) {
+				DBG("%s: ERROR: ancil_send_fd() failed: %s", __PRETTY_FUNCTION__, strerror(errno));
+			}
+		} else {
+			DBG("%s: ERROR: cannot find shmid 0x%x", __PRETTY_FUNCTION__, shmid);
+		}
+		pthread_mutex_unlock(&mutex);
+		close(sendsock);
+		len = sizeof(addr);
+	}
+	DBG ("%s: ERROR: listen() failed, thread stopped", __PRETTY_FUNCTION__);
+	return NULL;
+}
+
+static void android_shmem_delete(int idx)
+{
+	if (shmem[idx].descriptor) close(shmem[idx].descriptor);
+	shmem_amount--;
+	memmove(&shmem[idx], &shmem[idx+1], (shmem_amount - idx) * sizeof(shmem_t));
+}
+
+static int ashv_read_remote_segment(int shmid)
+{
+	struct sockaddr_un addr;
+	memset(&addr, 0, sizeof(addr));
+	addr.sun_family = AF_UNIX;
+	sprintf(&addr.sun_path[1], ANDROID_SHMEM_SOCKNAME, ashv_socket_id_from_shmid(shmid));
+	int addrlen = sizeof(addr.sun_family) + strlen(&addr.sun_path[1]) + 1;
+
+	int recvsock = socket(AF_UNIX, SOCK_STREAM, 0);
+	if (recvsock == -1) {
+		DBG ("%s: cannot create UNIX socket: %s", __PRETTY_FUNCTION__, strerror(errno));
+		return -1;
+	}
+	if (connect(recvsock, (struct sockaddr*) &addr, addrlen) != 0) {
+		DBG("%s: Cannot connect to UNIX socket %s: %s, len %d", __PRETTY_FUNCTION__, addr.sun_path + 1, strerror(errno), addrlen);
+		close(recvsock);
+		return -1;
+	}
+
+	if (send(recvsock, &shmid, sizeof(shmid), 0) != sizeof(shmid)) {
+		DBG ("%s: send() failed on socket %s: %s", __PRETTY_FUNCTION__, addr.sun_path + 1, strerror(errno));
+		close(recvsock);
+		return -1;
+	}
+
+	key_t key;
+	if (read(recvsock, &key, sizeof(key_t)) != sizeof(key_t)) {
+		DBG("%s: ERROR: failed read", __PRETTY_FUNCTION__);
+		close(recvsock);
+		return -1;
+	}
+
+	int descriptor = ancil_recv_fd(recvsock);
+	if (descriptor < 0) {
+		DBG("%s: ERROR: ancil_recv_fd() failed on socket %s: %s", __PRETTY_FUNCTION__, addr.sun_path + 1, strerror(errno));
+		close(recvsock);
+		return -1;
+	}
+	close(recvsock);
+
+	int size = ashmem_get_size_region(descriptor);
+	if (size == 0 || size == -1) {
+		DBG ("%s: ERROR: ashmem_get_size_region() returned %d on socket %s: %s", __PRETTY_FUNCTION__, size, addr.sun_path + 1, strerror(errno));
+		return -1;
+	}
+
+	int idx = shmem_amount;
+	shmem_amount ++;
+	shmem = realloc(shmem, shmem_amount * sizeof(shmem_t));
+	shmem[idx].id = shmid;
+	shmem[idx].descriptor = descriptor;
+	shmem[idx].size = size;
+	shmem[idx].addr = NULL;
+	shmem[idx].markedForDeletion = false;
+	shmem[idx].key = key;
+	return idx;
+}
+
+/* Get shared memory area identifier. */
+int android_shmget(key_t key, size_t size, int flags)
+{
+	(void) flags;
+
+	ashv_check_pid();
+
+	// Counter wrapping around at 15 bits.
+	static size_t shmem_counter = 0;
+
+	if (!ashv_listening_thread_id) {
+		int sock = socket(AF_UNIX, SOCK_STREAM, 0);
+		if (!sock) {
+			DBG ("%s: cannot create UNIX socket: %s", __PRETTY_FUNCTION__, strerror(errno));
+			errno = EINVAL;
+			return -1;
+		}
+		int i;
+		for (i = 0; i < 4096; i++) {
+			struct sockaddr_un addr;
+			int len;
+			memset (&addr, 0, sizeof(addr));
+			addr.sun_family = AF_UNIX;
+			ashv_local_socket_id = (getpid() + i) & 0xffff;
+			sprintf(&addr.sun_path[1], ANDROID_SHMEM_SOCKNAME, ashv_local_socket_id);
+			len = sizeof(addr.sun_family) + strlen(&addr.sun_path[1]) + 1;
+			if (bind(sock, (struct sockaddr *)&addr, len) != 0) continue;
+			DBG("%s: bound UNIX socket %s in pid=%d", __PRETTY_FUNCTION__, addr.sun_path + 1, getpid());
+			break;
+		}
+		if (i == 4096) {
+			DBG("%s: cannot bind UNIX socket, bailing out", __PRETTY_FUNCTION__);
+			ashv_local_socket_id = 0;
+			errno = ENOMEM;
+			return -1;
+		}
+		if (listen(sock, 4) != 0) {
+			DBG("%s: listen failed", __PRETTY_FUNCTION__);
+			errno = ENOMEM;
+			return -1;
+		}
+		int* socket_arg = malloc(sizeof(int));
+		*socket_arg = sock;
+		pthread_create(&ashv_listening_thread_id, NULL, &ashv_thread_function, socket_arg);
+	}
+
+	int shmid = -1;
+
+	pthread_mutex_lock(&mutex);
+	char symlink_path[256];
+	if (key != IPC_PRIVATE) {
+		// (1) Check if symlink exists telling us where to connect.
+		// (2) If so, try to connect and open.
+		// (3) If connected and opened, done. If connection refused
+		//     take ownership of the key and create the symlink.
+		// (4) If no symlink, create it.
+		sprintf(symlink_path, ASHV_KEY_SYMLINK_PATH, key);
+		char path_buffer[256];
+		char num_buffer[64];
+		while (true) {
+			int path_length = readlink(symlink_path, path_buffer, sizeof(path_buffer) - 1);
+			if (path_length != -1) {
+				path_buffer[path_length] = '\0';
+				int shmid = atoi(path_buffer);
+				if (shmid != 0) {
+					int idx = ashv_read_remote_segment(shmid);
+					if (idx != -1) {
+						pthread_mutex_unlock(&mutex);
+						return shmem[idx].id;
+					}
+				}
+				// TODO: Not sure we should try to remove previous owner if e.g.
+				// there was a tempporary failture to get a soket. Need to
+				// distinguish between why ashv_read_remote_segment failed.
+				unlink(symlink_path);
+			}
+			// Take ownership.
+			// TODO: HAndle error (out of resouces, no infinite loop)
+			if (shmid == -1) {
+				shmem_counter = (shmem_counter + 1) & 0x7fff;
+				shmid = ashv_shmid_from_counter(shmem_counter);
+				sprintf(num_buffer, "%d", shmid);
+			}
+			if (symlink(num_buffer, symlink_path) == 0) break;
+		}
+	}
+
+
+	int idx = shmem_amount;
+	char buf[256];
+	sprintf(buf, ANDROID_SHMEM_SOCKNAME "-%d", ashv_local_socket_id, idx);
+
+	shmem_amount++;
+	if (shmid == -1) {
+		shmem_counter = (shmem_counter + 1) & 0x7fff;
+		shmid = ashv_shmid_from_counter(shmem_counter);
+	}
+
+	shmem = realloc(shmem, shmem_amount * sizeof(shmem_t));
+	size = ROUND_UP(size, getpagesize());
+	shmem[idx].size = size;
+	shmem[idx].descriptor = ashmem_create_region(buf, size);
+	shmem[idx].addr = NULL;
+	shmem[idx].id = shmid;
+	shmem[idx].markedForDeletion = false;
+	shmem[idx].key = key;
+
+	if (shmem[idx].descriptor < 0) {
+		DBG("%s: ashmem_create_region() failed for size %zu: %s", __PRETTY_FUNCTION__, size, strerror(errno));
+		shmem_amount --;
+		shmem = realloc(shmem, shmem_amount * sizeof(shmem_t));
+		pthread_mutex_unlock (&mutex);
+		return -1;
+	}
+	//DBG("%s: ID %d shmid %x FD %d size %zu", __PRETTY_FUNCTION__, idx, shmid, shmem[idx].descriptor, shmem[idx].size);
+	/*
+	status = ashmem_set_prot_region (shmem[idx].descriptor, 0666);
+	if (status < 0) {
+		DBG ("%s: ashmem_set_prot_region() failed for size %zu: %s %d", __PRETTY_FUNCTION__, size, strerror(status), status);
+		shmem_amount --;
+		shmem = realloc (shmem, shmem_amount * sizeof(shmem_t));
+		pthread_mutex_unlock (&mutex);
+		return -1;
+	}
+	*/
+	/*
+	status = ashmem_pin_region (shmem[idx].descriptor, 0, shmem[idx].size);
+	if (status < 0) {
+		DBG ("%s: ashmem_pin_region() failed for size %zu: %s %d", __PRETTY_FUNCTION__, size, strerror(status), status);
+		shmem_amount --;
+		shmem = realloc (shmem, shmem_amount * sizeof(shmem_t));
+		pthread_mutex_unlock (&mutex);
+		return -1;
+	}
+	*/
+	pthread_mutex_unlock(&mutex);
+
+	return shmid;
+}
+
+/* Attach shared memory segment. */
+void* android_shmat(int shmid, void const* shmaddr, int shmflg)
+{
+	ashv_check_pid();
+
+	int socket_id = ashv_socket_id_from_shmid(shmid);
+	void *addr;
+
+	pthread_mutex_lock(&mutex);
+
+	int idx = ashv_find_local_index(shmid);
+	if (idx == -1 && socket_id != ashv_local_socket_id) {
+		idx = ashv_read_remote_segment(shmid);
+	}
+
+	if (idx == -1) {
+		DBG ("%s: shmid %x does not exist", __PRETTY_FUNCTION__, shmid);
+		pthread_mutex_unlock(&mutex);
+		errno = EINVAL;
+		return (void*) -1;
+	}
+
+	if (shmem[idx].addr == NULL) {
+		shmem[idx].addr = mmap((void*) shmaddr, shmem[idx].size, PROT_READ | (shmflg == 0 ? PROT_WRITE : 0), MAP_SHARED, shmem[idx].descriptor, 0);
+		if (shmem[idx].addr == MAP_FAILED) {
+			DBG ("%s: mmap() failed for ID %x FD %d: %s", __PRETTY_FUNCTION__, idx, shmem[idx].descriptor, strerror(errno));
+			shmem[idx].addr = NULL;
+		}
+	}
+	addr = shmem[idx].addr;
+	DBG ("%s: mapped addr %p for FD %d ID %d", __PRETTY_FUNCTION__, addr, shmem[idx].descriptor, idx);
+	pthread_mutex_unlock (&mutex);
+
+	return addr ? addr : (void *)-1;
+}
+
+/* Detach shared memory segment. */
+int android_shmdt(void const* shmaddr)
+{
+	ashv_check_pid();
+
+	pthread_mutex_lock(&mutex);
+	for (size_t i = 0; i < shmem_amount; i++) {
+		if (shmem[i].addr == shmaddr) {
+			if (munmap(shmem[i].addr, shmem[i].size) != 0) {
+				DBG("%s: munmap %p failed", __PRETTY_FUNCTION__, shmaddr);
+			}
+			shmem[i].addr = NULL;
+			DBG("%s: unmapped addr %p for FD %d ID %zu shmid %x", __PRETTY_FUNCTION__, shmaddr, shmem[i].descriptor, i, shmem[i].id);
+			if (shmem[i].markedForDeletion || ashv_socket_id_from_shmid(shmem[i].id) != ashv_local_socket_id) {
+				DBG ("%s: deleting shmid %x", __PRETTY_FUNCTION__, shmem[i].id);
+				android_shmem_delete(i);
+			}
+			pthread_mutex_unlock(&mutex);
+			return 0;
+		}
+	}
+	pthread_mutex_unlock(&mutex);
+
+	DBG("%s: invalid address %p", __PRETTY_FUNCTION__, shmaddr);
+	/* Could be a remove segment, do not report an error for that. */
+	return 0;
+}
+
+/* Shared memory control operation. */
+int android_shmctl(int shmid, int cmd, struct shmid_ds *buf)
+{
+	ashv_check_pid();
+
+	if (cmd == IPC_RMID) {
+		DBG("%s: IPC_RMID for shmid=%x", __PRETTY_FUNCTION__, shmid);
+		pthread_mutex_lock(&mutex);
+		int idx = ashv_find_local_index(shmid);
+		if (idx == -1) {
+			DBG("%s: shmid=%x does not exist locally", __PRETTY_FUNCTION__, shmid);
+			/* We do not rm non-local regions, but do not report an error for that. */
+			pthread_mutex_unlock(&mutex);
+			return 0;
+		}
+
+		if (shmem[idx].addr) {
+			// shmctl(2): The segment will actually be destroyed only
+			// after the last process detaches it (i.e., when the shm_nattch
+			// member of the associated structure shmid_ds is zero.
+			shmem[idx].markedForDeletion = true;
+		} else {
+			android_shmem_delete(idx);
+		}
+		pthread_mutex_unlock(&mutex);
+		return 0;
+	} else if (cmd == IPC_STAT) {
+		if (!buf) {
+			DBG ("%s: ERROR: buf == NULL for shmid %x", __PRETTY_FUNCTION__, shmid);
+			errno = EINVAL;
+			return -1;
+		}
+
+		pthread_mutex_lock(&mutex);
+		int idx = ashv_find_local_index(shmid);
+		if (idx == -1) {
+			DBG ("%s: ERROR: shmid %x does not exist", __PRETTY_FUNCTION__, shmid);
+			pthread_mutex_unlock (&mutex);
+			errno = EINVAL;
+			return -1;
+		}
+		/* Report max permissive mode */
+		memset(buf, 0, sizeof(struct shmid_ds));
+		buf->shm_segsz = shmem[idx].size;
+		buf->shm_nattch = 1;
+		buf->shm_perm.key = shmem[idx].key;
+		buf->shm_perm.uid = geteuid();
+		buf->shm_perm.gid = getegid();
+		buf->shm_perm.cuid = geteuid();
+		buf->shm_perm.cgid = getegid();
+		buf->shm_perm.mode = 0666;
+		buf->shm_perm.seq = 1;
+
+		pthread_mutex_unlock (&mutex);
+		return 0;
+	}
+
+	DBG("%s: cmd %d not implemented yet!", __PRETTY_FUNCTION__, cmd);
+	errno = EINVAL;
+	return -1;
+}
diff -uNr cairo-1.16.0/src/android-shmem.h cairo-1.16.0.mod/src/android-shmem.h
--- cairo-1.16.0/src/android-shmem.h	1970-01-01 03:00:00.000000000 +0300
+++ cairo-1.16.0.mod/src/android-shmem.h	2019-08-16 20:37:14.955977067 +0300
@@ -0,0 +1,28 @@
+#ifndef _SYS_SHM_H
+#define _SYS_SHM_H
+
+#include <linux/shm.h>
+#include <stdint.h>
+#include <sys/types.h>
+
+__BEGIN_DECLS
+
+#ifndef shmid_ds
+# define shmid_ds shmid64_ds
+#endif
+
+/* Shared memory control operations. */
+int android_shmctl(int shmid, int cmd, struct shmid_ds* buf);
+
+/* Get shared memory area identifier. */
+int android_shmget(key_t key, size_t size, int shmflg);
+
+/* Attach shared memory segment. */
+void *android_shmat(int shmid, void const* shmaddr, int shmflg);
+
+/* Detach shared memory segment. */
+int android_shmdt(void const* shmaddr);
+
+__END_DECLS
+
+#endif
diff -uNr cairo-1.16.0/src/cairo.pc.in cairo-1.16.0.mod/src/cairo.pc.in
--- cairo-1.16.0/src/cairo.pc.in	2018-08-17 04:10:53.000000000 +0300
+++ cairo-1.16.0.mod/src/cairo.pc.in	2019-08-16 20:37:14.955977067 +0300
@@ -9,5 +9,5 @@
 
 @PKGCONFIG_REQUIRES@: @CAIRO_REQUIRES@
 Libs: -L${libdir} -lcairo
-Libs.private: @CAIRO_NONPKGCONFIG_LIBS@
+Libs.private: @CAIRO_NONPKGCONFIG_LIBS@ -llog
 Cflags: -I${includedir}/cairo
diff -uNr cairo-1.16.0/src/cairo-xcb-connection.c cairo-1.16.0.mod/src/cairo-xcb-connection.c
--- cairo-1.16.0/src/cairo-xcb-connection.c	2018-08-17 04:10:53.000000000 +0300
+++ cairo-1.16.0.mod/src/cairo-xcb-connection.c	2019-08-16 20:38:23.676405816 +0300
@@ -32,6 +32,7 @@
 
 #include "cairoint.h"
 
+#include "android-shmem.h"
 #include "cairo-xcb-private.h"
 #include "cairo-hash-private.h"
 #include "cairo-freelist-private.h"
@@ -43,7 +44,6 @@
 
 #if CAIRO_HAS_XCB_SHM_FUNCTIONS
 #include <sys/ipc.h>
-#include <sys/shm.h>
 #include <xcb/shm.h>
 #endif
 
@@ -452,13 +452,13 @@
     uint32_t shmseg;
     void *ptr;
 
-    shmid = shmget (IPC_PRIVATE, 0x1000, IPC_CREAT | 0600);
+    shmid = android_shmget (IPC_PRIVATE, 0x1000, IPC_CREAT | 0600);
     if (shmid == -1)
 	return FALSE;
 
-    ptr = shmat (shmid, NULL, 0);
+    ptr = android_shmat (shmid, NULL, 0);
     if (ptr == (char *) -1) {
-	shmctl (shmid, IPC_RMID, NULL);
+	android_shmctl (shmid, IPC_RMID, NULL);
 	return FALSE;
     }
 
@@ -475,8 +475,8 @@
     if (error != NULL)
 	success = FALSE;
 
-    shmctl (shmid, IPC_RMID, NULL);
-    shmdt (ptr);
+    android_shmctl (shmid, IPC_RMID, NULL);
+    android_shmdt (ptr);
 
     return success;
 }
diff -uNr cairo-1.16.0/src/cairo-xcb-shm.c cairo-1.16.0.mod/src/cairo-xcb-shm.c
--- cairo-1.16.0/src/cairo-xcb-shm.c	2018-08-17 04:10:53.000000000 +0300
+++ cairo-1.16.0.mod/src/cairo-xcb-shm.c	2019-08-16 20:37:48.552853136 +0300
@@ -38,13 +38,13 @@
 
 #if CAIRO_HAS_XCB_SHM_FUNCTIONS
 
+#include "android-shmem.h"
 #include "cairo-xcb-private.h"
 #include "cairo-list-inline.h"
 #include "cairo-mempool-private.h"
 
 #include <xcb/shm.h>
 #include <sys/ipc.h>
-#include <sys/shm.h>
 #include <errno.h>
 
 #define CAIRO_MAX_SHM_MEMORY (16*1024*1024)
@@ -75,7 +75,7 @@
 {
     cairo_list_del (&pool->link);
 
-    shmdt (pool->shm);
+    android_shmdt (pool->shm);
     _cairo_mempool_fini (&pool->mem);
 
     free (pool);
@@ -221,7 +221,7 @@
     bytes <<= 3;
 
     do {
-	pool->shmid = shmget (IPC_PRIVATE, bytes, IPC_CREAT | 0600);
+	pool->shmid = android_shmget (IPC_PRIVATE, bytes, IPC_CREAT | 0600);
 	if (pool->shmid != -1)
 	    break;
 
@@ -240,9 +240,9 @@
 	return CAIRO_INT_STATUS_UNSUPPORTED;
     }
 
-    pool->shm = shmat (pool->shmid, NULL, 0);
+    pool->shm = android_shmat (pool->shmid, NULL, 0);
     if (unlikely (pool->shm == (char *) -1)) {
-	shmctl (pool->shmid, IPC_RMID, NULL);
+	android_shmctl (pool->shmid, IPC_RMID, NULL);
 	free (pool);
 	CAIRO_MUTEX_UNLOCK (connection->shm_mutex);
 	return _cairo_error (CAIRO_STATUS_NO_MEMORY);
@@ -251,14 +251,14 @@
     status = _cairo_mempool_init (&pool->mem, pool->shm, bytes,
 				  minbits, maxbits - minbits + 1);
     if (unlikely (status)) {
-	shmdt (pool->shm);
+	android_shmdt (pool->shm);
 	free (pool);
 	CAIRO_MUTEX_UNLOCK (connection->shm_mutex);
 	return status;
     }
 
     pool->shmseg = _cairo_xcb_connection_shm_attach (connection, pool->shmid, FALSE);
-    shmctl (pool->shmid, IPC_RMID, NULL);
+    android_shmctl (pool->shmid, IPC_RMID, NULL);
 
     cairo_list_add (&pool->link, &connection->shm_pools);
     mem = _cairo_mempool_alloc (&pool->mem, size);
diff -uNr cairo-1.16.0/src/cairo-xlib-surface.c cairo-1.16.0.mod/src/cairo-xlib-surface.c
--- cairo-1.16.0/src/cairo-xlib-surface.c	2018-08-17 04:10:53.000000000 +0300
+++ cairo-1.16.0.mod/src/cairo-xlib-surface.c	2019-08-16 20:37:56.532902932 +0300
@@ -70,7 +70,6 @@
 
 #include <X11/extensions/XShm.h>
 #include <sys/ipc.h>
-#include <sys/shm.h>
 
 #define XLIB_COORD_MAX 32767
 
@@ -1390,7 +1389,7 @@
     *image_extra = NULL;
     *image_out = (cairo_image_surface_t *)
 	_cairo_xlib_surface_get_shm (abstract_surface, FALSE);
-    if (*image_out) 
+    if (*image_out)
 	    return (*image_out)->base.status;
 
     extents.x = extents.y = 0;
diff -uNr cairo-1.16.0/src/cairo-xlib-surface-shm.c cairo-1.16.0.mod/src/cairo-xlib-surface-shm.c
--- cairo-1.16.0/src/cairo-xlib-surface-shm.c	2018-08-17 04:10:53.000000000 +0300
+++ cairo-1.16.0.mod/src/cairo-xlib-surface-shm.c	2019-08-16 20:38:09.702985163 +0300
@@ -39,6 +39,7 @@
 
 #if !CAIRO_HAS_XLIB_XCB_FUNCTIONS
 
+#include "android-shmem.h"
 #include "cairo-xlib-private.h"
 #include "cairo-xlib-surface-private.h"
 
@@ -150,7 +151,6 @@
 #include <X11/extensions/shmstr.h>
 #endif
 #include <sys/ipc.h>
-#include <sys/shm.h>
 
 #define MIN_PIXMAP_SIZE 4096
 
@@ -372,14 +372,14 @@
 
     XShmQueryVersion (dpy, &major, &minor, has_pixmap);
 
-    shm.shmid = shmget (IPC_PRIVATE, 0x1000, IPC_CREAT | 0600);
+    shm.shmid = android_shmget (IPC_PRIVATE, 0x1000, IPC_CREAT | 0600);
     if (shm.shmid == -1)
 	return FALSE;
 
     shm.readOnly = FALSE;
-    shm.shmaddr = shmat (shm.shmid, NULL, 0);
+    shm.shmaddr = android_shmat (shm.shmid, NULL, 0);
     if (shm.shmaddr == (char *) -1) {
-	shmctl (shm.shmid, IPC_RMID, NULL);
+	android_shmctl (shm.shmid, IPC_RMID, NULL);
 	return FALSE;
     }
 
@@ -398,8 +398,8 @@
     XSetErrorHandler (old_handler);
     XUnlockDisplay (dpy);
 
-    shmctl (shm.shmid, IPC_RMID, NULL);
-    shmdt (shm.shmaddr);
+    android_shmctl (shm.shmid, IPC_RMID, NULL);
+    android_shmdt (shm.shmaddr);
 
     return success && ! _x_error_occurred;
 }
@@ -420,7 +420,7 @@
 _cairo_xlib_display_shm_pool_destroy (cairo_xlib_display_t *display,
 				      cairo_xlib_shm_t *pool)
 {
-    shmdt (pool->shm.shmaddr);
+    android_shmdt (pool->shm.shmaddr);
     if (display->display) /* may be called after CloseDisplay */
 	XShmDetach (display->display, &pool->shm);
 
@@ -584,18 +584,18 @@
 
     minbits += (maxbits - 16) / 2;
 
-    pool->shm.shmid = shmget (IPC_PRIVATE, bytes, IPC_CREAT | 0600);
+    pool->shm.shmid = android_shmget (IPC_PRIVATE, bytes, IPC_CREAT | 0600);
     while (pool->shm.shmid == -1 && bytes >= 2*size) {
 	bytes >>= 1;
-	pool->shm.shmid = shmget (IPC_PRIVATE, bytes, IPC_CREAT | 0600);
+	pool->shm.shmid = android_shmget (IPC_PRIVATE, bytes, IPC_CREAT | 0600);
     }
     if (pool->shm.shmid == -1)
 	goto cleanup;
 
     pool->shm.readOnly = FALSE;
-    pool->shm.shmaddr = shmat (pool->shm.shmid, NULL, 0);
+    pool->shm.shmaddr = android_shmat (pool->shm.shmid, NULL, 0);
     if (pool->shm.shmaddr == (char *) -1) {
-	shmctl (pool->shm.shmid, IPC_RMID, NULL);
+	android_shmctl (pool->shm.shmid, IPC_RMID, NULL);
 	goto cleanup;
     }
 
@@ -604,7 +604,7 @@
 #if !IPC_RMID_DEFERRED_RELEASE
     XSync (dpy, FALSE);
 #endif
-    shmctl (pool->shm.shmid, IPC_RMID, NULL);
+    android_shmctl (pool->shm.shmid, IPC_RMID, NULL);
 
     if (! success)
 	goto cleanup_shm;
@@ -622,7 +622,7 @@
 cleanup_detach:
     XShmDetach (dpy, &pool->shm);
 cleanup_shm:
-    shmdt (pool->shm.shmaddr);
+    android_shmdt (pool->shm.shmaddr);
 cleanup:
     free (pool);
     return NULL;
@@ -1307,14 +1307,14 @@
     XShmCompletionEvent ev;
     XShmSegmentInfo info;
 
-    info.shmid = shmget (IPC_PRIVATE, 0x1000, IPC_CREAT | 0600);
+    info.shmid = android_shmget (IPC_PRIVATE, 0x1000, IPC_CREAT | 0600);
     if (info.shmid == -1)
 	return TRUE;
 
     info.readOnly = FALSE;
-    info.shmaddr = shmat (info.shmid, NULL, 0);
+    info.shmaddr = android_shmat (info.shmid, NULL, 0);
     if (info.shmaddr == (char *) -1) {
-	shmctl (info.shmid, IPC_RMID, NULL);
+	android_shmctl (info.shmid, IPC_RMID, NULL);
 	return TRUE;
     }
 
@@ -1343,8 +1343,8 @@
     XSetErrorHandler (old_handler);
     XUnlockDisplay (dpy);
 
-    shmctl (info.shmid, IPC_RMID, NULL);
-    shmdt (info.shmaddr);
+    android_shmctl (info.shmid, IPC_RMID, NULL);
+    android_shmdt (info.shmaddr);
 
     return _x_error_occurred;
 }
diff -uNr cairo-1.16.0/src/Makefile.am cairo-1.16.0.mod/src/Makefile.am
--- cairo-1.16.0/src/Makefile.am	2018-08-17 04:10:53.000000000 +0300
+++ cairo-1.16.0.mod/src/Makefile.am	2019-08-16 20:37:14.955977067 +0300
@@ -35,7 +35,7 @@
 	$(enabled_cairo_cxx_sources) \
 	$(NULL)
 libcairo_cxx_la_LDFLAGS = $(AM_LDFLAGS) $(export_symbols)
-libcairo_cxx_la_LIBADD = $(CAIRO_LIBS)
+libcairo_cxx_la_LIBADD = $(CAIRO_LIBS) -llog
 libcairo_cxx_la_DEPENDENCIES = $(cairo_def_dependency)
 
 
@@ -46,7 +46,7 @@
 	$(NULL)
 libcairo_la_LDFLAGS = $(AM_LDFLAGS) -version-info $(CAIRO_LIBTOOL_VERSION_INFO) -no-undefined $(export_symbols)
 libcairo_la_LIBADD = $(CAIRO_LIBS) \
-	$(cairo_cxx_lib)
+	$(cairo_cxx_lib) -llog
 libcairo_la_DEPENDENCIES = $(cairo_def_dependency) $(cairo_cxx_lib)
 
 # Special headers
diff -uNr cairo-1.16.0/src/Makefile.in cairo-1.16.0.mod/src/Makefile.in
--- cairo-1.16.0/src/Makefile.in	2018-10-19 23:20:07.000000000 +0300
+++ cairo-1.16.0.mod/src/Makefile.in	2019-08-16 20:37:14.959310422 +0300
@@ -568,7 +568,7 @@
 	cairo-svg-surface.c test-compositor-surface.c \
 	test-null-compositor-surface.c test-base-compositor-surface.c \
 	test-paginated-surface.c cairo-tee-surface.c \
-	cairo-xml-surface.c cairo-version.h
+	cairo-xml-surface.c cairo-version.h android-shmem.c
 am__objects_1 =
 @CAIRO_HAS_XLIB_SURFACE_TRUE@am__objects_2 = $(am__objects_1)
 @CAIRO_HAS_XLIB_XRENDER_SURFACE_TRUE@am__objects_3 = $(am__objects_1)
@@ -780,7 +780,7 @@
 AM_V_lt = $(am__v_lt_@AM_V@)
 am__v_lt_ = $(am__v_lt_@AM_DEFAULT_V@)
 am__v_lt_0 = --silent
-am__v_lt_1 = 
+am__v_lt_1 =
 libcairo_la_LINK = $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) \
 	$(LIBTOOLFLAGS) --mode=link $(CCLD) $(AM_CFLAGS) $(CFLAGS) \
 	$(libcairo_la_LDFLAGS) $(LDFLAGS) -o $@
@@ -896,11 +896,11 @@
 AM_V_GEN = $(am__v_GEN_@AM_V@)
 am__v_GEN_ = $(am__v_GEN_@AM_DEFAULT_V@)
 am__v_GEN_0 = @echo "  GEN     " $@;
-am__v_GEN_1 = 
+am__v_GEN_1 =
 AM_V_at = $(am__v_at_@AM_V@)
 am__v_at_ = $(am__v_at_@AM_DEFAULT_V@)
 am__v_at_0 = @
-am__v_at_1 = 
+am__v_at_1 =
 DEFAULT_INCLUDES = -I.@am__isrc@ -I$(top_builddir)
 depcomp = $(SHELL) $(top_srcdir)/build/depcomp
 am__depfiles_maybe = depfiles
@@ -914,7 +914,7 @@
 AM_V_CC = $(am__v_CC_@AM_V@)
 am__v_CC_ = $(am__v_CC_@AM_DEFAULT_V@)
 am__v_CC_0 = @echo "  CC      " $@;
-am__v_CC_1 = 
+am__v_CC_1 =
 CCLD = $(CC)
 LINK = $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) \
 	$(LIBTOOLFLAGS) --mode=link $(CCLD) $(AM_CFLAGS) $(CFLAGS) \
@@ -922,7 +922,7 @@
 AM_V_CCLD = $(am__v_CCLD_@AM_V@)
 am__v_CCLD_ = $(am__v_CCLD_@AM_DEFAULT_V@)
 am__v_CCLD_0 = @echo "  CCLD    " $@;
-am__v_CCLD_1 = 
+am__v_CCLD_1 =
 CXXCOMPILE = $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) \
 	$(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS)
 LTCXXCOMPILE = $(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) \
@@ -932,7 +932,7 @@
 AM_V_CXX = $(am__v_CXX_@AM_V@)
 am__v_CXX_ = $(am__v_CXX_@AM_DEFAULT_V@)
 am__v_CXX_0 = @echo "  CXX     " $@;
-am__v_CXX_1 = 
+am__v_CXX_1 =
 CXXLD = $(CXX)
 CXXLINK = $(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) \
 	$(LIBTOOLFLAGS) --mode=link $(CXXLD) $(AM_CXXFLAGS) \
@@ -940,7 +940,7 @@
 AM_V_CXXLD = $(am__v_CXXLD_@AM_V@)
 am__v_CXXLD_ = $(am__v_CXXLD_@AM_DEFAULT_V@)
 am__v_CXXLD_0 = @echo "  CXXLD   " $@;
-am__v_CXXLD_1 = 
+am__v_CXXLD_1 =
 SOURCES = $(libcairo_la_SOURCES) $(nodist_libcairo_la_SOURCES) \
 	$(libcairo_cxx_la_SOURCES) check-link.c
 DIST_SOURCES = $(am__libcairo_la_SOURCES_DIST) \
@@ -1177,7 +1177,7 @@
 CAIROBOILERPLATE_LIBS = @CAIROBOILERPLATE_LIBS@
 CAIRO_CFLAGS = @CAIRO_CFLAGS@
 CAIRO_LDFLAGS = @CAIRO_LDFLAGS@
-CAIRO_LIBS = @CAIRO_LIBS@
+CAIRO_LIBS = @CAIRO_LIBS@ -llog
 CAIRO_LIBTOOL_VERSION_INFO = @CAIRO_LIBTOOL_VERSION_INFO@
 CAIRO_NONPKGCONFIG_CFLAGS = @CAIRO_NONPKGCONFIG_CFLAGS@
 CAIRO_NONPKGCONFIG_LIBS = @CAIRO_NONPKGCONFIG_LIBS@
@@ -1390,7 +1390,7 @@
 	cairo-supported-features.h
 EXTRA_DIST = Makefile.win32 Makefile.win32.features $(TESTS_SH) \
 	check-has-hidden-symbols.c check-doc-syntax.awk
-EXTRA_LTLIBRARIES = 
+EXTRA_LTLIBRARIES =
 MAINTAINERCLEANFILES = Makefile.in
 cairo_headers = cairo.h cairo-deprecated.h
 cairo_private = cairoint.h cairo-analysis-surface-private.h \
@@ -1901,7 +1901,7 @@
 cairoinclude_HEADERS = $(enabled_cairo_headers) \
 	$(top_srcdir)/cairo-version.h
 lib_LTLIBRARIES = libcairo.la
-@BUILD_CXX_FALSE@cairo_cxx_lib = 
+@BUILD_CXX_FALSE@cairo_cxx_lib =
 @BUILD_CXX_TRUE@cairo_cxx_lib = libcairo_cxx.la
 noinst_LTLIBRARIES = $(cairo_cxx_lib)
 libcairo_cxx_la_SOURCES = \
@@ -2103,10 +2103,10 @@
 	  rm -f $${locs}; \
 	}
 
-libcairo.la: $(libcairo_la_OBJECTS) $(libcairo_la_DEPENDENCIES) $(EXTRA_libcairo_la_DEPENDENCIES) 
+libcairo.la: $(libcairo_la_OBJECTS) $(libcairo_la_DEPENDENCIES) $(EXTRA_libcairo_la_DEPENDENCIES)
 	$(AM_V_CCLD)$(libcairo_la_LINK) -rpath $(libdir) $(libcairo_la_OBJECTS) $(libcairo_la_LIBADD) $(LIBS)
 
-libcairo_cxx.la: $(libcairo_cxx_la_OBJECTS) $(libcairo_cxx_la_DEPENDENCIES) $(EXTRA_libcairo_cxx_la_DEPENDENCIES) 
+libcairo_cxx.la: $(libcairo_cxx_la_OBJECTS) $(libcairo_cxx_la_DEPENDENCIES) $(EXTRA_libcairo_cxx_la_DEPENDENCIES)
 	$(AM_V_CXXLD)$(libcairo_cxx_la_LINK) $(am_libcairo_cxx_la_rpath) $(libcairo_cxx_la_OBJECTS) $(libcairo_cxx_la_LIBADD) $(LIBS)
 
 clean-checkPROGRAMS:
@@ -2118,7 +2118,7 @@
 	echo " rm -f" $$list; \
 	rm -f $$list
 
-check-link$(EXEEXT): $(check_link_OBJECTS) $(check_link_DEPENDENCIES) $(EXTRA_check_link_DEPENDENCIES) 
+check-link$(EXEEXT): $(check_link_OBJECTS) $(check_link_DEPENDENCIES) $(EXTRA_check_link_DEPENDENCIES)
 	@rm -f check-link$(EXEEXT)
 	$(AM_V_CCLD)$(LINK) $(check_link_OBJECTS) $(check_link_LDADD) $(LIBS)
 
diff -uNr cairo-1.16.0/src/Makefile.sources cairo-1.16.0.mod/src/Makefile.sources
--- cairo-1.16.0/src/Makefile.sources	2018-10-18 03:21:03.000000000 +0300
+++ cairo-1.16.0.mod/src/Makefile.sources	2019-08-16 20:37:14.959310422 +0300
@@ -240,6 +240,7 @@
 	cairo-version.c \
 	cairo-wideint.c \
 	cairo.c \
+	android-shmem.c \
 	$(NULL)
 
 _cairo_font_subset_private = \