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 +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#define __u32 uint32_t +#include + +#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 = ¬hing, .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 = ¬hing_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 = ¬hing, .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 = ¬hing_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 +#include +#include + +__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 -#include #include #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 #include -#include #include #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 #include -#include #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 #endif #include -#include #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 = \