Merge "Apply restorecon_recursive to all of /data."
diff --git a/adb/file_sync_service.c b/adb/file_sync_service.c
index 577fb8f..e981c2a 100644
--- a/adb/file_sync_service.c
+++ b/adb/file_sync_service.c
@@ -68,7 +68,7 @@
*x = '/';
return ret;
}
- selinux_android_restorecon(name);
+ selinux_android_restorecon(name, 0);
}
*x++ = '/';
}
@@ -246,7 +246,7 @@
if(fd >= 0) {
struct utimbuf u;
adb_close(fd);
- selinux_android_restorecon(path);
+ selinux_android_restorecon(path, 0);
u.actime = timestamp;
u.modtime = timestamp;
utime(path, &u);
diff --git a/charger/charger.c b/charger/charger.c
index 66ddeaf..8f9169d 100644
--- a/charger/charger.c
+++ b/charger/charger.c
@@ -47,6 +47,8 @@
#include "minui/minui.h"
+char *locale;
+
#ifndef max
#define max(a,b) ((a) > (b) ? (a) : (b))
#endif
diff --git a/debuggerd/Android.mk b/debuggerd/Android.mk
index e0a2d96..77fcbe0 100644
--- a/debuggerd/Android.mk
+++ b/debuggerd/Android.mk
@@ -1,60 +1,14 @@
-# Copyright 2005 The Android Open Source Project
-
LOCAL_PATH:= $(call my-dir)
-include $(CLEAR_VARS)
-LOCAL_SRC_FILES:= \
- backtrace.cpp \
- debuggerd.cpp \
- getevent.cpp \
- tombstone.cpp \
- utility.cpp \
- $(TARGET_ARCH)/machine.cpp \
+debuggerd_2nd_arch_var_prefix :=
+include $(LOCAL_PATH)/debuggerd.mk
-LOCAL_CONLYFLAGS := -std=gnu99
-LOCAL_CPPFLAGS := -std=gnu++11
-LOCAL_CFLAGS := \
- -Wall \
- -Wno-array-bounds \
- -Werror \
- -Wno-unused-parameter \
-
-ifeq ($(TARGET_IS_64_BIT),true)
- LOCAL_MODULE := debuggerd64
-else
- LOCAL_MODULE := debuggerd
+ifdef TARGET_2ND_ARCH
+debuggerd_2nd_arch_var_prefix := $(TARGET_2ND_ARCH_VAR_PREFIX)
+include $(LOCAL_PATH)/debuggerd.mk
endif
ifeq ($(ARCH_ARM_HAVE_VFP),true)
-LOCAL_CFLAGS += -DWITH_VFP
-endif # ARCH_ARM_HAVE_VFP
-ifeq ($(ARCH_ARM_HAVE_VFP_D32),true)
-LOCAL_CFLAGS += -DWITH_VFP_D32
-endif # ARCH_ARM_HAVE_VFP_D32
-
-LOCAL_SHARED_LIBRARIES := \
- libbacktrace \
- libc \
- libcutils \
- liblog \
- libselinux \
-
-include external/stlport/libstlport.mk
-
-include $(BUILD_EXECUTABLE)
-
-include $(CLEAR_VARS)
-LOCAL_SRC_FILES := crasher.c
-LOCAL_SRC_FILES += $(TARGET_ARCH)/crashglue.S
-LOCAL_MODULE := crasher
-LOCAL_MODULE_PATH := $(TARGET_OUT_OPTIONAL_EXECUTABLES)
-LOCAL_MODULE_TAGS := optional
-LOCAL_CFLAGS += -fstack-protector-all -Wno-unused-parameter -Wno-free-nonheap-object
-#LOCAL_FORCE_STATIC_EXECUTABLE := true
-LOCAL_SHARED_LIBRARIES := libcutils liblog libc
-include $(BUILD_EXECUTABLE)
-
-ifeq ($(ARCH_ARM_HAVE_VFP),true)
include $(CLEAR_VARS)
LOCAL_CFLAGS += -DWITH_VFP
@@ -62,10 +16,20 @@
LOCAL_CFLAGS += -DWITH_VFP_D32
endif # ARCH_ARM_HAVE_VFP_D32
-LOCAL_SRC_FILES := vfp-crasher.c $(TARGET_ARCH)/vfp.S
+LOCAL_SRC_FILES := vfp-crasher.c arm/vfp.S
LOCAL_MODULE := vfp-crasher
LOCAL_MODULE_PATH := $(TARGET_OUT_OPTIONAL_EXECUTABLES)
LOCAL_MODULE_TAGS := optional
LOCAL_SHARED_LIBRARIES := libcutils liblog libc
+LOCAL_MODULE_TARGET_ARCH := arm
include $(BUILD_EXECUTABLE)
endif # ARCH_ARM_HAVE_VFP == true
+
+include $(CLEAR_VARS)
+LOCAL_SRC_FILES := vfp-crasher.c arm64/vfp.S
+LOCAL_MODULE := vfp-crasher64
+LOCAL_MODULE_PATH := $(TARGET_OUT_OPTIONAL_EXECUTABLES)
+LOCAL_MODULE_TAGS := optional
+LOCAL_SHARED_LIBRARIES := libcutils liblog libc
+LOCAL_MODULE_TARGET_ARCH := arm64
+include $(BUILD_EXECUTABLE)
diff --git a/debuggerd/debuggerd.cpp b/debuggerd/debuggerd.cpp
index c39aaf6..a2b164e 100644
--- a/debuggerd/debuggerd.cpp
+++ b/debuggerd/debuggerd.cpp
@@ -46,12 +46,12 @@
#include "tombstone.h"
#include "utility.h"
-typedef struct {
+struct debugger_request_t {
debugger_action_t action;
pid_t pid, tid;
uid_t uid, gid;
uintptr_t abort_msg_address;
-} debugger_request_t;
+};
static int write_string(const char* file, const char* string) {
int len;
@@ -116,7 +116,7 @@
dit,_,dit,_,dit,___,dah,_,dah,_,dah,___,dit,_,dit,_,dit,_______
};
size_t s = 0;
- struct input_event e;
+ input_event e;
bool done = false;
init_debug_led();
enable_debug_led();
@@ -176,8 +176,8 @@
}
static int read_request(int fd, debugger_request_t* out_request) {
- struct ucred cr;
- int len = sizeof(cr);
+ ucred cr;
+ socklen_t len = sizeof(cr);
int status = getsockopt(fd, SOL_SOCKET, SO_PEERCRED, &cr, &len);
if (status != 0) {
LOG("cannot get credentials\n");
@@ -187,7 +187,7 @@
XLOG("reading tid\n");
fcntl(fd, F_SETFL, O_NONBLOCK);
- struct pollfd pollfds[1];
+ pollfd pollfds[1];
pollfds[0].fd = fd;
pollfds[0].events = POLLIN;
pollfds[0].revents = 0;
@@ -441,13 +441,11 @@
LOG("debuggerd: " __DATE__ " " __TIME__ "\n");
for (;;) {
- struct sockaddr addr;
- socklen_t alen;
- int fd;
+ sockaddr addr;
+ socklen_t alen = sizeof(addr);
- alen = sizeof(addr);
XLOG("waiting for connection\n");
- fd = accept(s, &addr, &alen);
+ int fd = accept(s, &addr, &alen);
if (fd < 0) {
XLOG("accept failed: %s\n", strerror(errno));
continue;
diff --git a/debuggerd/debuggerd.mk b/debuggerd/debuggerd.mk
new file mode 100644
index 0000000..a3982c1
--- /dev/null
+++ b/debuggerd/debuggerd.mk
@@ -0,0 +1,75 @@
+# Copyright 2005 The Android Open Source Project
+
+LOCAL_PATH:= $(call my-dir)
+include $(CLEAR_VARS)
+
+LOCAL_SRC_FILES:= \
+ backtrace.cpp \
+ debuggerd.cpp \
+ getevent.cpp \
+ tombstone.cpp \
+ utility.cpp \
+
+LOCAL_SRC_FILES_arm := arm/machine.cpp
+LOCAL_SRC_FILES_arm64 := arm64/machine.cpp
+LOCAL_SRC_FILES_mips := mips/machine.cpp
+LOCAL_SRC_FILES_x86 := x86/machine.cpp
+LOCAL_SRC_FILES_x86_64 := x86_64/machine.cpp
+
+LOCAL_CONLYFLAGS := -std=gnu99
+LOCAL_CPPFLAGS := -std=gnu++11
+LOCAL_CFLAGS := \
+ -Wall \
+ -Wno-array-bounds \
+ -Werror \
+ -Wno-unused-parameter \
+
+ifeq ($(ARCH_ARM_HAVE_VFP),true)
+LOCAL_CFLAGS_arm += -DWITH_VFP
+endif # ARCH_ARM_HAVE_VFP
+ifeq ($(ARCH_ARM_HAVE_VFP_D32),true)
+LOCAL_CFLAGS_arm += -DWITH_VFP_D32
+endif # ARCH_ARM_HAVE_VFP_D32
+
+LOCAL_SHARED_LIBRARIES := \
+ libbacktrace \
+ libc \
+ libcutils \
+ liblog \
+ libselinux \
+
+include external/stlport/libstlport.mk
+
+ifeq ($(TARGET_IS_64_BIT)|$(debuggerd_2nd_arch_var_prefix),true|)
+LOCAL_MODULE := debuggerd64
+LOCAL_NO_2ND_ARCH := true
+else
+LOCAL_MODULE := debuggerd
+LOCAL_32_BIT_ONLY := true
+endif
+
+include $(BUILD_EXECUTABLE)
+
+include $(CLEAR_VARS)
+LOCAL_SRC_FILES := crasher.c
+LOCAL_SRC_FILES_arm := arm/crashglue.S
+LOCAL_SRC_FILES_arm64 := arm64/crashglue.S
+LOCAL_SRC_FILES_mips := mips/crashglue.S
+LOCAL_SRC_FILES_x86 := x86/crashglue.S
+LOCAL_SRC_FILES_x86_64 := x86_64/crashglue.S
+LOCAL_MODULE_PATH := $(TARGET_OUT_OPTIONAL_EXECUTABLES)
+LOCAL_MODULE_TAGS := optional
+LOCAL_CFLAGS += -fstack-protector-all -Wno-unused-parameter -Wno-free-nonheap-object
+#LOCAL_FORCE_STATIC_EXECUTABLE := true
+LOCAL_SHARED_LIBRARIES := libcutils liblog libc
+
+LOCAL_2ND_ARCH_VAR_PREFIX := $(debuggerd_2nd_arch_var_prefix)
+
+ifeq ($(TARGET_IS_64_BIT)|$(debuggerd_2nd_arch_var_prefix),true|)
+LOCAL_MODULE := crasher64
+LOCAL_NO_2ND_ARCH := true
+else
+LOCAL_MODULE := crasher
+LOCAL_32_BIT_ONLY := true
+endif
+include $(BUILD_EXECUTABLE)
diff --git a/debuggerd/tombstone.cpp b/debuggerd/tombstone.cpp
index c630020..6a1b963 100755
--- a/debuggerd/tombstone.cpp
+++ b/debuggerd/tombstone.cpp
@@ -55,11 +55,6 @@
// Must match the path defined in NativeCrashListener.java
#define NCRASH_SOCKET_PATH "/data/system/ndebugsocket"
-#define typecheck(x,y) { \
- typeof(x) __dummy1; \
- typeof(y) __dummy2; \
- (void)(&__dummy1 == &__dummy2); }
-
static bool signal_has_address(int sig) {
switch (sig) {
case SIGILL:
@@ -653,28 +648,19 @@
//
// Returns the path of the tombstone file, allocated using malloc(). Caller must free() it.
static char* find_and_open_tombstone(int* fd) {
-#ifdef __aarch64__
- long mtime = LONG_MAX;
-#else
- unsigned long mtime = ULONG_MAX;
-#endif
- struct stat sb;
-
- // XXX: Our stat.st_mtime isn't time_t. If it changes, as it probably ought
- // to, our logic breaks. This check will generate a warning if that happens.
- typecheck(mtime, sb.st_mtime);
-
- // In a single wolf-like pass, find an available slot and, in case none
+ // In a single pass, find an available slot and, in case none
// exist, find and record the least-recently-modified file.
char path[128];
- int oldest = 0;
+ int oldest = -1;
+ struct stat oldest_sb;
for (int i = 0; i < MAX_TOMBSTONES; i++) {
snprintf(path, sizeof(path), TOMBSTONE_TEMPLATE, i);
+ struct stat sb;
if (!stat(path, &sb)) {
- if (sb.st_mtime < mtime) {
+ if (oldest < 0 || sb.st_mtime < oldest_sb.st_mtime) {
oldest = i;
- mtime = sb.st_mtime;
+ oldest_sb.st_mtime = sb.st_mtime;
}
continue;
}
@@ -689,6 +675,11 @@
return strdup(path);
}
+ if (oldest < 0) {
+ LOG("Failed to find a valid tombstone, default to using tombstone 0.\n");
+ oldest = 0;
+ }
+
// we didn't find an available file, so we clobber the oldest one
snprintf(path, sizeof(path), TOMBSTONE_TEMPLATE, oldest);
*fd = open(path, O_CREAT | O_TRUNC | O_WRONLY, 0600);
@@ -741,7 +732,7 @@
LOG("failed to change ownership of %s: %s\n", TOMBSTONE_DIR, strerror(errno));
}
- if (selinux_android_restorecon(TOMBSTONE_DIR) == -1) {
+ if (selinux_android_restorecon(TOMBSTONE_DIR, 0) == -1) {
*detach_failed = false;
return NULL;
}
diff --git a/fs_mgr/fs_mgr.c b/fs_mgr/fs_mgr.c
index 4c2f247..dcda005 100644
--- a/fs_mgr/fs_mgr.c
+++ b/fs_mgr/fs_mgr.c
@@ -116,15 +116,24 @@
umount(target);
}
- INFO("Running %s on %s\n", E2FSCK_BIN, blk_device);
+ /*
+ * Some system images do not have e2fsck for licensing reasons
+ * (e.g. recent SDK system images). Detect these and skip the check.
+ */
+ if (access(E2FSCK_BIN, X_OK)) {
+ INFO("Not running %s on %s (executable not in system image)\n",
+ E2FSCK_BIN, blk_device);
+ } else {
+ INFO("Running %s on %s\n", E2FSCK_BIN, blk_device);
- ret = android_fork_execvp_ext(ARRAY_SIZE(e2fsck_argv), e2fsck_argv,
- &status, true, LOG_KLOG | LOG_FILE,
- true, FSCK_LOG_FILE);
+ ret = android_fork_execvp_ext(ARRAY_SIZE(e2fsck_argv), e2fsck_argv,
+ &status, true, LOG_KLOG | LOG_FILE,
+ true, FSCK_LOG_FILE);
- if (ret < 0) {
- /* No need to check for error in fork, we can't really handle it now */
- ERROR("Failed trying to run %s\n", E2FSCK_BIN);
+ if (ret < 0) {
+ /* No need to check for error in fork, we can't really handle it now */
+ ERROR("Failed trying to run %s\n", E2FSCK_BIN);
+ }
}
}
diff --git a/include/cutils/atomic-inline.h b/include/cutils/atomic-inline.h
index ae79e00..4f90ef1 100644
--- a/include/cutils/atomic-inline.h
+++ b/include/cutils/atomic-inline.h
@@ -47,8 +47,10 @@
#include <cutils/atomic-arm64.h>
#elif defined(__arm__)
#include <cutils/atomic-arm.h>
-#elif defined(__i386__) || defined(__x86_64__)
+#elif defined(__i386__)
#include <cutils/atomic-x86.h>
+#elif defined(__x86_64__)
+#include <cutils/atomic-x86_64.h>
#elif defined(__mips__)
#include <cutils/atomic-mips.h>
#else
diff --git a/include/cutils/atomic-x86_64.h b/include/cutils/atomic-x86_64.h
new file mode 100644
index 0000000..5b5c203
--- /dev/null
+++ b/include/cutils/atomic-x86_64.h
@@ -0,0 +1,226 @@
+/*
+ * Copyright (C) 2014 The Android Open Source Project
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in
+ * the documentation and/or other materials provided with the
+ * distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
+ * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+ * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
+ * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
+ * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
+ * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
+ * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
+ * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#ifndef ANDROID_CUTILS_ATOMIC_X86_64_H
+#define ANDROID_CUTILS_ATOMIC_X86_64_H
+
+#include <stdint.h>
+
+#ifndef ANDROID_ATOMIC_INLINE
+#define ANDROID_ATOMIC_INLINE inline __attribute__((always_inline))
+#endif
+
+extern ANDROID_ATOMIC_INLINE
+void android_compiler_barrier(void)
+{
+ __asm__ __volatile__ ("" : : : "memory");
+}
+
+#if ANDROID_SMP == 0
+extern ANDROID_ATOMIC_INLINE
+void android_memory_barrier(void)
+{
+ android_compiler_barrier();
+}
+extern ANDROID_ATOMIC_INLINE
+void android_memory_store_barrier(void)
+{
+ android_compiler_barrier();
+}
+#else
+extern ANDROID_ATOMIC_INLINE
+void android_memory_barrier(void)
+{
+ __asm__ __volatile__ ("mfence" : : : "memory");
+}
+extern ANDROID_ATOMIC_INLINE
+void android_memory_store_barrier(void)
+{
+ android_compiler_barrier();
+}
+#endif
+
+extern ANDROID_ATOMIC_INLINE
+int32_t android_atomic_acquire_load(volatile const int32_t *ptr)
+{
+ int32_t value = *ptr;
+ android_compiler_barrier();
+ return value;
+}
+
+extern ANDROID_ATOMIC_INLINE
+int64_t android_atomic_acquire_load64(volatile const int64_t *ptr)
+{
+ int64_t value = *ptr;
+ android_compiler_barrier();
+ return value;
+}
+
+extern ANDROID_ATOMIC_INLINE
+int32_t android_atomic_release_load(volatile const int32_t *ptr)
+{
+ android_memory_barrier();
+ return *ptr;
+}
+
+extern ANDROID_ATOMIC_INLINE
+int64_t android_atomic_release_load64(volatile const int64_t *ptr)
+{
+ android_memory_barrier();
+ return *ptr;
+}
+
+extern ANDROID_ATOMIC_INLINE
+void android_atomic_acquire_store(int32_t value, volatile int32_t *ptr)
+{
+ *ptr = value;
+ android_memory_barrier();
+}
+
+extern ANDROID_ATOMIC_INLINE
+void android_atomic_acquire_store64(int64_t value, volatile int64_t *ptr)
+{
+ *ptr = value;
+ android_memory_barrier();
+}
+
+extern ANDROID_ATOMIC_INLINE
+void android_atomic_release_store(int32_t value, volatile int32_t *ptr)
+{
+ android_compiler_barrier();
+ *ptr = value;
+}
+
+extern ANDROID_ATOMIC_INLINE
+void android_atomic_release_store64(int64_t value, volatile int64_t *ptr)
+{
+ android_compiler_barrier();
+ *ptr = value;
+}
+
+extern ANDROID_ATOMIC_INLINE
+int android_atomic_cas(int32_t old_value, int32_t new_value,
+ volatile int32_t *ptr)
+{
+ int32_t prev;
+ __asm__ __volatile__ ("lock; cmpxchgl %1, %2"
+ : "=a" (prev)
+ : "q" (new_value), "m" (*ptr), "0" (old_value)
+ : "memory");
+ return prev != old_value;
+}
+
+extern ANDROID_ATOMIC_INLINE
+int64_t android_atomic_cas64(int64_t old_value, int64_t new_value,
+ volatile int64_t *ptr)
+{
+ int64_t prev;
+ __asm__ __volatile__ ("lock; cmpxchgq %1, %2"
+ : "=a" (prev)
+ : "q" (new_value), "m" (*ptr), "0" (old_value)
+ : "memory");
+ return prev != old_value;
+}
+
+extern ANDROID_ATOMIC_INLINE
+int android_atomic_acquire_cas(int32_t old_value, int32_t new_value,
+ volatile int32_t *ptr)
+{
+ /* Loads are not reordered with other loads. */
+ return android_atomic_cas(old_value, new_value, ptr);
+}
+
+extern ANDROID_ATOMIC_INLINE
+int64_t android_atomic_acquire_cas64(int64_t old_value, int64_t new_value,
+ volatile int64_t *ptr)
+{
+ /* Loads are not reordered with other loads. */
+ return android_atomic_cas64(old_value, new_value, ptr);
+}
+
+extern ANDROID_ATOMIC_INLINE
+int android_atomic_release_cas(int32_t old_value, int32_t new_value,
+ volatile int32_t *ptr)
+{
+ /* Stores are not reordered with other stores. */
+ return android_atomic_cas(old_value, new_value, ptr);
+}
+
+extern ANDROID_ATOMIC_INLINE
+int64_t android_atomic_release_cas64(int64_t old_value, int64_t new_value,
+ volatile int64_t *ptr)
+{
+ /* Stores are not reordered with other stores. */
+ return android_atomic_cas64(old_value, new_value, ptr);
+}
+
+extern ANDROID_ATOMIC_INLINE
+int32_t android_atomic_add(int32_t increment, volatile int32_t *ptr)
+{
+ __asm__ __volatile__ ("lock; xaddl %0, %1"
+ : "+r" (increment), "+m" (*ptr)
+ : : "memory");
+ /* increment now holds the old value of *ptr */
+ return increment;
+}
+
+extern ANDROID_ATOMIC_INLINE
+int32_t android_atomic_inc(volatile int32_t *addr)
+{
+ return android_atomic_add(1, addr);
+}
+
+extern ANDROID_ATOMIC_INLINE
+int32_t android_atomic_dec(volatile int32_t *addr)
+{
+ return android_atomic_add(-1, addr);
+}
+
+extern ANDROID_ATOMIC_INLINE
+int32_t android_atomic_and(int32_t value, volatile int32_t *ptr)
+{
+ int32_t prev, status;
+ do {
+ prev = *ptr;
+ status = android_atomic_cas(prev, prev & value, ptr);
+ } while (__builtin_expect(status != 0, 0));
+ return prev;
+}
+
+extern ANDROID_ATOMIC_INLINE
+int32_t android_atomic_or(int32_t value, volatile int32_t *ptr)
+{
+ int32_t prev, status;
+ do {
+ prev = *ptr;
+ status = android_atomic_cas(prev, prev | value, ptr);
+ } while (__builtin_expect(status != 0, 0));
+ return prev;
+}
+
+#endif /* ANDROID_CUTILS_ATOMIC_X86_64_H */
diff --git a/include/cutils/klog.h b/include/cutils/klog.h
index ba728ac..4bcdd09 100644
--- a/include/cutils/klog.h
+++ b/include/cutils/klog.h
@@ -18,6 +18,7 @@
#define _CUTILS_KLOG_H_
#include <sys/cdefs.h>
+#include <stdarg.h>
__BEGIN_DECLS
@@ -26,14 +27,21 @@
void klog_close(void);
void klog_write(int level, const char *fmt, ...)
__attribute__ ((format(printf, 2, 3)));
+void klog_vwrite(int level, const char *fmt, va_list ap);
__END_DECLS
-#define KLOG_ERROR(tag,x...) klog_write(3, "<3>" tag ": " x)
-#define KLOG_WARNING(tag,x...) klog_write(4, "<4>" tag ": " x)
-#define KLOG_NOTICE(tag,x...) klog_write(5, "<5>" tag ": " x)
-#define KLOG_INFO(tag,x...) klog_write(6, "<6>" tag ": " x)
-#define KLOG_DEBUG(tag,x...) klog_write(7, "<7>" tag ": " x)
+#define KLOG_ERROR_LEVEL 3
+#define KLOG_WARNING_LEVEL 4
+#define KLOG_NOTICE_LEVEL 5
+#define KLOG_INFO_LEVEL 6
+#define KLOG_DEBUG_LEVEL 7
+
+#define KLOG_ERROR(tag,x...) klog_write(KLOG_ERROR_LEVEL, "<3>" tag ": " x)
+#define KLOG_WARNING(tag,x...) klog_write(KLOG_WARNING_LEVEL, "<4>" tag ": " x)
+#define KLOG_NOTICE(tag,x...) klog_write(KLOG_NOTICE_LEVEL, "<5>" tag ": " x)
+#define KLOG_INFO(tag,x...) klog_write(KLOG_INFO_LEVEL, "<6>" tag ": " x)
+#define KLOG_DEBUG(tag,x...) klog_write(KLOG_DEBUG_LEVEL, "<7>" tag ": " x)
#define KLOG_DEFAULT_LEVEL 3 /* messages <= this level are logged */
diff --git a/include/log/log.h b/include/log/log.h
index 7f952ff..d469f40 100644
--- a/include/log/log.h
+++ b/include/log/log.h
@@ -73,10 +73,11 @@
* Simplified macro to send a verbose log message using the current LOG_TAG.
*/
#ifndef ALOGV
+#define __ALOGV(...) ((void)ALOG(LOG_VERBOSE, LOG_TAG, __VA_ARGS__))
#if LOG_NDEBUG
-#define ALOGV(...) ((void)0)
+#define ALOGV(...) do { if (0) { __ALOGV(__VA_ARGS__); } } while (0)
#else
-#define ALOGV(...) ((void)ALOG(LOG_VERBOSE, LOG_TAG, __VA_ARGS__))
+#define ALOGV(...) __ALOGV(__VA_ARGS__)
#endif
#endif
@@ -202,10 +203,11 @@
* Simplified macro to send a verbose system log message using the current LOG_TAG.
*/
#ifndef SLOGV
+#define __SLOGV(...) ((void)__android_log_buf_print(LOG_ID_SYSTEM, ANDROID_LOG_VERBOSE, LOG_TAG, __VA_ARGS__))
#if LOG_NDEBUG
-#define SLOGV(...) ((void)0)
+#define SLOGV(...) do { if (0) { __SLOGV(__VA_ARGS__); } } while (0)
#else
-#define SLOGV(...) ((void)__android_log_buf_print(LOG_ID_SYSTEM, ANDROID_LOG_VERBOSE, LOG_TAG, __VA_ARGS__))
+#define SLOGV(...) __SLOGV(__VA_ARGS__)
#endif
#endif
@@ -284,10 +286,11 @@
* Simplified macro to send a verbose radio log message using the current LOG_TAG.
*/
#ifndef RLOGV
+#define __RLOGV(...) ((void)__android_log_buf_print(LOG_ID_RADIO, ANDROID_LOG_VERBOSE, LOG_TAG, __VA_ARGS__))
#if LOG_NDEBUG
-#define RLOGV(...) ((void)0)
+#define RLOGV(...) do { if (0) { __RLOGV(__VA_ARGS__); } } while (0)
#else
-#define RLOGV(...) ((void)__android_log_buf_print(LOG_ID_RADIO, ANDROID_LOG_VERBOSE, LOG_TAG, __VA_ARGS__))
+#define RLOGV(...) __RLOGV(__VA_ARGS__)
#endif
#endif
@@ -557,7 +560,11 @@
* Send a simple string to the log.
*/
int __android_log_buf_write(int bufID, int prio, const char *tag, const char *text);
-int __android_log_buf_print(int bufID, int prio, const char *tag, const char *fmt, ...);
+int __android_log_buf_print(int bufID, int prio, const char *tag, const char *fmt, ...)
+#if defined(__GNUC__)
+ __attribute__((__format__(printf, 4, 5)))
+#endif
+ ;
#ifdef __cplusplus
}
diff --git a/include/log/log_read.h b/include/log/log_read.h
index 861c192..2601622 100644
--- a/include/log/log_read.h
+++ b/include/log/log_read.h
@@ -23,12 +23,12 @@
#ifdef __cplusplus
struct log_time : public timespec {
public:
- log_time(timespec &T)
+ log_time(const timespec &T)
{
tv_sec = T.tv_sec;
tv_nsec = T.tv_nsec;
}
- log_time(void)
+ log_time()
{
}
log_time(clockid_t id)
@@ -67,7 +67,7 @@
{
return !(*this > T);
}
- uint64_t nsec(void) const
+ uint64_t nsec() const
{
return static_cast<uint64_t>(tv_sec) * NS_PER_SEC + tv_nsec;
}
diff --git a/include/log/logger.h b/include/log/logger.h
index 966397a..6414d84 100644
--- a/include/log/logger.h
+++ b/include/log/logger.h
@@ -35,7 +35,7 @@
/*
* The userspace structure for version 2 of the logger_entry ABI.
* This structure is returned to userspace if ioctl(LOGGER_SET_VERSION)
- * is called with version==2
+ * is called with version==2; or used with the user space log daemon.
*/
struct logger_entry_v2 {
uint16_t len; /* length of the payload */
@@ -48,6 +48,17 @@
char msg[0]; /* the entry's payload */
};
+struct logger_entry_v3 {
+ uint16_t len; /* length of the payload */
+ uint16_t hdr_size; /* sizeof(struct logger_entry_v2) */
+ int32_t pid; /* generating process's pid */
+ int32_t tid; /* generating process's tid */
+ int32_t sec; /* seconds since Epoch */
+ int32_t nsec; /* nanoseconds */
+ uint32_t lid; /* log id of the payload */
+ char msg[0]; /* the entry's payload */
+};
+
/*
* The maximum size of the log entry payload that can be
* written to the kernel logger driver. An attempt to write
@@ -69,6 +80,7 @@
union {
unsigned char buf[LOGGER_ENTRY_MAX_LEN + 1];
struct logger_entry_v2 entry;
+ struct logger_entry_v3 entry_v3;
struct logger_entry_v2 entry_v2;
struct logger_entry entry_v1;
struct {
@@ -106,21 +118,21 @@
{
return !(*this > T);
}
- uint64_t nsec(void) const
+ uint64_t nsec() const
{
return static_cast<uint64_t>(entry.sec) * NS_PER_SEC + entry.nsec;
}
/* packet methods */
- log_id_t id(void)
+ log_id_t id()
{
return extra.id;
}
- char *msg(void)
+ char *msg()
{
return entry.hdr_size ? (char *) buf + entry.hdr_size : entry_v1.msg;
}
- unsigned int len(void)
+ unsigned int len()
{
return (entry.hdr_size ? entry.hdr_size : sizeof(entry_v1)) + entry.len;
}
diff --git a/include/private/android_filesystem_config.h b/include/private/android_filesystem_config.h
index 0ed0d78..9c26baf 100644
--- a/include/private/android_filesystem_config.h
+++ b/include/private/android_filesystem_config.h
@@ -76,6 +76,7 @@
#define AID_SDCARD_PICS 1033 /* external storage photos access */
#define AID_SDCARD_AV 1034 /* external storage audio/video access */
#define AID_SDCARD_ALL 1035 /* access all users external storage */
+#define AID_LOGD 1036 /* log daemon */
#define AID_SHELL 2000 /* adb and debug shell user */
#define AID_CACHE 2001 /* cache access */
@@ -151,6 +152,7 @@
{ "sdcard_pics", AID_SDCARD_PICS, },
{ "sdcard_av", AID_SDCARD_AV, },
{ "sdcard_all", AID_SDCARD_ALL, },
+ { "logd", AID_LOGD, },
{ "shell", AID_SHELL, },
{ "cache", AID_CACHE, },
diff --git a/init/devices.c b/init/devices.c
index f7df453..a70c61d 100644
--- a/init/devices.c
+++ b/init/devices.c
@@ -37,7 +37,6 @@
#include <private/android_filesystem_config.h>
#include <sys/time.h>
-#include <asm/page.h>
#include <sys/wait.h>
#include <cutils/list.h>
diff --git a/init/init.c b/init/init.c
index 0250e97..1473fbc 100644
--- a/init/init.c
+++ b/init/init.c
@@ -934,12 +934,33 @@
return 0;
}
-int audit_callback(void *data, security_class_t cls, char *buf, size_t len)
+static int audit_callback(void *data, security_class_t cls __attribute__((unused)), char *buf, size_t len)
{
snprintf(buf, len, "property=%s", !data ? "NULL" : (char *)data);
return 0;
}
+static int log_callback(int type, const char *fmt, ...)
+{
+ int level;
+ va_list ap;
+ switch (type) {
+ case SELINUX_WARNING:
+ level = KLOG_WARNING_LEVEL;
+ break;
+ case SELINUX_INFO:
+ level = KLOG_INFO_LEVEL;
+ break;
+ default:
+ level = KLOG_ERROR_LEVEL;
+ break;
+ }
+ va_start(ap, fmt);
+ klog_vwrite(level, fmt, ap);
+ va_end(ap);
+ return 0;
+}
+
static void selinux_initialize(void)
{
if (selinux_is_disabled()) {
@@ -1013,7 +1034,7 @@
process_kernel_cmdline();
union selinux_callback cb;
- cb.func_log = klog_write;
+ cb.func_log = log_callback;
selinux_set_callback(SELINUX_CB_LOG, cb);
cb.func_audit = audit_callback;
diff --git a/init/util.c b/init/util.c
index e772342..0f69e1c 100644
--- a/init/util.c
+++ b/init/util.c
@@ -527,10 +527,10 @@
int restorecon(const char* pathname)
{
- return selinux_android_restorecon(pathname);
+ return selinux_android_restorecon(pathname, 0);
}
int restorecon_recursive(const char* pathname)
{
- return selinux_android_restorecon_recursive(pathname);
+ return selinux_android_restorecon(pathname, SELINUX_ANDROID_RESTORECON_RECURSE);
}
diff --git a/libbacktrace/BacktraceMap.cpp b/libbacktrace/BacktraceMap.cpp
index 6320800..6eb290d 100644
--- a/libbacktrace/BacktraceMap.cpp
+++ b/libbacktrace/BacktraceMap.cpp
@@ -93,7 +93,8 @@
}
ALOGV("Parsed map: start=%p, end=%p, flags=%x, name=%s",
- map->start, map->end, map->flags, map->name.c_str());
+ reinterpret_cast<void*>(map->start), reinterpret_cast<void*>(map->end),
+ map->flags, map->name.c_str());
return true;
}
diff --git a/libcutils/klog.c b/libcutils/klog.c
index d69fb10..d3c40df 100644
--- a/libcutils/klog.c
+++ b/libcutils/klog.c
@@ -49,18 +49,24 @@
#define LOG_BUF_MAX 512
-void klog_write(int level, const char *fmt, ...)
+void klog_vwrite(int level, const char *fmt, va_list ap)
{
char buf[LOG_BUF_MAX];
- va_list ap;
if (level > klog_level) return;
if (klog_fd < 0) klog_init();
if (klog_fd < 0) return;
- va_start(ap, fmt);
vsnprintf(buf, LOG_BUF_MAX, fmt, ap);
buf[LOG_BUF_MAX - 1] = 0;
- va_end(ap);
+
write(klog_fd, buf, strlen(buf));
}
+
+void klog_write(int level, const char *fmt, ...)
+{
+ va_list ap;
+ va_start(ap, fmt);
+ klog_vwrite(level, fmt, ap);
+ va_end(ap);
+}
diff --git a/libcutils/socket_local_server.c b/libcutils/socket_local_server.c
index 4971b1b..7628fe4 100644
--- a/libcutils/socket_local_server.c
+++ b/libcutils/socket_local_server.c
@@ -43,6 +43,8 @@
#define LISTEN_BACKLOG 4
+/* Only the bottom bits are really the socket type; there are flags too. */
+#define SOCK_TYPE_MASK 0xf
/**
* Binds a pre-created socket(AF_LOCAL) 's' to 'name'
@@ -107,7 +109,7 @@
return -1;
}
- if (type == SOCK_STREAM) {
+ if ((type & SOCK_TYPE_MASK) == SOCK_STREAM) {
int ret;
ret = listen(s, LISTEN_BACKLOG);
diff --git a/libcutils/tests/Android.mk b/libcutils/tests/Android.mk
deleted file mode 100644
index 6571161..0000000
--- a/libcutils/tests/Android.mk
+++ /dev/null
@@ -1 +0,0 @@
-include $(all-subdir-makefiles)
diff --git a/libcutils/tests/memset_mips/Android.mk b/libcutils/tests/memset_mips/Android.mk
deleted file mode 100644
index c22fca9..0000000
--- a/libcutils/tests/memset_mips/Android.mk
+++ /dev/null
@@ -1,23 +0,0 @@
-# Copyright 2012 The Android Open Source Project
-
-ifeq ($(TARGET_ARCH),mips)
-
-LOCAL_PATH:= $(call my-dir)
-include $(CLEAR_VARS)
-
-LOCAL_SRC_FILES:= \
- test_memset.c \
- android_memset_dumb.S \
- android_memset_test.S \
- memset_cmips.S \
- memset_omips.S
-
-LOCAL_MODULE:= test_memset
-
-LOCAL_FORCE_STATIC_EXECUTABLE := true
-LOCAL_STATIC_LIBRARIES := libcutils libc
-LOCAL_MODULE_TAGS := tests
-
-include $(BUILD_EXECUTABLE)
-
-endif
diff --git a/libcutils/tests/memset_mips/android_memset_dumb.S b/libcutils/tests/memset_mips/android_memset_dumb.S
deleted file mode 100644
index c8a1a37..0000000
--- a/libcutils/tests/memset_mips/android_memset_dumb.S
+++ /dev/null
@@ -1,36 +0,0 @@
- .global android_memset16_dumb
- .type android_memset16_dumb, @function
-android_memset16_dumb:
- .ent android_memset16_dumb
-
- .set noreorder
- beqz $a2,9f
- srl $a2,1
-
-1: sh $a1,($a0)
- subu $a2,1
- bnez $a2,1b
- addu $a0,2
- .set reorder
-
-9: j $ra
- .end android_memset16_dumb
- .size android_memset16_dumb,.-android_memset16_dumb
-
- .global android_memset32_dumb
- .type android_memset32_dumb, @function
-android_memset32_dumb:
- .ent android_memset32_dumb
- .set noreorder
- beqz $a2,9f
- srl $a2,2
-
-1: sw $a1,($a0)
- subu $a2,1
- bnez $a2,1b
- addu $a0,4
- .set reorder
-
-9: j $ra
- .end android_memset32_dumb
- .size android_memset32_dumb,.-android_memset32_dumb
diff --git a/libcutils/tests/memset_mips/android_memset_test.S b/libcutils/tests/memset_mips/android_memset_test.S
deleted file mode 100644
index e918843..0000000
--- a/libcutils/tests/memset_mips/android_memset_test.S
+++ /dev/null
@@ -1,152 +0,0 @@
-/*
- * Copyright (C) 2006 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.
- */
-
-#ifdef NDEBUG
-#define DBG #
-#else
-#define DBG
-#endif
-
- .text
- .align
-
- /*
- * Optimized memset16 for MIPS
- *
- * void android_memset16_test(uint16_t* dst, uint16_t value, size_t size);
- *
- */
-
- .global android_memset16_test
- .type android_memset16_test, @function
-android_memset16_test:
- .ent android_memset16_test
- .set noreorder
-
- /* Check parameters */
-DBG andi $t0,$a0,1 /* $a0 must be halfword aligned */
-DBG tne $t0
-DBG lui $t1,0xffff /* $a1 must be 16bits */
-DBG and $t1,$a1
-DBG tne $t1
-DBG andi $t2,$a2,1 /* $a2 must be even */
-DBG tne $t2
-
-#if (__mips==32) && (__mips_isa_rev>=2)
- ins $a2,$0,0,1
-#else
- li $t0,~1
- and $a2,$t0
-#endif
-
- move $t8,$ra
- blez $a2,9f /* Anything to do? */
- andi $t0,$a0,2 /* Check dst alignment */
- /* Expand value to 32 bits and check destination alignment */
-#if (__mips==32) && (__mips_isa_rev>=2)
- beqz $t0,.Laligned32 /* dst is 32 bit aligned */
- ins $a1,$a1,16,16
-#else
- sll $t2,$a1,16
- beqz $t0,.Laligned32 /* dst is 32 bit aligned */
- or $a1,$t2
-#endif
- sh $a1,($a0) /* do one halfword to get aligned */
- subu $a2,2
- addu $a0,2
-
-.Laligned32:
- and $t1,$a2,63 /* is there enough left to do a full 64 byte loop? */
- beq $a2,$t1,1f
- subu $t2,$a2,$t1 /* $t2 is the number of bytes to do in loop64 */
- addu $t3,$a0,$t2 /* $t3 is the end marker for loop64 */
- subu $a2,$t2
-.Lloop64:
- addu $a0,64
- sw $a1,-64($a0)
- sw $a1,-60($a0)
- sw $a1,-56($a0)
- sw $a1,-52($a0)
- sw $a1,-48($a0)
- sw $a1,-44($a0)
- sw $a1,-40($a0)
- sw $a1,-36($a0)
- sw $a1,-32($a0)
- sw $a1,-28($a0)
- sw $a1,-24($a0)
- sw $a1,-20($a0)
- sw $a1,-16($a0)
- sw $a1,-12($a0)
- sw $a1,-8($a0)
- bne $a0,$t3,.Lloop64
- sw $a1,-4($a0)
-
- /* Do the last 0..62 bytes */
-1: li $t0,64+12
- andi $t1,$a2,0x3c /* $t1 how many bytes to store using sw */
- bal 1f
- subu $t0,$t1 /* 64+12-$t0 is offset to jump from 1f */
-1: addu $ra,$t0
- j $ra
- subu $a2,$t1
-2: sw $a1,60($a0)
- sw $a1,56($a0)
- sw $a1,52($a0)
- sw $a1,48($a0)
- sw $a1,44($a0)
- sw $a1,40($a0)
- sw $a1,36($a0)
- sw $a1,32($a0)
- sw $a1,28($a0)
- sw $a1,24($a0)
- sw $a1,20($a0)
- sw $a1,16($a0)
- sw $a1,12($a0)
- sw $a1,8($a0)
- sw $a1,4($a0)
- sw $a1,0($a0)
-
- beqz $a2,9f
- addu $a0,$t1
- sh $a1,($a0)
-
-9: j $t8
- nop
- .end android_memset16_test
- .size android_memset16_test,.-android_memset16_test
-
- /*
- * Optimized memset32 for MIPS
- *
- * void android_memset32_test(uint32_t* dst, uint32_t value, size_t size);
- *
- */
- .global android_memset32_test
- .type android_memset32_test, @function
-android_memset32_test:
- .ent android_memset32_test
- .set noreorder
-
- /* Check parameters */
-DBG andi $t0,$a0,3 /* $a0 must be word aligned */
-DBG tne $t0
-DBG andi $t2,$a2,3 /* $a2 must be a multiple of 4 bytes */
-DBG tne $t2
-
- b .Laligned32
- move $t8,$ra
- .end android_memset32_test
- .size android_memset32_test,.-android_memset32_test
diff --git a/libcutils/tests/memset_mips/memset_cmips.S b/libcutils/tests/memset_mips/memset_cmips.S
deleted file mode 100644
index f8f3a91..0000000
--- a/libcutils/tests/memset_mips/memset_cmips.S
+++ /dev/null
@@ -1,227 +0,0 @@
-/*
- * Copyright (c) 2009
- * MIPS Technologies, Inc., California.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- * 1. Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- * 2. Redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in the
- * documentation and/or other materials provided with the distribution.
- * 3. Neither the name of the MIPS Technologies, Inc., nor the names of its
- * contributors may be used to endorse or promote products derived from
- * this software without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE MIPS TECHNOLOGIES, INC. ``AS IS'' AND
- * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
- * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
- * ARE DISCLAIMED. IN NO EVENT SHALL THE MIPS TECHNOLOGIES, INC. BE LIABLE
- * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
- * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
- * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
- * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
- * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
- * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
- * SUCH DAMAGE.
- */
-
-/************************************************************************
- *
- * memset.S, version "64h" with 1 cache line horizon for "pref 30" and 14 nops
- * Version: "043009"
- *
- ************************************************************************/
-
-
-/************************************************************************
- * Include files
- ************************************************************************/
-
-#include "machine/asm.h"
-
-/*
- * This routine could be optimized for MIPS64. The current code only
- * uses MIPS32 instructions.
- */
-
-#if defined(__MIPSEB__)
-# define SWHI swl /* high part is left in big-endian */
-#endif
-
-#if defined(__MIPSEL__)
-# define SWHI swr /* high part is right in little-endian */
-#endif
-
-#if !(defined(XGPROF) || defined(XPROF))
-#undef SETUP_GP
-#define SETUP_GP
-#endif
-
-LEAF(memset_cmips,0)
-
- .set noreorder
- .set noat
-
- addu t0,a0,a2 # t0 is the "past the end" address
- slti AT,a2,4 # is a2 less than 4?
- bne AT,zero,.Llast4 # if yes, go to last4
- move v0,a0 # memset returns the dst pointer
-
- beq a1,zero,.Lset0
- subu v1,zero,a0
-
- # smear byte into 32 bit word
-#if (__mips==32) && (__mips_isa_rev>=2)
- ins a1, a1, 8, 8 # Replicate fill byte into half-word.
- ins a1, a1, 16, 16 # Replicate fill byte into word.
-#else
- and a1,0xff
- sll AT,a1,8
- or a1,AT
- sll AT,a1,16
- or a1,AT
-#endif
-
-.Lset0: andi v1,v1,0x3 # word-unaligned address?
- beq v1,zero,.Laligned # v1 is the unalignment count
- subu a2,a2,v1
- SWHI a1,0(a0)
- addu a0,a0,v1
-
-# Here we have the "word-aligned" a0 (until the "last4")
-.Laligned:
- andi t8,a2,0x3f # any 64-byte chunks?
- # t8 is the byte count past 64-byte chunks
- beq a2,t8,.Lchk8w # when a2==t8, no 64-byte chunks
- # There will be at most 1 32-byte chunk then
- subu a3,a2,t8 # subtract from a2 the reminder
- # Here a3 counts bytes in 16w chunks
- addu a3,a0,a3 # Now a3 is the final dst after 64-byte chunks
-
-# Find out, if there are any 64-byte chunks after which will be still at least
-# 96 bytes left. The value "96" is calculated as needed buffer for
-# "pref 30,64(a0)" prefetch, which can be used as "pref 30,0(a0)" after
-# incrementing "a0" by 64.
-# For "a2" below 160 there will be no such "pref 30 safe" 64-byte chunk.
-#
- sltiu v1,a2,160
- bgtz v1,.Lloop16w_nopref30 # skip "pref 30,0(a0)"
- subu t7,a2,96 # subtract "pref 30 unsafe" region
- # below we have at least 1 64-byte chunk which is "pref 30 safe"
- andi t6,t7,0x3f # t6 is past "64-byte safe chunks" reminder
- subu t5,t7,t6 # subtract from t7 the reminder
- # Here t5 counts bytes in 16w "safe" chunks
- addu t4,a0,t5 # Now t4 is the dst after 64-byte "safe" chunks
-
-# Don't use "pref 30,0(a0)" for a0 in a "middle" of a cache line
-# pref 30,0(a0)
-# Here we are in the region, where it is safe to use "pref 30,64(a0)"
-.Lloop16w:
- addiu a0,a0,64
- pref 30,-32(a0) # continue setting up the dest, addr 64-32
- sw a1,-64(a0)
- sw a1,-60(a0)
- sw a1,-56(a0)
- sw a1,-52(a0)
- sw a1,-48(a0)
- sw a1,-44(a0)
- sw a1,-40(a0)
- sw a1,-36(a0)
- nop
- nop # the extra nop instructions help to balance
- nop # cycles needed for "store" + "fill" + "evict"
- nop # For 64byte store there are needed 8 fill
- nop # and 8 evict cycles, i.e. at least 32 instr.
- nop
- nop
- pref 30,0(a0) # continue setting up the dest, addr 64-0
- sw a1,-32(a0)
- sw a1,-28(a0)
- sw a1,-24(a0)
- sw a1,-20(a0)
- sw a1,-16(a0)
- sw a1,-12(a0)
- sw a1,-8(a0)
- sw a1,-4(a0)
- nop
- nop
- nop
- nop # NOTE: adding 14 nop-s instead of 12 nop-s
- nop # gives better results for "fast" memory
- nop
- bne a0,t4,.Lloop16w
- nop
-
- beq a0,a3,.Lchk8w # maybe no more 64-byte chunks?
- nop # this "delayed slot" is useless ...
-
-.Lloop16w_nopref30: # there could be up to 3 "64-byte nopref30" chunks
- addiu a0,a0,64
- sw a1,-64(a0)
- sw a1,-60(a0)
- sw a1,-56(a0)
- sw a1,-52(a0)
- sw a1,-48(a0)
- sw a1,-44(a0)
- sw a1,-40(a0)
- sw a1,-36(a0)
- sw a1,-32(a0)
- sw a1,-28(a0)
- sw a1,-24(a0)
- sw a1,-20(a0)
- sw a1,-16(a0)
- sw a1,-12(a0)
- sw a1,-8(a0)
- bne a0,a3,.Lloop16w_nopref30
- sw a1,-4(a0)
-
-.Lchk8w: # t8 here is the byte count past 64-byte chunks
-
- andi t7,t8,0x1f # is there a 32-byte chunk?
- # the t7 is the reminder count past 32-bytes
- beq t8,t7,.Lchk1w # when t8==t7, no 32-byte chunk
- move a2,t7
-
- sw a1,0(a0)
- sw a1,4(a0)
- sw a1,8(a0)
- sw a1,12(a0)
- sw a1,16(a0)
- sw a1,20(a0)
- sw a1,24(a0)
- sw a1,28(a0)
- addiu a0,a0,32
-
-.Lchk1w:
- andi t8,a2,0x3 # now t8 is the reminder past 1w chunks
- beq a2,t8,.Llast4
- subu a3,a2,t8 # a3 is the count of bytes in 1w chunks
- addu a3,a0,a3 # now a3 is the dst address past the 1w chunks
-
-# copying in words (4-byte chunks)
-.LwordCopy_loop:
- addiu a0,a0,4
- bne a0,a3,.LwordCopy_loop
- sw a1,-4(a0)
-
-.Llast4:beq a0,t0,.Llast4e
-.Llast4l:addiu a0,a0,1
- bne a0,t0,.Llast4l
- sb a1,-1(a0)
-
-.Llast4e:
- j ra
- nop
-
- .set at
- .set reorder
-
-END(memset_cmips)
-
-
-/************************************************************************
- * Implementation : Static functions
- ************************************************************************/
-
diff --git a/libcutils/tests/memset_mips/memset_omips.S b/libcutils/tests/memset_mips/memset_omips.S
deleted file mode 100644
index 4c47001..0000000
--- a/libcutils/tests/memset_mips/memset_omips.S
+++ /dev/null
@@ -1,90 +0,0 @@
-/* Copyright (C) 2002, 2003 Free Software Foundation, Inc.
- This file is part of the GNU C Library.
- Contributed by Hartvig Ekner <hartvige@mips.com>, 2002.
-
- The GNU C Library is free software; you can redistribute it and/or
- modify it under the terms of the GNU Lesser General Public
- License as published by the Free Software Foundation; either
- version 2.1 of the License, or (at your option) any later version.
-
- The GNU C Library is distributed in the hope that it will be useful,
- but WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- Lesser General Public License for more details.
-
- You should have received a copy of the GNU Lesser General Public
- License along with the GNU C Library; if not, write to the Free
- Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
- 02111-1307 USA. */
-
-/* void *memset_omips(void *s, int c, size_t n). */
-
-#include "machine/asm.h"
-
-#ifdef __mips64
-#error mips32 code being compiled for mips64!
-#endif
-
-#if defined(__MIPSEB__)
-#error big-endian is not supported in Broadcom MIPS Android platform
-# define SWHI swl /* high part is left in big-endian */
-#else
-# define SWHI swr /* high part is right in little-endian */
-#endif
-
-LEAF (memset_omips,0)
- .set noreorder
-
- slti t1, a2, 8 # Less than 8?
- bne t1, zero, .Llast8
- move v0, a0 # Setup exit value before too late
-
- beq a1, zero, .Lueven # If zero pattern, no need to extend
- andi a1, 0xff # Avoid problems with bogus arguments
- sll t0, a1, 8
- or a1, t0
- sll t0, a1, 16
- or a1, t0 # a1 is now pattern in full word
-
-.Lueven:
- subu t0, zero, a0 # Unaligned address?
- andi t0, 0x3
- beq t0, zero, .Lchkw
- subu a2, t0
- SWHI a1, 0(a0) # Yes, handle first unaligned part
- addu a0, t0 # Now both a0 and a2 are updated
-
-.Lchkw:
- andi t0, a2, 0x7 # Enough left for one loop iteration?
- beq t0, a2, .Lchkl
- subu a3, a2, t0
- addu a3, a0 # a3 is last loop address +1
- move a2, t0 # a2 is now # of bytes left after loop
-.Lloopw:
- addiu a0, 8 # Handle 2 words pr. iteration
- sw a1, -8(a0)
- bne a0, a3, .Lloopw
- sw a1, -4(a0)
-
-.Lchkl:
- andi t0, a2, 0x4 # Check if there is at least a full
- beq t0, zero, .Llast8 # word remaining after the loop
- subu a2, t0
- sw a1, 0(a0) # Yes...
- addiu a0, 4
-
-.Llast8:
- blez a2, .Lexit # Handle last 8 bytes (if cnt>0)
- addu a3, a2, a0 # a3 is last address +1
-.Llst8l:
- addiu a0, 1
- bne a0, a3, .Llst8l
- sb a1, -1(a0)
-.Lexit:
- j ra # Bye, bye
- nop
-
- .set reorder
-END (memset_omips)
-
-
diff --git a/libcutils/tests/memset_mips/test_memset.c b/libcutils/tests/memset_mips/test_memset.c
deleted file mode 100644
index 9705c65..0000000
--- a/libcutils/tests/memset_mips/test_memset.c
+++ /dev/null
@@ -1,235 +0,0 @@
-#include <stdio.h>
-#include <stdlib.h>
-#include <assert.h>
-#include <cutils/memory.h>
-#include <time.h>
-
-/*
- * All systems must implement or emulate the rdhwr instruction to read
- * the userlocal register. Systems that emulate also return teh count register
- * when accessing register $2 so this should work on most systems
- */
-#define USE_RDHWR
-
-#ifdef USE_RDHWR
-#define UNITS "cycles"
-#define SCALE 2 /* Most CPU's */
-static inline uint32_t
-get_count(void)
-{
- uint32_t res;
- asm volatile (".set push; .set mips32r2; rdhwr %[res],$2; .set pop" : [res] "=r" (res) : : "memory");
- return res;
-}
-#else
-#define UNITS "ns"
-#define SCALE 1
-static inline uint32_t
-get_count(void)
-{
- struct timespec now;
- uint32_t res;
- clock_gettime(CLOCK_REALTIME, &now);
- res = (uint32_t)(now.tv_sec * 1000000000LL + now.tv_nsec);
- // printf ("now=%d.%09d res=%d\n", (int)now.tv_sec, (int)now.tv_nsec, res);
- return res;
-}
-#endif
-
-uint32_t overhead;
-void
-measure_overhead(void)
-{
- int i;
- uint32_t start, stop, delta;
- for (i = 0; i < 32; i++) {
- start = get_count();
- stop = get_count();
- delta = stop - start;
- if (overhead == 0 || delta < overhead)
- overhead = delta;
- }
- printf("overhead is %d"UNITS"\n", overhead);
-}
-
-uint32_t
-timeone(void (*fn)(), void *d, uint32_t val, uint32_t bytes)
-{
- uint32_t start, stop, delta;
- start = get_count();
- (*fn)(d, val, bytes);
- stop = get_count();
- delta = stop - start - overhead;
- // printf ("start=0x%08x stop=0x%08x delta=0x%08x\n", start, stop, delta);
- return delta * SCALE;
-}
-
-/* define VERIFY to check that memset only touches the bytes it's supposed to */
-/*#define VERIFY*/
-
-/*
- * Using a big arena means that memset will most likely miss in the cache
- * NB Enabling verification effectively warms up the cache...
- */
-#define ARENASIZE 0x1000000
-#ifdef VERIFY
-char arena[ARENASIZE+8]; /* Allow space for guard words */
-#else
-char arena[ARENASIZE];
-#endif
-
-void
-testone(char *tag, void (*fn)(), int trials, int minbytes, int maxbytes, int size, int threshold)
-{
- int offset;
- void *d;
- void *p;
- uint32_t v, notv = 0;
- uint32_t n;
- int i, units;
- int totalunits = 0, totalbytes = 0, samples = 0;
-
- /* Reset RNG to ensure each test uses same random values */
- srand(0); /* FIXME should be able to use some other seed than 0 */
-
- for (i = 0; i < trials; i++) {
- n = minbytes + (rand() % (maxbytes-minbytes)); /* How many bytes to do */
- offset = ((rand() % (ARENASIZE-n))); /* Where to start */
-
-#ifdef VERIFY
- offset += 4; /* Allow space for guard word at beginning */
-#endif
- v = rand();
-
- /* Adjust alignment and sizes based on transfer size */
- switch (size) {
- case 1:
- v &= 0xff;
- notv = ~v & 0xff;
- break;
- case 2:
- v &= 0xffff;
- notv = ~v & 0xffff;
- offset &= ~1;
- n &= ~1;
- break;
- case 4:
- notv = ~v;
- offset &= ~3;
- n &= ~3;
- break;
- }
-
- d = &arena[offset];
-
-#ifdef VERIFY
- /* Initialise the area and guard words */
- for (p = &arena[offset-4]; p < (void *)&arena[offset+n+4]; p = (void *)((uint32_t)p + size)) {
- if (size == 1)
- *(uint8_t *)p = notv;
- else if (size == 2)
- *(uint16_t *)p = notv;
- else if (size == 4)
- *(uint32_t *)p = notv;
- }
-#endif
- units = timeone(fn, d, v, n);
-#ifdef VERIFY
- /* Check the area and guard words */
- for (p = &arena[offset-4]; p < (void *)&arena[offset+n+4]; p = (void *)((uint32_t)p + size)) {
- uint32_t got = 0;
- if (size == 1)
- got = *(uint8_t *)p;
- else if (size == 2)
- got = *(uint16_t *)p;
- else if (size == 4)
- got = *(uint32_t *)p;
- if (p < (void *)&arena[offset]) {
- if (got != notv)
- printf ("%s: verify failure: preguard:%p d=%p v=%08x got=%08x n=%d\n", tag, p, d, v, got, n);
- }
- else if (p < (void *)&arena[offset+n]) {
- if (got != v)
- printf ("%s: verify failure: arena:%p d=%p v=%08x got=%08x n=%d\n", tag, p, d, v, n);
- }
- else {
- if (got != notv)
- printf ("%s: verify failure: postguard:%p d=%p v=%08x got=%08x n=%d\n", tag, p, d, v, n);
- }
- }
-#endif
-
- /* If the cycle count looks reasonable include it in the statistics */
- if (units < threshold) {
- totalbytes += n;
- totalunits += units;
- samples++;
- }
- }
-
- printf("%s: samples=%d avglen=%d avg" UNITS "=%d bp"UNITS"=%g\n",
- tag, samples, totalbytes/samples, totalunits/samples, (double)totalbytes/(double)totalunits);
-}
-
-extern void android_memset32_dumb(uint32_t* dst, uint32_t value, size_t size);
-extern void android_memset16_dumb(uint32_t* dst, uint16_t value, size_t size);
-extern void android_memset32_test(uint32_t* dst, uint32_t value, size_t size);
-extern void android_memset16_test(uint32_t* dst, uint16_t value, size_t size);
-extern void memset_cmips(void* dst, int value, size_t size);
-extern void memset_omips(void* dst, int value, size_t size);
-
-int
-main(int argc, char **argv)
-{
- int i;
- struct {
- char *type;
- int trials;
- int minbytes, maxbytes;
- } *pp, params[] = {
- {"small", 10000, 0, 64},
- {"medium", 10000, 64, 512},
- {"large", 10000, 512, 1280},
- {"varied", 10000, 0, 1280},
- };
-#define NPARAMS (sizeof(params)/sizeof(params[0]))
- struct {
- char *name;
- void (*fn)();
- int size;
- } *fp, functions[] = {
- {"dmemset16", (void (*)())android_memset16_dumb, 2},
- {"tmemset16", (void (*)())android_memset16_test, 2},
- {"lmemset16", (void (*)())android_memset16, 2},
-
- {"dmemset32", (void (*)())android_memset32_dumb, 4},
- {"tmemset32", (void (*)())android_memset32_test, 4},
- {"lmemset32", (void (*)())android_memset32, 4},
-
- {"cmemset", (void (*)())memset_cmips, 1},
- {"omemset", (void (*)())memset_omips, 1},
- {"lmemset", (void (*)())memset, 1},
- };
-#define NFUNCTIONS (sizeof(functions)/sizeof(functions[0]))
- char tag[40];
- int threshold;
-
- measure_overhead();
-
- /* Warm up the page cache */
- memset(arena, 0xff, ARENASIZE); /* use 0xff now to avoid COW later */
-
- for (fp = functions; fp < &functions[NFUNCTIONS]; fp++) {
- (fp->fn)(arena, 0xffffffff, ARENASIZE); /* one call to get the code into Icache */
- for (pp = params; pp < ¶ms[NPARAMS]; pp++) {
- sprintf(tag, "%10s: %7s %4d-%4d", fp->name, pp->type, pp->minbytes, pp->maxbytes);
-
- /* Set the cycle threshold */
- threshold = pp->maxbytes * 4 * 10; /* reasonable for cycles and ns */
- testone(tag, fp->fn, pp->trials, pp->minbytes, pp->maxbytes, fp->size, threshold);
- }
- printf ("\n");
- }
-
- return 0;
-}
diff --git a/libpixelflinger/Android.mk b/libpixelflinger/Android.mk
index fe50cc6..c24384c 100644
--- a/libpixelflinger/Android.mk
+++ b/libpixelflinger/Android.mk
@@ -7,13 +7,13 @@
include $(CLEAR_VARS)
PIXELFLINGER_SRC_FILES:= \
- codeflinger/ARMAssemblerInterface.cpp \
- codeflinger/ARMAssemblerProxy.cpp \
- codeflinger/CodeCache.cpp \
- codeflinger/GGLAssembler.cpp \
- codeflinger/load_store.cpp \
- codeflinger/blending.cpp \
- codeflinger/texturing.cpp \
+ codeflinger/ARMAssemblerInterface.cpp \
+ codeflinger/ARMAssemblerProxy.cpp \
+ codeflinger/CodeCache.cpp \
+ codeflinger/GGLAssembler.cpp \
+ codeflinger/load_store.cpp \
+ codeflinger/blending.cpp \
+ codeflinger/texturing.cpp \
codeflinger/tinyutils/SharedBuffer.cpp \
codeflinger/tinyutils/VectorImpl.cpp \
fixed.cpp.arm \
@@ -26,39 +26,28 @@
raster.cpp \
buffer.cpp
-ifeq ($(TARGET_ARCH),arm)
-ifeq ($(TARGET_ARCH_VERSION),armv7-a)
-PIXELFLINGER_SRC_FILES += col32cb16blend_neon.S
-PIXELFLINGER_SRC_FILES += col32cb16blend.S
-else
-PIXELFLINGER_SRC_FILES += t32cb16blend.S
-PIXELFLINGER_SRC_FILES += col32cb16blend.S
-endif
+PIXELFLINGER_CFLAGS := -fstrict-aliasing -fomit-frame-pointer
+
+PIXELFLINGER_SRC_FILES_arm := \
+ codeflinger/ARMAssembler.cpp \
+ codeflinger/disassem.c \
+ col32cb16blend.S \
+ t32cb16blend.S \
+
+ifeq ($(ARCH_ARM_HAVE_NEON),armv7-a)
+PIXELFLINGER_SRC_FILES_arm += col32cb16blend_neon.S
endif
-ifeq ($(TARGET_ARCH),arm)
-PIXELFLINGER_SRC_FILES += codeflinger/ARMAssembler.cpp
-PIXELFLINGER_SRC_FILES += codeflinger/disassem.c
-# special optimization flags for pixelflinger
-PIXELFLINGER_CFLAGS += -fstrict-aliasing -fomit-frame-pointer
-endif
+PIXELFLINGER_SRC_FILES_arm64 := \
+ codeflinger/Arm64Assembler.cpp \
+ codeflinger/Arm64Disassembler.cpp \
+ arch-arm64/col32cb16blend.S \
+ arch-arm64/t32cb16blend.S \
-ifeq ($(TARGET_ARCH),mips)
-PIXELFLINGER_SRC_FILES += codeflinger/MIPSAssembler.cpp
-PIXELFLINGER_SRC_FILES += codeflinger/mips_disassem.c
-PIXELFLINGER_SRC_FILES += arch-mips/t32cb16blend.S
-PIXELFLINGER_CFLAGS += -fstrict-aliasing -fomit-frame-pointer
-endif
-
-LOCAL_SHARED_LIBRARIES := libcutils liblog
-
-ifeq ($(TARGET_ARCH),arm64)
-PIXELFLINGER_SRC_FILES += arch-arm64/t32cb16blend.S
-PIXELFLINGER_SRC_FILES += arch-arm64/col32cb16blend.S
-PIXELFLINGER_SRC_FILES += codeflinger/Arm64Assembler.cpp
-PIXELFLINGER_SRC_FILES += codeflinger/Arm64Disassembler.cpp
-PIXELFLINGER_CFLAGS += -fstrict-aliasing -fomit-frame-pointer
-endif
+PIXELFLINGER_SRC_FILES_mips := \
+ codeflinger/MIPSAssembler.cpp \
+ codeflinger/mips_disassem.c \
+ arch-mips/t32cb16blend.S \
#
# Shared library
@@ -66,7 +55,11 @@
LOCAL_MODULE:= libpixelflinger
LOCAL_SRC_FILES := $(PIXELFLINGER_SRC_FILES)
+LOCAL_SRC_FILES_arm := $(PIXELFLINGER_SRC_FILES_arm)
+LOCAL_SRC_FILES_arm64 := $(PIXELFLINGER_SRC_FILES_arm64)
+LOCAL_SRC_FILES_mips := $(PIXELFLINGER_SRC_FILES_mips)
LOCAL_CFLAGS := $(PIXELFLINGER_CFLAGS)
+LOCAL_SHARED_LIBRARIES := libcutils liblog
ifneq ($(BUILD_TINY_ANDROID),true)
# Really this should go away entirely or at least not depend on
@@ -83,6 +76,9 @@
include $(CLEAR_VARS)
LOCAL_MODULE:= libpixelflinger_static
LOCAL_SRC_FILES := $(PIXELFLINGER_SRC_FILES)
+LOCAL_SRC_FILES_arm := $(PIXELFLINGER_SRC_FILES_arm)
+LOCAL_SRC_FILES_arm64 := $(PIXELFLINGER_SRC_FILES_arm64)
+LOCAL_SRC_FILES_mips := $(PIXELFLINGER_SRC_FILES_mips)
LOCAL_CFLAGS := $(PIXELFLINGER_CFLAGS)
include $(BUILD_STATIC_LIBRARY)
diff --git a/libpixelflinger/buffer.cpp b/libpixelflinger/buffer.cpp
index cbdab5a..dcb95c5 100644
--- a/libpixelflinger/buffer.cpp
+++ b/libpixelflinger/buffer.cpp
@@ -130,7 +130,7 @@
}
}
-void readRGB565(const surface_t* s, context_t* c,
+void readRGB565(const surface_t* s, context_t* /*c*/,
uint32_t x, uint32_t y, pixel_t* pixel)
{
uint16_t v = *(reinterpret_cast<uint16_t*>(s->data) + (x + (s->stride * y)));
@@ -144,7 +144,7 @@
pixel->s[3] = 5;
}
-void readABGR8888(const surface_t* s, context_t* c,
+void readABGR8888(const surface_t* s, context_t* /*c*/,
uint32_t x, uint32_t y, pixel_t* pixel)
{
uint32_t v = *(reinterpret_cast<uint32_t*>(s->data) + (x + (s->stride * y)));
diff --git a/libpixelflinger/codeflinger/Arm64Assembler.cpp b/libpixelflinger/codeflinger/Arm64Assembler.cpp
index f37072a..bd11818 100644
--- a/libpixelflinger/codeflinger/Arm64Assembler.cpp
+++ b/libpixelflinger/codeflinger/Arm64Assembler.cpp
@@ -273,7 +273,7 @@
*mPC++ = (0x54 << 24) | cc;
}
-void ArmToArm64Assembler::BL(int cc, const char* label)
+void ArmToArm64Assembler::BL(int /*cc*/, const char* /*label*/)
{
NOT_IMPLEMENTED(); //Not Required
}
@@ -289,7 +289,7 @@
*mPC++ = A64_MOVZ_X(mZeroReg,0,0);
}
-void ArmToArm64Assembler::epilog(uint32_t touched)
+void ArmToArm64Assembler::epilog(uint32_t /*touched*/)
{
// write epilog code
static const int XLR = 30;
@@ -530,23 +530,23 @@
if(s != 0) { NOT_IMPLEMENTED(); return;} //Not required
*mPC++ = A64_MADD_W(Rd, Rm, Rs, mZeroReg);
}
-void ArmToArm64Assembler::UMULL(int cc, int s,
- int RdLo, int RdHi, int Rm, int Rs)
+void ArmToArm64Assembler::UMULL(int /*cc*/, int /*s*/,
+ int /*RdLo*/, int /*RdHi*/, int /*Rm*/, int /*Rs*/)
{
NOT_IMPLEMENTED(); //Not required
}
-void ArmToArm64Assembler::UMUAL(int cc, int s,
- int RdLo, int RdHi, int Rm, int Rs)
+void ArmToArm64Assembler::UMUAL(int /*cc*/, int /*s*/,
+ int /*RdLo*/, int /*RdHi*/, int /*Rm*/, int /*Rs*/)
{
NOT_IMPLEMENTED(); //Not required
}
-void ArmToArm64Assembler::SMULL(int cc, int s,
- int RdLo, int RdHi, int Rm, int Rs)
+void ArmToArm64Assembler::SMULL(int /*cc*/, int /*s*/,
+ int /*RdLo*/, int /*RdHi*/, int /*Rm*/, int /*Rs*/)
{
NOT_IMPLEMENTED(); //Not required
}
-void ArmToArm64Assembler::SMUAL(int cc, int s,
- int RdLo, int RdHi, int Rm, int Rs)
+void ArmToArm64Assembler::SMUAL(int /*cc*/, int /*s*/,
+ int /*RdLo*/, int /*RdHi*/, int /*Rm*/, int /*Rs*/)
{
NOT_IMPLEMENTED(); //Not required
}
@@ -554,15 +554,15 @@
// ----------------------------------------------------------------------------
// branches relative to PC...
// ----------------------------------------------------------------------------
-void ArmToArm64Assembler::B(int cc, uint32_t* pc){
+void ArmToArm64Assembler::B(int /*cc*/, uint32_t* /*pc*/){
NOT_IMPLEMENTED(); //Not required
}
-void ArmToArm64Assembler::BL(int cc, uint32_t* pc){
+void ArmToArm64Assembler::BL(int /*cc*/, uint32_t* /*pc*/){
NOT_IMPLEMENTED(); //Not required
}
-void ArmToArm64Assembler::BX(int cc, int Rn){
+void ArmToArm64Assembler::BX(int /*cc*/, int /*Rn*/){
NOT_IMPLEMENTED(); //Not required
}
@@ -661,11 +661,11 @@
{
return dataTransfer(opLDRH, cc, Rd, Rn, op_type);
}
-void ArmToArm64Assembler::LDRSB(int cc, int Rd, int Rn, uint32_t offset)
+void ArmToArm64Assembler::LDRSB(int /*cc*/, int /*Rd*/, int /*Rn*/, uint32_t /*offset*/)
{
NOT_IMPLEMENTED(); //Not required
}
-void ArmToArm64Assembler::LDRSH(int cc, int Rd, int Rn, uint32_t offset)
+void ArmToArm64Assembler::LDRSH(int /*cc*/, int /*Rd*/, int /*Rn*/, uint32_t /*offset*/)
{
NOT_IMPLEMENTED(); //Not required
}
@@ -723,15 +723,15 @@
// ----------------------------------------------------------------------------
// special...
// ----------------------------------------------------------------------------
-void ArmToArm64Assembler::SWP(int cc, int Rn, int Rd, int Rm)
+void ArmToArm64Assembler::SWP(int /*cc*/, int /*Rn*/, int /*Rd*/, int /*Rm*/)
{
NOT_IMPLEMENTED(); //Not required
}
-void ArmToArm64Assembler::SWPB(int cc, int Rn, int Rd, int Rm)
+void ArmToArm64Assembler::SWPB(int /*cc*/, int /*Rn*/, int /*Rd*/, int /*Rm*/)
{
NOT_IMPLEMENTED(); //Not required
}
-void ArmToArm64Assembler::SWI(int cc, uint32_t comment)
+void ArmToArm64Assembler::SWI(int /*cc*/, uint32_t /*comment*/)
{
NOT_IMPLEMENTED(); //Not required
}
@@ -739,31 +739,31 @@
// ----------------------------------------------------------------------------
// DSP instructions...
// ----------------------------------------------------------------------------
-void ArmToArm64Assembler::PLD(int Rn, uint32_t offset) {
+void ArmToArm64Assembler::PLD(int /*Rn*/, uint32_t /*offset*/) {
NOT_IMPLEMENTED(); //Not required
}
-void ArmToArm64Assembler::CLZ(int cc, int Rd, int Rm)
+void ArmToArm64Assembler::CLZ(int /*cc*/, int /*Rd*/, int /*Rm*/)
{
NOT_IMPLEMENTED(); //Not required
}
-void ArmToArm64Assembler::QADD(int cc, int Rd, int Rm, int Rn)
+void ArmToArm64Assembler::QADD(int /*cc*/, int /*Rd*/, int /*Rm*/, int /*Rn*/)
{
NOT_IMPLEMENTED(); //Not required
}
-void ArmToArm64Assembler::QDADD(int cc, int Rd, int Rm, int Rn)
+void ArmToArm64Assembler::QDADD(int /*cc*/, int /*Rd*/, int /*Rm*/, int /*Rn*/)
{
NOT_IMPLEMENTED(); //Not required
}
-void ArmToArm64Assembler::QSUB(int cc, int Rd, int Rm, int Rn)
+void ArmToArm64Assembler::QSUB(int /*cc*/, int /*Rd*/, int /*Rm*/, int /*Rn*/)
{
NOT_IMPLEMENTED(); //Not required
}
-void ArmToArm64Assembler::QDSUB(int cc, int Rd, int Rm, int Rn)
+void ArmToArm64Assembler::QDSUB(int /*cc*/, int /*Rd*/, int /*Rm*/, int /*Rn*/)
{
NOT_IMPLEMENTED(); //Not required
}
@@ -817,15 +817,15 @@
*mPC++ = A64_MADD_W(Rd, mTmpReg1, mTmpReg2, Rn);
}
-void ArmToArm64Assembler::SMLAL(int cc, int xy,
- int RdHi, int RdLo, int Rs, int Rm)
+void ArmToArm64Assembler::SMLAL(int /*cc*/, int /*xy*/,
+ int /*RdHi*/, int /*RdLo*/, int /*Rs*/, int /*Rm*/)
{
NOT_IMPLEMENTED(); //Not required
return;
}
-void ArmToArm64Assembler::SMLAW(int cc, int y,
- int Rd, int Rm, int Rs, int Rn)
+void ArmToArm64Assembler::SMLAW(int /*cc*/, int /*y*/,
+ int /*Rd*/, int /*Rm*/, int /*Rs*/, int /*Rn*/)
{
NOT_IMPLEMENTED(); //Not required
return;
@@ -890,13 +890,13 @@
return OPERAND_REG_IMM;
}
-uint32_t ArmToArm64Assembler::reg_rrx(int Rm)
+uint32_t ArmToArm64Assembler::reg_rrx(int /*Rm*/)
{
NOT_IMPLEMENTED();
return OPERAND_UNSUPPORTED;
}
-uint32_t ArmToArm64Assembler::reg_reg(int Rm, int type, int Rs)
+uint32_t ArmToArm64Assembler::reg_reg(int /*Rm*/, int /*type*/, int /*Rs*/)
{
NOT_IMPLEMENTED(); //Not required
return OPERAND_UNSUPPORTED;
@@ -937,7 +937,7 @@
}
}
-uint32_t ArmToArm64Assembler::reg_scale_post(int Rm, int type, uint32_t shift)
+uint32_t ArmToArm64Assembler::reg_scale_post(int /*Rm*/, int /*type*/, uint32_t /*shift*/)
{
NOT_IMPLEMENTED(); //Not required
return OPERAND_UNSUPPORTED;
@@ -975,7 +975,7 @@
}
}
-uint32_t ArmToArm64Assembler::reg_post(int Rm)
+uint32_t ArmToArm64Assembler::reg_post(int /*Rm*/)
{
NOT_IMPLEMENTED(); //Not required
return OPERAND_UNSUPPORTED;
diff --git a/libpixelflinger/codeflinger/CodeCache.cpp b/libpixelflinger/codeflinger/CodeCache.cpp
index 4fe30d9..7446da2 100644
--- a/libpixelflinger/codeflinger/CodeCache.cpp
+++ b/libpixelflinger/codeflinger/CodeCache.cpp
@@ -201,13 +201,9 @@
mCacheInUse += assemblySize;
mWhen++;
// synchronize caches...
-#if defined(__arm__) || defined(__mips__) || defined(__aarch64__)
const long base = long(assembly->base());
const long curr = base + long(assembly->size());
- err = cacheflush(base, curr, 0);
- ALOGE_IF(err, "cacheflush error %s\n",
- strerror(errno));
-#endif
+ __builtin___clear_cache((void*)base, (void*)curr);
}
pthread_mutex_unlock(&mLock);
diff --git a/libpixelflinger/codeflinger/GGLAssembler.cpp b/libpixelflinger/codeflinger/GGLAssembler.cpp
index 2422d7b..325caba 100644
--- a/libpixelflinger/codeflinger/GGLAssembler.cpp
+++ b/libpixelflinger/codeflinger/GGLAssembler.cpp
@@ -694,7 +694,7 @@
// ---------------------------------------------------------------------------
void GGLAssembler::build_alpha_test(component_t& fragment,
- const fragment_parts_t& parts)
+ const fragment_parts_t& /*parts*/)
{
if (mAlphaTest != GGL_ALWAYS) {
comment("Alpha Test");
@@ -796,7 +796,7 @@
}
}
-void GGLAssembler::build_iterate_f(const fragment_parts_t& parts)
+void GGLAssembler::build_iterate_f(const fragment_parts_t& /*parts*/)
{
const needs_t& needs = mBuilderContext.needs;
if (GGL_READ_NEEDS(P_FOG, needs.p)) {
diff --git a/libpixelflinger/codeflinger/texturing.cpp b/libpixelflinger/codeflinger/texturing.cpp
index b2cfbb3..81950bf 100644
--- a/libpixelflinger/codeflinger/texturing.cpp
+++ b/libpixelflinger/codeflinger/texturing.cpp
@@ -694,7 +694,7 @@
}
void GGLAssembler::filter8(
- const fragment_parts_t& parts,
+ const fragment_parts_t& /*parts*/,
pixel_t& texel, const texture_unit_t& tmu,
int U, int V, pointer_t& txPtr,
int FRAC_BITS)
@@ -761,7 +761,7 @@
}
void GGLAssembler::filter16(
- const fragment_parts_t& parts,
+ const fragment_parts_t& /*parts*/,
pixel_t& texel, const texture_unit_t& tmu,
int U, int V, pointer_t& txPtr,
int FRAC_BITS)
@@ -879,10 +879,10 @@
}
void GGLAssembler::filter24(
- const fragment_parts_t& parts,
- pixel_t& texel, const texture_unit_t& tmu,
- int U, int V, pointer_t& txPtr,
- int FRAC_BITS)
+ const fragment_parts_t& /*parts*/,
+ pixel_t& texel, const texture_unit_t& /*tmu*/,
+ int /*U*/, int /*V*/, pointer_t& txPtr,
+ int /*FRAC_BITS*/)
{
// not supported yet (currently disabled)
load(txPtr, texel, 0);
@@ -989,8 +989,8 @@
}
#else
void GGLAssembler::filter32(
- const fragment_parts_t& parts,
- pixel_t& texel, const texture_unit_t& tmu,
+ const fragment_parts_t& /*parts*/,
+ pixel_t& texel, const texture_unit_t& /*tmu*/,
int U, int V, pointer_t& txPtr,
int FRAC_BITS)
{
diff --git a/libpixelflinger/picker.cpp b/libpixelflinger/picker.cpp
index 030ef19..aa55229 100644
--- a/libpixelflinger/picker.cpp
+++ b/libpixelflinger/picker.cpp
@@ -26,7 +26,7 @@
// ----------------------------------------------------------------------------
-void ggl_init_picker(context_t* c)
+void ggl_init_picker(context_t* /*c*/)
{
}
diff --git a/libpixelflinger/pixelflinger.cpp b/libpixelflinger/pixelflinger.cpp
index 84e584e..ea5bc8e 100644
--- a/libpixelflinger/pixelflinger.cpp
+++ b/libpixelflinger/pixelflinger.cpp
@@ -662,7 +662,7 @@
}
}
-void ggl_enable_stencil_test(context_t* c, int enable)
+void ggl_enable_stencil_test(context_t* /*c*/, int /*enable*/)
{
}
diff --git a/libpixelflinger/raster.cpp b/libpixelflinger/raster.cpp
index 32b2a97..26d8e45 100644
--- a/libpixelflinger/raster.cpp
+++ b/libpixelflinger/raster.cpp
@@ -51,7 +51,7 @@
}
void ggl_copyPixels(void* con, GGLint xs, GGLint ys,
- GGLsizei width, GGLsizei height, GGLenum type)
+ GGLsizei width, GGLsizei height, GGLenum /*type*/)
{
GGL_CONTEXT(c, con);
diff --git a/libpixelflinger/scanline.cpp b/libpixelflinger/scanline.cpp
index aa23ca6..cd78713 100644
--- a/libpixelflinger/scanline.cpp
+++ b/libpixelflinger/scanline.cpp
@@ -534,7 +534,7 @@
return x;
}
-void blend_factor(context_t* c, pixel_t* r,
+void blend_factor(context_t* /*c*/, pixel_t* r,
uint32_t factor, const pixel_t* src, const pixel_t* dst)
{
switch (factor) {
@@ -1161,7 +1161,7 @@
* blender.blend(<32-bit-src-pixel-value>,<ptr-to-16-bit-dest-pixel>)
*/
struct blender_32to16 {
- blender_32to16(context_t* c) { }
+ blender_32to16(context_t* /*c*/) { }
void write(uint32_t s, uint16_t* dst) {
if (s == 0)
return;
@@ -1218,7 +1218,7 @@
* where dstFactor=srcA*(1-srcA) srcFactor=srcA
*/
struct blender_32to16_srcA {
- blender_32to16_srcA(const context_t* c) { }
+ blender_32to16_srcA(const context_t* /*c*/) { }
void write(uint32_t s, uint16_t* dst) {
if (!s) {
return;
@@ -2317,7 +2317,7 @@
memset(dst, 0xFF, size);
}
-void scanline_noop(context_t* c)
+void scanline_noop(context_t* /*c*/)
{
}
diff --git a/libpixelflinger/tests/arch-arm64/assembler/arm64_assembler_test.cpp b/libpixelflinger/tests/arch-arm64/assembler/arm64_assembler_test.cpp
index 84381d5..456be58 100644
--- a/libpixelflinger/tests/arch-arm64/assembler/arm64_assembler_test.cpp
+++ b/libpixelflinger/tests/arch-arm64/assembler/arm64_assembler_test.cpp
@@ -405,11 +405,11 @@
};
-int flushcache()
+void flushcache()
{
const long base = long(instrMem);
const long curr = base + long(instrMemSize);
- return cacheflush(base, curr, 0);
+ __builtin___clear_cache((void*)base, (void*)curr);
}
void dataOpTest(dataOpTest_t test, ARMAssemblerInterface *a64asm, uint32_t Rd = 0,
uint32_t Rn = 1, uint32_t Rm = 2, uint32_t Rs = 3)
diff --git a/libpixelflinger/tests/gglmul/gglmul_test.cpp b/libpixelflinger/tests/gglmul/gglmul_test.cpp
index 073368e..5d460d6 100644
--- a/libpixelflinger/tests/gglmul/gglmul_test.cpp
+++ b/libpixelflinger/tests/gglmul/gglmul_test.cpp
@@ -28,6 +28,7 @@
#include <stdio.h>
#include <stdint.h>
+#include <inttypes.h>
#include "private/pixelflinger/ggl_fixed.h"
@@ -260,12 +261,12 @@
if(actual == expected)
printf(" Passed\n");
else
- printf(" Failed Actual(%ld) Expected(%ld)\n",
+ printf(" Failed Actual(%" PRId64 ") Expected(%" PRId64 ")\n",
actual, expected);
}
}
-int main(int argc, char** argv)
+int main(int /*argc*/, char** /*argv*/)
{
gglClampx_test();
gglClz_test();
diff --git a/libusbhost/Android.mk b/libusbhost/Android.mk
index 9565cc5..acfc020 100644
--- a/libusbhost/Android.mk
+++ b/libusbhost/Android.mk
@@ -14,7 +14,7 @@
# limitations under the License.
#
-LOCAL_PATH := $(my-dir)
+LOCAL_PATH := $(call my-dir)
# Static library for Linux host
# ========================================================
diff --git a/libutils/String8.cpp b/libutils/String8.cpp
index e852d77..8acb4d4 100644
--- a/libutils/String8.cpp
+++ b/libutils/String8.cpp
@@ -323,8 +323,17 @@
status_t String8::appendFormatV(const char* fmt, va_list args)
{
- int result = NO_ERROR;
- int n = vsnprintf(NULL, 0, fmt, args);
+ int n, result = NO_ERROR;
+ va_list tmp_args;
+
+ /* args is undefined after vsnprintf.
+ * So we need a copy here to avoid the
+ * second vsnprintf access undefined args.
+ */
+ va_copy(tmp_args, args);
+ n = vsnprintf(NULL, 0, fmt, tmp_args);
+ va_end(tmp_args);
+
if (n != 0) {
size_t oldLength = length();
char* buf = lockBuffer(oldLength + n);
diff --git a/libziparchive/zip_archive.cc b/libziparchive/zip_archive.cc
index a23d4ae..8ef0962 100644
--- a/libziparchive/zip_archive.cc
+++ b/libziparchive/zip_archive.cc
@@ -279,7 +279,7 @@
ent = (ent + 1) & (hash_table_size - 1);
}
- ALOGV("Zip: Unable to find entry %.*s", name_length, name);
+ ALOGV("Zip: Unable to find entry %.*s", length, name);
return kEntryNotFound;
}
diff --git a/logcat/tests/logcat_test.cpp b/logcat/tests/logcat_test.cpp
index f963a3a..fc696bb 100644
--- a/logcat/tests/logcat_test.cpp
+++ b/logcat/tests/logcat_test.cpp
@@ -319,12 +319,16 @@
TEST(logcat, blocking) {
FILE *fp;
- unsigned long long v = 0xDEADBEEFA55A0000ULL;
+ unsigned long long v = 0xDEADBEEFA55F0000ULL;
pid_t pid = getpid();
v += pid & 0xFFFF;
+ LOG_FAILURE_RETRY(__android_log_btwrite(0, EVENT_TYPE_LONG, &v, sizeof(v)));
+
+ v &= 0xFFFFFFFFFFFAFFFFULL;
+
ASSERT_EQ(0, NULL == (fp = popen(
"( trap exit HUP QUIT INT PIPE KILL ; sleep 6; echo DONE )&"
" logcat -b events 2>&1",
@@ -341,12 +345,12 @@
while (fgets(buffer, sizeof(buffer), fp)) {
alarm(2);
- ++count;
-
if (!strncmp(buffer, "DONE", 4)) {
break;
}
+ ++count;
+
int p;
unsigned long long l;
@@ -369,7 +373,7 @@
pclose(fp);
- ASSERT_LT(10, count);
+ ASSERT_LE(2, count);
ASSERT_EQ(1, signals);
}
@@ -385,12 +389,16 @@
TEST(logcat, blocking_tail) {
FILE *fp;
- unsigned long long v = 0xA55ADEADBEEF0000ULL;
+ unsigned long long v = 0xA55FDEADBEEF0000ULL;
pid_t pid = getpid();
v += pid & 0xFFFF;
+ LOG_FAILURE_RETRY(__android_log_btwrite(0, EVENT_TYPE_LONG, &v, sizeof(v)));
+
+ v &= 0xFFFAFFFFFFFFFFFFULL;
+
ASSERT_EQ(0, NULL == (fp = popen(
"( trap exit HUP QUIT INT PIPE KILL ; sleep 6; echo DONE )&"
" logcat -b events -T 5 2>&1",
@@ -407,12 +415,12 @@
while (fgets(buffer, sizeof(buffer), fp)) {
alarm(2);
- ++count;
-
if (!strncmp(buffer, "DONE", 4)) {
break;
}
+ ++count;
+
int p;
unsigned long long l;
@@ -431,13 +439,91 @@
alarm(0);
signal(SIGALRM, SIG_DFL);
- /* Generate SIGPIPE */
+ // Generate SIGPIPE
fclose(fp);
caught_blocking_tail(0);
pclose(fp);
- ASSERT_LT(5, count);
+ ASSERT_LE(2, count);
+
+ ASSERT_EQ(1, signals);
+}
+
+static void caught_blocking_clear(int signum)
+{
+ unsigned long long v = 0xDEADBEEFA55C0000ULL;
+
+ v += getpid() & 0xFFFF;
+
+ LOG_FAILURE_RETRY(__android_log_btwrite(0, EVENT_TYPE_LONG, &v, sizeof(v)));
+}
+
+TEST(logcat, blocking_clear) {
+ FILE *fp;
+ unsigned long long v = 0xDEADBEEFA55C0000ULL;
+
+ pid_t pid = getpid();
+
+ v += pid & 0xFFFF;
+
+ // This test is racey; an event occurs between clear and dump.
+ // We accept that we will get a false positive, but never a false negative.
+ ASSERT_EQ(0, NULL == (fp = popen(
+ "( trap exit HUP QUIT INT PIPE KILL ; sleep 6; echo DONE )&"
+ " logcat -b events -c 2>&1 ;"
+ " logcat -b events 2>&1",
+ "r")));
+
+ char buffer[5120];
+
+ int count = 0;
+
+ int signals = 0;
+
+ signal(SIGALRM, caught_blocking_clear);
+ alarm(2);
+ while (fgets(buffer, sizeof(buffer), fp)) {
+ alarm(2);
+
+ if (!strncmp(buffer, "clearLog: ", 10)) {
+ fprintf(stderr, "WARNING: Test lacks permission to run :-(\n");
+ count = signals = 1;
+ break;
+ }
+
+ if (!strncmp(buffer, "DONE", 4)) {
+ break;
+ }
+
+ ++count;
+
+ int p;
+ unsigned long long l;
+
+ if ((2 != sscanf(buffer, "I/[0] ( %u): %lld", &p, &l))
+ || (p != pid)) {
+ continue;
+ }
+
+ if (l == v) {
+ if (count > 1) {
+ fprintf(stderr, "WARNING: Possible false positive\n");
+ }
+ ++signals;
+ break;
+ }
+ }
+ alarm(0);
+ signal(SIGALRM, SIG_DFL);
+
+ // Generate SIGPIPE
+ fclose(fp);
+ caught_blocking_clear(0);
+
+ pclose(fp);
+
+ ASSERT_LE(1, count);
ASSERT_EQ(1, signals);
}
diff --git a/logd/Android.mk b/logd/Android.mk
new file mode 100644
index 0000000..f536dad
--- /dev/null
+++ b/logd/Android.mk
@@ -0,0 +1,28 @@
+LOCAL_PATH:= $(call my-dir)
+
+include $(CLEAR_VARS)
+
+LOCAL_MODULE:= logd
+
+LOCAL_SRC_FILES := \
+ main.cpp \
+ LogCommand.cpp \
+ CommandListener.cpp \
+ LogListener.cpp \
+ LogReader.cpp \
+ FlushCommand.cpp \
+ LogBuffer.cpp \
+ LogBufferElement.cpp \
+ LogTimes.cpp
+
+LOCAL_C_INCLUDES := $(KERNEL_HEADERS)
+
+LOCAL_SHARED_LIBRARIES := \
+ libsysutils \
+ liblog \
+ libcutils
+
+LOCAL_MODULE_TAGS := optional
+
+include $(BUILD_EXECUTABLE)
+
diff --git a/logd/CommandListener.cpp b/logd/CommandListener.cpp
new file mode 100644
index 0000000..f5cb8dc
--- /dev/null
+++ b/logd/CommandListener.cpp
@@ -0,0 +1,137 @@
+/*
+ * Copyright (C) 2012-2013 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 <arpa/inet.h>
+#include <dirent.h>
+#include <errno.h>
+#include <fcntl.h>
+#include <netinet/in.h>
+#include <string.h>
+#include <stdlib.h>
+#include <sys/socket.h>
+#include <sys/types.h>
+
+#include <sysutils/SocketClient.h>
+#include <private/android_filesystem_config.h>
+
+#include "CommandListener.h"
+
+CommandListener::CommandListener(LogBuffer *buf, LogReader * /*reader*/,
+ LogListener * /*swl*/)
+ : FrameworkListener("logd")
+ , mBuf(*buf) {
+ // registerCmd(new ShutdownCmd(buf, writer, swl));
+ registerCmd(new ClearCmd(buf));
+ registerCmd(new GetBufSizeCmd(buf));
+ registerCmd(new GetBufSizeUsedCmd(buf));
+}
+
+CommandListener::ShutdownCmd::ShutdownCmd(LogBuffer *buf, LogReader *reader,
+ LogListener *swl)
+ : LogCommand("shutdown")
+ , mBuf(*buf)
+ , mReader(*reader)
+ , mSwl(*swl)
+{ }
+
+int CommandListener::ShutdownCmd::runCommand(SocketClient * /*cli*/,
+ int /*argc*/,
+ char ** /*argv*/) {
+ mSwl.stopListener();
+ mReader.stopListener();
+ exit(0);
+}
+
+CommandListener::ClearCmd::ClearCmd(LogBuffer *buf)
+ : LogCommand("clear")
+ , mBuf(*buf)
+{ }
+
+int CommandListener::ClearCmd::runCommand(SocketClient *cli,
+ int argc, char **argv) {
+ if ((cli->getUid() != AID_ROOT)
+ && (cli->getGid() != AID_ROOT)
+ && (cli->getGid() != AID_LOG)) {
+ cli->sendMsg("Permission Denied");
+ return 0;
+ }
+
+ if (argc < 2) {
+ cli->sendMsg("Missing Argument");
+ return 0;
+ }
+
+ int id = atoi(argv[1]);
+ if ((id < LOG_ID_MIN) || (id >= LOG_ID_MAX)) {
+ cli->sendMsg("Range Error");
+ return 0;
+ }
+
+ mBuf.clear((log_id_t) id);
+ cli->sendMsg("success");
+ return 0;
+}
+
+
+CommandListener::GetBufSizeCmd::GetBufSizeCmd(LogBuffer *buf)
+ : LogCommand("getLogSize")
+ , mBuf(*buf)
+{ }
+
+int CommandListener::GetBufSizeCmd::runCommand(SocketClient *cli,
+ int argc, char **argv) {
+ if (argc < 2) {
+ cli->sendMsg("Missing Argument");
+ return 0;
+ }
+
+ int id = atoi(argv[1]);
+ if ((id < LOG_ID_MIN) || (id >= LOG_ID_MAX)) {
+ cli->sendMsg("Range Error");
+ return 0;
+ }
+
+ unsigned long size = mBuf.getSize((log_id_t) id);
+ char buf[512];
+ snprintf(buf, sizeof(buf), "%lu", size);
+ cli->sendMsg(buf);
+ return 0;
+}
+
+CommandListener::GetBufSizeUsedCmd::GetBufSizeUsedCmd(LogBuffer *buf)
+ : LogCommand("getLogSizeUsed")
+ , mBuf(*buf)
+{ }
+
+int CommandListener::GetBufSizeUsedCmd::runCommand(SocketClient *cli,
+ int argc, char **argv) {
+ if (argc < 2) {
+ cli->sendMsg("Missing Argument");
+ return 0;
+ }
+
+ int id = atoi(argv[1]);
+ if ((id < LOG_ID_MIN) || (id >= LOG_ID_MAX)) {
+ cli->sendMsg("Range Error");
+ return 0;
+ }
+
+ unsigned long size = mBuf.getSizeUsed((log_id_t) id);
+ char buf[512];
+ snprintf(buf, sizeof(buf), "%lu", size);
+ cli->sendMsg(buf);
+ return 0;
+}
diff --git a/logd/CommandListener.h b/logd/CommandListener.h
new file mode 100644
index 0000000..861abbf
--- /dev/null
+++ b/logd/CommandListener.h
@@ -0,0 +1,59 @@
+/*
+ * Copyright (C) 2012-2014 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 _COMMANDLISTENER_H__
+#define _COMMANDLISTENER_H__
+
+#include <sysutils/FrameworkListener.h>
+#include "LogCommand.h"
+#include "LogBuffer.h"
+#include "LogReader.h"
+#include "LogListener.h"
+
+class CommandListener : public FrameworkListener {
+ LogBuffer &mBuf;
+
+public:
+ CommandListener(LogBuffer *buf, LogReader *reader, LogListener *swl);
+ virtual ~CommandListener() {}
+
+private:
+ class ShutdownCmd : public LogCommand {
+ LogBuffer &mBuf;
+ LogReader &mReader;
+ LogListener &mSwl;
+
+ public:
+ ShutdownCmd(LogBuffer *buf, LogReader *reader, LogListener *swl);
+ virtual ~ShutdownCmd() {}
+ int runCommand(SocketClient *c, int argc, char ** argv);
+ };
+
+#define LogBufferCmd(name) \
+ class name##Cmd : public LogCommand { \
+ LogBuffer &mBuf; \
+ public: \
+ name##Cmd(LogBuffer *buf); \
+ virtual ~name##Cmd() {} \
+ int runCommand(SocketClient *c, int argc, char ** argv); \
+ };
+
+ LogBufferCmd(Clear)
+ LogBufferCmd(GetBufSize)
+ LogBufferCmd(GetBufSizeUsed)
+};
+
+#endif
diff --git a/logd/FlushCommand.cpp b/logd/FlushCommand.cpp
new file mode 100644
index 0000000..f6f8cb8
--- /dev/null
+++ b/logd/FlushCommand.cpp
@@ -0,0 +1,86 @@
+/*
+ * Copyright (C) 2012-2013 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 <stdlib.h>
+#include <private/android_filesystem_config.h>
+#include "FlushCommand.h"
+#include "LogBufferElement.h"
+#include "LogTimes.h"
+#include "LogReader.h"
+
+FlushCommand::FlushCommand(LogReader &reader,
+ bool nonBlock,
+ unsigned long tail,
+ unsigned int logMask,
+ pid_t pid)
+ : mReader(reader)
+ , mNonBlock(nonBlock)
+ , mTail(tail)
+ , mLogMask(logMask)
+ , mPid(pid)
+{ }
+
+// runSocketCommand is called once for every open client on the
+// log reader socket. Here we manage and associated the reader
+// client tracking and log region locks LastLogTimes list of
+// LogTimeEntrys, and spawn a transitory per-client thread to
+// work at filing data to the socket.
+//
+// global LogTimeEntry::lock() is used to protect access,
+// reference counts are used to ensure that individual
+// LogTimeEntry lifetime is managed when not protected.
+void FlushCommand::runSocketCommand(SocketClient *client) {
+ LogTimeEntry *entry = NULL;
+ LastLogTimes × = mReader.logbuf().mTimes;
+
+ LogTimeEntry::lock();
+ LastLogTimes::iterator it = times.begin();
+ while(it != times.end()) {
+ entry = (*it);
+ if (entry->mClient == client) {
+ entry->triggerReader_Locked();
+ if (entry->runningReader_Locked()) {
+ LogTimeEntry::unlock();
+ return;
+ }
+ entry->incRef_Locked();
+ break;
+ }
+ it++;
+ }
+
+ if (it == times.end()) {
+ // Create LogTimeEntry in notifyNewLog() ?
+ if (mTail == (unsigned long) -1) {
+ LogTimeEntry::unlock();
+ return;
+ }
+ entry = new LogTimeEntry(mReader, client, mNonBlock, mTail, mLogMask, mPid);
+ times.push_back(entry);
+ }
+
+ client->incRef();
+
+ // release client and entry reference counts once done
+ entry->startReader_Locked();
+ LogTimeEntry::unlock();
+}
+
+bool FlushCommand::hasReadLogs(SocketClient *client) {
+ return (client->getUid() == AID_ROOT)
+ || (client->getGid() == AID_ROOT)
+ || (client->getGid() == AID_LOG);
+}
diff --git a/logd/FlushCommand.h b/logd/FlushCommand.h
new file mode 100644
index 0000000..715daac
--- /dev/null
+++ b/logd/FlushCommand.h
@@ -0,0 +1,41 @@
+/*
+ * Copyright (C) 2012-2013 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 _FLUSH_COMMAND_H
+#define _FLUSH_COMMAND_H
+
+#include <sysutils/SocketClientCommand.h>
+
+class LogReader;
+
+class FlushCommand : public SocketClientCommand {
+ LogReader &mReader;
+ bool mNonBlock;
+ unsigned long mTail;
+ unsigned int mLogMask;
+ pid_t mPid;
+
+public:
+ FlushCommand(LogReader &mReader,
+ bool nonBlock = false,
+ unsigned long tail = -1,
+ unsigned int logMask = -1,
+ pid_t pid = 0);
+ virtual void runSocketCommand(SocketClient *client);
+
+ static bool hasReadLogs(SocketClient *client);
+};
+
+#endif
diff --git a/logd/LogBuffer.cpp b/logd/LogBuffer.cpp
new file mode 100644
index 0000000..7340a36
--- /dev/null
+++ b/logd/LogBuffer.cpp
@@ -0,0 +1,223 @@
+/*
+ * Copyright (C) 2012-2014 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 <stdio.h>
+#include <string.h>
+#include <time.h>
+#include <unistd.h>
+
+#include <log/logger.h>
+
+#include "LogBuffer.h"
+#include "LogReader.h"
+
+#define LOG_BUFFER_SIZE (256 * 1024) // Tuned on a per-platform basis here?
+
+LogBuffer::LogBuffer(LastLogTimes *times)
+ : mTimes(*times) {
+ int i;
+ for (i = 0; i < LOG_ID_MAX; i++) {
+ mSizes[i] = 0;
+ mElements[i] = 0;
+ }
+ pthread_mutex_init(&mLogElementsLock, NULL);
+}
+
+void LogBuffer::log(log_id_t log_id, struct timespec realtime,
+ uid_t uid, pid_t pid, const char *msg,
+ unsigned short len) {
+ if ((log_id >= LOG_ID_MAX) || (log_id < 0)) {
+ return;
+ }
+ LogBufferElement *elem = new LogBufferElement(log_id, realtime,
+ uid, pid, msg, len);
+
+ pthread_mutex_lock(&mLogElementsLock);
+
+ // Insert elements in time sorted order if possible
+ // NB: if end is region locked, place element at end of list
+ LogBufferElementCollection::iterator it = mLogElements.end();
+ LogBufferElementCollection::iterator last = it;
+ while (--it != mLogElements.begin()) {
+ if ((*it)->getRealTime() <= realtime) {
+ break;
+ }
+ last = it;
+ }
+
+ if (last == mLogElements.end()) {
+ mLogElements.push_back(elem);
+ } else {
+ log_time end;
+ bool end_set = false;
+ bool end_always = false;
+
+ LogTimeEntry::lock();
+
+ LastLogTimes::iterator t = mTimes.begin();
+ while(t != mTimes.end()) {
+ LogTimeEntry *entry = (*t);
+ if (entry->owned_Locked()) {
+ if (!entry->mNonBlock) {
+ end_always = true;
+ break;
+ }
+ if (!end_set || (end <= entry->mEnd)) {
+ end = entry->mEnd;
+ end_set = true;
+ }
+ }
+ t++;
+ }
+
+ if (end_always
+ || (end_set && (end >= (*last)->getMonotonicTime()))) {
+ mLogElements.push_back(elem);
+ } else {
+ mLogElements.insert(last,elem);
+ }
+
+ LogTimeEntry::unlock();
+ }
+
+ mSizes[log_id] += len;
+ mElements[log_id]++;
+ maybePrune(log_id);
+ pthread_mutex_unlock(&mLogElementsLock);
+}
+
+// If we're using more than 256K of memory for log entries, prune
+// at least 10% of the log entries.
+//
+// mLogElementsLock must be held when this function is called.
+void LogBuffer::maybePrune(log_id_t id) {
+ unsigned long sizes = mSizes[id];
+ if (sizes > LOG_BUFFER_SIZE) {
+ unsigned long sizeOver90Percent = sizes - ((LOG_BUFFER_SIZE * 9) / 10);
+ unsigned long elements = mElements[id];
+ unsigned long pruneRows = elements * sizeOver90Percent / sizes;
+ elements /= 10;
+ if (pruneRows <= elements) {
+ pruneRows = elements;
+ }
+ prune(id, pruneRows);
+ }
+}
+
+// prune "pruneRows" of type "id" from the buffer.
+//
+// mLogElementsLock must be held when this function is called.
+void LogBuffer::prune(log_id_t id, unsigned long pruneRows) {
+ LogTimeEntry *oldest = NULL;
+
+ LogTimeEntry::lock();
+
+ // Region locked?
+ LastLogTimes::iterator t = mTimes.begin();
+ while(t != mTimes.end()) {
+ LogTimeEntry *entry = (*t);
+ if (entry->owned_Locked()
+ && (!oldest || (oldest->mStart > entry->mStart))) {
+ oldest = entry;
+ }
+ t++;
+ }
+
+ LogBufferElementCollection::iterator it = mLogElements.begin();
+ while((pruneRows > 0) && (it != mLogElements.end())) {
+ LogBufferElement *e = *it;
+ if (e->getLogId() == id) {
+ if (oldest && (oldest->mStart <= e->getMonotonicTime())) {
+ if (mSizes[id] > (2 * LOG_BUFFER_SIZE)) {
+ // kick a misbehaving log reader client off the island
+ oldest->release_Locked();
+ } else {
+ oldest->triggerSkip_Locked(pruneRows);
+ }
+ break;
+ }
+ it = mLogElements.erase(it);
+ mSizes[id] -= e->getMsgLen();
+ mElements[id]--;
+ delete e;
+ pruneRows--;
+ } else {
+ it++;
+ }
+ }
+
+ LogTimeEntry::unlock();
+}
+
+// clear all rows of type "id" from the buffer.
+void LogBuffer::clear(log_id_t id) {
+ pthread_mutex_lock(&mLogElementsLock);
+ prune(id, ULONG_MAX);
+ pthread_mutex_unlock(&mLogElementsLock);
+}
+
+// get the used space associated with "id".
+unsigned long LogBuffer::getSizeUsed(log_id_t id) {
+ pthread_mutex_lock(&mLogElementsLock);
+ unsigned long retval = mSizes[id];
+ pthread_mutex_unlock(&mLogElementsLock);
+ return retval;
+}
+
+// get the total space allocated to "id"
+unsigned long LogBuffer::getSize(log_id_t /*id*/) {
+ return LOG_BUFFER_SIZE;
+}
+
+struct timespec LogBuffer::flushTo(
+ SocketClient *reader, const struct timespec start, bool privileged,
+ bool (*filter)(const LogBufferElement *element, void *arg), void *arg) {
+ LogBufferElementCollection::iterator it;
+ log_time max = start;
+ uid_t uid = reader->getUid();
+
+ pthread_mutex_lock(&mLogElementsLock);
+ for (it = mLogElements.begin(); it != mLogElements.end(); ++it) {
+ LogBufferElement *element = *it;
+
+ if (!privileged && (element->getUid() != uid)) {
+ continue;
+ }
+
+ if (element->getMonotonicTime() <= start) {
+ continue;
+ }
+
+ // NB: calling out to another object with mLogElementsLock held (safe)
+ if (filter && !(*filter)(element, arg)) {
+ continue;
+ }
+
+ pthread_mutex_unlock(&mLogElementsLock);
+
+ // range locking in LastLogTimes looks after us
+ max = element->flushTo(reader);
+
+ if (max == element->FLUSH_ERROR) {
+ return max;
+ }
+
+ pthread_mutex_lock(&mLogElementsLock);
+ }
+ pthread_mutex_unlock(&mLogElementsLock);
+
+ return max;
+}
diff --git a/logd/LogBuffer.h b/logd/LogBuffer.h
new file mode 100644
index 0000000..7c69f1b
--- /dev/null
+++ b/logd/LogBuffer.h
@@ -0,0 +1,60 @@
+/*
+ * Copyright (C) 2012-2014 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 _LOGD_LOG_BUFFER_H__
+#define _LOGD_LOG_BUFFER_H__
+
+#include <sys/types.h>
+
+#include <log/log.h>
+#include <sysutils/SocketClient.h>
+#include <utils/List.h>
+
+#include "LogBufferElement.h"
+#include "LogTimes.h"
+
+typedef android::List<LogBufferElement *> LogBufferElementCollection;
+
+class LogBuffer {
+ LogBufferElementCollection mLogElements;
+ pthread_mutex_t mLogElementsLock;
+
+ unsigned long mSizes[LOG_ID_MAX];
+ unsigned long mElements[LOG_ID_MAX];
+
+public:
+ LastLogTimes &mTimes;
+
+ LogBuffer(LastLogTimes *times);
+
+ void log(log_id_t log_id, struct timespec realtime,
+ uid_t uid, pid_t pid, const char *msg, unsigned short len);
+ struct timespec flushTo(SocketClient *writer, const struct timespec start,
+ bool privileged,
+ bool (*filter)(const LogBufferElement *element, void *arg) = NULL,
+ void *arg = NULL);
+
+ void clear(log_id_t id);
+ unsigned long getSize(log_id_t id);
+ unsigned long getSizeUsed(log_id_t id);
+
+private:
+ void maybePrune(log_id_t id);
+ void prune(log_id_t id, unsigned long pruneRows);
+
+};
+
+#endif
diff --git a/logd/LogBufferElement.cpp b/logd/LogBufferElement.cpp
new file mode 100644
index 0000000..1c55623
--- /dev/null
+++ b/logd/LogBufferElement.cpp
@@ -0,0 +1,64 @@
+/*
+ * Copyright (C) 2012-2014 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 <stdio.h>
+#include <string.h>
+#include <time.h>
+#include <unistd.h>
+
+#include <log/logger.h>
+
+#include "LogBufferElement.h"
+#include "LogReader.h"
+
+const struct timespec LogBufferElement::FLUSH_ERROR = { 0, 0 };
+
+LogBufferElement::LogBufferElement(log_id_t log_id, struct timespec realtime, uid_t uid, pid_t pid, const char *msg, unsigned short len)
+ : mLogId(log_id)
+ , mUid(uid)
+ , mPid(pid)
+ , mMsgLen(len)
+ , mMonotonicTime(CLOCK_MONOTONIC)
+ , mRealTime(realtime) {
+ mMsg = new char[len];
+ memcpy(mMsg, msg, len);
+}
+
+LogBufferElement::~LogBufferElement() {
+ delete [] mMsg;
+}
+
+struct timespec LogBufferElement::flushTo(SocketClient *reader) {
+ struct logger_entry_v3 entry;
+ memset(&entry, 0, sizeof(struct logger_entry_v3));
+ entry.hdr_size = sizeof(struct logger_entry_v3);
+ entry.len = mMsgLen;
+ entry.lid = mLogId;
+ entry.pid = mPid;
+ entry.sec = mRealTime.tv_sec;
+ entry.nsec = mRealTime.tv_nsec;
+
+ struct iovec iovec[2];
+ iovec[0].iov_base = &entry;
+ iovec[0].iov_len = sizeof(struct logger_entry_v3);
+ iovec[1].iov_base = mMsg;
+ iovec[1].iov_len = mMsgLen;
+ if (reader->sendDatav(iovec, 2)) {
+ return FLUSH_ERROR;
+ }
+
+ return mMonotonicTime;
+}
diff --git a/logd/LogBufferElement.h b/logd/LogBufferElement.h
new file mode 100644
index 0000000..390c97c
--- /dev/null
+++ b/logd/LogBufferElement.h
@@ -0,0 +1,50 @@
+/*
+ * Copyright (C) 2012-2014 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 _LOGD_LOG_BUFFER_ELEMENT_H__
+#define _LOGD_LOG_BUFFER_ELEMENT_H__
+
+#include <sys/types.h>
+#include <sysutils/SocketClient.h>
+#include <log/log.h>
+#include <log/log_read.h>
+
+class LogBufferElement {
+ const log_id_t mLogId;
+ const uid_t mUid;
+ const pid_t mPid;
+ char *mMsg;
+ const unsigned short mMsgLen;
+ const log_time mMonotonicTime;
+ const log_time mRealTime;
+
+public:
+ LogBufferElement(log_id_t log_id, struct timespec realtime,
+ uid_t uid, pid_t pid, const char *msg, unsigned short len);
+ virtual ~LogBufferElement();
+
+ log_id_t getLogId() const { return mLogId; }
+ uid_t getUid(void) const { return mUid; }
+ pid_t getPid(void) const { return mPid; }
+ unsigned short getMsgLen() const { return mMsgLen; }
+ log_time getMonotonicTime(void) const { return mMonotonicTime; }
+ log_time getRealTime(void) const { return mRealTime; }
+
+ static const struct timespec FLUSH_ERROR;
+ struct timespec flushTo(SocketClient *writer);
+};
+
+#endif
diff --git a/logd/LogCommand.cpp b/logd/LogCommand.cpp
new file mode 100644
index 0000000..6ccc93e
--- /dev/null
+++ b/logd/LogCommand.cpp
@@ -0,0 +1,21 @@
+/*
+ * Copyright (C) 2012-2013 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 "LogCommand.h"
+
+LogCommand::LogCommand(const char *cmd)
+ : FrameworkCommand(cmd) {
+}
diff --git a/logd/LogCommand.h b/logd/LogCommand.h
new file mode 100644
index 0000000..aef6706
--- /dev/null
+++ b/logd/LogCommand.h
@@ -0,0 +1,28 @@
+/*
+ * Copyright (C) 2012-2013 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 _LOGD_COMMAND_H
+#define _LOGD_COMMAND_H
+
+#include <sysutils/FrameworkCommand.h>
+
+class LogCommand : public FrameworkCommand {
+public:
+ LogCommand(const char *cmd);
+ virtual ~LogCommand() {}
+};
+
+#endif
diff --git a/logd/LogListener.cpp b/logd/LogListener.cpp
new file mode 100644
index 0000000..c6b248b
--- /dev/null
+++ b/logd/LogListener.cpp
@@ -0,0 +1,108 @@
+/*
+ * Copyright (C) 2012-2014 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 <sys/socket.h>
+#include <sys/types.h>
+#include <sys/un.h>
+#include <unistd.h>
+
+#include <cutils/sockets.h>
+#include <log/logger.h>
+
+#include "LogListener.h"
+
+LogListener::LogListener(LogBuffer *buf, LogReader *reader)
+ : SocketListener(getLogSocket(), false)
+ , logbuf(buf)
+ , reader(reader)
+{ }
+
+bool LogListener::onDataAvailable(SocketClient *cli) {
+ char buffer[1024];
+ struct iovec iov = { buffer, sizeof(buffer) };
+ memset(buffer, 0, sizeof(buffer));
+
+ char control[CMSG_SPACE(sizeof(struct ucred))];
+ struct msghdr hdr = {
+ NULL,
+ 0,
+ &iov,
+ 1,
+ control,
+ sizeof(control),
+ 0,
+ };
+
+ int socket = cli->getSocket();
+
+ ssize_t n = recvmsg(socket, &hdr, 0);
+ if (n <= (ssize_t) sizeof_log_id_t) {
+ return false;
+ }
+
+ struct ucred *cred = NULL;
+
+ struct cmsghdr *cmsg = CMSG_FIRSTHDR(&hdr);
+ while (cmsg != NULL) {
+ if (cmsg->cmsg_level == SOL_SOCKET
+ && cmsg->cmsg_type == SCM_CREDENTIALS) {
+ cred = (struct ucred *)CMSG_DATA(cmsg);
+ break;
+ }
+ cmsg = CMSG_NXTHDR(&hdr, cmsg);
+ }
+
+ if (cred == NULL) {
+ return false;
+ }
+
+ if (cred->uid == getuid()) {
+ // ignore log messages we send to ourself.
+ // Such log messages are often generated by libraries we depend on
+ // which use standard Android logging.
+ return false;
+ }
+
+ // First log element is always log_id.
+ log_id_t log_id = (log_id_t) *((typeof_log_id_t *) buffer);
+ if (log_id < 0 || log_id >= LOG_ID_MAX) {
+ return false;
+ }
+
+ char *msg = ((char *)buffer) + sizeof_log_id_t;
+ n -= sizeof_log_id_t;
+
+ log_time realtime(msg);
+ msg += sizeof(log_time);
+ n -= sizeof(log_time);
+
+ unsigned short len = n;
+ if (len == n) {
+ logbuf->log(log_id, realtime, cred->uid, cred->pid, msg, len);
+ reader->notifyNewLog();
+ }
+
+ return true;
+}
+
+int LogListener::getLogSocket() {
+ int sock = android_get_control_socket("logdw");
+ int on = 1;
+ if (setsockopt(sock, SOL_SOCKET, SO_PASSCRED, &on, sizeof(on)) < 0) {
+ return -1;
+ }
+ return sock;
+}
diff --git a/logd/LogListener.h b/logd/LogListener.h
new file mode 100644
index 0000000..7099e13
--- /dev/null
+++ b/logd/LogListener.h
@@ -0,0 +1,37 @@
+/*
+ * Copyright (C) 2012-2013 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 _LOGD_LOG_LISTENER_H__
+#define _LOGD_LOG_LISTENER_H__
+
+#include <sysutils/SocketListener.h>
+#include "LogReader.h"
+
+class LogListener : public SocketListener {
+ LogBuffer *logbuf;
+ LogReader *reader;
+
+public:
+ LogListener(LogBuffer *buf, LogReader *reader);
+
+protected:
+ virtual bool onDataAvailable(SocketClient *cli);
+
+private:
+ static int getLogSocket();
+};
+
+#endif
diff --git a/logd/LogReader.cpp b/logd/LogReader.cpp
new file mode 100644
index 0000000..5b540bf
--- /dev/null
+++ b/logd/LogReader.cpp
@@ -0,0 +1,105 @@
+/*
+ * Copyright (C) 2012-2013 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 <poll.h>
+#include <sys/socket.h>
+#include <cutils/sockets.h>
+
+#include "LogReader.h"
+#include "FlushCommand.h"
+
+LogReader::LogReader(LogBuffer *logbuf)
+ : SocketListener("logdr", true)
+ , mLogbuf(*logbuf)
+{ }
+
+// When we are notified a new log entry is available, inform
+// all of our listening sockets.
+void LogReader::notifyNewLog() {
+ FlushCommand command(*this);
+ runOnEachSocket(&command);
+}
+
+bool LogReader::onDataAvailable(SocketClient *cli) {
+ char buffer[255];
+
+ int len = read(cli->getSocket(), buffer, sizeof(buffer) - 1);
+ if (len <= 0) {
+ doSocketDelete(cli);
+ return false;
+ }
+ buffer[len] = '\0';
+
+ unsigned long tail = 0;
+ static const char _tail[] = " tail=";
+ char *cp = strstr(buffer, _tail);
+ if (cp) {
+ tail = atol(cp + sizeof(_tail) - 1);
+ }
+
+ unsigned int logMask = -1;
+ static const char _logIds[] = " lids=";
+ cp = strstr(buffer, _logIds);
+ if (cp) {
+ logMask = 0;
+ cp += sizeof(_logIds) - 1;
+ while (*cp && *cp != '\0') {
+ int val = 0;
+ while (('0' <= *cp) && (*cp <= '9')) {
+ val *= 10;
+ val += *cp - '0';
+ ++cp;
+ }
+ logMask |= 1 << val;
+ if (*cp != ',') {
+ break;
+ }
+ ++cp;
+ }
+ }
+
+ pid_t pid = 0;
+ static const char _pid[] = " pid=";
+ cp = strstr(buffer, _pid);
+ if (cp) {
+ pid = atol(cp + sizeof(_pid) - 1);
+ }
+
+ bool nonBlock = false;
+ if (strncmp(buffer, "dumpAndClose", 12) == 0) {
+ nonBlock = true;
+ }
+
+ FlushCommand command(*this, nonBlock, tail, logMask, pid);
+ command.runSocketCommand(cli);
+ return true;
+}
+
+void LogReader::doSocketDelete(SocketClient *cli) {
+ LastLogTimes × = mLogbuf.mTimes;
+ LogTimeEntry::lock();
+ LastLogTimes::iterator it = times.begin();
+ while(it != times.end()) {
+ LogTimeEntry *entry = (*it);
+ if (entry->mClient == cli) {
+ times.erase(it);
+ entry->release_Locked();
+ break;
+ }
+ it++;
+ }
+ LogTimeEntry::unlock();
+}
diff --git a/logd/LogReader.h b/logd/LogReader.h
new file mode 100644
index 0000000..b267c75
--- /dev/null
+++ b/logd/LogReader.h
@@ -0,0 +1,41 @@
+/*
+ * Copyright (C) 2012-2013 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 _LOGD_LOG_WRITER_H__
+#define _LOGD_LOG_WRITER_H__
+
+#include <sysutils/SocketListener.h>
+#include "LogBuffer.h"
+#include "LogTimes.h"
+
+class LogReader : public SocketListener {
+ LogBuffer &mLogbuf;
+
+public:
+ LogReader(LogBuffer *logbuf);
+ void notifyNewLog();
+
+ LogBuffer &logbuf(void) const { return mLogbuf; }
+
+protected:
+ virtual bool onDataAvailable(SocketClient *cli);
+
+private:
+ void doSocketDelete(SocketClient *cli);
+
+};
+
+#endif
diff --git a/logd/LogTimes.cpp b/logd/LogTimes.cpp
new file mode 100644
index 0000000..67cc65e
--- /dev/null
+++ b/logd/LogTimes.cpp
@@ -0,0 +1,225 @@
+/*
+ * Copyright (C) 2014 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 "FlushCommand.h"
+#include "LogBuffer.h"
+#include "LogTimes.h"
+#include "LogReader.h"
+
+pthread_mutex_t LogTimeEntry::timesLock = PTHREAD_MUTEX_INITIALIZER;
+
+const struct timespec LogTimeEntry::EPOCH = { 0, 1 };
+
+LogTimeEntry::LogTimeEntry(LogReader &reader, SocketClient *client,
+ bool nonBlock, unsigned long tail,
+ unsigned int logMask, pid_t pid)
+ : mRefCount(1)
+ , mRelease(false)
+ , mError(false)
+ , threadRunning(false)
+ , threadTriggered(true)
+ , mReader(reader)
+ , mLogMask(logMask)
+ , mPid(pid)
+ , skipAhead(0)
+ , mCount(0)
+ , mTail(tail)
+ , mIndex(0)
+ , mClient(client)
+ , mStart(EPOCH)
+ , mNonBlock(nonBlock)
+ , mEnd(CLOCK_MONOTONIC)
+{ }
+
+void LogTimeEntry::startReader_Locked(void) {
+ threadRunning = true;
+ if (pthread_create(&mThread, NULL, LogTimeEntry::threadStart, this)) {
+ threadRunning = false;
+ if (mClient) {
+ mClient->decRef();
+ }
+ decRef_Locked();
+ }
+}
+
+void LogTimeEntry::threadStop(void *obj) {
+ LogTimeEntry *me = reinterpret_cast<LogTimeEntry *>(obj);
+
+ lock();
+
+ me->threadRunning = false;
+ if (me->mNonBlock) {
+ me->error_Locked();
+ }
+
+ SocketClient *client = me->mClient;
+
+ if (me->isError_Locked()) {
+ LogReader &reader = me->mReader;
+ LastLogTimes × = reader.logbuf().mTimes;
+
+ LastLogTimes::iterator it = times.begin();
+ while(it != times.end()) {
+ if (*it == me) {
+ times.erase(it);
+ me->release_Locked();
+ break;
+ }
+ it++;
+ }
+
+ me->mClient = NULL;
+ reader.release(client);
+ }
+
+ if (client) {
+ client->decRef();
+ }
+
+ me->decRef_Locked();
+
+ unlock();
+}
+
+void *LogTimeEntry::threadStart(void *obj) {
+ LogTimeEntry *me = reinterpret_cast<LogTimeEntry *>(obj);
+
+ pthread_cleanup_push(threadStop, obj);
+
+ SocketClient *client = me->mClient;
+ if (!client) {
+ me->error();
+ pthread_exit(NULL);
+ }
+
+ LogBuffer &logbuf = me->mReader.logbuf();
+
+ bool privileged = FlushCommand::hasReadLogs(client);
+
+ lock();
+
+ me->threadTriggered = true;
+
+ while(me->threadTriggered && !me->isError_Locked()) {
+
+ me->threadTriggered = false;
+
+ log_time start = me->mStart;
+
+ unlock();
+
+ if (me->mTail) {
+ logbuf.flushTo(client, start, privileged, FilterFirstPass, me);
+ }
+ start = logbuf.flushTo(client, start, privileged, FilterSecondPass, me);
+
+ if (start == LogBufferElement::FLUSH_ERROR) {
+ me->error();
+ }
+
+ if (me->mNonBlock) {
+ lock();
+ break;
+ }
+
+ sched_yield();
+
+ lock();
+ }
+
+ unlock();
+
+ pthread_exit(NULL);
+
+ pthread_cleanup_pop(true);
+
+ return NULL;
+}
+
+// A first pass to count the number of elements
+bool LogTimeEntry::FilterFirstPass(const LogBufferElement *element, void *obj) {
+ LogTimeEntry *me = reinterpret_cast<LogTimeEntry *>(obj);
+
+ LogTimeEntry::lock();
+
+ if (me->mCount == 0) {
+ me->mStart = element->getMonotonicTime();
+ }
+
+ if ((!me->mPid || (me->mPid == element->getPid()))
+ && (me->mLogMask & (1 << element->getLogId()))) {
+ ++me->mCount;
+ }
+
+ LogTimeEntry::unlock();
+
+ return false;
+}
+
+// A second pass to send the selected elements
+bool LogTimeEntry::FilterSecondPass(const LogBufferElement *element, void *obj) {
+ LogTimeEntry *me = reinterpret_cast<LogTimeEntry *>(obj);
+
+ LogTimeEntry::lock();
+
+ if (me->skipAhead) {
+ me->skipAhead--;
+ }
+
+ me->mStart = element->getMonotonicTime();
+
+ // Truncate to close race between first and second pass
+ if (me->mNonBlock && me->mTail && (me->mIndex >= me->mCount)) {
+ goto skip;
+ }
+
+ if ((me->mLogMask & (1 << element->getLogId())) == 0) {
+ goto skip;
+ }
+
+ if (me->mPid && (me->mPid != element->getPid())) {
+ goto skip;
+ }
+
+ if (me->isError_Locked()) {
+ goto skip;
+ }
+
+ if (!me->mTail) {
+ goto ok;
+ }
+
+ ++me->mIndex;
+
+ if ((me->mCount > me->mTail) && (me->mIndex <= (me->mCount - me->mTail))) {
+ goto skip;
+ }
+
+ if (!me->mNonBlock) {
+ me->mTail = 0;
+ }
+
+ok:
+ if (!me->skipAhead) {
+ LogTimeEntry::unlock();
+ return true;
+ }
+ // FALLTHRU
+
+skip:
+ LogTimeEntry::unlock();
+ return false;
+}
diff --git a/logd/LogTimes.h b/logd/LogTimes.h
new file mode 100644
index 0000000..cb6f566
--- /dev/null
+++ b/logd/LogTimes.h
@@ -0,0 +1,105 @@
+/*
+ * Copyright (C) 2012-2013 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 _LOGD_LOG_TIMES_H__
+#define _LOGD_LOG_TIMES_H__
+
+#include <pthread.h>
+#include <time.h>
+#include <sys/types.h>
+#include <sysutils/SocketClient.h>
+#include <utils/List.h>
+
+class LogReader;
+
+class LogTimeEntry {
+ static pthread_mutex_t timesLock;
+ unsigned int mRefCount;
+ bool mRelease;
+ bool mError;
+ bool threadRunning;
+ bool threadTriggered;
+ pthread_t mThread;
+ LogReader &mReader;
+ static void *threadStart(void *me);
+ static void threadStop(void *me);
+ const unsigned int mLogMask;
+ const pid_t mPid;
+ unsigned int skipAhead;
+ unsigned long mCount;
+ unsigned long mTail;
+ unsigned long mIndex;
+
+public:
+ LogTimeEntry(LogReader &reader, SocketClient *client, bool nonBlock,
+ unsigned long tail, unsigned int logMask, pid_t pid);
+
+ SocketClient *mClient;
+ static const struct timespec EPOCH;
+ log_time mStart;
+ const bool mNonBlock;
+ const log_time mEnd; // only relevant if mNonBlock
+
+ // Protect List manipulations
+ static void lock(void) { pthread_mutex_lock(×Lock); }
+ static void unlock(void) { pthread_mutex_unlock(×Lock); }
+
+ void startReader_Locked(void);
+
+ bool runningReader_Locked(void) const {
+ return threadRunning || mRelease || mError || mNonBlock;
+ }
+ void triggerReader_Locked(void) { threadTriggered = true; }
+ void triggerSkip_Locked(unsigned int skip) { skipAhead = skip; }
+
+ // Called after LogTimeEntry removed from list, lock implicitly held
+ void release_Locked(void) {
+ mRelease = true;
+ if (mRefCount || threadRunning) {
+ return;
+ }
+ // No one else is holding a reference to this
+ delete this;
+ }
+
+ // Called to mark socket in jeopardy
+ void error_Locked(void) { mError = true; }
+ void error(void) { lock(); mError = true; unlock(); }
+
+ bool isError_Locked(void) const { return mRelease || mError; }
+
+ // Mark Used
+ // Locking implied, grabbed when protection around loop iteration
+ void incRef_Locked(void) { ++mRefCount; }
+
+ bool owned_Locked(void) const { return mRefCount != 0; }
+
+ void decRef_Locked(void) {
+ if ((mRefCount && --mRefCount) || !mRelease || threadRunning) {
+ return;
+ }
+ // No one else is holding a reference to this
+ delete this;
+ }
+
+ // flushTo filter callbacks
+ static bool FilterFirstPass(const LogBufferElement *element, void *me);
+ static bool FilterSecondPass(const LogBufferElement *element, void *me);
+};
+
+typedef android::List<LogTimeEntry *> LastLogTimes;
+
+#endif
diff --git a/logd/main.cpp b/logd/main.cpp
new file mode 100644
index 0000000..1891206
--- /dev/null
+++ b/logd/main.cpp
@@ -0,0 +1,123 @@
+/*
+ * Copyright (C) 2012-2013 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 <dirent.h>
+#include <errno.h>
+#include <fcntl.h>
+#include <sched.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <sys/capability.h>
+#include <sys/stat.h>
+#include <sys/types.h>
+
+#include <linux/prctl.h>
+
+#include "private/android_filesystem_config.h"
+#include "CommandListener.h"
+#include "LogBuffer.h"
+#include "LogListener.h"
+
+static int drop_privs() {
+ struct sched_param param;
+ memset(¶m, 0, sizeof(param));
+
+ if (sched_setscheduler((pid_t) 0, SCHED_BATCH, ¶m) < 0) {
+ return -1;
+ }
+
+ if (prctl(PR_SET_KEEPCAPS, 1) < 0) {
+ return -1;
+ }
+
+ if (setgid(AID_LOGD) != 0) {
+ return -1;
+ }
+
+ if (setuid(AID_LOGD) != 0) {
+ return -1;
+ }
+
+ struct __user_cap_header_struct capheader;
+ struct __user_cap_data_struct capdata[2];
+ memset(&capheader, 0, sizeof(capheader));
+ memset(&capdata, 0, sizeof(capdata));
+ capheader.version = _LINUX_CAPABILITY_VERSION_3;
+ capheader.pid = 0;
+
+ capdata[CAP_TO_INDEX(CAP_SYSLOG)].permitted = CAP_TO_MASK(CAP_SYSLOG);
+ capdata[CAP_TO_INDEX(CAP_SYSLOG)].effective = CAP_TO_MASK(CAP_SYSLOG);
+ capdata[0].inheritable = 0;
+ capdata[1].inheritable = 0;
+
+ if (capset(&capheader, &capdata[0]) < 0) {
+ return -1;
+ }
+
+ return 0;
+}
+
+// Foreground waits for exit of the three main persistent threads that
+// are started here. The three threads are created to manage UNIX
+// domain client sockets for writing, reading and controlling the user
+// space logger. Additional transitory per-client threads are created
+// for each reader once they register.
+int main() {
+ if (drop_privs() != 0) {
+ return -1;
+ }
+
+ // Serves the purpose of managing the last logs times read on a
+ // socket connection, and as a reader lock on a range of log
+ // entries.
+
+ LastLogTimes *times = new LastLogTimes();
+
+ // LogBuffer is the object which is responsible for holding all
+ // log entries.
+
+ LogBuffer *logBuf = new LogBuffer(times);
+
+ // LogReader listens on /dev/socket/logdr. When a client
+ // connects, log entries in the LogBuffer are written to the client.
+
+ LogReader *reader = new LogReader(logBuf);
+ if (reader->startListener()) {
+ exit(1);
+ }
+
+ // LogListener listens on /dev/socket/logdw for client
+ // initiated log messages. New log entries are added to LogBuffer
+ // and LogReader is notified to send updates to connected clients.
+
+ LogListener *swl = new LogListener(logBuf, reader);
+ if (swl->startListener()) {
+ exit(1);
+ }
+
+ // Command listener listens on /dev/socket/logd for incoming logd
+ // administrative commands.
+
+ CommandListener *cl = new CommandListener(logBuf, reader, swl);
+ if (cl->startListener()) {
+ exit(1);
+ }
+
+ pause();
+ exit(0);
+}
+
diff --git a/rootdir/init.rc b/rootdir/init.rc
index 55eb429..9975368 100644
--- a/rootdir/init.rc
+++ b/rootdir/init.rc
@@ -451,6 +451,12 @@
on property:ro.kernel.qemu=1
start adbd
+service logd /system/bin/logd
+ class main
+ socket logd stream 0666 logd logd
+ socket logdr seqpacket 0666 logd logd
+ socket logdw dgram 0222 logd logd
+
service servicemanager /system/bin/servicemanager
class core
user system
@@ -476,6 +482,9 @@
service debuggerd /system/bin/debuggerd
class main
+service debuggerd64 /system/bin/debuggerd64
+ class main
+
service ril-daemon /system/bin/rild
class main
socket rild stream 660 root radio
diff --git a/sdcard/sdcard.c b/sdcard/sdcard.c
index 4722708..6a9c2eb 100644
--- a/sdcard/sdcard.c
+++ b/sdcard/sdcard.c
@@ -232,7 +232,7 @@
* buffer at the same time. This allows us to share the underlying storage. */
union {
__u8 request_buffer[MAX_REQUEST_SIZE];
- __u8 read_buffer[MAX_READ];
+ __u8 read_buffer[MAX_READ + PAGESIZE];
};
};
@@ -1218,6 +1218,7 @@
__u32 size = req->size;
__u64 offset = req->offset;
int res;
+ __u8 *read_buffer = (__u8 *) ((uintptr_t)(handler->read_buffer + PAGESIZE) & ~((uintptr_t)PAGESIZE-1));
/* Don't access any other fields of hdr or req beyond this point, the read buffer
* overlaps the request buffer and will clobber data in the request. This
@@ -1225,14 +1226,14 @@
TRACE("[%d] READ %p(%d) %u@%llu\n", handler->token,
h, h->fd, size, offset);
- if (size > sizeof(handler->read_buffer)) {
+ if (size > MAX_READ) {
return -EINVAL;
}
- res = pread64(h->fd, handler->read_buffer, size, offset);
+ res = pread64(h->fd, read_buffer, size, offset);
if (res < 0) {
return -errno;
}
- fuse_reply(fuse, unique, handler->read_buffer, res);
+ fuse_reply(fuse, unique, read_buffer, res);
return NO_STATUS;
}
@@ -1243,6 +1244,12 @@
struct fuse_write_out out;
struct handle *h = id_to_ptr(req->fh);
int res;
+ __u8 aligned_buffer[req->size] __attribute__((__aligned__(PAGESIZE)));
+
+ if (req->flags & O_DIRECT) {
+ memcpy(aligned_buffer, buffer, req->size);
+ buffer = (const __u8*) aligned_buffer;
+ }
TRACE("[%d] WRITE %p(%d) %u@%llu\n", handler->token,
h, h->fd, req->size, req->offset);
@@ -1496,7 +1503,8 @@
return handle_release(fuse, handler, hdr, req);
}
- case FUSE_FSYNC: {
+ case FUSE_FSYNC:
+ case FUSE_FSYNCDIR: {
const struct fuse_fsync_in *req = data;
return handle_fsync(fuse, handler, hdr, req);
}
@@ -1524,7 +1532,6 @@
return handle_releasedir(fuse, handler, hdr, req);
}
-// case FUSE_FSYNCDIR:
case FUSE_INIT: { /* init_in -> init_out */
const struct fuse_init_in *req = data;
return handle_init(fuse, handler, hdr, req);
diff --git a/toolbox/mkswap.c b/toolbox/mkswap.c
index 1710ef6..0904152 100644
--- a/toolbox/mkswap.c
+++ b/toolbox/mkswap.c
@@ -1,6 +1,5 @@
#include <stdio.h>
#include <unistd.h>
-#include <asm/page.h>
#include <sys/swap.h>
#include <sys/types.h>
#include <sys/stat.h>
diff --git a/toolbox/nandread.c b/toolbox/nandread.c
index d43b2fe..971c232 100644
--- a/toolbox/nandread.c
+++ b/toolbox/nandread.c
@@ -177,11 +177,7 @@
if (rawmode) {
rawmode = mtdinfo.oobsize;
-#if !defined(MTD_STUPID_LOCK) /* using uapi kernel headers */
ret = ioctl(fd, MTDFILEMODE, MTD_FILE_MODE_RAW);
-#else /* still using old kernel headers */
- ret = ioctl(fd, MTDFILEMODE, MTD_MODE_RAW);
-#endif
if (ret) {
fprintf(stderr, "failed set raw mode for %s, %s\n",
devname, strerror(errno));
diff --git a/toolbox/restorecon.c b/toolbox/restorecon.c
index f9f604f..3568625 100644
--- a/toolbox/restorecon.c
+++ b/toolbox/restorecon.c
@@ -2,76 +2,44 @@
#include <stdio.h>
#include <stdlib.h>
#include <errno.h>
-#include <sys/types.h>
-#include <sys/stat.h>
-#include <fts.h>
#include <selinux/selinux.h>
-#include <selinux/label.h>
#include <selinux/android.h>
-static struct selabel_handle *sehandle;
static const char *progname;
-static int nochange;
-static int verbose;
static void usage(void)
{
- fprintf(stderr, "usage: %s [-nrRv] pathname...\n", progname);
+ fprintf(stderr, "usage: %s [-DFnrRv] pathname...\n", progname);
exit(1);
}
-static int restore(const char *pathname, const struct stat *sb)
-{
- char *oldcontext, *newcontext;
-
- if (lgetfilecon(pathname, &oldcontext) < 0) {
- fprintf(stderr, "Could not get context of %s: %s\n",
- pathname, strerror(errno));
- return -1;
- }
- if (selabel_lookup(sehandle, &newcontext, pathname, sb->st_mode) < 0) {
- fprintf(stderr, "Could not lookup context for %s: %s\n", pathname,
- strerror(errno));
- return -1;
- }
- if (strcmp(newcontext, "<<none>>") &&
- strcmp(oldcontext, newcontext)) {
- if (verbose)
- printf("Relabeling %s from %s to %s.\n", pathname, oldcontext, newcontext);
- if (!nochange) {
- if (lsetfilecon(pathname, newcontext) < 0) {
- fprintf(stderr, "Could not label %s with %s: %s\n",
- pathname, newcontext, strerror(errno));
- return -1;
- }
- }
- }
- freecon(oldcontext);
- freecon(newcontext);
- return 0;
-}
-
int restorecon_main(int argc, char **argv)
{
- int ch, recurse = 0, ftsflags = FTS_PHYSICAL;
- int i = 0;
+ int ch, i, rc;
+ unsigned int flags = 0;
progname = argv[0];
do {
- ch = getopt(argc, argv, "nrRv");
+ ch = getopt(argc, argv, "DFnrRv");
if (ch == EOF)
break;
switch (ch) {
+ case 'D':
+ flags |= SELINUX_ANDROID_RESTORECON_DATADATA;
+ break;
+ case 'F':
+ flags |= SELINUX_ANDROID_RESTORECON_FORCE;
+ break;
case 'n':
- nochange = 1;
+ flags |= SELINUX_ANDROID_RESTORECON_NOCHANGE;
break;
case 'r':
case 'R':
- recurse = 1;
+ flags |= SELINUX_ANDROID_RESTORECON_RECURSE;
break;
case 'v':
- verbose = 1;
+ flags |= SELINUX_ANDROID_RESTORECON_VERBOSE;
break;
default:
usage();
@@ -83,53 +51,11 @@
if (!argc)
usage();
- sehandle = selinux_android_file_context_handle();
-
- if (!sehandle) {
- fprintf(stderr, "Could not load file_contexts: %s\n",
- strerror(errno));
- return -1;
- }
-
- if (recurse) {
- FTS *fts;
- FTSENT *ftsent;
- fts = fts_open(argv, ftsflags, NULL);
- if (!fts) {
- fprintf(stderr, "Could not traverse filesystems (first was %s): %s\n",
- argv[0], strerror(errno));
- return -1;
- }
- while ((ftsent = fts_read(fts))) {
- switch (ftsent->fts_info) {
- case FTS_DP:
- break;
- case FTS_DNR:
- case FTS_ERR:
- case FTS_NS:
- fprintf(stderr, "Could not access %s: %s\n", ftsent->fts_path,
- strerror(errno));
- fts_set(fts, ftsent, FTS_SKIP);
- break;
- default:
- if (restore(ftsent->fts_path, ftsent->fts_statp) < 0)
- fts_set(fts, ftsent, FTS_SKIP);
- break;
- }
- }
- } else {
- int i, rc;
- struct stat sb;
-
- for (i = 0; i < argc; i++) {
- rc = lstat(argv[i], &sb);
- if (rc < 0) {
- fprintf(stderr, "Could not stat %s: %s\n", argv[i],
- strerror(errno));
- continue;
- }
- restore(argv[i], &sb);
- }
+ for (i = 0; i < argc; i++) {
+ rc = selinux_android_restorecon(argv[i], flags);
+ if (rc < 0)
+ fprintf(stderr, "Could not restorecon %s: %s\n", argv[i],
+ strerror(errno));
}
return 0;
diff --git a/toolbox/swapoff.c b/toolbox/swapoff.c
index 8f14158..d8f6a00 100644
--- a/toolbox/swapoff.c
+++ b/toolbox/swapoff.c
@@ -1,6 +1,5 @@
#include <stdio.h>
#include <unistd.h>
-#include <asm/page.h>
#include <sys/swap.h>
int swapoff_main(int argc, char **argv)
diff --git a/toolbox/swapon.c b/toolbox/swapon.c
index a810b3d..21d2287 100644
--- a/toolbox/swapon.c
+++ b/toolbox/swapon.c
@@ -2,7 +2,6 @@
#include <stdlib.h>
#include <unistd.h>
#include <getopt.h>
-#include <asm/page.h>
#include <sys/swap.h>
void usage(char *name)