diff options
83 files changed, 2374 insertions, 1998 deletions
@@ -339,6 +339,8 @@ int adb_commandline(int argc, const char **argv); int connection_state(atransport *t); +extern int recovery_mode; + #define CS_ANY -1 #define CS_OFFLINE 0 #define CS_BOOTLOADER 1 @@ -350,6 +352,9 @@ int connection_state(atransport *t); #define CS_UNAUTHORIZED 7 extern const char *adb_device_banner; + +#define CS_ONLINE 10 /* recovery or device */ + extern int HOST; extern int SHELL_EXIT_NOTIFY_FD; diff --git a/adb/adb_main.cpp b/adb/adb_main.cpp index 45a2158..4025fbe 100644 --- a/adb/adb_main.cpp +++ b/adb/adb_main.cpp @@ -239,7 +239,9 @@ int adb_main(int is_daemon, int server_port) // descriptor will always be open. adbd_cloexec_auth_socket(); - if (ALLOW_ADBD_NO_AUTH && property_get_bool("ro.adb.secure", 0) == 0) { + // Override auth in factory test mode + if ((ALLOW_ADBD_NO_AUTH && property_get_bool("ro.adb.secure", 0) == 0) || + (property_get_bool("ro.boot.ftm", 0) == 1)) { auth_required = false; } @@ -359,6 +361,10 @@ void close_stdin() { } #endif +#if !ADB_HOST +int recovery_mode = 0; +#endif + // TODO(danalbert): Split this file up into adb_main.cpp and adbd_main.cpp. int main(int argc, char **argv) { #if ADB_HOST @@ -397,6 +403,8 @@ int main(int argc, char **argv) { } } + recovery_mode = (strcmp(adb_device_banner, "recovery") == 0); + close_stdin(); adb_trace_init(); diff --git a/adb/commandline.cpp b/adb/commandline.cpp index fd9953c..d38588f 100644 --- a/adb/commandline.cpp +++ b/adb/commandline.cpp @@ -497,6 +497,8 @@ static int adb_download_buffer(const char *service, const char *fn, const void* #define SIDELOAD_HOST_BLOCK_SIZE (CHUNK_SIZE) +#define MB (1024*1024) + /* * The sideload-host protocol serves the data in a file (given on the * command line) to the client, using a simple protocol: @@ -517,10 +519,13 @@ static int adb_download_buffer(const char *service, const char *fn, const void* * we hang up. */ static int adb_sideload_host(const char* fn) { + static const char spinner[] = "/-\\|"; + static const int spinlen = sizeof(spinner)-1; + size_t last_xfer = 0; + int spin_index = 0; unsigned sz; size_t xfer = 0; int status; - int last_percent = -1; int opt = SIDELOAD_HOST_BLOCK_SIZE; printf("loading: '%s'", fn); @@ -531,6 +536,11 @@ static int adb_sideload_host(const char* fn) { fprintf(stderr, "* cannot read '%s' *\n", fn); return -1; } + if (sz == 0) { + printf("\n"); + fprintf(stderr, "* '%s' is empty *\n", fn); + return -1; + } std::string service = android::base::StringPrintf("sideload-host:%d:%d", sz, SIDELOAD_HOST_BLOCK_SIZE); @@ -547,6 +557,24 @@ static int adb_sideload_host(const char* fn) { opt = adb_setsockopt(fd, SOL_SOCKET, SO_SNDBUF, (const void *) &opt, sizeof(opt)); while (true) { + fd_set fds; + struct timeval tv; + FD_ZERO(&fds); + FD_SET(fd, &fds); + tv.tv_sec = 1; + tv.tv_usec = 0; + int rc = select(fd+1, &fds, NULL, NULL, &tv); + size_t diff = xfer - last_xfer; + if (rc == 0 || diff >= (1*MB)) { + spin_index = (spin_index+1) % spinlen; + printf("\rserving: '%s' %4umb %.2fx %c", fn, + (unsigned)xfer/(1*MB), (double)xfer/sz, spinner[spin_index]); + fflush(stdout); + last_xfer = xfer; + } + if (rc == 0) { + continue; + } char buf[9]; if (!ReadFdExactly(fd, buf, 8)) { fprintf(stderr, "* failed to read command: %s\n", strerror(errno)); @@ -582,22 +610,9 @@ static int adb_sideload_host(const char* fn) { goto done; } xfer += to_write; - - // For normal OTA packages, we expect to transfer every byte - // twice, plus a bit of overhead (one read during - // verification, one read of each byte for installation, plus - // extra access to things like the zip central directory). - // This estimate of the completion becomes 100% when we've - // transferred ~2.13 (=100/47) times the package size. - int percent = (int)(xfer * 47LL / (sz ? sz : 1)); - if (percent != last_percent) { - printf("\rserving: '%s' (~%d%%) ", fn, percent); - fflush(stdout); - last_percent = percent; - } } - printf("\rTotal xfer: %.2fx%*s\n", (double)xfer / (sz ? sz : 1), (int)strlen(fn)+10, ""); + printf("\ntotal xfer: %4umb %.2fx\n", (unsigned)xfer/(1*MB), (double)xfer/sz); done: if (fd >= 0) adb_close(fd); diff --git a/adb/services.cpp b/adb/services.cpp index 1847447..ef2fa56 100644 --- a/adb/services.cpp +++ b/adb/services.cpp @@ -76,6 +76,18 @@ void restart_root_service(int fd, void *cookie) { return; } + char build_type[PROPERTY_VALUE_MAX]; + char cm_version[PROPERTY_VALUE_MAX]; + property_get("persist.sys.root_access", value, "0"); + property_get("ro.build.type", build_type, ""); + property_get("ro.cm.version", cm_version, ""); + + if (strlen(cm_version) > 0 && strcmp(build_type, "eng") != 0 && (atoi(value) & 2) != 2) { + WriteFdExactly(fd, "root access is disabled by system setting - enable in settings -> development options\n"); + adb_close(fd); + return; + } + property_set("service.adb.root", "1"); WriteFdExactly(fd, "restarting adbd as root\n"); adb_close(fd); @@ -342,8 +354,10 @@ static int create_subproc_raw(const char *cmd, const char *arg0, const char *arg #if ADB_HOST #define SHELL_COMMAND "/bin/sh" +#define ALTERNATE_SHELL_COMMAND "" #else #define SHELL_COMMAND "/system/bin/sh" +#define ALTERNATE_SHELL_COMMAND "/sbin/sh" #endif #if !ADB_HOST @@ -384,6 +398,9 @@ static int create_subproc_thread(const char *name, const subproc_mode mode) int ret_fd; pid_t pid = -1; + const char* shell_command; + struct stat st; + const char *arg0, *arg1; if (name == 0 || *name == 0) { arg0 = "-"; arg1 = 0; @@ -391,12 +408,24 @@ static int create_subproc_thread(const char *name, const subproc_mode mode) arg0 = "-c"; arg1 = name; } + char value[PROPERTY_VALUE_MAX]; + property_get("persist.sys.adb.shell", value, ""); + if (value[0] != '\0' && stat(value, &st) == 0) { + shell_command = value; + } + else if (stat(ALTERNATE_SHELL_COMMAND, &st) == 0) { + shell_command = ALTERNATE_SHELL_COMMAND; + } + else { + shell_command = SHELL_COMMAND; + } + switch (mode) { case SUBPROC_PTY: - ret_fd = create_subproc_pty(SHELL_COMMAND, arg0, arg1, &pid); + ret_fd = create_subproc_pty(shell_command, arg0, arg1, &pid); break; case SUBPROC_RAW: - ret_fd = create_subproc_raw(SHELL_COMMAND, arg0, arg1, &pid); + ret_fd = create_subproc_raw(shell_command, arg0, arg1, &pid); break; default: fprintf(stderr, "invalid subproc_mode %d\n", mode); @@ -422,6 +451,13 @@ static int create_subproc_thread(const char *name, const subproc_mode mode) } #endif +#if !ADB_HOST +static const char* bu_path() +{ + return (recovery_mode ? "/sbin/bu" : "/system/bin/bu"); +} +#endif + int service_to_fd(const char *name) { int ret = -1; @@ -478,10 +514,14 @@ int service_to_fd(const char *name) } else if(!strncmp(name, "unroot:", 7)) { ret = create_service_thread(restart_unroot_service, NULL); } else if(!strncmp(name, "backup:", 7)) { - ret = create_subproc_thread(android::base::StringPrintf("/system/bin/bu backup %s", + ret = create_subproc_thread(android::base::StringPrintf("%s backup %s", bu_path(), (name + 7)).c_str(), SUBPROC_RAW); } else if(!strncmp(name, "restore:", 8)) { - ret = create_subproc_thread("/system/bin/bu restore", SUBPROC_RAW); + char* cmd; + if (asprintf(&cmd, "%s restore", bu_path()) != -1) { + ret = create_subproc_thread(cmd, SUBPROC_RAW); + free(cmd); + } } else if(!strncmp(name, "tcpip:", 6)) { int port; if (sscanf(name + 6, "%d", &port) != 1) { @@ -672,6 +712,15 @@ asocket* host_service_to_socket(const char* name, const char *serial) } else if (!strncmp(name, "any", strlen("any"))) { sinfo->transport = kTransportAny; sinfo->state = CS_DEVICE; + } else if (!strncmp(name, "sideload", strlen("sideload"))) { + sinfo->transport = kTransportAny; + sinfo->state = CS_SIDELOAD; + } else if (!strncmp(name, "recovery", strlen("recovery"))) { + sinfo->transport = kTransportAny; + sinfo->state = CS_RECOVERY; + } else if (!strncmp(name, "online", strlen("online"))) { + sinfo->transport = kTransportAny; + sinfo->state = CS_ONLINE; } else { free(sinfo); return NULL; diff --git a/adb/transport.cpp b/adb/transport.cpp index 2cd6ac2..5ae49d3 100644 --- a/adb/transport.cpp +++ b/adb/transport.cpp @@ -821,8 +821,10 @@ retry: result = NULL; } - /* check for required connection state */ - if (result && state != CS_ANY && result->connection_state != state) { + /* check for required connection state */ + if (result && state != CS_ANY && ((state != CS_ONLINE && result->connection_state != state) + || (state == CS_ONLINE && !(result->connection_state == CS_DEVICE + || result->connection_state == CS_RECOVERY)))) { if (error_out) *error_out = "invalid device state"; result = NULL; } diff --git a/adb/usb_linux_client.cpp b/adb/usb_linux_client.cpp index f3db346..44df695 100644 --- a/adb/usb_linux_client.cpp +++ b/adb/usb_linux_client.cpp @@ -333,37 +333,35 @@ static void init_functionfs(struct usb_handle *h) v2_descriptor.hs_descs = hs_descriptors; v2_descriptor.ss_descs = ss_descriptors; - if (h->control < 0) { // might have already done this before - D("OPENING %s\n", USB_FFS_ADB_EP0); - h->control = adb_open(USB_FFS_ADB_EP0, O_RDWR); - if (h->control < 0) { - D("[ %s: cannot open control endpoint: errno=%d]\n", USB_FFS_ADB_EP0, errno); - goto err; - } - - ret = adb_write(h->control, &v2_descriptor, sizeof(v2_descriptor)); - if (ret < 0) { - v1_descriptor.header.magic = cpu_to_le32(FUNCTIONFS_DESCRIPTORS_MAGIC); - v1_descriptor.header.length = cpu_to_le32(sizeof(v1_descriptor)); - v1_descriptor.header.fs_count = 3; - v1_descriptor.header.hs_count = 3; - v1_descriptor.fs_descs = fs_descriptors; - v1_descriptor.hs_descs = hs_descriptors; - D("[ %s: Switching to V1_descriptor format errno=%d ]\n", USB_FFS_ADB_EP0, errno); - ret = adb_write(h->control, &v1_descriptor, sizeof(v1_descriptor)); - if (ret < 0) { - D("[ %s: write descriptors failed: errno=%d ]\n", USB_FFS_ADB_EP0, errno); - goto err; - } - } + D("OPENING %s\n", USB_FFS_ADB_EP0); + h->control = adb_open(USB_FFS_ADB_EP0, O_RDWR); + if (h->control < 0) { + D("[ %s: cannot open control endpoint: errno=%d]\n", USB_FFS_ADB_EP0, errno); + goto err; + } - ret = adb_write(h->control, &strings, sizeof(strings)); + ret = adb_write(h->control, &v2_descriptor, sizeof(v2_descriptor)); + if (ret < 0) { + v1_descriptor.header.magic = cpu_to_le32(FUNCTIONFS_DESCRIPTORS_MAGIC); + v1_descriptor.header.length = cpu_to_le32(sizeof(v1_descriptor)); + v1_descriptor.header.fs_count = 3; + v1_descriptor.header.hs_count = 3; + v1_descriptor.fs_descs = fs_descriptors; + v1_descriptor.hs_descs = hs_descriptors; + D("[ %s: Switching to V1_descriptor format errno=%d ]\n", USB_FFS_ADB_EP0, errno); + ret = adb_write(h->control, &v1_descriptor, sizeof(v1_descriptor)); if (ret < 0) { - D("[ %s: writing strings failed: errno=%d]\n", USB_FFS_ADB_EP0, errno); + D("[ %s: write descriptors failed: errno=%d ]\n", USB_FFS_ADB_EP0, errno); goto err; } } + ret = adb_write(h->control, &strings, sizeof(strings)); + if (ret < 0) { + D("[ %s: writing strings failed: errno=%d]\n", USB_FFS_ADB_EP0, errno); + goto err; + } + h->bulk_out = adb_open(USB_FFS_ADB_OUT, O_RDWR); if (h->bulk_out < 0) { D("[ %s: cannot open bulk-out ep: errno=%d ]\n", USB_FFS_ADB_OUT, errno); @@ -401,14 +399,14 @@ static void *usb_ffs_open_thread(void *x) while (true) { // wait until the USB device needs opening adb_mutex_lock(&usb->lock); - while (usb->control != -1 && usb->bulk_in != -1 && usb->bulk_out != -1) + while (usb->control != -1) adb_cond_wait(&usb->notify, &usb->lock); adb_mutex_unlock(&usb->lock); while (true) { init_functionfs(usb); - if (usb->control >= 0 && usb->bulk_in >= 0 && usb->bulk_out >= 0) + if (usb->control >= 0) break; adb_sleep_ms(1000); @@ -500,13 +498,10 @@ static void usb_ffs_kick(usb_handle *h) D("[ kick: sink (fd=%d) clear halt failed (%d) ]", h->bulk_out, errno); adb_mutex_lock(&h->lock); - - // don't close ep0 here, since we may not need to reinitialize it with - // the same descriptors again. if however ep1/ep2 fail to re-open in - // init_functionfs, only then would we close and open ep0 again. + adb_close(h->control); adb_close(h->bulk_out); adb_close(h->bulk_in); - h->bulk_out = h->bulk_in = -1; + h->control = h->bulk_out = h->bulk_in = -1; // notify usb_ffs_open_thread that we are disconnected adb_cond_signal(&h->notify); diff --git a/debuggerd/debuggerd.cpp b/debuggerd/debuggerd.cpp index 9c8a41e..984b931 100644 --- a/debuggerd/debuggerd.cpp +++ b/debuggerd/debuggerd.cpp @@ -14,6 +14,8 @@ * limitations under the License. */ +#define LOG_TAG "DEBUG" + #include <stdio.h> #include <errno.h> #include <signal.h> @@ -84,11 +86,13 @@ static void wait_for_user_action(const debugger_request_t &request) { "* and start gdbclient:\n" "*\n" "* gdbclient %s :5039 %d\n" + "* or\n" + "* dddclient %s :5039 %d\n" "*\n" "* Wait for gdb to start, then press the VOLUME DOWN key\n" "* to let the process continue crashing.\n" "********************************************************", - request.pid, exe, request.tid); + request.pid, exe, request.tid, exe, request.tid); // Wait for VOLUME DOWN. if (init_getevent() == 0) { @@ -258,7 +262,19 @@ static bool should_attach_gdb(debugger_request_t* request) { char value[PROPERTY_VALUE_MAX]; property_get("debug.db.uid", value, "-1"); int debug_uid = atoi(value); - return debug_uid >= 0 && request->uid <= (uid_t)debug_uid; + if (debug_uid >= 0 && request->uid <= (uid_t)debug_uid) { + return true; + } else { + /* External docs say to use 10,000 but more is likely needed; be helpful. */ + if (request->uid > (uid_t)debug_uid) { + ALOGI("request->uid:%d > property debug.db.uid:%d; NOT waiting for gdb.", + request->uid, debug_uid); + } else { + ALOGI("property debug.db.uid not set; NOT waiting for gdb."); + ALOGI("HINT: adb shell setprop debug.db.uid 100000"); + ALOGI("HINT: adb forward tcp:5039 tcp:5039"); + } + } } return false; } diff --git a/fastboot/Android.mk b/fastboot/Android.mk index 66a470a..b5212ba 100644 --- a/fastboot/Android.mk +++ b/fastboot/Android.mk @@ -68,14 +68,14 @@ ifneq ($(HOST_OS),windows) LOCAL_STATIC_LIBRARIES += libselinux endif # HOST_OS != windows -ifeq ($(HOST_OS),linux) +ifneq (,$(filter linux darwin,$(HOST_OS))) # libf2fs_dlutils_host will dlopen("libf2fs_fmt_host_dyn") LOCAL_CFLAGS += -DUSE_F2FS LOCAL_LDFLAGS += -ldl -rdynamic -Wl,-rpath,. LOCAL_REQUIRED_MODULES := libf2fs_fmt_host_dyn # The following libf2fs_* are from system/extras/f2fs_utils, # and do not use code in external/f2fs-tools. -LOCAL_STATIC_LIBRARIES += libf2fs_utils_host libf2fs_ioutils_host libf2fs_dlutils_host +LOCAL_STATIC_LIBRARIES += libf2fs_utils_host libf2fs_dlutils_host endif # libc++ not available on windows yet @@ -91,7 +91,7 @@ LOCAL_SHARED_LIBRARIES := include $(BUILD_HOST_EXECUTABLE) my_dist_files := $(LOCAL_BUILT_MODULE) -ifeq ($(HOST_OS),linux) +ifneq (,$(filter linux darwin,$(HOST_OS))) my_dist_files += $(HOST_LIBRARY_PATH)/libf2fs_fmt_host_dyn$(HOST_SHLIB_SUFFIX) endif $(call dist-for-goals,dist_files sdk,$(my_dist_files)) diff --git a/fastboot/fastboot.cpp b/fastboot/fastboot.cpp index de4c0ea..ec3b84a 100644 --- a/fastboot/fastboot.cpp +++ b/fastboot/fastboot.cpp @@ -203,7 +203,11 @@ int match_fastboot_with_serial(usb_ifc_info *info, const char *local_serial) (info->dev_vendor != 0x413c) && // DELL (info->dev_vendor != 0x2314) && // INQ Mobile (info->dev_vendor != 0x0b05) && // Asus - (info->dev_vendor != 0x0bb4)) // HTC + (info->dev_vendor != 0x0bb4) && // HTC + (info->dev_vendor != 0x0421) && // Nokia + (info->dev_vendor != 0x1ebf) && // Coolpad + (info->dev_vendor != 0x2b4c) && // Zuk + (info->dev_vendor != 0x2a96)) // MMX return -1; if(info->ifc_class != 0xff) return -1; if(info->ifc_subclass != 0x42) return -1; diff --git a/fs_mgr/Android.mk b/fs_mgr/Android.mk index 8ed5cc9..d105b0b 100644 --- a/fs_mgr/Android.mk +++ b/fs_mgr/Android.mk @@ -12,8 +12,8 @@ LOCAL_C_INCLUDES := $(LOCAL_PATH)/include \ external/openssl/include LOCAL_MODULE:= libfs_mgr -LOCAL_STATIC_LIBRARIES := liblogwrap libmincrypt libext4_utils_static libsquashfs_utils -LOCAL_C_INCLUDES += system/extras/ext4_utils system/extras/squashfs_utils +LOCAL_STATIC_LIBRARIES := liblogwrap libmincrypt libext4_utils_static libsquashfs_utils libext2_blkid libext2_uuid_static +LOCAL_C_INCLUDES += system/extras/ext4_utils system/extras/squashfs_utils external/e2fsprogs/lib LOCAL_EXPORT_C_INCLUDE_DIRS := $(LOCAL_PATH)/include LOCAL_CFLAGS := -Werror @@ -38,7 +38,7 @@ LOCAL_FORCE_STATIC_EXECUTABLE := true LOCAL_MODULE_PATH := $(TARGET_ROOT_OUT)/sbin LOCAL_UNSTRIPPED_PATH := $(TARGET_ROOT_OUT_UNSTRIPPED) -LOCAL_STATIC_LIBRARIES := libfs_mgr liblogwrap libcutils liblog libc libmincrypt libext4_utils_static libsquashfs_utils +LOCAL_STATIC_LIBRARIES := libfs_mgr liblogwrap libcutils liblog libc libmincrypt libext4_utils_static libsquashfs_utils libext2_blkid libext2_uuid_static LOCAL_STATIC_LIBRARIES += libsparse_static libz libselinux LOCAL_CXX_STL := libc++_static diff --git a/fs_mgr/fs_mgr.c b/fs_mgr/fs_mgr.c index 15d44ef..c80e531 100644 --- a/fs_mgr/fs_mgr.c +++ b/fs_mgr/fs_mgr.c @@ -39,6 +39,7 @@ #include <cutils/partition_utils.h> #include <cutils/properties.h> #include <logwrap/logwrap.h> +#include <blkid/blkid.h> #include "mincrypt/rsa.h" #include "mincrypt/sha.h" @@ -60,6 +61,7 @@ #define FSCK_LOG_FILE "/dev/fscklogs/log" #define ZRAM_CONF_DEV "/sys/block/zram0/disksize" +#define ZRAM_STREAMS "/sys/block/zram0/max_comp_streams" #define ARRAY_SIZE(a) (sizeof(a) / sizeof(*(a))) @@ -159,12 +161,12 @@ static void check_fs(char *blk_device, char *fs_type, char *target) } } } else if (!strcmp(fs_type, "f2fs")) { - char *f2fs_fsck_argv[] = { - F2FS_FSCK_BIN, - "-f", - blk_device - }; - INFO("Running %s -f %s\n", F2FS_FSCK_BIN, blk_device); + char *f2fs_fsck_argv[] = { + F2FS_FSCK_BIN, + "-a", + blk_device + }; + INFO("Running %s on %s\n", F2FS_FSCK_BIN, blk_device); ret = android_fork_execvp_ext(ARRAY_SIZE(f2fs_fsck_argv), f2fs_fsck_argv, &status, true, LOG_KLOG | LOG_FILE, @@ -304,6 +306,8 @@ static int mount_with_alternatives(struct fstab *fstab, int start_idx, int *end_ int i; int mount_errno = 0; int mounted = 0; + int cmp_len; + char *detected_fs_type; if (!end_idx || !attempted_idx || start_idx >= fstab->num_entries) { errno = EINVAL; @@ -329,8 +333,16 @@ static int mount_with_alternatives(struct fstab *fstab, int start_idx, int *end_ } if (fstab->recs[i].fs_mgr_flags & MF_CHECK) { - check_fs(fstab->recs[i].blk_device, fstab->recs[i].fs_type, - fstab->recs[i].mount_point); + /* Skip file system check unless we are sure we are the right type */ + detected_fs_type = blkid_get_tag_value(NULL, "TYPE", fstab->recs[i].blk_device); + if (detected_fs_type) { + cmp_len = (!strncmp(detected_fs_type, "ext", 3) && + strlen(detected_fs_type) == 4) ? 3 : strlen(detected_fs_type); + if (!strncmp(fstab->recs[i].fs_type, detected_fs_type, cmp_len)) { + check_fs(fstab->recs[i].blk_device, fstab->recs[i].fs_type, + fstab->recs[i].mount_point); + } + } } if (!__mount(fstab->recs[i].blk_device, fstab->recs[i].mount_point, &fstab->recs[i])) { *attempted_idx = i; @@ -492,6 +504,52 @@ static int handle_encryptable(struct fstab *fstab, const struct fstab_rec* rec) return FS_MGR_MNTALL_DEV_NOT_ENCRYPTED; } +/* + * Reads the kernel cmdline to check if MDTP is activated. + * When MDTP is activated, kernel cmdline will have the word 'mdtp'. + */ +int fs_mgr_is_mdtp_activated() +{ + char cmdline[2048]; + char *ptr; + int fd; + static int mdtp_activated = 0; + static int mdtp_activated_set = 0; + + if (mdtp_activated_set) { + return mdtp_activated; + } + + fd = open("/proc/cmdline", O_RDONLY); + if (fd >= 0) { + int n = read(fd, cmdline, sizeof(cmdline) - 1); + if (n < 0) n = 0; + + /* get rid of trailing newline, it happens */ + if (n > 0 && cmdline[n-1] == '\n') n--; + + cmdline[n] = 0; + close(fd); + } else { + cmdline[0] = 0; + } + + ptr = cmdline; + while (ptr && *ptr) { + char *x = strchr(ptr, ' '); + if (x != 0) *x++ = 0; + if (!strcmp(ptr,"mdtp")) { + mdtp_activated = 1; + break; + } + ptr = x; + } + + mdtp_activated_set = 1; + + return mdtp_activated; +} + /* When multiple fstab records share the same mount_point, it will * try to mount each one in turn, and ignore any duplicates after a * first successful mount. @@ -547,91 +605,106 @@ int fs_mgr_mount_all(struct fstab *fstab) continue; } } - int last_idx_inspected; - int top_idx = i; - mret = mount_with_alternatives(fstab, i, &last_idx_inspected, &attempted_idx); - i = last_idx_inspected; - mount_errno = errno; + if (fs_mgr_is_mdtp_activated() && ((fstab->recs[i].fs_mgr_flags & MF_FORCECRYPT) || + device_is_force_encrypted())) { + INFO("%s(): mdtp activated, blkdev %s for mount %s type %s expected to be encrypted)\n", + __func__, fstab->recs[i].blk_device, fstab->recs[i].mount_point, + fstab->recs[i].fs_type); + if (fs_mgr_do_tmpfs_mount(fstab->recs[i].mount_point) < 0) { + ++error_count; + continue; + } - /* Deal with encryptability. */ - if (!mret) { - int status = handle_encryptable(fstab, &fstab->recs[attempted_idx]); + encryptable = FS_MGR_MNTALL_DEV_MIGHT_BE_ENCRYPTED; - if (status == FS_MGR_MNTALL_FAIL) { - /* Fatal error - no point continuing */ - return status; - } + } else { + int last_idx_inspected; + int top_idx = i; - if (status != FS_MGR_MNTALL_DEV_NOT_ENCRYPTED) { - if (encryptable != FS_MGR_MNTALL_DEV_NOT_ENCRYPTED) { - // Log and continue - ERROR("Only one encryptable/encrypted partition supported\n"); - } - encryptable = status; - } + mret = mount_with_alternatives(fstab, i, &last_idx_inspected, &attempted_idx); + i = last_idx_inspected; + mount_errno = errno; - /* Success! Go get the next one */ - continue; - } + /* Deal with encryptability. */ + if (!mret) { + int status = handle_encryptable(fstab, &fstab->recs[attempted_idx]); - /* mount(2) returned an error, handle the encryptable/formattable case */ - bool wiped = partition_wiped(fstab->recs[top_idx].blk_device); - if (mret && mount_errno != EBUSY && mount_errno != EACCES && - fs_mgr_is_formattable(&fstab->recs[top_idx]) && wiped) { - /* top_idx and attempted_idx point at the same partition, but sometimes - * at two different lines in the fstab. Use the top one for formatting - * as that is the preferred one. - */ - ERROR("%s(): %s is wiped and %s %s is formattable. Format it.\n", __func__, - fstab->recs[top_idx].blk_device, fstab->recs[top_idx].mount_point, - fstab->recs[top_idx].fs_type); - if (fs_mgr_is_encryptable(&fstab->recs[top_idx]) && - strcmp(fstab->recs[top_idx].key_loc, KEY_IN_FOOTER)) { - int fd = open(fstab->recs[top_idx].key_loc, O_WRONLY, 0644); - if (fd >= 0) { - INFO("%s(): also wipe %s\n", __func__, fstab->recs[top_idx].key_loc); - wipe_block_device(fd, get_file_size(fd)); - close(fd); - } else { - ERROR("%s(): %s wouldn't open (%s)\n", __func__, - fstab->recs[top_idx].key_loc, strerror(errno)); + if (status == FS_MGR_MNTALL_FAIL) { + /* Fatal error - no point continuing */ + return status; } - } - if (fs_mgr_do_format(&fstab->recs[top_idx]) == 0) { - /* Let's replay the mount actions. */ - i = top_idx - 1; + + if (status != FS_MGR_MNTALL_DEV_NOT_ENCRYPTED) { + if (encryptable != FS_MGR_MNTALL_DEV_NOT_ENCRYPTED) { + // Log and continue + ERROR("Only one encryptable/encrypted partition supported\n"); + } + encryptable = status; + } + + /* Success! Go get the next one */ continue; } - } - if (mret && mount_errno != EBUSY && mount_errno != EACCES && - fs_mgr_is_encryptable(&fstab->recs[attempted_idx])) { - if (wiped) { - ERROR("%s(): %s is wiped and %s %s is encryptable. Suggest recovery...\n", __func__, - fstab->recs[attempted_idx].blk_device, fstab->recs[attempted_idx].mount_point, - fstab->recs[attempted_idx].fs_type); - encryptable = FS_MGR_MNTALL_DEV_NEEDS_RECOVERY; - continue; - } else { - /* Need to mount a tmpfs at this mountpoint for now, and set - * properties that vold will query later for decrypting + + /* mount(2) returned an error, handle the encryptable/formattable case */ + bool wiped = partition_wiped(fstab->recs[top_idx].blk_device); + if (mret && mount_errno != EBUSY && mount_errno != EACCES && + fs_mgr_is_formattable(&fstab->recs[top_idx]) && wiped) { + /* top_idx and attempted_idx point at the same partition, but sometimes + * at two different lines in the fstab. Use the top one for formatting + * as that is the preferred one. */ - ERROR("%s(): possibly an encryptable blkdev %s for mount %s type %s )\n", __func__, - fstab->recs[attempted_idx].blk_device, fstab->recs[attempted_idx].mount_point, - fstab->recs[attempted_idx].fs_type); - if (fs_mgr_do_tmpfs_mount(fstab->recs[attempted_idx].mount_point) < 0) { - ++error_count; + ERROR("%s(): %s is wiped and %s %s is formattable. Format it.\n", __func__, + fstab->recs[top_idx].blk_device, fstab->recs[top_idx].mount_point, + fstab->recs[top_idx].fs_type); + if (fs_mgr_is_encryptable(&fstab->recs[top_idx]) && + strcmp(fstab->recs[top_idx].key_loc, KEY_IN_FOOTER)) { + int fd = open(fstab->recs[top_idx].key_loc, O_WRONLY, 0644); + if (fd >= 0) { + INFO("%s(): also wipe %s\n", __func__, fstab->recs[top_idx].key_loc); + wipe_block_device(fd, get_file_size(fd)); + close(fd); + } else { + ERROR("%s(): %s wouldn't open (%s)\n", __func__, + fstab->recs[top_idx].key_loc, strerror(errno)); + } + } + if (fs_mgr_do_format(&fstab->recs[top_idx]) == 0) { + /* Let's replay the mount actions. */ + i = top_idx - 1; continue; } } - encryptable = FS_MGR_MNTALL_DEV_MIGHT_BE_ENCRYPTED; - } else { - ERROR("Failed to mount an un-encryptable or wiped partition on" - "%s at %s options: %s error: %s\n", - fstab->recs[attempted_idx].blk_device, fstab->recs[attempted_idx].mount_point, - fstab->recs[attempted_idx].fs_options, strerror(mount_errno)); - ++error_count; - continue; + if (mret && mount_errno != EBUSY && mount_errno != EACCES && + fs_mgr_is_encryptable(&fstab->recs[attempted_idx])) { + if (wiped) { + ERROR("%s(): %s is wiped and %s %s is encryptable. Suggest recovery...\n", __func__, + fstab->recs[attempted_idx].blk_device, fstab->recs[attempted_idx].mount_point, + fstab->recs[attempted_idx].fs_type); + encryptable = FS_MGR_MNTALL_DEV_NEEDS_RECOVERY; + continue; + } else { + /* Need to mount a tmpfs at this mountpoint for now, and set + * properties that vold will query later for decrypting + */ + ERROR("%s(): possibly an encryptable blkdev %s for mount %s type %s )\n", __func__, + fstab->recs[attempted_idx].blk_device, fstab->recs[attempted_idx].mount_point, + fstab->recs[attempted_idx].fs_type); + if (fs_mgr_do_tmpfs_mount(fstab->recs[attempted_idx].mount_point) < 0) { + ++error_count; + continue; + } + } + encryptable = FS_MGR_MNTALL_DEV_MIGHT_BE_ENCRYPTED; + } else { + ERROR("Failed to mount an un-encryptable or wiped partition on" + "%s at %s options: %s error: %s\n", + fstab->recs[attempted_idx].blk_device, fstab->recs[attempted_idx].mount_point, + fstab->recs[attempted_idx].fs_options, strerror(mount_errno)); + ++error_count; + continue; + } } } @@ -799,6 +872,14 @@ int fs_mgr_swapon_all(struct fstab *fstab) */ FILE *zram_fp; + /* The stream count parameter is only available on new kernels. + * It must be set before the disk size. */ + zram_fp = fopen(ZRAM_STREAMS, "r+"); + if (zram_fp) { + fprintf(zram_fp, "%d\n", fstab->recs[i].zram_streams); + fclose(zram_fp); + } + zram_fp = fopen(ZRAM_CONF_DEV, "r+"); if (zram_fp == NULL) { ERROR("Unable to open zram conf device %s\n", ZRAM_CONF_DEV); diff --git a/fs_mgr/fs_mgr_format.c b/fs_mgr/fs_mgr_format.c index c73045d..e932990 100644 --- a/fs_mgr/fs_mgr_format.c +++ b/fs_mgr/fs_mgr_format.c @@ -31,7 +31,7 @@ extern struct fs_info info; /* magic global from ext4_utils */ extern void reset_ext4fs_info(); -static int format_ext4(char *fs_blkdev, char *fs_mnt_point) +static int format_ext4(char *fs_blkdev, char *fs_mnt_point, long long fs_length) { unsigned int nr_sec; int fd, rc = 0; @@ -51,6 +51,12 @@ static int format_ext4(char *fs_blkdev, char *fs_mnt_point) reset_ext4fs_info(); info.len = ((off64_t)nr_sec * 512); + if (fs_length > 0) { + info.len = fs_length; + } else if (fs_length < 0) { + info.len += fs_length; + } + /* Use make_ext4fs_internal to avoid wiping an already-wiped partition. */ rc = make_ext4fs_internal(fd, NULL, NULL, fs_mnt_point, 0, 0, 0, 0, 0, 0, 0, 0, 0, NULL); if (rc) { @@ -61,15 +67,27 @@ static int format_ext4(char *fs_blkdev, char *fs_mnt_point) return rc; } -static int format_f2fs(char *fs_blkdev) +static int format_f2fs(char *fs_blkdev, long long fs_length) { - char * args[3]; + char * args[5]; int pid; int rc = 0; - - args[0] = (char *)"/sbin/mkfs.f2fs"; - args[1] = fs_blkdev; - args[2] = (char *)0; + char buff[65]; + + args[0] = (char *)"/system/bin/mkfs.f2fs"; + + if (fs_length >= 0) { + snprintf(buff, sizeof(buff), "%lld", fs_length / 512); + args[1] = fs_blkdev; + args[2] = buff; + args[3] = (char *)0; + } else if (fs_length < 0) { + snprintf(buff, sizeof(buff), "%lld", -fs_length); + args[1] = "-r"; + args[2] = buff; + args[3] = fs_blkdev; + args[4] = (char *)0; + } pid = fork(); if (pid < 0) { @@ -77,7 +95,7 @@ static int format_f2fs(char *fs_blkdev) } if (!pid) { /* This doesn't return */ - execv("/sbin/mkfs.f2fs", args); + execv("/system/bin/mkfs.f2fs", args); exit(1); } for(;;) { @@ -108,9 +126,9 @@ int fs_mgr_do_format(struct fstab_rec *fstab) ERROR("%s: Format %s as '%s'.\n", __func__, fstab->blk_device, fstab->fs_type); if (!strncmp(fstab->fs_type, "f2fs", 4)) { - rc = format_f2fs(fstab->blk_device); + rc = format_f2fs(fstab->blk_device, fstab->length); } else if (!strncmp(fstab->fs_type, "ext4", 4)) { - rc = format_ext4(fstab->blk_device, fstab->mount_point); + rc = format_ext4(fstab->blk_device, fstab->mount_point, fstab->length); } else { ERROR("File system type '%s' is not supported\n", fstab->fs_type); } diff --git a/fs_mgr/fs_mgr_fstab.c b/fs_mgr/fs_mgr_fstab.c index f24af1f..b1b0325 100644 --- a/fs_mgr/fs_mgr_fstab.c +++ b/fs_mgr/fs_mgr_fstab.c @@ -32,6 +32,7 @@ struct fs_mgr_flag_values { int partnum; int swap_prio; unsigned int zram_size; + unsigned int zram_streams; }; struct flag_list { @@ -74,6 +75,7 @@ static struct flag_list fs_mgr_flags[] = { { "noemulatedsd", MF_NOEMULATEDSD }, { "notrim", MF_NOTRIM }, { "formattable", MF_FORMATTABLE }, + { "zramstreams=",MF_ZRAMSTREAMS }, { "defaults", 0 }, { 0, 0 }, }; @@ -106,6 +108,7 @@ static int parse_flags(char *flags, struct flag_list *fl, memset(flag_vals, 0, sizeof(*flag_vals)); flag_vals->partnum = -1; flag_vals->swap_prio = -1; /* negative means it wasn't specified. */ + flag_vals->zram_streams = 1; } /* initialize fs_options to the null string */ @@ -178,6 +181,8 @@ static int parse_flags(char *flags, struct flag_list *fl, flag_vals->zram_size = calculate_zram_size(val); else flag_vals->zram_size = val; + } else if ((fl[i].flag == MF_ZRAMSTREAMS) && flag_vals) { + flag_vals->zram_streams = strtoll(strchr(p, '=') + 1, NULL, 0); } break; } @@ -329,6 +334,7 @@ struct fstab *fs_mgr_read_fstab(const char *fstab_path) fstab->recs[cnt].partnum = flag_vals.partnum; fstab->recs[cnt].swap_prio = flag_vals.swap_prio; fstab->recs[cnt].zram_size = flag_vals.zram_size; + fstab->recs[cnt].zram_streams = flag_vals.zram_streams; cnt++; } fclose(fstab_file); diff --git a/fs_mgr/fs_mgr_priv.h b/fs_mgr/fs_mgr_priv.h index 682fd11..b72e200 100644 --- a/fs_mgr/fs_mgr_priv.h +++ b/fs_mgr/fs_mgr_priv.h @@ -79,6 +79,7 @@ #define MF_NOTRIM 0x1000 #define MF_FILEENCRYPTION 0x2000 #define MF_FORMATTABLE 0x4000 +#define MF_ZRAMSTREAMS 0x8000 #define DM_BUF_SIZE 4096 diff --git a/fs_mgr/include/fs_mgr.h b/fs_mgr/include/fs_mgr.h index 27fccf7..5e05d9a 100644 --- a/fs_mgr/include/fs_mgr.h +++ b/fs_mgr/include/fs_mgr.h @@ -65,6 +65,7 @@ struct fstab_rec { int partnum; int swap_prio; unsigned int zram_size; + unsigned int zram_streams; }; // Callback function for verity status @@ -97,6 +98,7 @@ int fs_mgr_add_entry(struct fstab *fstab, const char *mount_point, const char *fs_type, const char *blk_device); struct fstab_rec *fs_mgr_get_entry_for_mount_point(struct fstab *fstab, const char *path); +struct fstab_rec *fs_mgr_get_entry_for_mount_point_after(struct fstab_rec *start_rec, struct fstab *fstab, const char *path); int fs_mgr_is_voldmanaged(const struct fstab_rec *fstab); int fs_mgr_is_nonremovable(const struct fstab_rec *fstab); int fs_mgr_is_verified(const struct fstab_rec *fstab); @@ -106,6 +108,7 @@ int fs_mgr_is_noemulatedsd(const struct fstab_rec *fstab); int fs_mgr_is_notrim(struct fstab_rec *fstab); int fs_mgr_is_formattable(struct fstab_rec *fstab); int fs_mgr_swapon_all(struct fstab *fstab); +int fs_mgr_is_mdtp_activated(void); int fs_mgr_do_format(struct fstab_rec *fstab); diff --git a/gatekeeperd/SoftGateKeeper.h b/gatekeeperd/SoftGateKeeper.h index 75fe11d..c8010ca 100644 --- a/gatekeeperd/SoftGateKeeper.h +++ b/gatekeeperd/SoftGateKeeper.h @@ -25,8 +25,10 @@ extern "C" { #include <crypto_scrypt.h> } +#include <base/memory.h> #include <UniquePtr.h> #include <gatekeeper/gatekeeper.h> + #include <iostream> #include <unordered_map> @@ -150,14 +152,15 @@ public: } bool DoVerify(const password_handle_t *expected_handle, const SizedBuffer &password) { - FastHashMap::const_iterator it = fast_hash_map_.find(expected_handle->user_id); + uint64_t user_id = android::base::get_unaligned(&expected_handle->user_id); + FastHashMap::const_iterator it = fast_hash_map_.find(user_id); if (it != fast_hash_map_.end() && VerifyFast(it->second, password)) { return true; } else { if (GateKeeper::DoVerify(expected_handle, password)) { uint64_t salt; GetRandom(&salt, sizeof(salt)); - fast_hash_map_[expected_handle->user_id] = ComputeFastHash(password, salt); + fast_hash_map_[user_id] = ComputeFastHash(password, salt); return true; } } diff --git a/gatekeeperd/tests/Android.mk b/gatekeeperd/tests/Android.mk index 6fc4ac0..a62b1d4 100644 --- a/gatekeeperd/tests/Android.mk +++ b/gatekeeperd/tests/Android.mk @@ -20,7 +20,7 @@ include $(CLEAR_VARS) LOCAL_MODULE := gatekeeperd-unit-tests LOCAL_ADDITIONAL_DEPENDENCIES := $(LOCAL_PATH)/Android.mk LOCAL_CFLAGS += -g -Wall -Werror -std=gnu++11 -Wno-missing-field-initializers -LOCAL_SHARED_LIBRARIES := libgatekeeper libcrypto +LOCAL_SHARED_LIBRARIES := libgatekeeper libcrypto libbase LOCAL_STATIC_LIBRARIES := libscrypt_static LOCAL_C_INCLUDES := external/scrypt/lib/crypto LOCAL_SRC_FILES := \ diff --git a/healthd/Android.mk b/healthd/Android.mk index 07e1d73..e5fffc0 100644 --- a/healthd/Android.mk +++ b/healthd/Android.mk @@ -25,6 +25,18 @@ LOCAL_UNSTRIPPED_PATH := $(TARGET_ROOT_OUT_SBIN_UNSTRIPPED) LOCAL_CFLAGS := -D__STDC_LIMIT_MACROS -Werror +HEALTHD_CHARGER_DEFINES := RED_LED_PATH \ + GREEN_LED_PATH \ + BLUE_LED_PATH \ + BACKLIGHT_PATH \ + CHARGING_ENABLED_PATH + +$(foreach healthd_charger_define,$(HEALTHD_CHARGER_DEFINES), \ + $(if $($(healthd_charger_define)), \ + $(eval LOCAL_CFLAGS += -D$(healthd_charger_define)=\"$($(healthd_charger_define))\") \ + ) \ +) + ifeq ($(strip $(BOARD_CHARGER_DISABLE_INIT_BLANK)),true) LOCAL_CFLAGS += -DCHARGER_DISABLE_INIT_BLANK endif @@ -45,7 +57,7 @@ LOCAL_HAL_STATIC_LIBRARIES := libhealthd # Symlink /charger to /sbin/healthd LOCAL_POST_INSTALL_CMD := $(hide) mkdir -p $(TARGET_ROOT_OUT) \ - && ln -sf /sbin/healthd $(TARGET_ROOT_OUT)/charger + && rm -f $(TARGET_ROOT_OUT)/charger && ln -sf /sbin/healthd $(TARGET_ROOT_OUT)/charger include $(BUILD_EXECUTABLE) @@ -63,8 +75,13 @@ include $$(BUILD_PREBUILT) endef _img_modules := +ifeq ($(strip $(BOARD_HEALTHD_CUSTOM_CHARGER_RES)),) +IMAGES_DIR := images +else +IMAGES_DIR := ../../../$(BOARD_HEALTHD_CUSTOM_CHARGER_RES) +endif _images := -$(foreach _img, $(call find-subdir-subdir-files, "images", "*.png"), \ +$(foreach _img, $(call find-subdir-subdir-files, "$(IMAGES_DIR)", "*.png"), \ $(eval $(call _add-charger-image,$(_img)))) include $(CLEAR_VARS) diff --git a/healthd/BatteryMonitor.cpp b/healthd/BatteryMonitor.cpp index 396dfef..67a8ad0 100644 --- a/healthd/BatteryMonitor.cpp +++ b/healthd/BatteryMonitor.cpp @@ -1,5 +1,6 @@ /* * Copyright (C) 2013 The Android Open Source Project + * Copyright (C) 2015 The CyanogenMod Project * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -137,7 +138,12 @@ BatteryMonitor::PowerSupplyType BatteryMonitor::readPowerSupplyType(const String { "USB_DCP", ANDROID_POWER_SUPPLY_TYPE_AC }, { "USB_CDP", ANDROID_POWER_SUPPLY_TYPE_AC }, { "USB_ACA", ANDROID_POWER_SUPPLY_TYPE_AC }, + { "USB_HVDCP", ANDROID_POWER_SUPPLY_TYPE_AC }, + { "USB_HVDCP_3", ANDROID_POWER_SUPPLY_TYPE_AC }, { "Wireless", ANDROID_POWER_SUPPLY_TYPE_WIRELESS }, + { "Wipower", ANDROID_POWER_SUPPLY_TYPE_WIRELESS }, + { "DockBattery", ANDROID_POWER_SUPPLY_TYPE_DOCK_BATTERY }, + { "DockAC", ANDROID_POWER_SUPPLY_TYPE_DOCK_AC }, { NULL, 0 }, }; @@ -182,9 +188,12 @@ bool BatteryMonitor::update(void) { props.chargerAcOnline = false; props.chargerUsbOnline = false; props.chargerWirelessOnline = false; + props.chargerDockAcOnline = false; props.batteryStatus = BATTERY_STATUS_UNKNOWN; props.batteryHealth = BATTERY_HEALTH_UNKNOWN; props.maxChargingCurrent = 0; + props.dockBatteryStatus = BATTERY_STATUS_UNKNOWN; + props.dockBatteryHealth = BATTERY_HEALTH_UNKNOWN; if (!mHealthdConfig->batteryPresentPath.isEmpty()) props.batteryPresent = getBooleanField(mHealthdConfig->batteryPresentPath); @@ -222,53 +231,109 @@ bool BatteryMonitor::update(void) { if (readFromFile(mHealthdConfig->batteryTechnologyPath, buf, SIZE) > 0) props.batteryTechnology = String8(buf); - unsigned int i; + props.dockBatterySupported = mHealthdConfig->dockBatterySupported; + if (props.dockBatterySupported) { + if (!mHealthdConfig->dockBatteryPresentPath.isEmpty()) + props.dockBatteryPresent = getBooleanField(mHealthdConfig->dockBatteryPresentPath); + else + props.dockBatteryPresent = mDockBatteryDevicePresent; - for (i = 0; i < mChargerNames.size(); i++) { - String8 path; - path.appendFormat("%s/%s/online", POWER_SUPPLY_SYSFS_PATH, - mChargerNames[i].string()); + props.dockBatteryLevel = mBatteryFixedCapacity ? + mBatteryFixedCapacity : + getIntField(mHealthdConfig->dockBatteryCapacityPath); + props.dockBatteryVoltage = getIntField(mHealthdConfig->dockBatteryVoltagePath) / 1000; - if (readFromFile(path, buf, SIZE) > 0) { - if (buf[0] != '0') { - path.clear(); - path.appendFormat("%s/%s/type", POWER_SUPPLY_SYSFS_PATH, - mChargerNames[i].string()); - switch(readPowerSupplyType(path)) { - case ANDROID_POWER_SUPPLY_TYPE_AC: - props.chargerAcOnline = true; - break; - case ANDROID_POWER_SUPPLY_TYPE_USB: - props.chargerUsbOnline = true; - break; - case ANDROID_POWER_SUPPLY_TYPE_WIRELESS: - props.chargerWirelessOnline = true; - break; - default: - KLOG_WARNING(LOG_TAG, "%s: Unknown power supply type\n", - mChargerNames[i].string()); - } + props.dockBatteryTemperature = mBatteryFixedTemperature ? + mBatteryFixedTemperature : + getIntField(mHealthdConfig->dockBatteryTemperaturePath); + + if (readFromFile(mHealthdConfig->dockBatteryStatusPath, buf, SIZE) > 0) + props.dockBatteryStatus = getBatteryStatus(buf); + + if (readFromFile(mHealthdConfig->dockBatteryHealthPath, buf, SIZE) > 0) + props.dockBatteryHealth = getBatteryHealth(buf); + + if (readFromFile(mHealthdConfig->dockBatteryTechnologyPath, buf, SIZE) > 0) + props.dockBatteryTechnology = String8(buf); + } + + // reinitialize the mChargerNames vector everytime there is an update + String8 path; + DIR* dir = opendir(POWER_SUPPLY_SYSFS_PATH); + if (dir == NULL) { + KLOG_ERROR(LOG_TAG, "Could not open %s\n", POWER_SUPPLY_SYSFS_PATH); + } else { + struct dirent* entry; + // reconstruct the charger strings + mChargerNames.clear(); + while ((entry = readdir(dir))) { + const char* name = entry->d_name; + + if (!strcmp(name, ".") || !strcmp(name, "..")) + continue; + + // Look for "type" file in each subdirectory + path.clear(); + path.appendFormat("%s/%s/type", POWER_SUPPLY_SYSFS_PATH, name); + switch(readPowerSupplyType(path)) { + case ANDROID_POWER_SUPPLY_TYPE_BATTERY: + case ANDROID_POWER_SUPPLY_TYPE_DOCK_BATTERY: + break; + default: path.clear(); - path.appendFormat("%s/%s/current_max", POWER_SUPPLY_SYSFS_PATH, - mChargerNames[i].string()); + path.appendFormat("%s/%s/online", POWER_SUPPLY_SYSFS_PATH, name); if (access(path.string(), R_OK) == 0) { - int maxChargingCurrent = getIntField(path); - if (props.maxChargingCurrent < maxChargingCurrent) { - props.maxChargingCurrent = maxChargingCurrent; + mChargerNames.add(String8(name)); + if (readFromFile(path, buf, SIZE) > 0) { + if (buf[0] != '0') { + path.clear(); + path.appendFormat("%s/%s/type", POWER_SUPPLY_SYSFS_PATH, + name); + switch(readPowerSupplyType(path)) { + case ANDROID_POWER_SUPPLY_TYPE_AC: + props.chargerAcOnline = true; + break; + case ANDROID_POWER_SUPPLY_TYPE_USB: + props.chargerUsbOnline = true; + break; + case ANDROID_POWER_SUPPLY_TYPE_WIRELESS: + props.chargerWirelessOnline = true; + break; + case ANDROID_POWER_SUPPLY_TYPE_DOCK_AC: + if (mHealthdConfig->dockBatterySupported) { + props.chargerDockAcOnline = true; + } + default: + KLOG_WARNING(LOG_TAG, "%s: Unknown power supply type\n", + name); + } + path.clear(); + path.appendFormat("%s/%s/current_max", POWER_SUPPLY_SYSFS_PATH, + name); + if (access(path.string(), R_OK) == 0) { + int maxChargingCurrent = getIntField(path); + if (props.maxChargingCurrent < maxChargingCurrent) { + props.maxChargingCurrent = maxChargingCurrent; + } + } + } } } - } - } - } + break; + } //switch + } //while + closedir(dir); + }//else logthis = !healthd_board_battery_update(&props); if (logthis) { char dmesgline[256]; + char dmesglinedock[256]; if (props.batteryPresent) { snprintf(dmesgline, sizeof(dmesgline), - "battery l=%d v=%d t=%s%d.%d h=%d st=%d", + "battery [l=%d v=%d t=%s%d.%d h=%d st=%d]", props.batteryLevel, props.batteryVoltage, props.batteryTemperature < 0 ? "-" : "", abs(props.batteryTemperature / 10), @@ -287,6 +352,27 @@ bool BatteryMonitor::update(void) { "battery none"); } + if (props.dockBatteryPresent) { + snprintf(dmesglinedock, sizeof(dmesglinedock), + "dock-battery [l=%d v=%d t=%s%d.%d h=%d st=%d]", + props.dockBatteryLevel, props.dockBatteryVoltage, + props.dockBatteryTemperature < 0 ? "-" : "", + abs(props.dockBatteryTemperature / 10), + abs(props.dockBatteryTemperature % 10), props.dockBatteryHealth, + props.dockBatteryStatus); + + if (!mHealthdConfig->dockBatteryCurrentNowPath.isEmpty()) { + int c = getIntField(mHealthdConfig->dockBatteryCurrentNowPath); + char b[20]; + + snprintf(b, sizeof(b), " c=%d", c / 1000); + strlcat(dmesglinedock, b, sizeof(dmesglinedock)); + } + } else { + snprintf(dmesglinedock, sizeof(dmesglinedock), + "dock-battery none"); + } + size_t len = strlen(dmesgline); snprintf(dmesgline + len, sizeof(dmesgline) - len, " chg=%s%s%s", props.chargerAcOnline ? "a" : "", @@ -317,7 +403,7 @@ bool BatteryMonitor::update(void) { healthd_mode_ops->battery_update(&props); return props.chargerAcOnline | props.chargerUsbOnline | - props.chargerWirelessOnline; + props.chargerWirelessOnline | props.chargerDockAcOnline; } status_t BatteryMonitor::getProperty(int id, struct BatteryProperty *val) { @@ -381,13 +467,77 @@ status_t BatteryMonitor::getProperty(int id, struct BatteryProperty *val) { return ret; } +status_t BatteryMonitor::getDockProperty(int id, struct BatteryProperty *val) { + status_t ret = BAD_VALUE; + if (!mHealthdConfig->dockBatterySupported) { + return ret; + } + + val->valueInt64 = LONG_MIN; + + switch(id) { + case BATTERY_PROP_CHARGE_COUNTER: + if (!mHealthdConfig->dockBatteryChargeCounterPath.isEmpty()) { + val->valueInt64 = + getIntField(mHealthdConfig->dockBatteryChargeCounterPath); + ret = NO_ERROR; + } else { + ret = NAME_NOT_FOUND; + } + break; + + case BATTERY_PROP_CURRENT_NOW: + if (!mHealthdConfig->dockBatteryCurrentNowPath.isEmpty()) { + val->valueInt64 = + getIntField(mHealthdConfig->dockBatteryCurrentNowPath); + ret = NO_ERROR; + } else { + ret = NAME_NOT_FOUND; + } + break; + + case BATTERY_PROP_CURRENT_AVG: + if (!mHealthdConfig->dockBatteryCurrentAvgPath.isEmpty()) { + val->valueInt64 = + getIntField(mHealthdConfig->dockBatteryCurrentAvgPath); + ret = NO_ERROR; + } else { + ret = NAME_NOT_FOUND; + } + break; + + case BATTERY_PROP_CAPACITY: + if (!mHealthdConfig->dockBatteryCapacityPath.isEmpty()) { + val->valueInt64 = + getIntField(mHealthdConfig->dockBatteryCapacityPath); + ret = NO_ERROR; + } else { + ret = NAME_NOT_FOUND; + } + break; + + case BATTERY_PROP_ENERGY_COUNTER: + if (mHealthdConfig->dockEnergyCounter) { + ret = mHealthdConfig->dockEnergyCounter(&val->valueInt64); + } else { + ret = NAME_NOT_FOUND; + } + break; + + default: + break; + } + + return ret; +} + void BatteryMonitor::dumpState(int fd) { int v; char vs[128]; - snprintf(vs, sizeof(vs), "ac: %d usb: %d wireless: %d current_max: %d\n", + snprintf(vs, sizeof(vs), "ac: %d usb: %d wireless: %d dock-ac: %d current_max: %d\n", props.chargerAcOnline, props.chargerUsbOnline, - props.chargerWirelessOnline, props.maxChargingCurrent); + props.chargerWirelessOnline, props.chargerDockAcOnline, props.maxChargingCurrent); write(fd, vs, strlen(vs)); snprintf(vs, sizeof(vs), "status: %d health: %d present: %d\n", props.batteryStatus, props.batteryHealth, props.batteryPresent); @@ -414,6 +564,34 @@ void BatteryMonitor::dumpState(int fd) { snprintf(vs, sizeof(vs), "charge counter: %d\n", v); write(fd, vs, strlen(vs)); } + + if (mHealthdConfig->dockBatterySupported) { + snprintf(vs, sizeof(vs), "dock-status: %d dock-health: %d dock-present: %d\n", + props.dockBatteryStatus, props.dockBatteryHealth, props.dockBatteryPresent); + write(fd, vs, strlen(vs)); + snprintf(vs, sizeof(vs), "dock-level: %d dock-voltage: %d dock-temp: %d\n", + props.dockBatteryLevel, props.dockBatteryVoltage, + props.dockBatteryTemperature); + write(fd, vs, strlen(vs)); + + if (!mHealthdConfig->dockBatteryCurrentNowPath.isEmpty()) { + v = getIntField(mHealthdConfig->dockBatteryCurrentNowPath); + snprintf(vs, sizeof(vs), "dock-current now: %d\n", v); + write(fd, vs, strlen(vs)); + } + + if (!mHealthdConfig->dockBatteryCurrentAvgPath.isEmpty()) { + v = getIntField(mHealthdConfig->dockBatteryCurrentAvgPath); + snprintf(vs, sizeof(vs), "dock-current avg: %d\n", v); + write(fd, vs, strlen(vs)); + } + + if (!mHealthdConfig->dockBatteryChargeCounterPath.isEmpty()) { + v = getIntField(mHealthdConfig->dockBatteryChargeCounterPath); + snprintf(vs, sizeof(vs), "dock-charge counter: %d\n", v); + write(fd, vs, strlen(vs)); + } + } } void BatteryMonitor::init(struct healthd_config *hc) { @@ -440,6 +618,7 @@ void BatteryMonitor::init(struct healthd_config *hc) { case ANDROID_POWER_SUPPLY_TYPE_AC: case ANDROID_POWER_SUPPLY_TYPE_USB: case ANDROID_POWER_SUPPLY_TYPE_WIRELESS: + case ANDROID_POWER_SUPPLY_TYPE_DOCK_AC: path.clear(); path.appendFormat("%s/%s/online", POWER_SUPPLY_SYSFS_PATH, name); if (access(path.string(), R_OK) == 0) @@ -545,6 +724,107 @@ void BatteryMonitor::init(struct healthd_config *hc) { break; + case ANDROID_POWER_SUPPLY_TYPE_DOCK_BATTERY: + if (mHealthdConfig->dockBatterySupported) { + mDockBatteryDevicePresent = true; + + if (mHealthdConfig->dockBatteryStatusPath.isEmpty()) { + path.clear(); + path.appendFormat("%s/%s/status", POWER_SUPPLY_SYSFS_PATH, + name); + if (access(path, R_OK) == 0) + mHealthdConfig->dockBatteryStatusPath = path; + } + + if (mHealthdConfig->dockBatteryHealthPath.isEmpty()) { + path.clear(); + path.appendFormat("%s/%s/health", POWER_SUPPLY_SYSFS_PATH, + name); + if (access(path, R_OK) == 0) + mHealthdConfig->dockBatteryHealthPath = path; + } + + if (mHealthdConfig->dockBatteryPresentPath.isEmpty()) { + path.clear(); + path.appendFormat("%s/%s/present", POWER_SUPPLY_SYSFS_PATH, + name); + if (access(path, R_OK) == 0) + mHealthdConfig->dockBatteryPresentPath = path; + } + + if (mHealthdConfig->dockBatteryCapacityPath.isEmpty()) { + path.clear(); + path.appendFormat("%s/%s/capacity", POWER_SUPPLY_SYSFS_PATH, + name); + if (access(path, R_OK) == 0) + mHealthdConfig->dockBatteryCapacityPath = path; + } + + if (mHealthdConfig->dockBatteryVoltagePath.isEmpty()) { + path.clear(); + path.appendFormat("%s/%s/voltage_now", + POWER_SUPPLY_SYSFS_PATH, name); + if (access(path, R_OK) == 0) { + mHealthdConfig->dockBatteryVoltagePath = path; + } else { + path.clear(); + path.appendFormat("%s/%s/batt_vol", + POWER_SUPPLY_SYSFS_PATH, name); + if (access(path, R_OK) == 0) + mHealthdConfig->dockBatteryVoltagePath = path; + } + } + + if (mHealthdConfig->dockBatteryCurrentNowPath.isEmpty()) { + path.clear(); + path.appendFormat("%s/%s/current_now", + POWER_SUPPLY_SYSFS_PATH, name); + if (access(path, R_OK) == 0) + mHealthdConfig->dockBatteryCurrentNowPath = path; + } + + if (mHealthdConfig->dockBatteryCurrentAvgPath.isEmpty()) { + path.clear(); + path.appendFormat("%s/%s/current_avg", + POWER_SUPPLY_SYSFS_PATH, name); + if (access(path, R_OK) == 0) + mHealthdConfig->dockBatteryCurrentAvgPath = path; + } + + if (mHealthdConfig->dockBatteryChargeCounterPath.isEmpty()) { + path.clear(); + path.appendFormat("%s/%s/charge_counter", + POWER_SUPPLY_SYSFS_PATH, name); + if (access(path, R_OK) == 0) + mHealthdConfig->dockBatteryChargeCounterPath = path; + } + + if (mHealthdConfig->dockBatteryTemperaturePath.isEmpty()) { + path.clear(); + path.appendFormat("%s/%s/temp", POWER_SUPPLY_SYSFS_PATH, + name); + if (access(path, R_OK) == 0) { + mHealthdConfig->dockBatteryTemperaturePath = path; + } else { + path.clear(); + path.appendFormat("%s/%s/batt_temp", + POWER_SUPPLY_SYSFS_PATH, name); + if (access(path, R_OK) == 0) + mHealthdConfig->dockBatteryTemperaturePath = path; + } + } + + if (mHealthdConfig->dockBatteryTechnologyPath.isEmpty()) { + path.clear(); + path.appendFormat("%s/%s/technology", + POWER_SUPPLY_SYSFS_PATH, name); + if (access(path, R_OK) == 0) + mHealthdConfig->dockBatteryTechnologyPath = path; + } + } + + break; + case ANDROID_POWER_SUPPLY_TYPE_UNKNOWN: break; } @@ -561,7 +841,7 @@ void BatteryMonitor::init(struct healthd_config *hc) { mBatteryFixedTemperature = FAKE_BATTERY_TEMPERATURE; mAlwaysPluggedDevice = true; } - if (!mBatteryDevicePresent) { + if (!mBatteryDevicePresent && !mDockBatteryDevicePresent) { KLOG_WARNING(LOG_TAG, "No battery devices found\n"); hc->periodic_chores_interval_fast = -1; hc->periodic_chores_interval_slow = -1; @@ -580,6 +860,23 @@ void BatteryMonitor::init(struct healthd_config *hc) { KLOG_WARNING(LOG_TAG, "BatteryTemperaturePath not found\n"); if (mHealthdConfig->batteryTechnologyPath.isEmpty()) KLOG_WARNING(LOG_TAG, "BatteryTechnologyPath not found\n"); + + if (mHealthdConfig->dockBatterySupported) { + if (mHealthdConfig->dockBatteryStatusPath.isEmpty()) + KLOG_WARNING(LOG_TAG, "DockBatteryStatusPath not found\n"); + if (mHealthdConfig->dockBatteryHealthPath.isEmpty()) + KLOG_WARNING(LOG_TAG, "DockBatteryHealthPath not found\n"); + if (mHealthdConfig->dockBatteryPresentPath.isEmpty()) + KLOG_WARNING(LOG_TAG, "DockBatteryPresentPath not found\n"); + if (mHealthdConfig->dockBatteryCapacityPath.isEmpty()) + KLOG_WARNING(LOG_TAG, "DockBatteryCapacityPath not found\n"); + if (mHealthdConfig->dockBatteryVoltagePath.isEmpty()) + KLOG_WARNING(LOG_TAG, "DockBatteryVoltagePath not found\n"); + if (mHealthdConfig->dockBatteryTemperaturePath.isEmpty()) + KLOG_WARNING(LOG_TAG, "DockBatteryTemperaturePath not found\n"); + if (mHealthdConfig->dockBatteryTechnologyPath.isEmpty()) + KLOG_WARNING(LOG_TAG, "DockBatteryTechnologyPath not found\n"); + } } if (property_get("ro.boot.fake_battery", pval, NULL) > 0 diff --git a/healthd/BatteryMonitor.h b/healthd/BatteryMonitor.h index a61171f..4320348 100644 --- a/healthd/BatteryMonitor.h +++ b/healthd/BatteryMonitor.h @@ -1,5 +1,6 @@ /* * Copyright (C) 2013 The Android Open Source Project + * Copyright (C) 2015 The CyanogenMod Project * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -34,18 +35,22 @@ class BatteryMonitor { ANDROID_POWER_SUPPLY_TYPE_AC, ANDROID_POWER_SUPPLY_TYPE_USB, ANDROID_POWER_SUPPLY_TYPE_WIRELESS, - ANDROID_POWER_SUPPLY_TYPE_BATTERY + ANDROID_POWER_SUPPLY_TYPE_BATTERY, + ANDROID_POWER_SUPPLY_TYPE_DOCK_AC, + ANDROID_POWER_SUPPLY_TYPE_DOCK_BATTERY }; void init(struct healthd_config *hc); bool update(void); status_t getProperty(int id, struct BatteryProperty *val); + status_t getDockProperty(int id, struct BatteryProperty *val); void dumpState(int fd); private: struct healthd_config *mHealthdConfig; Vector<String8> mChargerNames; bool mBatteryDevicePresent; + bool mDockBatteryDevicePresent; bool mAlwaysPluggedDevice; int mBatteryFixedCapacity; int mBatteryFixedTemperature; diff --git a/healthd/BatteryPropertiesRegistrar.cpp b/healthd/BatteryPropertiesRegistrar.cpp index 09667a1..7a28ead 100644 --- a/healthd/BatteryPropertiesRegistrar.cpp +++ b/healthd/BatteryPropertiesRegistrar.cpp @@ -1,5 +1,6 @@ /* * Copyright (C) 2013 The Android Open Source Project + * Copyright (C) 2015 The CyanogenMod Project * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -76,6 +77,10 @@ status_t BatteryPropertiesRegistrar::getProperty(int id, struct BatteryProperty return healthd_get_property(id, val); } +status_t BatteryPropertiesRegistrar::getDockProperty(int id, struct BatteryProperty *val) { + return healthd_get_dock_property(id, val); +} + status_t BatteryPropertiesRegistrar::dump(int fd, const Vector<String16>& /*args*/) { IPCThreadState* self = IPCThreadState::self(); const int pid = self->getCallingPid(); diff --git a/healthd/BatteryPropertiesRegistrar.h b/healthd/BatteryPropertiesRegistrar.h index 8853874..5ca4fc1 100644 --- a/healthd/BatteryPropertiesRegistrar.h +++ b/healthd/BatteryPropertiesRegistrar.h @@ -1,5 +1,6 @@ /* * Copyright (C) 2013 The Android Open Source Project + * Copyright (C) 2015 The CyanogenMod Project * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -40,6 +41,7 @@ private: void registerListener(const sp<IBatteryPropertiesListener>& listener); void unregisterListener(const sp<IBatteryPropertiesListener>& listener); status_t getProperty(int id, struct BatteryProperty *val); + status_t getDockProperty(int id, struct BatteryProperty *val); status_t dump(int fd, const Vector<String16>& args); void binderDied(const wp<IBinder>& who); }; diff --git a/healthd/healthd.cpp b/healthd/healthd.cpp index b0002cc..1489912 100644 --- a/healthd/healthd.cpp +++ b/healthd/healthd.cpp @@ -1,5 +1,6 @@ /* * Copyright (C) 2013 The Android Open Source Project + * Copyright (C) 2015 The CyanogenMod Project * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -36,8 +37,15 @@ using namespace android; // Periodic chores intervals in seconds +#ifdef QCOM_HARDWARE +#define DEFAULT_PERIODIC_CHORES_INTERVAL_FAST (60 * 10) +//For the designs without low battery detection,need to enable +//the default 60*10s wakeup timer to periodic check. +#define DEFAULT_PERIODIC_CHORES_INTERVAL_SLOW -1 +#else #define DEFAULT_PERIODIC_CHORES_INTERVAL_FAST (60 * 1) #define DEFAULT_PERIODIC_CHORES_INTERVAL_SLOW (60 * 10) +#endif static struct healthd_config healthd_config = { .periodic_chores_interval_fast = DEFAULT_PERIODIC_CHORES_INTERVAL_FAST, @@ -55,6 +63,18 @@ static struct healthd_config healthd_config = { .energyCounter = NULL, .boot_min_cap = 0, .screen_on = NULL, + .dockBatterySupported = false, + .dockBatteryStatusPath = String8(String8::kEmptyString), + .dockBatteryHealthPath = String8(String8::kEmptyString), + .dockBatteryPresentPath = String8(String8::kEmptyString), + .dockBatteryCapacityPath = String8(String8::kEmptyString), + .dockBatteryVoltagePath = String8(String8::kEmptyString), + .dockBatteryTemperaturePath = String8(String8::kEmptyString), + .dockBatteryTechnologyPath = String8(String8::kEmptyString), + .dockBatteryCurrentNowPath = String8(String8::kEmptyString), + .dockBatteryCurrentAvgPath = String8(String8::kEmptyString), + .dockBatteryChargeCounterPath = String8(String8::kEmptyString), + .dockEnergyCounter = NULL, }; static int eventct; @@ -173,6 +193,10 @@ status_t healthd_get_property(int id, struct BatteryProperty *val) { return gBatteryMonitor->getProperty(id, val); } +status_t healthd_get_dock_property(int id, struct BatteryProperty *val) { + return gBatteryMonitor->getDockProperty(id, val); +} + void healthd_battery_update(void) { // Fast wake interval when on charger (watch for overheat); // slow wake interval when on battery (watch for drained battery). @@ -357,6 +381,9 @@ int main(int argc, char **argv) { exit(2); } + periodic_chores(); + healthd_mode_ops->heartbeat(); + healthd_mainloop(); KLOG_ERROR("Main loop terminated, exiting\n"); return 3; diff --git a/healthd/healthd.h b/healthd/healthd.h index 84b6d76..0b2a16e 100644 --- a/healthd/healthd.h +++ b/healthd/healthd.h @@ -1,5 +1,6 @@ /* * Copyright (C) 2013 The Android Open Source Project + * Copyright (C) 2015 The CyanogenMod Project * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -48,8 +49,25 @@ // batteryTemperaturePath: battery temperature (POWER_SUPPLY_PROP_TEMP) // batteryTechnologyPath: battery technology (POWER_SUPPLY_PROP_TECHNOLOGY) // batteryCurrentNowPath: battery current (POWER_SUPPLY_PROP_CURRENT_NOW) +// batteryCurrentAvgPath: battery average (POWER_SUPPLY_PROP_CURRENT_AVG) // batteryChargeCounterPath: battery accumulated charge // (POWER_SUPPLY_PROP_CHARGE_COUNTER) +// +// dockBatteryStatusPath: dock charging status (POWER_SUPPLY_PROP_STATUS) +// dockBatteryHealthPath: dock battery health (POWER_SUPPLY_PROP_HEALTH) +// dockBatteryPresentPath: dock battery present (POWER_SUPPLY_PROP_PRESENT) +// dockBatteryCapacityPath: remaining dock capacity (POWER_SUPPLY_PROP_CAPACITY) +// dockBatteryVoltagePath: dock battery voltage (POWER_SUPPLY_PROP_VOLTAGE_NOW) +// dockBatteryTemperaturePath: dock battery temperature (POWER_SUPPLY_PROP_TEMP) +// dockBatteryTechnologyPath: dock battery technology (POWER_SUPPLY_PROP_TECHNOLOGY) +// dockBatteryCurrentNowPath: dock battery current (POWER_SUPPLY_PROP_CURRENT_NOW) +// dockBatteryCurrentAvgPath: dock battery average (POWER_SUPPLY_PROP_CURRENT_AVG) +// dockBatteryChargeCounterPath: dock battery accumulated charge +// (POWER_SUPPLY_PROP_CHARGE_COUNTER) +// +// The dockBatterySupported property indicates whether a dock battery is supported +// by the device, and whether this module should fetch dock battery values. +// Defaults is to false. struct healthd_config { int periodic_chores_interval_fast; @@ -69,6 +87,20 @@ struct healthd_config { int (*energyCounter)(int64_t *); int boot_min_cap; bool (*screen_on)(android::BatteryProperties *props); + + bool dockBatterySupported; + android::String8 dockBatteryStatusPath; + android::String8 dockBatteryHealthPath; + android::String8 dockBatteryPresentPath; + android::String8 dockBatteryCapacityPath; + android::String8 dockBatteryVoltagePath; + android::String8 dockBatteryTemperaturePath; + android::String8 dockBatteryTechnologyPath; + android::String8 dockBatteryCurrentNowPath; + android::String8 dockBatteryCurrentAvgPath; + android::String8 dockBatteryChargeCounterPath; + + int (*dockEnergyCounter)(int64_t *); }; // Global helper functions @@ -77,6 +109,8 @@ int healthd_register_event(int fd, void (*handler)(uint32_t)); void healthd_battery_update(); android::status_t healthd_get_property(int id, struct android::BatteryProperty *val); +android::status_t healthd_get_dock_property(int id, + struct android::BatteryProperty *val); void healthd_dump_battery_state(int fd); struct healthd_mode_ops { @@ -121,4 +155,20 @@ void healthd_board_init(struct healthd_config *config); int healthd_board_battery_update(struct android::BatteryProperties *props); +//This API is called to turn on/off the display backlight incase it can't be +//handle correcty in the display driver by calling gr_fg_blank(); +void healthd_board_mode_charger_set_backlight(bool en); + +//This API is called to update the battery/charging status by using the user +//noticeable method other then the animation, such as: LEDs +void healthd_board_mode_charger_battery_update(struct android::BatteryProperties *batt_prop); + +//This API is used to handle some board specific charger mode initialization, +//such as: checking the charging is enabled or not. +void healthd_board_mode_charger_init(void); + +//This API is called in the draw_battery() function to draw more infomation +//about the battery on the animation, such as the SoC (State of Charge). +void healthd_board_mode_charger_draw_battery(struct android::BatteryProperties *batt_prop); + #endif /* _HEALTHD_H_ */ diff --git a/healthd/healthd_board_default.cpp b/healthd/healthd_board_default.cpp index ed4ddb4..c511c9c 100644 --- a/healthd/healthd_board_default.cpp +++ b/healthd/healthd_board_default.cpp @@ -25,5 +25,25 @@ void healthd_board_init(struct healthd_config*) int healthd_board_battery_update(struct android::BatteryProperties*) { // return 0 to log periodic polled battery status to kernel log - return 0; + return 1; +} + +void healthd_board_mode_charger_draw_battery(struct android::BatteryProperties*) +{ + +} + +void healthd_board_mode_charger_battery_update(struct android::BatteryProperties*) +{ + +} + +void healthd_board_mode_charger_set_backlight(bool) +{ + +} + +void healthd_board_mode_charger_init() +{ + } diff --git a/healthd/healthd_mode_charger.cpp b/healthd/healthd_mode_charger.cpp index 6800ad2..1b6e216 100644 --- a/healthd/healthd_mode_charger.cpp +++ b/healthd/healthd_mode_charger.cpp @@ -65,13 +65,22 @@ char *locale; #define BATTERY_UNKNOWN_TIME (2 * MSEC_PER_SEC) #define POWER_ON_KEY_TIME (2 * MSEC_PER_SEC) -#define UNPLUGGED_SHUTDOWN_TIME (10 * MSEC_PER_SEC) +#define UNPLUGGED_SHUTDOWN_TIME (5 * MSEC_PER_SEC) #define BATTERY_FULL_THRESH 95 #define LAST_KMSG_PATH "/proc/last_kmsg" #define LAST_KMSG_PSTORE_PATH "/sys/fs/pstore/console-ramoops" #define LAST_KMSG_MAX_SZ (32 * 1024) +#ifndef RED_LED_PATH +#define RED_LED_PATH "/sys/class/leds/red/brightness" +#endif +#ifndef GREEN_LED_PATH +#define GREEN_LED_PATH "/sys/class/leds/green/brightness" +#endif +#ifndef BLUE_LED_PATH +#define BLUE_LED_PATH "/sys/class/leds/blue/brightness" +#endif #define LOGE(x...) do { KLOG_ERROR("charger", x); } while (0) #define LOGW(x...) do { KLOG_WARNING("charger", x); } while (0) @@ -168,6 +177,33 @@ static struct animation battery_animation = { .capacity = 0, }; +enum { + RED_LED = 0x01 << 0, + GREEN_LED = 0x01 << 1, + BLUE_LED = 0x01 << 2, +}; + +struct led_ctl { + int color; + const char *path; +}; + +struct led_ctl leds[3] = + {{RED_LED, RED_LED_PATH}, + {GREEN_LED, GREEN_LED_PATH}, + {BLUE_LED, BLUE_LED_PATH}}; + +struct soc_led_color_mapping { + int soc; + int color; +}; + +struct soc_led_color_mapping soc_leds[3] = { + {15, RED_LED}, + {90, RED_LED | GREEN_LED}, + {100, GREEN_LED}, +}; + static struct charger charger_state; static struct healthd_config *healthd_config; static struct android::BatteryProperties *batt_prop; @@ -175,6 +211,53 @@ static int char_width; static int char_height; static bool minui_inited; +static int set_tricolor_led(int on, int color) +{ + int fd, i; + char buffer[10]; + + for (i = 0; i < (int)ARRAY_SIZE(leds); i++) { + if ((color & leds[i].color) && (access(leds[i].path, R_OK | W_OK) == 0)) { + fd = open(leds[i].path, O_RDWR); + if (fd < 0) { + LOGE("Could not open led node %d\n", i); + continue; + } + if (on) + snprintf(buffer, sizeof(int), "%d\n", 255); + else + snprintf(buffer, sizeof(int), "%d\n", 0); + + if (write(fd, buffer, strlen(buffer)) < 0) + LOGE("Could not write to led node\n"); + if (fd >= 0) + close(fd); + } + } + + return 0; +} + +static int set_battery_soc_leds(int soc) +{ + int i, color; + static int old_color = 0; + + for (i = 0; i < (int)ARRAY_SIZE(soc_leds); i++) { + if (soc <= soc_leds[i].soc) + break; + } + color = soc_leds[i].color; + if (old_color != color) { + set_tricolor_led(0, old_color); + set_tricolor_led(1, color); + old_color = color; + LOGV("soc = %d, set led color 0x%x\n", soc, soc_leds[i].color); + } + + return 0; +} + /* current time in milliseconds */ static int64_t curr_time_ms(void) { @@ -314,6 +397,7 @@ static void draw_battery(struct charger *charger) batt_anim->cur_frame, frame->min_capacity, frame->disp_time); } + healthd_board_mode_charger_draw_battery(batt_prop); } static void redraw_screen(struct charger *charger) @@ -367,6 +451,7 @@ static void update_screen_state(struct charger *charger, int64_t now) gr_font_size(&char_width, &char_height); #ifndef CHARGER_DISABLE_INIT_BLANK + healthd_board_mode_charger_set_backlight(false); gr_fb_blank(true); #endif minui_inited = true; @@ -376,6 +461,7 @@ static void update_screen_state(struct charger *charger, int64_t now) if (batt_anim->cur_cycle == batt_anim->num_cycles) { reset_animation(batt_anim); charger->next_screen_transition = -1; + healthd_board_mode_charger_set_backlight(false); gr_fb_blank(true); LOGV("[%" PRId64 "] animation done\n", now); if (charger->charger_connected) @@ -406,9 +492,11 @@ static void update_screen_state(struct charger *charger, int64_t now) batt_anim->capacity = batt_prop->batteryLevel; } - /* unblank the screen on first cycle */ - if (batt_anim->cur_cycle == 0) + /* unblank the screen on first cycle */ + if (batt_anim->cur_cycle == 0) { gr_fb_blank(false); + healthd_board_mode_charger_set_backlight(true); + } /* draw the new frame (@ cur_frame) */ redraw_screen(charger); @@ -508,6 +596,7 @@ static void set_next_key_check(struct charger *charger, static void process_key(struct charger *charger, int code, int64_t now) { + struct animation *batt_anim = charger->batt_anim; struct key_state *key = &charger->keys[code]; if (code == KEY_POWER) { @@ -519,6 +608,8 @@ static void process_key(struct charger *charger, int code, int64_t now) accordingly. */ if (property_get_bool("ro.enable_boot_charger_mode", false)) { LOGW("[%" PRId64 "] booting from charger mode\n", now); + healthd_board_mode_charger_set_backlight(false); + gr_fb_blank(true); property_set("sys.boot_from_charger_mode", "1"); } else { if (charger->batt_anim->capacity >= charger->boot_min_cap) { @@ -534,19 +625,32 @@ static void process_key(struct charger *charger, int code, int64_t now) * make sure we wake up at the right-ish time to check */ set_next_key_check(charger, key, POWER_ON_KEY_TIME); - - /* Turn on the display and kick animation on power-key press - * rather than on key release - */ - kick_animation(charger->batt_anim); - request_suspend(false); } } else { - /* if the power key got released, force screen state cycle */ if (key->pending) { - kick_animation(charger->batt_anim); + /* If key is pressed when the animation is not running, kick + * the animation and quite suspend; If key is pressed when + * the animation is running, turn off the animation and request + * suspend. + */ + if (!batt_anim->run) { + kick_animation(batt_anim); + request_suspend(false); + } else { + reset_animation(batt_anim); + charger->next_screen_transition = -1; + healthd_board_mode_charger_set_backlight(false); + gr_fb_blank(true); + if (charger->charger_connected) + request_suspend(true); + } } } + } else { + if (key->pending) { + request_suspend(false); + kick_animation(charger->batt_anim); + } } key->pending = false; @@ -555,6 +659,7 @@ static void process_key(struct charger *charger, int code, int64_t now) static void handle_input_state(struct charger *charger, int64_t now) { process_key(charger, KEY_POWER, now); + process_key(charger, KEY_HOME, now); if (charger->next_key_check != -1 && now > charger->next_key_check) charger->next_key_check = -1; @@ -562,9 +667,23 @@ static void handle_input_state(struct charger *charger, int64_t now) static void handle_power_supply_state(struct charger *charger, int64_t now) { + static int old_soc = 0; + int soc = 0; + if (!charger->have_battery_state) return; + healthd_board_mode_charger_battery_update(batt_prop); + + if (batt_prop && batt_prop->batteryLevel >= 0) { + soc = batt_prop->batteryLevel; + } + + if (old_soc != soc) { + old_soc = soc; + set_battery_soc_leds(soc); + } + if (!charger->charger_connected) { /* Last cycle would have stopped at the extreme top of battery-icon @@ -683,6 +802,8 @@ void healthd_mode_charger_init(struct healthd_config* config) LOGW("--------------- STARTING CHARGER MODE ---------------\n"); + healthd_board_mode_charger_init(); + ret = ev_init(input_callback, charger); if (!ret) { epollfd = ev_get_epollfd(); diff --git a/include/cutils/iosched_policy.h b/include/cutils/iosched_policy.h index 07c5d1f..25b87ba 100644 --- a/include/cutils/iosched_policy.h +++ b/include/cutils/iosched_policy.h @@ -31,6 +31,8 @@ typedef enum { extern int android_set_ioprio(int pid, IoSchedClass clazz, int ioprio); extern int android_get_ioprio(int pid, IoSchedClass *clazz, int *ioprio); +extern int android_set_rt_ioprio(int pid, int rt); + #ifdef __cplusplus } #endif diff --git a/include/private/android_filesystem_config.h b/include/private/android_filesystem_config.h index 2ed27dc..8b3390c 100644 --- a/include/private/android_filesystem_config.h +++ b/include/private/android_filesystem_config.h @@ -97,6 +97,12 @@ #define AID_NET_BW_STATS 3006 /* read bandwidth statistics */ #define AID_NET_BW_ACCT 3007 /* change bandwidth statistics accounting */ #define AID_NET_BT_STACK 3008 /* bluetooth: access config files */ +#define AID_QCOM_DIAG 3009 /* can read/write /dev/diag */ + +#define AID_SENSORS 3011 /* access to /dev/socket/sensor_ctl_socket & QCCI/QCSI */ + +#define AID_RFS 3012 /* Remote Filesystem for peripheral processors */ +#define AID_RFS_SHARED 3013 /* Shared files for Remote Filesystem for peripheral processors */ #define AID_EVERYBODY 9997 /* shared between all apps in the same profile */ #define AID_MISC 9998 /* access to misc storage */ @@ -172,6 +178,7 @@ static const struct android_id_info android_ids[] = { { "shell", AID_SHELL, }, { "cache", AID_CACHE, }, { "diag", AID_DIAG, }, + { "qcom_diag", AID_QCOM_DIAG, }, { "net_bt_admin", AID_NET_BT_ADMIN, }, { "net_bt", AID_NET_BT, }, @@ -182,6 +189,11 @@ static const struct android_id_info android_ids[] = { { "net_bw_acct", AID_NET_BW_ACCT, }, { "net_bt_stack", AID_NET_BT_STACK, }, + { "sensors", AID_SENSORS, }, + + { "rfs", AID_RFS, }, + { "rfs_shared", AID_RFS_SHARED, }, + { "everybody", AID_EVERYBODY, }, { "misc", AID_MISC, }, { "nobody", AID_NOBODY, }, diff --git a/include/system/camera.h b/include/system/camera.h index 5d0873a..0570ca0 100644 --- a/include/system/camera.h +++ b/include/system/camera.h @@ -88,9 +88,20 @@ enum { // Notify on autofocus start and stop. This is useful in continuous // autofocus - FOCUS_MODE_CONTINUOUS_VIDEO and FOCUS_MODE_CONTINUOUS_PICTURE. CAMERA_MSG_FOCUS_MOVE = 0x0800, // notifyCallback + CAMERA_MSG_VENDOR_START = 0x1000, + CAMERA_MSG_STATS_DATA = CAMERA_MSG_VENDOR_START, + CAMERA_MSG_META_DATA = 0x2000, + CAMERA_MSG_VENDOR_END = 0x8000, CAMERA_MSG_ALL_MSGS = 0xFFFF }; +/** meta data type in CameraMetaDataCallback */ +enum { + CAMERA_META_DATA_ASD = 0x001, //ASD data + CAMERA_META_DATA_FD = 0x002, //FD/FP data + CAMERA_META_DATA_HDR = 0x003, //Auto HDR data +}; + /** cmdType in sendCommand functions */ enum { CAMERA_CMD_START_SMOOTH_ZOOM = 1, @@ -189,7 +200,41 @@ enum { * IMPLEMENTATION_DEFINED, then HALv3 devices will use gralloc usage flags * of SW_READ_OFTEN. */ - CAMERA_CMD_SET_VIDEO_FORMAT = 11 +#ifndef CAMERA_VENDOR_L_COMPAT + CAMERA_CMD_SET_VIDEO_FORMAT = 11, + + CAMERA_CMD_VENDOR_START = 20, + /** + * Commands to enable/disable preview histogram + * + * Based on user's input to enable/disable histogram from the camera + * UI, send the appropriate command to the HAL to turn on/off the histogram + * stats and start sending the data to the application. + */ + CAMERA_CMD_HISTOGRAM_ON = CAMERA_CMD_VENDOR_START, + CAMERA_CMD_HISTOGRAM_OFF = CAMERA_CMD_VENDOR_START + 1, + CAMERA_CMD_HISTOGRAM_SEND_DATA = CAMERA_CMD_VENDOR_START + 2, + CAMERA_CMD_LONGSHOT_ON = CAMERA_CMD_VENDOR_START + 3, + CAMERA_CMD_LONGSHOT_OFF = CAMERA_CMD_VENDOR_START + 4, + CAMERA_CMD_STOP_LONGSHOT = CAMERA_CMD_VENDOR_START + 5, + CAMERA_CMD_METADATA_ON = CAMERA_CMD_VENDOR_START + 6, + CAMERA_CMD_METADATA_OFF = CAMERA_CMD_VENDOR_START + 7, + CAMERA_CMD_VENDOR_END = 200, +#else + + /** + * Values used by older HALs, provided as an option for compatibility + */ + CAMERA_CMD_HISTOGRAM_ON = 11, + CAMERA_CMD_HISTOGRAM_OFF = 12, + CAMERA_CMD_HISTOGRAM_SEND_DATA = 13, + CAMERA_CMD_LONGSHOT_ON = 14, + CAMERA_CMD_LONGSHOT_OFF = 15, + CAMERA_CMD_STOP_LONGSHOT = 16, + CAMERA_CMD_METADATA_ON = 100, + CAMERA_CMD_METADATA_OFF = 101, + CAMERA_CMD_SET_VIDEO_FORMAT = 102, +#endif }; /** camera fatal errors */ @@ -275,10 +320,32 @@ typedef struct camera_face { * -2000, -2000 if this is not supported. */ int32_t mouth[2]; + int32_t smile_degree; + int32_t smile_score; + int32_t blink_detected; + int32_t face_recognised; + int32_t gaze_angle; + int32_t updown_dir; + int32_t leftright_dir; + int32_t roll_dir; + int32_t left_right_gaze; + int32_t top_bottom_gaze; + int32_t leye_blink; + int32_t reye_blink; } camera_face_t; /** + * The information of a data type received in a camera frame. + */ +typedef enum { + /** Data buffer */ + CAMERA_FRAME_DATA_BUF = 0x000, + /** File descriptor */ + CAMERA_FRAME_DATA_FD = 0x100 +} camera_frame_data_type_t; + +/** * The metadata of the frame data. */ typedef struct camera_frame_metadata { diff --git a/init/Android.mk b/init/Android.mk index de065dc..159c4f2 100644 --- a/init/Android.mk +++ b/init/Android.mk @@ -48,9 +48,29 @@ LOCAL_SRC_FILES:= \ ueventd.cpp \ ueventd_parser.cpp \ watchdogd.cpp \ + vendor_init.cpp + +SYSTEM_CORE_INIT_DEFINES := BOARD_CHARGING_MODE_BOOTING_LPM \ + BOARD_CHARGING_CMDLINE_NAME \ + BOARD_CHARGING_CMDLINE_VALUE + +$(foreach system_core_init_define,$(SYSTEM_CORE_INIT_DEFINES), \ + $(if $($(system_core_init_define)), \ + $(eval LOCAL_CFLAGS += -D$(system_core_init_define)=\"$($(system_core_init_define))\") \ + ) \ +) + +ifneq ($(TARGET_IGNORE_RO_BOOT_SERIALNO),) +LOCAL_CFLAGS += -DIGNORE_RO_BOOT_SERIALNO +endif + +ifneq ($(TARGET_IGNORE_RO_BOOT_REVISION),) +LOCAL_CFLAGS += -DIGNORE_RO_BOOT_REVISION +endif LOCAL_MODULE:= init LOCAL_C_INCLUDES += \ + external/zlib \ system/extras/ext4_utils \ system/core/mkbootimg @@ -71,6 +91,9 @@ LOCAL_STATIC_LIBRARIES := \ libc \ libselinux \ libmincrypt \ + libext4_utils_static \ + libext2_blkid \ + libext2_uuid_static \ libc++_static \ libdl \ libsparse_static \ @@ -82,6 +105,11 @@ LOCAL_POST_INSTALL_CMD := $(hide) mkdir -p $(TARGET_ROOT_OUT)/sbin; \ ln -sf ../init $(TARGET_ROOT_OUT)/sbin/watchdogd LOCAL_CLANG := $(init_clang) + +ifneq ($(strip $(TARGET_INIT_VENDOR_LIB)),) +LOCAL_WHOLE_STATIC_LIBRARIES += $(TARGET_INIT_VENDOR_LIB) +endif + include $(BUILD_EXECUTABLE) diff --git a/init/NOTICE b/init/NOTICE index c5b1efa..383d0f5 100644 --- a/init/NOTICE +++ b/init/NOTICE @@ -188,3 +188,29 @@ END OF TERMS AND CONDITIONS +Copyright (c) 2013, The Linux Foundation. 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. + * Neither the name of The Linux Foundation 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 "AS IS" AND ANY EXPRESS OR IMPLIED +WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF +MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT +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. diff --git a/init/builtins.cpp b/init/builtins.cpp index 8eb5b5b..e3e64f4 100644 --- a/init/builtins.cpp +++ b/init/builtins.cpp @@ -111,23 +111,35 @@ static void service_start_if_not_disabled(struct service *svc) int do_class_start(int nargs, char **args) { - /* Starting a class does not start services - * which are explicitly disabled. They must - * be started individually. - */ + char prop[PROP_NAME_MAX]; + snprintf(prop, PROP_NAME_MAX, "class_start:%s", args[1]); + + /* Starting a class does not start services + * which are explicitly disabled. They must + * be started individually. + */ service_for_each_class(args[1], service_start_if_not_disabled); + action_for_each_trigger(prop, action_add_queue_tail); return 0; } int do_class_stop(int nargs, char **args) { + char prop[PROP_NAME_MAX]; + snprintf(prop, PROP_NAME_MAX, "class_stop:%s", args[1]); + service_for_each_class(args[1], service_stop); + action_for_each_trigger(prop, action_add_queue_tail); return 0; } int do_class_reset(int nargs, char **args) { + char prop[PROP_NAME_MAX]; + snprintf(prop, PROP_NAME_MAX, "class_reset:%s", args[1]); + service_for_each_class(args[1], service_reset); + action_for_each_trigger(prop, action_add_queue_tail); return 0; } @@ -401,6 +413,7 @@ int do_mount_all(int nargs, char **args) int ret = -1; int child_ret = -1; int status; + char boot_mode[PROP_VALUE_MAX] = {0}; struct fstab *fstab; if (nargs != 2) { @@ -450,10 +463,13 @@ int do_mount_all(int nargs, char **args) property_set("vold.decrypt", "trigger_default_encryption"); } else if (ret == FS_MGR_MNTALL_DEV_NOT_ENCRYPTED) { property_set("ro.crypto.state", "unencrypted"); - /* If fs_mgr determined this is an unencrypted device, then trigger - * that action. + /* If fs_mgr determined this is an unencrypted device and we are + * not booting into ffbm(fast factory boot mode),then trigger + * that action. */ - action_for_each_trigger("nonencrypted", action_add_queue_tail); + property_get("ro.bootmode", boot_mode); + if (strncmp(boot_mode, "ffbm", 4)) + action_for_each_trigger("nonencrypted", action_add_queue_tail); } else if (ret == FS_MGR_MNTALL_DEV_NEEDS_RECOVERY) { /* Setup a wipe via recovery, and reboot into recovery */ ERROR("fs_mgr_mount_all suggested recovery, so wiping data via recovery.\n"); @@ -468,7 +484,9 @@ int do_mount_all(int nargs, char **args) // Although encrypted, we have device key, so we do not need to // do anything different from the nonencrypted case. - action_for_each_trigger("nonencrypted", action_add_queue_tail); + property_get("ro.bootmode", boot_mode); + if (strncmp(boot_mode, "ffbm", 4)) + action_for_each_trigger("nonencrypted", action_add_queue_tail); } else if (ret == FS_MGR_MNTALL_DEV_NON_DEFAULT_FILE_ENCRYPTED) { if (e4crypt_install_keyring()) { return -1; @@ -578,7 +596,14 @@ int do_powerctl(int nargs, char **args) } if (command[len] == ',') { + char prop_value[PROP_VALUE_MAX] = {0}; reboot_target = &command[len + 1]; + + if ((property_get("init.svc.recovery", prop_value) == 0) && + (strncmp(reboot_target, "keys", 4) == 0)) { + ERROR("powerctl: permission denied\n"); + return -EINVAL; + } } else if (command[len] == '\0') { reboot_target = ""; } else { diff --git a/init/devices.cpp b/init/devices.cpp index 4944cec..bb54cca 100644 --- a/init/devices.cpp +++ b/init/devices.cpp @@ -47,6 +47,8 @@ #include "ueventd_parser.h" #include "util.h" #include "log.h" +#include "property_service.h" +#include <zlib.h> #define SYSFS_PREFIX "/sys" static const char *firmware_dirs[] = { "/etc/firmware", @@ -55,6 +57,8 @@ static const char *firmware_dirs[] = { "/etc/firmware", extern struct selabel_handle *sehandle; +extern char boot_device[PROP_VALUE_MAX]; + static int device_fd = -1; struct uevent { @@ -323,6 +327,35 @@ static void remove_platform_device(const char *path) } } +/* Given a path that may start with an MTD device (/devices/virtual/mtd/mtd8/mtdblock8), + * populate the supplied buffer with the MTD partition number and return 0. + * If it doesn't start with an MTD device, or there is some error, return -1 */ +static int find_mtd_device_prefix(const char *path, char *buf, ssize_t buf_sz) +{ + const char *start, *end; + + if (strncmp(path, "/devices/virtual/mtd", 20)) + return -1; + + /* Beginning of the prefix is the initial "mtdXX" after "/devices/virtual/mtd/" */ + start = path + 21; + + /* End of the prefix is one path '/' later, capturing the partition number + * Example: mtd8 */ + end = strchr(start, '/'); + if (!end) { + return -1; + } + + /* Make sure we have enough room for the string plus null terminator */ + if (end - start + 1 > buf_sz) + return -1; + + strncpy(buf, start, end - start); + buf[end - start] = '\0'; + return 0; +} + /* Given a path that may start with a PCI device, populate the supplied buffer * with the PCI domain/bus number and the peripheral ID and return 0. * If it doesn't start with a PCI device, or there is some error, return -1 */ @@ -472,6 +505,11 @@ static char **get_block_device_symlinks(struct uevent *uevent) char link_path[256]; int link_num = 0; char *p; + int is_bootdevice = -1; + int mtd_fd = -1; + int nr; + char mtd_name_path[256]; + char mtd_name[64]; pdev = find_platform_device(uevent->path); if (pdev) { @@ -480,19 +518,52 @@ static char **get_block_device_symlinks(struct uevent *uevent) } else if (!find_pci_device_prefix(uevent->path, buf, sizeof(buf))) { device = buf; type = "pci"; + } else if (!find_mtd_device_prefix(uevent->path, buf, sizeof(buf))) { + device = buf; + type = "mtd"; } else { return NULL; } - char **links = (char**) malloc(sizeof(char *) * 4); + char **links = (char**) malloc(sizeof(char *) * 6); if (!links) return NULL; - memset(links, 0, sizeof(char *) * 4); + memset(links, 0, sizeof(char *) * 6); INFO("found %s device %s\n", type, device); snprintf(link_path, sizeof(link_path), "/dev/block/%s/%s", type, device); + if(!strcmp(type, "mtd")) { + snprintf(mtd_name_path, sizeof(mtd_name_path), + "/sys/devices/virtual/%s/%s/name", type, device); + mtd_fd = open(mtd_name_path, O_RDONLY); + if(mtd_fd < 0) { + ERROR("Unable to open %s for reading", mtd_name_path); + return NULL; + } + nr = read(mtd_fd, mtd_name, sizeof(mtd_name) - 1); + if (nr <= 0) + return NULL; + close(mtd_fd); + mtd_name[nr - 1] = '\0'; + + p = strdup(mtd_name); + sanitize(p); + if (asprintf(&links[link_num], "/dev/block/%s/by-name/%s", type, p) > 0) + link_num++; + else + links[link_num] = NULL; + free(p); + } + + if (pdev && boot_device[0] != '\0' && strstr(device, boot_device)) { + make_link_init(link_path, "/dev/block/bootdevice"); + is_bootdevice = 1; + } else { + is_bootdevice = 0; + } + if (uevent->partition_name) { p = strdup(uevent->partition_name); sanitize(p); @@ -502,6 +573,13 @@ static char **get_block_device_symlinks(struct uevent *uevent) link_num++; else links[link_num] = NULL; + + if (is_bootdevice > 0) { + if (asprintf(&links[link_num], "/dev/block/bootdevice/by-name/%s", p) > 0) + link_num++; + else + links[link_num] = NULL; + } free(p); } @@ -510,6 +588,13 @@ static char **get_block_device_symlinks(struct uevent *uevent) link_num++; else links[link_num] = NULL; + + if (is_bootdevice > 0) { + if (asprintf(&links[link_num], "/dev/block/bootdevice/by-num/p%d", uevent->partition_num) > 0) + link_num++; + else + links[link_num] = NULL; + } } slash = strrchr(uevent->path, '/'); @@ -748,23 +833,20 @@ static void handle_device_event(struct uevent *uevent) } } -static int load_firmware(int fw_fd, int loading_fd, int data_fd) +static int load_firmware(int fw_fd, gzFile gz_fd, int loading_fd, int data_fd) { - struct stat st; - long len_to_copy; int ret = 0; - if(fstat(fw_fd, &st) < 0) - return -1; - len_to_copy = st.st_size; - write(loading_fd, "1", 1); /* start transfer */ - while (len_to_copy > 0) { + while (1) { char buf[PAGE_SIZE]; ssize_t nr; - nr = read(fw_fd, buf, sizeof(buf)); + if (gz_fd) + nr = gzread(gz_fd, buf, sizeof(buf)); + else + nr = read(fw_fd, buf, sizeof(buf)); if(!nr) break; if(nr < 0) { @@ -772,7 +854,6 @@ static int load_firmware(int fw_fd, int loading_fd, int data_fd) break; } - len_to_copy -= nr; while (nr > 0) { ssize_t nw = 0; @@ -788,8 +869,10 @@ static int load_firmware(int fw_fd, int loading_fd, int data_fd) out: if(!ret) write(loading_fd, "0", 1); /* successful end of transfer */ - else + else { + ERROR("%s: aborted transfer\n", __func__); write(loading_fd, "-1", 2); /* abort transfer */ + } return ret; } @@ -799,12 +882,29 @@ static int is_booting(void) return access("/dev/.booting", F_OK) == 0; } +gzFile fw_gzopen(const char *fname, const char *mode) +{ + char *file1 = NULL; + int l; + gzFile gz_fd = NULL; + + l = asprintf(&file1, "%s.gz", fname); + if (l == -1) + goto out; + + gz_fd = gzopen(file1, mode); + free(file1); +out: + return gz_fd; +} + static void process_firmware_event(struct uevent *uevent) { char *root, *loading, *data; int l, loading_fd, data_fd, fw_fd; size_t i; int booting = is_booting(); + gzFile gz_fd = NULL; INFO("firmware: loading '%s' for '%s'\n", uevent->firmware, uevent->path); @@ -837,15 +937,18 @@ try_loading_again: goto data_free_out; fw_fd = open(file, O_RDONLY|O_CLOEXEC); free(file); - if (fw_fd >= 0) { - if(!load_firmware(fw_fd, loading_fd, data_fd)) + if (fw_fd < 0){ + gz_fd = fw_gzopen(file, "rb"); + } + if (fw_fd >= 0 || gz_fd) { + if(!load_firmware(fw_fd, gz_fd, loading_fd, data_fd)) INFO("firmware: copy success { '%s', '%s' }\n", root, uevent->firmware); else INFO("firmware: copy failure { '%s', '%s' }\n", root, uevent->firmware); break; } } - if (fw_fd < 0) { + if ((fw_fd < 0) && !gz_fd) { if (booting) { /* If we're not fully booted, we may be missing * filesystems needed for firmware, wait and retry. @@ -859,7 +962,10 @@ try_loading_again: goto data_close_out; } - close(fw_fd); + if (gz_fd) + gzclose(gz_fd); + else + close(fw_fd); data_close_out: close(data_fd); loading_close_out: diff --git a/init/init.cpp b/init/init.cpp index 93fe944..402331b 100644 --- a/init/init.cpp +++ b/init/init.cpp @@ -63,13 +63,20 @@ #include "util.h" #include "ueventd.h" #include "watchdogd.h" +#include "vendor_init.h" struct selabel_handle *sehandle; struct selabel_handle *sehandle_prop; static int property_triggers_enabled = 0; +#ifndef BOARD_CHARGING_CMDLINE_NAME +#define BOARD_CHARGING_CMDLINE_NAME "androidboot.battchg_pause" +#define BOARD_CHARGING_CMDLINE_VALUE "true" +#endif + static char qemu[32]; +static char battchg_pause[32]; static struct action *cur_action = NULL; static struct command *cur_command = NULL; @@ -529,6 +536,9 @@ static void msg_restart(const char *name) void handle_control_message(const char *msg, const char *arg) { + if (!vendor_handle_control_message(msg, arg)) + return; + if (!strcmp(msg,"start")) { msg_start(arg); } else if (!strcmp(msg,"stop")) { @@ -782,6 +792,8 @@ static void import_kernel_nv(char *name, bool for_emulator) if (!strcmp(name,"qemu")) { strlcpy(qemu, value, sizeof(qemu)); + } else if (!strcmp(name,BOARD_CHARGING_CMDLINE_NAME)) { + strlcpy(battchg_pause, value, sizeof(battchg_pause)); } else if (!strncmp(name, "androidboot.", 12) && name_len > 12) { const char *boot_prop_name = name + 12; char prop[PROP_NAME_MAX]; @@ -799,12 +811,16 @@ static void export_kernel_boot_props() { const char *dst_prop; const char *default_value; } prop_map[] = { +#ifndef IGNORE_RO_BOOT_SERIALNO { "ro.boot.serialno", "ro.serialno", "", }, +#endif { "ro.boot.mode", "ro.bootmode", "unknown", }, { "ro.boot.baseband", "ro.baseband", "unknown", }, { "ro.boot.bootloader", "ro.bootloader", "unknown", }, { "ro.boot.hardware", "ro.hardware", "unknown", }, +#ifndef IGNORE_RO_BOOT_REVISION { "ro.boot.revision", "ro.revision", "0", }, +#endif }; for (size_t i = 0; i < ARRAY_SIZE(prop_map); i++) { char value[PROP_VALUE_MAX]; @@ -986,6 +1002,24 @@ static void selinux_initialize(bool in_kernel_domain) { } } +static int charging_mode_booting(void) { +#ifndef BOARD_CHARGING_MODE_BOOTING_LPM + return 0; +#else + int f; + char cmb; + f = open(BOARD_CHARGING_MODE_BOOTING_LPM, O_RDONLY); + if (f < 0) + return 0; + + if (1 != read(f, (void *)&cmb,1)) + return 0; + + close(f); + return ('1' == cmb); +#endif +} + int main(int argc, char** argv) { if (!strcmp(basename(argv[0]), "ueventd")) { return ueventd_main(argc, argv); @@ -1097,8 +1131,13 @@ int main(int argc, char** argv) { // Don't mount filesystems or start core system services in charger mode. char bootmode[PROP_VALUE_MAX]; - if (property_get("ro.bootmode", bootmode) > 0 && strcmp(bootmode, "charger") == 0) { + if (((property_get("ro.bootmode", bootmode) > 0 && strcmp(bootmode, "charger") == 0) || + strcmp(battchg_pause, BOARD_CHARGING_CMDLINE_VALUE) == 0) + || charging_mode_booting()) { action_for_each_trigger("charger", action_add_queue_tail); + } else if (strncmp(bootmode, "ffbm", 4) == 0) { + KLOG_ERROR("Booting into ffbm mode\n"); + action_for_each_trigger("ffbm", action_add_queue_tail); } else { action_for_each_trigger("late-init", action_add_queue_tail); } diff --git a/init/init_parser.cpp b/init/init_parser.cpp index 9bab67d..c36d36e 100644 --- a/init/init_parser.cpp +++ b/init/init_parser.cpp @@ -44,7 +44,7 @@ struct import { const char *filename; }; -static void *parse_service(struct parse_state *state, int nargs, char **args); +static void *parse_service(struct parse_state *state, int nargs, char **args, bool redefine); static void parse_line_service(struct parse_state *state, int nargs, char **args); static void *parse_action(struct parse_state *state, int nargs, char **args); @@ -184,6 +184,7 @@ static int lookup_keyword(const char *s) case 's': if (!strcmp(s, "eclabel")) return K_seclabel; if (!strcmp(s, "ervice")) return K_service; + if (!strcmp(s, "ervice_redefine")) return K_service_redefine; if (!strcmp(s, "etenv")) return K_setenv; if (!strcmp(s, "etprop")) return K_setprop; if (!strcmp(s, "etrlimit")) return K_setrlimit; @@ -362,7 +363,8 @@ static void parse_new_section(struct parse_state *state, int kw, nargs > 1 ? args[1] : ""); switch(kw) { case K_service: - state->context = parse_service(state, nargs, args); + case K_service_redefine: + state->context = parse_service(state, nargs, args, (kw == K_service_redefine)); if (state->context) { state->parse_line = parse_line_service; return; @@ -725,7 +727,7 @@ service* make_exec_oneshot_service(int nargs, char** args) { return svc; } -static void *parse_service(struct parse_state *state, int nargs, char **args) +static void *parse_service(struct parse_state *state, int nargs, char **args, bool redefine) { if (nargs < 3) { parse_error(state, "services must have a name and a program\n"); @@ -737,13 +739,18 @@ static void *parse_service(struct parse_state *state, int nargs, char **args) } service* svc = (service*) service_find_by_name(args[1]); - if (svc) { + if (svc && !redefine) { parse_error(state, "ignored duplicate definition of service '%s'\n", args[1]); return 0; } nargs -= 2; - svc = (service*) calloc(1, sizeof(*svc) + sizeof(char*) * nargs); + + if (!svc) { + svc = (service*) calloc(1, sizeof(*svc) + sizeof(char*) * nargs); + redefine = false; + } + if (!svc) { parse_error(state, "out of memory\n"); return 0; @@ -758,7 +765,8 @@ static void *parse_service(struct parse_state *state, int nargs, char **args) cur_trigger->name = "onrestart"; list_add_tail(&svc->onrestart.triggers, &cur_trigger->nlist); list_init(&svc->onrestart.commands); - list_add_tail(&service_list, &svc->slist); + if (!redefine) + list_add_tail(&service_list, &svc->slist); return svc; } diff --git a/init/keywords.h b/init/keywords.h index 0910f60..303685d 100644 --- a/init/keywords.h +++ b/init/keywords.h @@ -84,6 +84,7 @@ enum { KEYWORD(rmdir, COMMAND, 1, do_rmdir) KEYWORD(seclabel, OPTION, 0, 0) KEYWORD(service, SECTION, 0, 0) + KEYWORD(service_redefine, SECTION, 0, 0) KEYWORD(setenv, OPTION, 2, 0) KEYWORD(setprop, COMMAND, 2, do_setprop) KEYWORD(setrlimit, COMMAND, 3, do_setrlimit) diff --git a/init/property_service.cpp b/init/property_service.cpp index 52f6b98..11ff06b 100644 --- a/init/property_service.cpp +++ b/init/property_service.cpp @@ -54,6 +54,7 @@ #include "init.h" #include "util.h" #include "log.h" +#include "vendor_init.h" #define PERSISTENT_PROPERTY_DIR "/data/property" #define FSTAB_PREFIX "/fstab." @@ -518,6 +519,11 @@ void load_persist_props(void) { load_override_properties(); /* Read persistent properties after all default values have been loaded. */ load_persistent_properties(); + + /* update with vendor-specific property runtime + * overrides + */ + vendor_load_properties(); } void load_recovery_id_prop() { @@ -564,6 +570,7 @@ void load_system_props() { load_properties_from_file(PROP_PATH_SYSTEM_BUILD, NULL); load_properties_from_file(PROP_PATH_VENDOR_BUILD, NULL); load_properties_from_file(PROP_PATH_FACTORY, "ro.*"); + load_recovery_id_prop(); } diff --git a/init/ueventd.cpp b/init/ueventd.cpp index c63fdaa..2dd8b01 100644 --- a/init/ueventd.cpp +++ b/init/ueventd.cpp @@ -33,6 +33,8 @@ #include "ueventd_parser.h" #include "property_service.h" +char boot_device[PROP_VALUE_MAX]; + int ueventd_main(int argc, char **argv) { /* @@ -65,6 +67,8 @@ int ueventd_main(int argc, char **argv) ueventd_parse_config_file("/ueventd.rc"); ueventd_parse_config_file(android::base::StringPrintf("/ueventd.%s.rc", hardware).c_str()); + property_get("ro.boot.bootdevice", boot_device); + device_init(); pollfd ufd; diff --git a/init/util.cpp b/init/util.cpp index a5392c6..b006e0b 100644 --- a/init/util.cpp +++ b/init/util.cpp @@ -458,9 +458,13 @@ int restorecon(const char* pathname) return selinux_android_restorecon(pathname, 0); } +#define RESTORECON_RECURSIVE_FLAGS \ + (SELINUX_ANDROID_RESTORECON_FORCE | \ + SELINUX_ANDROID_RESTORECON_RECURSE) + int restorecon_recursive(const char* pathname) { - return selinux_android_restorecon(pathname, SELINUX_ANDROID_RESTORECON_RECURSE); + return selinux_android_restorecon(pathname, RESTORECON_RECURSIVE_FLAGS); } /* diff --git a/init/vendor_init.cpp b/init/vendor_init.cpp new file mode 100644 index 0000000..d2964ad --- /dev/null +++ b/init/vendor_init.cpp @@ -0,0 +1,44 @@ +/* +Copyright (c) 2013, The Linux Foundation. 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. + * Neither the name of The Linux Foundation 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 "AS IS" AND ANY EXPRESS OR IMPLIED +WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF +MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT +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. + */ + +#include "vendor_init.h" +#include <errno.h> + +/* init vendor override stubs */ + +__attribute__ ((weak)) +void vendor_load_properties() +{ +} + +__attribute__ ((weak)) +int vendor_handle_control_message(const char *msg, const char *arg) +{ + return -ENOSYS; +} diff --git a/init/vendor_init.h b/init/vendor_init.h new file mode 100644 index 0000000..efa4eea --- /dev/null +++ b/init/vendor_init.h @@ -0,0 +1,34 @@ +/* +Copyright (c) 2013, The Linux Foundation. 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. + * Neither the name of The Linux Foundation 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 "AS IS" AND ANY EXPRESS OR IMPLIED +WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF +MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT +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 __INIT_VENDOR__H__ +#define __INIT_VENDOR__H__ +extern void vendor_load_properties(void); +extern int vendor_handle_control_message(const char *msg, const char *arg); +#endif /* __INIT_VENDOR__H__ */ diff --git a/libcutils/fs_config.c b/libcutils/fs_config.c index 9a1ad19..7b23d71 100644 --- a/libcutils/fs_config.c +++ b/libcutils/fs_config.c @@ -121,9 +121,10 @@ static const struct fs_path_config android_files[] = { { 00644, AID_SYSTEM, AID_SYSTEM, 0, "data/app-private/*" }, { 00644, AID_APP, AID_APP, 0, "data/data/*" }, + /* CM's daemonized su doesn't need the setuid bit */ + { 00755, AID_ROOT, AID_SHELL, 0, "system/xbin/su" }, /* the following five files are INTENTIONALLY set-uid, but they * are NOT included on user builds. */ - { 04750, AID_ROOT, AID_SHELL, 0, "system/xbin/su" }, { 06755, AID_ROOT, AID_ROOT, 0, "system/xbin/librank" }, { 06755, AID_ROOT, AID_ROOT, 0, "system/xbin/procrank" }, { 06755, AID_ROOT, AID_ROOT, 0, "system/xbin/procmem" }, @@ -136,6 +137,7 @@ static const struct fs_path_config android_files[] = { { 00750, AID_ROOT, AID_ROOT, 0, "system/bin/uncrypt" }, { 00750, AID_ROOT, AID_ROOT, 0, "system/bin/install-recovery.sh" }, { 00755, AID_ROOT, AID_SHELL, 0, "system/bin/*" }, + { 00755, AID_ROOT, AID_SHELL, 0, "system/etc/init.d/*" }, { 00755, AID_ROOT, AID_ROOT, 0, "system/lib/valgrind/*" }, { 00755, AID_ROOT, AID_ROOT, 0, "system/lib64/valgrind/*" }, { 00755, AID_ROOT, AID_SHELL, 0, "system/xbin/*" }, diff --git a/libcutils/iosched_policy.c b/libcutils/iosched_policy.c index 8946d3c..745e2b6 100644 --- a/libcutils/iosched_policy.c +++ b/libcutils/iosched_policy.c @@ -1,9 +1,10 @@ /* -** Copyright 2007, The Android Open Source Project +** Copyright 2007-2014, The Android Open Source Project +** Copyright 2015, The CyanogenMod 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 +** 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 ** @@ -20,28 +21,30 @@ #include <stdlib.h> #include <string.h> #include <unistd.h> +#include <pthread.h> #include <cutils/iosched_policy.h> +#define LOG_TAG "iosched_policy" +#include <cutils/log.h> + +#define __android_unused __attribute__((__unused__)) #ifdef HAVE_ANDROID_OS #include <linux/ioprio.h> #include <sys/syscall.h> -#define __android_unused -#else -#define __android_unused __attribute__((__unused__)) -#endif +#include <sys/stat.h> + +static int __rtio_cgroup_supported = -1; +static pthread_once_t __rtio_init_once = PTHREAD_ONCE_INIT; int android_set_ioprio(int pid __android_unused, IoSchedClass clazz __android_unused, int ioprio __android_unused) { -#ifdef HAVE_ANDROID_OS if (syscall(SYS_ioprio_set, IOPRIO_WHO_PROCESS, pid, ioprio | (clazz << IOPRIO_CLASS_SHIFT))) { return -1; } -#endif return 0; } int android_get_ioprio(int pid __android_unused, IoSchedClass *clazz, int *ioprio) { -#ifdef HAVE_ANDROID_OS int rc; if ((rc = syscall(SYS_ioprio_get, IOPRIO_WHO_PROCESS, pid)) < 0) { @@ -50,9 +53,83 @@ int android_get_ioprio(int pid __android_unused, IoSchedClass *clazz, int *iopri *clazz = (rc >> IOPRIO_CLASS_SHIFT); *ioprio = (rc & 0xff); + return 0; +} + +static void __initialize_rtio(void) { + if (!access("/sys/fs/cgroup/bfqio/tasks", W_OK) || + !access("/sys/fs/cgroup/bfqio/rt-display/tasks", W_OK)) { + __rtio_cgroup_supported = 1; + } else { + __rtio_cgroup_supported = 0; + } +} + +int android_set_rt_ioprio(int tid, int rt) { + int fd = -1, rc = -1; + + pthread_once(&__rtio_init_once, __initialize_rtio); + if (__rtio_cgroup_supported != 1) { + return -1; + } + + if (rt) { + fd = open("/sys/fs/cgroup/bfqio/rt-display/tasks", O_WRONLY | O_CLOEXEC); + } else { + fd = open("/sys/fs/cgroup/bfqio/tasks", O_WRONLY | O_CLOEXEC); + } + + if (fd < 0) { + return -1; + } + +#ifdef HAVE_GETTID + if (tid == 0) { + tid = gettid(); + } +#endif + + // specialized itoa -- works for tid > 0 + char text[22]; + char *end = text + sizeof(text) - 1; + char *ptr = end; + *ptr = '\0'; + while (tid > 0) { + *--ptr = '0' + (tid % 10); + tid = tid / 10; + } + + rc = write(fd, ptr, end - ptr); + if (rc < 0) { + /* + * If the thread is in the process of exiting, + * don't flag an error + */ + if (errno == ESRCH) { + rc = 0; + } else { + SLOGV("android_set_rt_ioprio failed to write '%s' (%s); fd=%d\n", + ptr, strerror(errno), fd); + } + } + + close(fd); + return rc; +} + #else +int android_set_ioprio(int pid __android_unused, IoSchedClass clazz __android_unused, int ioprio __android_unused) { + return 0; +} + +int android_get_ioprio(int pid __android_unused, IoSchedClass *clazz, int *ioprio) { *clazz = IoSchedClass_NONE; *ioprio = 0; -#endif return 0; } + +int android_set_rt_ioprio(int tid __android_unused, int rt __android_unused) +{ + return 0; +} +#endif diff --git a/libdiskconfig/Android.mk b/libdiskconfig/Android.mk index 624e385..5e7400e 100644 --- a/libdiskconfig/Android.mk +++ b/libdiskconfig/Android.mk @@ -15,6 +15,13 @@ LOCAL_SYSTEM_SHARED_LIBRARIES := libcutils liblog libc LOCAL_CFLAGS := -Werror include $(BUILD_SHARED_LIBRARY) +include $(CLEAR_VARS) +LOCAL_SRC_FILES := $(commonSources) +LOCAL_MODULE := libdiskconfig +LOCAL_MODULE_TAGS := optional +#LOCAL_STATIC_LIBRARIES := libcutils liblog libc +include $(BUILD_STATIC_LIBRARY) + ifeq ($(HOST_OS),linux) include $(CLEAR_VARS) LOCAL_SRC_FILES := $(commonSources) diff --git a/liblog/log_is_loggable.c b/liblog/log_is_loggable.c index 7a8e33f..cd85ff6 100644 --- a/liblog/log_is_loggable.c +++ b/liblog/log_is_loggable.c @@ -93,7 +93,7 @@ static int __android_log_level(const char *tag, int def) if (taglen) { uint32_t current_local_serial = current_global_serial; - if (!last_tag || strcmp(last_tag, tag)) { + if (!last_tag || (last_tag[0] != tag[0]) || strcmp(last_tag + 1, tag + 1)) { /* invalidate log.tag.<tag> cache */ for(i = 0; i < (sizeof(tag_cache) / sizeof(tag_cache[0])); ++i) { tag_cache[i].pinfo = NULL; diff --git a/liblog/logd_write_kern.c b/liblog/logd_write_kern.c index 8742b34..bd43238 100644 --- a/liblog/logd_write_kern.c +++ b/liblog/logd_write_kern.c @@ -26,7 +26,9 @@ #include <time.h> #include <unistd.h> +#ifdef __BIONIC__ #include <android/set_abort_message.h> +#endif #include <log/log.h> #include <log/logd.h> @@ -167,9 +169,11 @@ int __android_log_buf_write(int bufID, int prio, const char *tag, const char *ms tag = tmp_tag; } +#ifdef __BIONIC__ if (prio == ANDROID_LOG_FATAL) { android_set_abort_message(msg); } +#endif vec[0].iov_base = (unsigned char *) &prio; vec[0].iov_len = 1; diff --git a/libnetutils/ifc_utils.c b/libnetutils/ifc_utils.c index 7d2a5fb..3bd59c7 100644 --- a/libnetutils/ifc_utils.c +++ b/libnetutils/ifc_utils.c @@ -698,6 +698,8 @@ ifc_configure(const char *ifname, property_set(dns_prop_name, dns1 ? ipaddr_to_string(dns1) : ""); snprintf(dns_prop_name, sizeof(dns_prop_name), "net.%s.dns2", ifname); property_set(dns_prop_name, dns2 ? ipaddr_to_string(dns2) : ""); + snprintf(dns_prop_name, sizeof(dns_prop_name), "net.%s.gw", ifname); + property_set(dns_prop_name, gateway ? ipaddr_to_string(gateway) : ""); return 0; } diff --git a/libsysutils/Android.mk b/libsysutils/Android.mk index 7bf53e3..7e44c7a 100644 --- a/libsysutils/Android.mk +++ b/libsysutils/Android.mk @@ -1,8 +1,6 @@ LOCAL_PATH:= $(call my-dir) -include $(CLEAR_VARS) - -LOCAL_SRC_FILES:= \ +common_src_files := \ src/SocketListener.cpp \ src/FrameworkListener.cpp \ src/NetlinkListener.cpp \ @@ -12,14 +10,21 @@ LOCAL_SRC_FILES:= \ src/ServiceManager.cpp \ EventLogTags.logtags -LOCAL_MODULE:= libsysutils - -LOCAL_CFLAGS := -Werror - -LOCAL_SHARED_LIBRARIES := \ +common_shared_libraries := \ libcutils \ liblog \ libnl +include $(CLEAR_VARS) +LOCAL_SRC_FILES:= $(common_src_files) +LOCAL_MODULE:= libsysutils +LOCAL_CFLAGS := -Werror +LOCAL_SHARED_LIBRARIES := $(common_shared_libraries) include $(BUILD_SHARED_LIBRARY) +include $(CLEAR_VARS) +LOCAL_SRC_FILES:= $(common_src_files) +LOCAL_MODULE:= libsysutils +LOCAL_CFLAGS := -Werror +LOCAL_SHARED_LIBRARIES := $(common_shared_libraries) +include $(BUILD_STATIC_LIBRARY) diff --git a/libutils/SystemClock.cpp b/libutils/SystemClock.cpp index ac3dd98..c3b5d74 100644 --- a/libutils/SystemClock.cpp +++ b/libutils/SystemClock.cpp @@ -40,6 +40,9 @@ namespace android { +static pthread_mutex_t clock_lock = PTHREAD_MUTEX_INITIALIZER; +static int clock_method = -1; + /* * native public static long uptimeMillis(); */ @@ -119,29 +122,47 @@ int64_t elapsedRealtimeNano() static int s_fd = -1; - if (s_fd == -1) { - int fd = open("/dev/alarm", O_RDONLY); - if (android_atomic_cmpxchg(-1, fd, &s_fd)) { - close(fd); - } + if (clock_method < 0) { + pthread_mutex_lock(&clock_lock); } - result = ioctl(s_fd, - ANDROID_ALARM_GET_TIME(ANDROID_ALARM_ELAPSED_REALTIME), &ts); + if (clock_method < 0 || clock_method == METHOD_IOCTL) { + if (s_fd == -1) { + int fd = open("/dev/alarm", O_RDONLY); + if (android_atomic_cmpxchg(-1, fd, &s_fd)) { + close(fd); + } + } - if (result == 0) { - timestamp = seconds_to_nanoseconds(ts.tv_sec) + ts.tv_nsec; - checkTimeStamps(timestamp, &prevTimestamp, &prevMethod, METHOD_IOCTL); - return timestamp; + if (s_fd > -1) { + result = ioctl(s_fd, + ANDROID_ALARM_GET_TIME(ANDROID_ALARM_ELAPSED_REALTIME), &ts); + + if (result == 0) { + timestamp = seconds_to_nanoseconds(ts.tv_sec) + ts.tv_nsec; + checkTimeStamps(timestamp, &prevTimestamp, &prevMethod, METHOD_IOCTL); + if (clock_method < 0) { + clock_method = METHOD_IOCTL; + pthread_mutex_unlock(&clock_lock); + } + return timestamp; + } + } } // /dev/alarm doesn't exist, fallback to CLOCK_BOOTTIME - result = clock_gettime(CLOCK_BOOTTIME, &ts); - if (result == 0) { - timestamp = seconds_to_nanoseconds(ts.tv_sec) + ts.tv_nsec; - checkTimeStamps(timestamp, &prevTimestamp, &prevMethod, - METHOD_CLOCK_GETTIME); - return timestamp; + if (clock_method < 0 || clock_method == METHOD_CLOCK_GETTIME) { + result = clock_gettime(CLOCK_BOOTTIME, &ts); + if (result == 0) { + timestamp = seconds_to_nanoseconds(ts.tv_sec) + ts.tv_nsec; + checkTimeStamps(timestamp, &prevTimestamp, &prevMethod, + METHOD_CLOCK_GETTIME); + if (clock_method < 0) { + clock_method = METHOD_CLOCK_GETTIME; + pthread_mutex_unlock(&clock_lock); + } + return timestamp; + } } // XXX: there was an error, probably because the driver didn't @@ -150,6 +171,10 @@ int64_t elapsedRealtimeNano() timestamp = systemTime(SYSTEM_TIME_MONOTONIC); checkTimeStamps(timestamp, &prevTimestamp, &prevMethod, METHOD_SYSTEMTIME); + if (clock_method < 0) { + clock_method = METHOD_SYSTEMTIME; + pthread_mutex_unlock(&clock_lock); + } return timestamp; #else return systemTime(SYSTEM_TIME_MONOTONIC); diff --git a/logcat/logcat.cpp b/logcat/logcat.cpp index e598bb8..07d0a5c 100644 --- a/logcat/logcat.cpp +++ b/logcat/logcat.cpp @@ -284,6 +284,7 @@ static void show_help(const char *cmd) " other pruning activity is oldest first. Special case ~!\n" " represents an automatic quicker pruning for the noisiest\n" " UID as determined by the current statistics.\n" + " -C colored output\n" " -P '<list> ...' set prune white and ~black list, using same format as\n" " printed above. Must be quoted.\n"); @@ -492,7 +493,7 @@ int main(int argc, char **argv) for (;;) { int ret; - ret = getopt(argc, argv, ":cdDLt:T:gG:sQf:r:n:v:b:BSpP:"); + ret = getopt(argc, argv, ":cdDLt:T:gG:sQf:r:n:v:b:BSpCP:"); if (ret < 0) { break; @@ -597,6 +598,10 @@ int main(int argc, char **argv) setPruneList = optarg; break; + case 'C': + setLogFormat ("color"); + break; + case 'b': { if (strcmp(optarg, "all") == 0) { while (devices) { diff --git a/logd/CommandListener.cpp b/logd/CommandListener.cpp index 5489cc9..489bea6 100644 --- a/logd/CommandListener.cpp +++ b/logd/CommandListener.cpp @@ -34,8 +34,7 @@ CommandListener::CommandListener(LogBuffer *buf, LogReader * /*reader*/, LogListener * /*swl*/) : - FrameworkListener(getLogSocket()), - mBuf(*buf) { + FrameworkListener(getLogSocket()) { // registerCmd(new ShutdownCmd(buf, writer, swl)); registerCmd(new ClearCmd(buf)); registerCmd(new GetBufSizeCmd(buf)); @@ -47,10 +46,9 @@ CommandListener::CommandListener(LogBuffer *buf, LogReader * /*reader*/, registerCmd(new ReinitCmd()); } -CommandListener::ShutdownCmd::ShutdownCmd(LogBuffer *buf, LogReader *reader, +CommandListener::ShutdownCmd::ShutdownCmd(LogReader *reader, LogListener *swl) : LogCommand("shutdown"), - mBuf(*buf), mReader(*reader), mSwl(*swl) { } diff --git a/logd/CommandListener.h b/logd/CommandListener.h index 83e06b4..3877675 100644 --- a/logd/CommandListener.h +++ b/logd/CommandListener.h @@ -27,7 +27,6 @@ void reinit_signal_handler(int /*signal*/); class CommandListener : public FrameworkListener { - LogBuffer &mBuf; public: CommandListener(LogBuffer *buf, LogReader *reader, LogListener *swl); @@ -37,12 +36,11 @@ private: static int getLogSocket(); class ShutdownCmd : public LogCommand { - LogBuffer &mBuf; LogReader &mReader; LogListener &mSwl; public: - ShutdownCmd(LogBuffer *buf, LogReader *reader, LogListener *swl); + ShutdownCmd(LogReader *reader, LogListener *swl); virtual ~ShutdownCmd() {} int runCommand(SocketClient *c, int argc, char ** argv); }; diff --git a/logd/LogAudit.cpp b/logd/LogAudit.cpp index 4b3547c..808d17a 100644 --- a/logd/LogAudit.cpp +++ b/logd/LogAudit.cpp @@ -24,6 +24,7 @@ #include <sys/uio.h> #include <syslog.h> +#include <log/logger.h> #include <private/android_filesystem_config.h> #include <private/android_logger.h> @@ -153,15 +154,16 @@ int LogAudit::logPrint(const char *fmt, ...) { // log to events - size_t l = strlen(str); + size_t l = strnlen(str, LOGGER_ENTRY_MAX_PAYLOAD); size_t n = l + sizeof(android_log_event_string_t); bool notify = false; - android_log_event_string_t *event = static_cast<android_log_event_string_t *>(malloc(n)); - if (!event) { - rc = -ENOMEM; - } else { + { // begin scope for event buffer + uint32_t buffer[(n + sizeof(uint32_t) - 1) / sizeof(uint32_t)]; + + android_log_event_string_t *event + = reinterpret_cast<android_log_event_string_t *>(buffer); event->header.tag = htole32(AUDITD_LOG_TAG); event->type = EVENT_TYPE_STRING; event->length = htole32(l); @@ -170,11 +172,10 @@ int LogAudit::logPrint(const char *fmt, ...) { rc = logbuf->log(LOG_ID_EVENTS, now, uid, pid, tid, reinterpret_cast<char *>(event), (n <= USHRT_MAX) ? (unsigned short) n : USHRT_MAX); - free(event); - if (rc >= 0) { notify = true; } + // end scope for event buffer } // log to main @@ -206,24 +207,28 @@ int LogAudit::logPrint(const char *fmt, ...) { l = strlen(comm) + 1; ecomm = ""; } - n = (estr - str) + strlen(ecomm) + l + 2; + size_t b = estr - str; + if (b > LOGGER_ENTRY_MAX_PAYLOAD) { + b = LOGGER_ENTRY_MAX_PAYLOAD; + } + size_t e = strnlen(ecomm, LOGGER_ENTRY_MAX_PAYLOAD - b); + n = b + e + l + 2; + + { // begin scope for main buffer + char newstr[n]; - char *newstr = static_cast<char *>(malloc(n)); - if (!newstr) { - rc = -ENOMEM; - } else { *newstr = info ? ANDROID_LOG_INFO : ANDROID_LOG_WARN; strlcpy(newstr + 1, comm, l); - strncpy(newstr + 1 + l, str, estr - str); - strcpy(newstr + 1 + l + (estr - str), ecomm); + strncpy(newstr + 1 + l, str, b); + strncpy(newstr + 1 + l + b, ecomm, e); rc = logbuf->log(LOG_ID_MAIN, now, uid, pid, tid, newstr, (n <= USHRT_MAX) ? (unsigned short) n : USHRT_MAX); - free(newstr); if (rc >= 0) { notify = true; } + // end scope for main buffer } free(commfree); @@ -239,9 +244,9 @@ int LogAudit::logPrint(const char *fmt, ...) { return rc; } -int LogAudit::log(char *buf) { +int LogAudit::log(char *buf, size_t len) { char *audit = strstr(buf, " audit("); - if (!audit) { + if (!audit || (audit >= &buf[len])) { return 0; } @@ -249,7 +254,7 @@ int LogAudit::log(char *buf) { int rc; char *type = strstr(buf, "type="); - if (type) { + if (type && (type < &buf[len])) { rc = logPrint("%s %s", type, audit + 1); } else { rc = logPrint("%s", audit + 1); diff --git a/logd/LogAudit.h b/logd/LogAudit.h index f977be9..2342822 100644 --- a/logd/LogAudit.h +++ b/logd/LogAudit.h @@ -28,7 +28,7 @@ class LogAudit : public SocketListener { public: LogAudit(LogBuffer *buf, LogReader *reader, int fdDmesg); - int log(char *buf); + int log(char *buf, size_t len); protected: virtual bool onDataAvailable(SocketClient *cli); diff --git a/logd/LogBufferElement.cpp b/logd/LogBufferElement.cpp index 9fb1439..150ce22 100644 --- a/logd/LogBufferElement.cpp +++ b/logd/LogBufferElement.cpp @@ -91,7 +91,8 @@ char *android::tidToName(pid_t tid) { size_t retval_len = strlen(retval); size_t name_len = strlen(name); // KISS: ToDo: Only checks prefix truncated, not suffix, or both - if ((retval_len < name_len) && !strcmp(retval, name + name_len - retval_len)) { + if ((retval_len < name_len) + && !fast<strcmp>(retval, name + name_len - retval_len)) { free(retval); retval = name; } else { @@ -123,14 +124,16 @@ size_t LogBufferElement::populateDroppedMessage(char *&buffer, commName = parent->pidToName(mPid); parent->unlock(); } - size_t len = name ? strlen(name) : 0; - if (len && commName && !strncmp(name, commName, len)) { - if (commName[len] == '\0') { - free(commName); - commName = NULL; - } else { - free(name); - name = NULL; + if (name && name[0] && commName && (name[0] == commName[0])) { + size_t len = strlen(name + 1); + if (!strncmp(name + 1, commName + 1, len)) { + if (commName[len + 1] == '\0') { + free(commName); + commName = NULL; + } else { + free(name); + name = NULL; + } } } if (name) { @@ -150,9 +153,9 @@ size_t LogBufferElement::populateDroppedMessage(char *&buffer, } } // identical to below to calculate the buffer size required - len = snprintf(NULL, 0, format_uid, mUid, name ? name : "", - commName ? commName : "", - mDropped, (mDropped > 1) ? "s" : ""); + size_t len = snprintf(NULL, 0, format_uid, mUid, name ? name : "", + commName ? commName : "", + mDropped, (mDropped > 1) ? "s" : ""); size_t hdrLen; if (mLogId == LOG_ID_EVENTS) { diff --git a/logd/LogBufferElement.h b/logd/LogBufferElement.h index ca2c3a6..30e43c6 100644 --- a/logd/LogBufferElement.h +++ b/logd/LogBufferElement.h @@ -25,27 +25,6 @@ #include <log/log.h> #include <log/log_read.h> -// Hijack this header as a common include file used by most all sources -// to report some utilities defined here and there. - -namespace android { - -// Furnished in main.cpp. Caller must own and free returned value -char *uidToName(uid_t uid); - -// Furnished in LogStatistics.cpp. Caller must own and free returned value -char *pidToName(pid_t pid); -char *tidToName(pid_t tid); - -// Furnished in main.cpp. Thread safe. -const char *tagToName(uint32_t tag); - -} - -static inline bool worstUidEnabledForLogid(log_id_t id) { - return (id != LOG_ID_CRASH) && (id != LOG_ID_KERNEL) && (id != LOG_ID_EVENTS); -} - class LogBuffer; #define EXPIRE_HOUR_THRESHOLD 24 // Only expire chatty UID logs to preserve @@ -85,7 +64,7 @@ public: unsigned short getDropped(void) const { return mMsg ? 0 : mDropped; } unsigned short setDropped(unsigned short value) { if (mMsg) { - free(mMsg); + delete [] mMsg; mMsg = NULL; } return mDropped = value; diff --git a/logd/LogKlog.cpp b/logd/LogKlog.cpp index 0a5df24..d28161e 100644 --- a/logd/LogKlog.cpp +++ b/logd/LogKlog.cpp @@ -39,14 +39,15 @@ static const char priority_message[] = { KMSG_PRIORITY(LOG_INFO), '\0' }; // Parsing is hard // called if we see a '<', s is the next character, returns pointer after '>' -static char *is_prio(char *s) { - if (!isdigit(*s++)) { +static char *is_prio(char *s, size_t len) { + if (!len || !isdigit(*s++)) { return NULL; } - static const size_t max_prio_len = 4; - size_t len = 0; + --len; + static const size_t max_prio_len = (len < 4) ? len : 4; + size_t priolen = 0; char c; - while (((c = *s++)) && (++len <= max_prio_len)) { + while (((c = *s++)) && (++priolen <= max_prio_len)) { if (!isdigit(c)) { return ((c == '>') && (*s == '[')) ? s : NULL; } @@ -55,16 +56,19 @@ static char *is_prio(char *s) { } // called if we see a '[', s is the next character, returns pointer after ']' -static char *is_timestamp(char *s) { - while (*s == ' ') { +static char *is_timestamp(char *s, size_t len) { + while (len && (*s == ' ')) { ++s; + --len; } - if (!isdigit(*s++)) { + if (!len || !isdigit(*s++)) { return NULL; } + --len; bool first_period = true; char c; - while ((c = *s++)) { + while (len && ((c = *s++))) { + --len; if ((c == '.') && first_period) { first_period = false; } else if (!isdigit(c)) { @@ -77,6 +81,8 @@ static char *is_timestamp(char *s) { // Like strtok_r with "\r\n" except that we look for log signatures (regex) // \(\(<[0-9]\{1,4\}>\)\([[] *[0-9]+[.][0-9]+[]] \)\{0,1\}\|[[] *[0-9]+[.][0-9]+[]] \) // and split if we see a second one without a newline. +// We allow nuls in content, monitoring the overall length and sub-length of +// the discovered tokens. #define SIGNATURE_MASK 0xF0 // <digit> following ('0' to '9' masked with ~SIGNATURE_MASK) added to signature @@ -85,7 +91,11 @@ static char *is_timestamp(char *s) { // space is one more than <digit> of 9 #define OPEN_BRACKET_SPACE ((char)(OPEN_BRACKET_SIG | 10)) -char *log_strtok_r(char *s, char **last) { +char *log_strntok_r(char *s, size_t *len, char **last, size_t *sublen) { + *sublen = 0; + if (!*len) { + return NULL; + } if (!s) { if (!(s = *last)) { return NULL; @@ -95,6 +105,7 @@ char *log_strtok_r(char *s, char **last) { if ((*s & SIGNATURE_MASK) == LESS_THAN_SIG) { *s = (*s & ~SIGNATURE_MASK) + '0'; *--s = '<'; + ++*len; } // fixup for log signature split [, // OPEN_BRACKET_SPACE is space, OPEN_BRACKET_SIG + <digit> @@ -105,24 +116,30 @@ char *log_strtok_r(char *s, char **last) { *s = (*s & ~SIGNATURE_MASK) + '0'; } *--s = '['; + ++*len; } } - s += strspn(s, "\r\n"); + while (*len && ((*s == '\r') || (*s == '\n'))) { + ++s; + --*len; + } - if (!*s) { // no non-delimiter characters + if (!*len) { *last = NULL; return NULL; } char *peek, *tok = s; for (;;) { - char c = *s++; - switch (c) { - case '\0': + if (*len == 0) { *last = NULL; return tok; - + } + char c = *s++; + --*len; + size_t adjust; + switch (c) { case '\r': case '\n': s[-1] = '\0'; @@ -130,7 +147,7 @@ char *log_strtok_r(char *s, char **last) { return tok; case '<': - peek = is_prio(s); + peek = is_prio(s, *len); if (!peek) { break; } @@ -141,14 +158,26 @@ char *log_strtok_r(char *s, char **last) { *last = s; return tok; } + adjust = peek - s; + if (adjust > *len) { + adjust = *len; + } + *sublen += adjust; + *len -= adjust; s = peek; - if ((*s == '[') && ((peek = is_timestamp(s + 1)))) { + if ((*s == '[') && ((peek = is_timestamp(s + 1, *len - 1)))) { + adjust = peek - s; + if (adjust > *len) { + adjust = *len; + } + *sublen += adjust; + *len -= adjust; s = peek; } break; case '[': - peek = is_timestamp(s); + peek = is_timestamp(s, *len); if (!peek) { break; } @@ -163,9 +192,16 @@ char *log_strtok_r(char *s, char **last) { *last = s; return tok; } + adjust = peek - s; + if (adjust > *len) { + adjust = *len; + } + *sublen += adjust; + *len -= adjust; s = peek; break; } + ++*sublen; } // NOTREACHED } @@ -177,8 +213,6 @@ LogKlog::LogKlog(LogBuffer *buf, LogReader *reader, int fdWrite, int fdRead, boo logbuf(buf), reader(reader), signature(CLOCK_MONOTONIC), - fdWrite(fdWrite), - fdRead(fdRead), initialized(false), enableLogging(true), auditd(auditd) { @@ -214,17 +248,17 @@ bool LogKlog::onDataAvailable(SocketClient *cli) { bool full = len == (sizeof(buffer) - 1); char *ep = buffer + len; *ep = '\0'; - len = 0; + size_t sublen; for(char *ptr = NULL, *tok = buffer; - ((tok = log_strtok_r(tok, &ptr))); + ((tok = log_strntok_r(tok, &len, &ptr, &sublen))); tok = NULL) { - if (((tok + strlen(tok)) == ep) && (retval != 0) && full) { - len = strlen(tok); - memmove(buffer, tok, len); + if (((tok + sublen) >= ep) && (retval != 0) && full) { + memmove(buffer, tok, sublen); + len = sublen; break; } if (*tok) { - log(tok); + log(tok, sublen); } } } @@ -234,9 +268,11 @@ bool LogKlog::onDataAvailable(SocketClient *cli) { void LogKlog::calculateCorrection(const log_time &monotonic, - const char *real_string) { + const char *real_string, + size_t len) { log_time real; - if (!real.strptime(real_string, "%Y-%m-%d %H:%M:%S.%09q UTC")) { + const char *ep = real.strptime(real_string, "%Y-%m-%d %H:%M:%S.%09q UTC"); + if (!ep || (ep > &real_string[len])) { return; } // kernel report UTC, log_time::strptime is localtime from calendar. @@ -251,36 +287,85 @@ void LogKlog::calculateCorrection(const log_time &monotonic, correction = real - monotonic; } -void LogKlog::sniffTime(log_time &now, const char **buf, bool reverse) { - const char *cp; - if ((cp = now.strptime(*buf, "[ %s.%q]"))) { - static const char suspend[] = "PM: suspend entry "; - static const char resume[] = "PM: suspend exit "; - static const char healthd[] = "healthd: battery "; - static const char suspended[] = "Suspended for "; +static const char suspendStr[] = "PM: suspend entry "; +static const char resumeStr[] = "PM: suspend exit "; +static const char suspendedStr[] = "Suspended for "; + +static const char *strnstr(const char *s, size_t len, const char *needle) { + char c; + + if (!len) { + return NULL; + } + if ((c = *needle++) != 0) { + size_t needleLen = strlen(needle); + do { + do { + if (len <= needleLen) { + return NULL; + } + --len; + } while (*s++ != c); + } while (fast<memcmp>(s, needle, needleLen)); + s--; + } + return s; +} + +void LogKlog::sniffTime(log_time &now, + const char **buf, size_t len, + bool reverse) { + const char *cp = now.strptime(*buf, "[ %s.%q]"); + if (cp && (cp >= &(*buf)[len])) { + cp = NULL; + } + len -= cp - *buf; + if (cp) { + static const char healthd[] = "healthd"; + static const char battery[] = ": battery "; - if (isspace(*cp)) { + if (len && isspace(*cp)) { ++cp; + --len; } - if (!strncmp(cp, suspend, sizeof(suspend) - 1)) { - calculateCorrection(now, cp + sizeof(suspend) - 1); - } else if (!strncmp(cp, resume, sizeof(resume) - 1)) { - calculateCorrection(now, cp + sizeof(resume) - 1); - } else if (!strncmp(cp, healthd, sizeof(healthd) - 1)) { + *buf = cp; + + const char *b; + if (((b = strnstr(cp, len, suspendStr))) + && ((size_t)((b += sizeof(suspendStr) - 1) - cp) < len)) { + len -= b - cp; + calculateCorrection(now, b, len); + } else if (((b = strnstr(cp, len, resumeStr))) + && ((size_t)((b += sizeof(resumeStr) - 1) - cp) < len)) { + len -= b - cp; + calculateCorrection(now, b, len); + } else if (((b = strnstr(cp, len, healthd))) + && ((size_t)((b += sizeof(healthd) - 1) - cp) < len) + && ((b = strnstr(b, len -= b - cp, battery))) + && ((size_t)((b += sizeof(battery) - 1) - cp) < len)) { + len -= b - cp; + // NB: healthd is roughly 150us late, worth the price to deal with + // ntp-induced or hardware clock drift. // look for " 2???-??-?? ??:??:??.????????? ???" - const char *tp; - for (tp = cp + sizeof(healthd) - 1; *tp && (*tp != '\n'); ++tp) { - if ((tp[0] == ' ') && (tp[1] == '2') && (tp[5] == '-')) { - calculateCorrection(now, tp + 1); + for (; len && *b && (*b != '\n'); ++b, --len) { + if ((b[0] == ' ') && (b[1] == '2') && (b[5] == '-')) { + calculateCorrection(now, b + 1, len - 1); break; } } - } else if (!strncmp(cp, suspended, sizeof(suspended) - 1)) { + } else if (((b = strnstr(cp, len, suspendedStr))) + && ((size_t)((b += sizeof(suspendStr) - 1) - cp) < len)) { + len -= b - cp; log_time real; char *endp; - real.tv_sec = strtol(cp + sizeof(suspended) - 1, &endp, 10); - if (*endp == '.') { - real.tv_nsec = strtol(endp + 1, &endp, 10) * 1000000L; + real.tv_sec = strtol(b, &endp, 10); + if ((*endp == '.') && ((size_t)(endp - b) < len)) { + unsigned long multiplier = NS_PER_SEC; + real.tv_nsec = 0; + len -= endp - b; + while (--len && isdigit(*++endp) && (multiplier /= 10)) { + real.tv_nsec += (*endp - '0') * multiplier; + } if (reverse) { correction -= real; } else { @@ -290,14 +375,13 @@ void LogKlog::sniffTime(log_time &now, const char **buf, bool reverse) { } convertMonotonicToReal(now); - *buf = cp; } else { now = log_time(CLOCK_REALTIME); } } -pid_t LogKlog::sniffPid(const char *cp) { - while (*cp) { +pid_t LogKlog::sniffPid(const char *cp, size_t len) { + while (len) { // Mediatek kernels with modified printk if (*cp == '[') { int pid = 0; @@ -308,26 +392,59 @@ pid_t LogKlog::sniffPid(const char *cp) { break; // Only the first one } ++cp; + --len; } return 0; } +// kernel log prefix, convert to a kernel log priority number +static int parseKernelPrio(const char **buf, size_t len) { + int pri = LOG_USER | LOG_INFO; + const char *cp = *buf; + if (len && (*cp == '<')) { + pri = 0; + while(--len && isdigit(*++cp)) { + pri = (pri * 10) + *cp - '0'; + } + if (len && (*cp == '>')) { + ++cp; + } else { + cp = *buf; + pri = LOG_USER | LOG_INFO; + } + *buf = cp; + } + return pri; +} + // Passed the entire SYSLOG_ACTION_READ_ALL buffer and interpret a // compensated start time. -void LogKlog::synchronize(const char *buf) { - const char *cp = strstr(buf, "] PM: suspend e"); +void LogKlog::synchronize(const char *buf, size_t len) { + const char *cp = strnstr(buf, len, suspendStr); if (!cp) { - return; + cp = strnstr(buf, len, resumeStr); + if (!cp) { + return; + } + } else { + const char *rp = strnstr(buf, len, resumeStr); + if (rp && (rp < cp)) { + cp = rp; + } } do { --cp; - } while ((cp > buf) && (isdigit(*cp) || isspace(*cp) || (*cp == '.'))); + } while ((cp > buf) && (*cp != '\n')); + if (*cp == '\n') { + ++cp; + } + parseKernelPrio(&cp, len - (cp - buf)); log_time now; - sniffTime(now, &cp, true); + sniffTime(now, &cp, len - (cp - buf), true); - char *suspended = strstr(buf, "] Suspended for "); + const char *suspended = strnstr(buf, len, suspendedStr); if (!suspended || (suspended > cp)) { return; } @@ -335,29 +452,13 @@ void LogKlog::synchronize(const char *buf) { do { --cp; - } while ((cp > buf) && (isdigit(*cp) || isspace(*cp) || (*cp == '.'))); - - sniffTime(now, &cp, true); -} - -// kernel log prefix, convert to a kernel log priority number -static int parseKernelPrio(const char **buf) { - int pri = LOG_USER | LOG_INFO; - const char *cp = *buf; - if (*cp == '<') { - pri = 0; - while(isdigit(*++cp)) { - pri = (pri * 10) + *cp - '0'; - } - if (*cp == '>') { - ++cp; - } else { - cp = *buf; - pri = LOG_USER | LOG_INFO; - } - *buf = cp; + } while ((cp > buf) && (*cp != '\n')); + if (*cp == '\n') { + ++cp; } - return pri; + parseKernelPrio(&cp, len - (cp - buf)); + + sniffTime(now, &cp, len - (cp - buf), true); } // Convert kernel log priority number into an Android Logger priority number @@ -390,6 +491,16 @@ static int convertKernelPrioToAndroidPrio(int pri) { return ANDROID_LOG_INFO; } +static const char *strnrchr(const char *s, size_t len, char c) { + const char *save = NULL; + for (;len; ++s, len--) { + if (*s == c) { + save = s; + } + } + return save; +} + // // log a message into the kernel log buffer // @@ -423,19 +534,20 @@ static int convertKernelPrioToAndroidPrio(int pri) { // logd.klogd: // return -1 if message logd.klogd: <signature> // -int LogKlog::log(const char *buf) { - if (auditd && strstr(buf, " audit(")) { +int LogKlog::log(const char *buf, size_t len) { + if (auditd && strnstr(buf, len, " audit(")) { return 0; } - int pri = parseKernelPrio(&buf); + const char *p = buf; + int pri = parseKernelPrio(&p, len); log_time now; - sniffTime(now, &buf, false); + sniffTime(now, &p, len - (p - buf), false); // sniff for start marker const char klogd_message[] = "logd.klogd: "; - const char *start = strstr(buf, klogd_message); + const char *start = strnstr(p, len - (p - buf), klogd_message); if (start) { uint64_t sig = strtoll(start + sizeof(klogd_message) - 1, NULL, 10); if (sig == signature.nsec()) { @@ -454,7 +566,7 @@ int LogKlog::log(const char *buf) { } // Parse pid, tid and uid - const pid_t pid = sniffPid(buf); + const pid_t pid = sniffPid(p, len - (p - buf)); const pid_t tid = pid; const uid_t uid = pid ? logbuf->pidToUid(pid) : 0; @@ -462,109 +574,116 @@ int LogKlog::log(const char *buf) { // Some may view the following as an ugly heuristic, the desire is to // beautify the kernel logs into an Android Logging format; the goal is // admirable but costly. - while (isspace(*buf)) { - ++buf; + while ((isspace(*p) || !*p) && (p < &buf[len])) { + ++p; } - if (!*buf) { + if (p >= &buf[len]) { // timestamp, no content return 0; } - start = buf; + start = p; const char *tag = ""; const char *etag = tag; - if (!isspace(*buf)) { + size_t taglen = len - (p - buf); + if (!isspace(*p) && *p) { const char *bt, *et, *cp; - bt = buf; - if (!strncmp(buf, "[INFO]", 6)) { + bt = p; + if (!fast<strncmp>(p, "[INFO]", 6)) { // <PRI>[<TIME>] "[INFO]"<tag> ":" message - bt = buf + 6; + bt = p + 6; + taglen -= 6; } - for(et = bt; *et && (*et != ':') && !isspace(*et); ++et) { + for(et = bt; taglen && *et && (*et != ':') && !isspace(*et); ++et, --taglen) { // skip ':' within [ ... ] if (*et == '[') { - while (*et && *et != ']') { + while (taglen && *et && *et != ']') { ++et; + --taglen; } } } - for(cp = et; isspace(*cp); ++cp); + for(cp = et; taglen && isspace(*cp); ++cp, --taglen); size_t size; if (*cp == ':') { // One Word tag = bt; etag = et; - buf = cp + 1; - } else { + p = cp + 1; + } else if (taglen) { size = et - bt; - if (strncmp(bt, cp, size)) { + if ((*bt == *cp) && fast<strncmp>(bt + 1, cp + 1, size - 1)) { // <PRI>[<TIME>] <tag>_host '<tag>.<num>' : message - if (!strncmp(bt + size - 5, "_host", 5) - && !strncmp(bt, cp, size - 5)) { + if (!fast<strncmp>(bt + size - 5, "_host", 5) + && !fast<strncmp>(bt + 1, cp + 1, size - 6)) { const char *b = cp; cp += size - 5; + taglen -= size - 5; if (*cp == '.') { - while (!isspace(*++cp) && (*cp != ':')); + while (--taglen && !isspace(*++cp) && (*cp != ':')); const char *e; - for(e = cp; isspace(*cp); ++cp); + for(e = cp; taglen && isspace(*cp); ++cp, --taglen); if (*cp == ':') { tag = b; etag = e; - buf = cp + 1; + p = cp + 1; } } } else { - while (!isspace(*++cp) && (*cp != ':')); + while (--taglen && !isspace(*++cp) && (*cp != ':')); const char *e; - for(e = cp; isspace(*cp); ++cp); + for(e = cp; taglen && isspace(*cp); ++cp, --taglen); // Two words if (*cp == ':') { tag = bt; etag = e; - buf = cp + 1; + p = cp + 1; } } } else if (isspace(cp[size])) { - const char *b = cp; cp += size; - while (isspace(*++cp)); + taglen -= size; + while (--taglen && isspace(*++cp)); // <PRI>[<TIME>] <tag> <tag> : message if (*cp == ':') { tag = bt; etag = et; - buf = cp + 1; + p = cp + 1; } } else if (cp[size] == ':') { // <PRI>[<TIME>] <tag> <tag> : message tag = bt; etag = et; - buf = cp + size + 1; + p = cp + size + 1; } else if ((cp[size] == '.') || isdigit(cp[size])) { // <PRI>[<TIME>] <tag> '<tag>.<num>' : message // <PRI>[<TIME>] <tag> '<tag><num>' : message const char *b = cp; cp += size; - while (!isspace(*++cp) && (*cp != ':')); + taglen -= size; + while (--taglen && !isspace(*++cp) && (*cp != ':')); const char *e = cp; - while (isspace(*cp)) { + while (taglen && isspace(*cp)) { ++cp; + --taglen; } if (*cp == ':') { tag = b; etag = e; - buf = cp + 1; + p = cp + 1; } } else { - while (!isspace(*++cp) && (*cp != ':')); + while (--taglen && !isspace(*++cp) && (*cp != ':')); const char *e = cp; - while (isspace(*cp)) { + while (taglen && isspace(*cp)) { ++cp; + --taglen; } // Two words if (*cp == ':') { tag = bt; etag = e; - buf = cp + 1; + p = cp + 1; } } } @@ -575,68 +694,69 @@ int LogKlog::log(const char *buf) { // register names like x18 but not driver names like en0 || ((size == 3) && (isdigit(tag[1]) && isdigit(tag[2]))) // blacklist - || ((size == 3) && !strncmp(tag, "CPU", 3)) - || ((size == 7) && !strncmp(tag, "WARNING", 7)) - || ((size == 5) && !strncmp(tag, "ERROR", 5)) - || ((size == 4) && !strncmp(tag, "INFO", 4))) { - buf = start; + || ((size == 3) && !fast<strncmp>(tag, "CPU", 3)) + || ((size == 7) && !fast<strncasecmp>(tag, "WARNING", 7)) + || ((size == 5) && !fast<strncasecmp>(tag, "ERROR", 5)) + || ((size == 4) && !fast<strncasecmp>(tag, "INFO", 4))) { + p = start; etag = tag = ""; } } // Suppress additional stutter in tag: // eg: [143:healthd]healthd -> [143:healthd] - size_t taglen = etag - tag; + taglen = etag - tag; // Mediatek-special printk induced stutter - char *np = strrchr(tag, ']'); - if (np && (++np < etag)) { - size_t s = etag - np; - if (((s + s) < taglen) && !strncmp(np, np - 1 - s, s)) { - taglen = np - tag; + const char *mp = strnrchr(tag, ']', taglen); + if (mp && (++mp < etag)) { + size_t s = etag - mp; + if (((s + s) < taglen) && !fast<memcmp>(mp, mp - 1 - s, s)) { + taglen = mp - tag; } } // skip leading space - while (isspace(*buf)) { - ++buf; + while ((isspace(*p) || !*p) && (p < &buf[len])) { + ++p; } - // truncate trailing space - size_t b = strlen(buf); - while (b && isspace(buf[b-1])) { + // truncate trailing space or nuls + size_t b = len - (p - buf); + while (b && (isspace(p[b-1]) || !p[b-1])) { --b; } // trick ... allow tag with empty content to be logged. log() drops empty if (!b && taglen) { - buf = " "; + p = " "; b = 1; } + if (b > LOGGER_ENTRY_MAX_PAYLOAD) { + b = LOGGER_ENTRY_MAX_PAYLOAD; + } size_t n = 1 + taglen + 1 + b + 1; - - // Allocate a buffer to hold the interpreted log message int rc = n; - char *newstr = reinterpret_cast<char *>(malloc(n)); - if (!newstr) { - rc = -ENOMEM; + if ((taglen > n) || (b > n)) { // Can not happen ... + rc = -EINVAL; return rc; } - np = newstr; + + char newstr[n]; + char *np = newstr; // Convert priority into single-byte Android logger priority *np = convertKernelPrioToAndroidPrio(pri); ++np; // Copy parsed tag following priority - strncpy(np, tag, taglen); + memcpy(np, tag, taglen); np += taglen; *np = '\0'; ++np; // Copy main message to the remainder - strncpy(np, buf, b); + memcpy(np, p, b); np[b] = '\0'; // Log message rc = logbuf->log(LOG_ID_KERNEL, now, uid, pid, tid, newstr, (n <= USHRT_MAX) ? (unsigned short) n : USHRT_MAX); - free(newstr); // notify readers if (!rc) { diff --git a/logd/LogKlog.h b/logd/LogKlog.h index 081d344..469affd 100644 --- a/logd/LogKlog.h +++ b/logd/LogKlog.h @@ -21,14 +21,12 @@ #include <log/log_read.h> #include "LogReader.h" -char *log_strtok_r(char *str, char **saveptr); +char *log_strntok_r(char *s, size_t *len, char **saveptr, size_t *sublen); class LogKlog : public SocketListener { LogBuffer *logbuf; LogReader *reader; const log_time signature; - const int fdWrite; // /dev/kmsg - const int fdRead; // /proc/kmsg // Set once thread is started, separates KLOG_ACTION_READ_ALL // and KLOG_ACTION_READ phases. bool initialized; @@ -42,15 +40,16 @@ class LogKlog : public SocketListener { public: LogKlog(LogBuffer *buf, LogReader *reader, int fdWrite, int fdRead, bool auditd); - int log(const char *buf); - void synchronize(const char *buf); + int log(const char *buf, size_t len); + void synchronize(const char *buf, size_t len); static void convertMonotonicToReal(log_time &real) { real += correction; } protected: - void sniffTime(log_time &now, const char **buf, bool reverse); - pid_t sniffPid(const char *buf); - void calculateCorrection(const log_time &monotonic, const char *real_string); + void sniffTime(log_time &now, const char **buf, size_t len, bool reverse); + pid_t sniffPid(const char *buf, size_t len); + void calculateCorrection(const log_time &monotonic, + const char *real_string, size_t len); virtual bool onDataAvailable(SocketClient *cli); }; diff --git a/logd/LogReader.cpp b/logd/LogReader.cpp index c7deec0..3833843 100644 --- a/logd/LogReader.cpp +++ b/logd/LogReader.cpp @@ -95,7 +95,7 @@ bool LogReader::onDataAvailable(SocketClient *cli) { } bool nonBlock = false; - if (strncmp(buffer, "dumpAndClose", 12) == 0) { + if (!fast<strncmp>(buffer, "dumpAndClose", 12)) { // Allow writer to get some cycles, and wait for pending notifications sched_yield(); LogTimeEntry::lock(); diff --git a/logd/LogStatistics.cpp b/logd/LogStatistics.cpp index 48c2fe6..099a4c4 100644 --- a/logd/LogStatistics.cpp +++ b/logd/LogStatistics.cpp @@ -51,7 +51,7 @@ char *pidToName(pid_t pid) { if (ret > 0) { buffer[sizeof(buffer)-1] = '\0'; // frameworks intermediate state - if (strcmp(buffer, "<pre-initialized>")) { + if (fast<strcmp>(buffer, "<pre-initialized>")) { retval = strdup(buffer); } } @@ -170,7 +170,7 @@ char *LogStatistics::uidToName(uid_t uid) { if (n) { if (!name) { name = strdup(n); - } else if (strcmp(name, n)) { + } else if (fast<strcmp>(name, n)) { free(name); name = NULL; break; diff --git a/logd/LogStatistics.h b/logd/LogStatistics.h index 760d6b2..42084de 100644 --- a/logd/LogStatistics.h +++ b/logd/LogStatistics.h @@ -26,6 +26,7 @@ #include <log/log.h> #include "LogBufferElement.h" +#include "LogUtils.h" #define log_id_for_each(i) \ for (log_id_t i = LOG_ID_MIN; i < LOG_ID_MAX; i = (log_id_t) (i + 1)) @@ -188,7 +189,7 @@ struct PidEntry : public EntryBaseDropped { const char*getName() const { return name; } inline void add(pid_t p) { - if (name && !strncmp(name, "zygote", 6)) { + if (name && !fast<strncmp>(name, "zygote", 6)) { free(name); name = NULL; } @@ -240,7 +241,7 @@ struct TidEntry : public EntryBaseDropped { const char*getName() const { return name; } inline void add(pid_t t) { - if (name && !strncmp(name, "zygote", 6)) { + if (name && !fast<strncmp>(name, "zygote", 6)) { free(name); name = NULL; } diff --git a/logd/LogUtils.h b/logd/LogUtils.h new file mode 100644 index 0000000..533eb1c --- /dev/null +++ b/logd/LogUtils.h @@ -0,0 +1,62 @@ +/* + * Copyright (C) 2012-2015 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef _LOGD_LOG_UTILS_H__ +#define _LOGD_LOG_UTILS_H__ + +#include <sys/types.h> + +#include <log/log.h> + +// Hijack this header as a common include file used by most all sources +// to report some utilities defined here and there. + +namespace android { + +// Furnished in main.cpp. Caller must own and free returned value +char *uidToName(uid_t uid); + +// Furnished in LogStatistics.cpp. Caller must own and free returned value +char *pidToName(pid_t pid); +char *tidToName(pid_t tid); + +// Furnished in main.cpp. Thread safe. +const char *tagToName(uint32_t tag); + +} + +static inline bool worstUidEnabledForLogid(log_id_t id) { + return (id != LOG_ID_CRASH) && (id != LOG_ID_KERNEL) && (id != LOG_ID_EVENTS); +} + +template <int (*cmp)(const char *l, const char *r, const size_t s)> +static inline int fast(const char *l, const char *r, const size_t s) { + return (*l != *r) || cmp(l + 1, r + 1, s - 1); +} + +template <int (*cmp)(const void *l, const void *r, const size_t s)> +static inline int fast(const void *lv, const void *rv, const size_t s) { + const char *l = static_cast<const char *>(lv); + const char *r = static_cast<const char *>(rv); + return (*l != *r) || cmp(l + 1, r + 1, s - 1); +} + +template <int (*cmp)(const char *l, const char *r)> +static inline int fast(const char *l, const char *r) { + return (*l != *r) || cmp(l + 1, r + 1); +} + +#endif // _LOGD_LOG_UTILS_H__ diff --git a/logd/LogWhiteBlackList.h b/logd/LogWhiteBlackList.h index 57cd03b..99e3d82 100644 --- a/logd/LogWhiteBlackList.h +++ b/logd/LogWhiteBlackList.h @@ -21,7 +21,7 @@ #include <list> -#include <LogBufferElement.h> +#include "LogBufferElement.h" // White and Blacklist diff --git a/logd/main.cpp b/logd/main.cpp index a3241d0..2ed52be 100644 --- a/logd/main.cpp +++ b/logd/main.cpp @@ -47,6 +47,7 @@ #include "LogListener.h" #include "LogAudit.h" #include "LogKlog.h" +#include "LogUtils.h" #define KMSG_PRIORITY(PRI) \ '<', \ @@ -286,36 +287,37 @@ static void readDmesg(LogAudit *al, LogKlog *kl) { return; } - int len = klogctl(KLOG_SIZE_BUFFER, NULL, 0); - if (len <= 0) { + int rc = klogctl(KLOG_SIZE_BUFFER, NULL, 0); + if (rc <= 0) { return; } - len += 1024; // Margin for additional input race or trailing nul + size_t len = rc + 1024; // Margin for additional input race or trailing nul std::unique_ptr<char []> buf(new char[len]); - int rc = klogctl(KLOG_READ_ALL, buf.get(), len); + rc = klogctl(KLOG_READ_ALL, buf.get(), len); if (rc <= 0) { return; } - if (rc < len) { + if ((size_t)rc < len) { len = rc + 1; } - buf[len - 1] = '\0'; + buf[--len] = '\0'; if (kl) { - kl->synchronize(buf.get()); + kl->synchronize(buf.get(), len); } + size_t sublen; for (char *ptr = NULL, *tok = buf.get(); - (rc >= 0) && ((tok = log_strtok_r(tok, &ptr))); + (rc >= 0) && ((tok = log_strntok_r(tok, &len, &ptr, &sublen))); tok = NULL) { if (al) { - rc = al->log(tok); + rc = al->log(tok, sublen); } if (kl) { - rc = kl->log(tok); + rc = kl->log(tok, sublen); } } } diff --git a/mkbootimg/Android.mk b/mkbootimg/Android.mk index 0c9b0c6..c020323 100644 --- a/mkbootimg/Android.mk +++ b/mkbootimg/Android.mk @@ -10,4 +10,33 @@ LOCAL_MODULE := mkbootimg include $(BUILD_HOST_EXECUTABLE) +include $(CLEAR_VARS) +LOCAL_SRC_FILES := unpackbootimg.c +LOCAL_MODULE := unpackbootimg +include $(BUILD_HOST_EXECUTABLE) + +include $(CLEAR_VARS) +LOCAL_SRC_FILES := mkbootimg.c +LOCAL_STATIC_LIBRARIES := libmincrypt libcutils libc +LOCAL_MODULE := utility_mkbootimg +LOCAL_MODULE_TAGS := eng +LOCAL_MODULE_STEM := mkbootimg +LOCAL_MODULE_CLASS := EXECUTABLES +LOCAL_UNSTRIPPED_PATH := $(PRODUCT_OUT)/symbols/utilities +LOCAL_MODULE_PATH := $(PRODUCT_OUT)/utilities +LOCAL_FORCE_STATIC_EXECUTABLE := true +include $(BUILD_EXECUTABLE) + +include $(CLEAR_VARS) +LOCAL_SRC_FILES := unpackbootimg.c +LOCAL_STATIC_LIBRARIES := libcutils libc +LOCAL_MODULE := utility_unpackbootimg +LOCAL_MODULE_TAGS := eng +LOCAL_MODULE_STEM := unpackbootimg +LOCAL_MODULE_CLASS := EXECUTABLES +LOCAL_UNSTRIPPED_PATH := $(PRODUCT_OUT)/symbols/utilities +LOCAL_MODULE_PATH := $(PRODUCT_OUT)/utilities +LOCAL_FORCE_STATIC_EXECUTABLE := true +include $(BUILD_EXECUTABLE) + $(call dist-for-goals,dist_files,$(LOCAL_BUILT_MODULE)) diff --git a/mkbootimg/bootimg.h b/mkbootimg/bootimg.h index 5ab6195..e66e269 100644 --- a/mkbootimg/bootimg.h +++ b/mkbootimg/bootimg.h @@ -43,7 +43,8 @@ struct boot_img_hdr uint32_t tags_addr; /* physical addr for kernel tags */ uint32_t page_size; /* flash page size we assume */ - uint32_t unused[2]; /* future expansion: should be 0 */ + uint32_t dt_size; /* device tree in bytes */ + uint32_t unused; /* future expansion: should be 0 */ uint8_t name[BOOT_NAME_SIZE]; /* asciiz product name */ @@ -66,10 +67,13 @@ struct boot_img_hdr ** +-----------------+ ** | second stage | o pages ** +-----------------+ +** | device tree | p pages +** +-----------------+ ** ** n = (kernel_size + page_size - 1) / page_size ** m = (ramdisk_size + page_size - 1) / page_size ** o = (second_size + page_size - 1) / page_size +** p = (dt_size + page_size - 1) / page_size ** ** 0. all entities are page_size aligned in flash ** 1. kernel and ramdisk are required (size != 0) diff --git a/mkbootimg/mkbootimg.c b/mkbootimg/mkbootimg.c index b6a2801..ec7c61f 100644 --- a/mkbootimg/mkbootimg.c +++ b/mkbootimg/mkbootimg.c @@ -66,6 +66,10 @@ int usage(void) " [ --board <boardname> ]\n" " [ --base <address> ]\n" " [ --pagesize <pagesize> ]\n" + " [ --dt <filename> ]\n" + " [ --ramdisk_offset <address> ]\n" + " [ --second_offset <address> ]\n" + " [ --tags_offset <address> ]\n" " [ --id ]\n" " -o|--output <filename>\n" ); @@ -74,11 +78,12 @@ int usage(void) -static unsigned char padding[16384] = { 0, }; +static unsigned char padding[131072] = { 0, }; static void print_id(const uint8_t *id, size_t id_len) { printf("0x"); - for (unsigned i = 0; i < id_len; i++) { + unsigned i = 0; + for (i = 0; i < id_len; i++) { printf("%02x", id[i]); } printf("\n"); @@ -115,6 +120,8 @@ int main(int argc, char **argv) char *cmdline = ""; char *bootimg = NULL; char *board = ""; + char *dt_fn = 0; + void *dt_data = 0; uint32_t pagesize = 2048; int fd; SHA_CTX ctx; @@ -167,10 +174,14 @@ int main(int argc, char **argv) } else if(!strcmp(arg,"--pagesize")) { pagesize = strtoul(val, 0, 10); if ((pagesize != 2048) && (pagesize != 4096) - && (pagesize != 8192) && (pagesize != 16384)) { + && (pagesize != 8192) && (pagesize != 16384) + && (pagesize != 32768) && (pagesize != 65536) + && (pagesize != 131072)) { fprintf(stderr,"error: unsupported page size %d\n", pagesize); return -1; } + } else if(!strcmp(arg, "--dt")) { + dt_fn = val; } else { return usage(); } @@ -243,6 +254,14 @@ int main(int argc, char **argv) } } + if(dt_fn) { + dt_data = load_file(dt_fn, &hdr.dt_size); + if (dt_data == 0) { + fprintf(stderr,"error: could not load device tree image '%s'\n", dt_fn); + return 1; + } + } + /* put a hash of the contents in the header so boot images can be * differentiated based on their first 2k. */ @@ -253,6 +272,10 @@ int main(int argc, char **argv) SHA_update(&ctx, &hdr.ramdisk_size, sizeof(hdr.ramdisk_size)); SHA_update(&ctx, second_data, hdr.second_size); SHA_update(&ctx, &hdr.second_size, sizeof(hdr.second_size)); + if(dt_data) { + SHA_update(&ctx, dt_data, hdr.dt_size); + SHA_update(&ctx, &hdr.dt_size, sizeof(hdr.dt_size)); + } sha = SHA_final(&ctx); memcpy(hdr.id, sha, SHA_DIGEST_SIZE > sizeof(hdr.id) ? sizeof(hdr.id) : SHA_DIGEST_SIZE); @@ -281,6 +304,10 @@ int main(int argc, char **argv) print_id((uint8_t *) hdr.id, sizeof(hdr.id)); } + if(dt_data) { + if(write(fd, dt_data, hdr.dt_size) != (ssize_t) hdr.dt_size) goto fail; + if(write_padding(fd, pagesize, hdr.dt_size)) goto fail; + } return 0; fail: diff --git a/mkbootimg/unpackbootimg.c b/mkbootimg/unpackbootimg.c new file mode 100644 index 0000000..3d2fda7 --- /dev/null +++ b/mkbootimg/unpackbootimg.c @@ -0,0 +1,211 @@ +#include <stdio.h> +#include <stdlib.h> +#include <string.h> +#include <unistd.h> +#include <fcntl.h> +#include <errno.h> +#include <limits.h> +#include <libgen.h> + +#include "mincrypt/sha.h" +#include "bootimg.h" + +typedef unsigned char byte; + +int read_padding(FILE* f, unsigned itemsize, int pagesize) +{ + byte* buf = (byte*)malloc(sizeof(byte) * pagesize); + unsigned pagemask = pagesize - 1; + unsigned count; + + if((itemsize & pagemask) == 0) { + free(buf); + return 0; + } + + count = pagesize - (itemsize & pagemask); + + fread(buf, count, 1, f); + free(buf); + return count; +} + +void write_string_to_file(char* file, char* string) +{ + FILE* f = fopen(file, "w"); + fwrite(string, strlen(string), 1, f); + fwrite("\n", 1, 1, f); + fclose(f); +} + +int usage() { + printf("usage: unpackbootimg\n"); + printf("\t-i|--input boot.img\n"); + printf("\t[ -o|--output output_directory]\n"); + printf("\t[ -p|--pagesize <size-in-hexadecimal> ]\n"); + return 0; +} + +int main(int argc, char** argv) +{ + char tmp[PATH_MAX]; + char* directory = "./"; + char* filename = NULL; + int pagesize = 0; + + argc--; + argv++; + while(argc > 0){ + char *arg = argv[0]; + char *val = argv[1]; + argc -= 2; + argv += 2; + if(!strcmp(arg, "--input") || !strcmp(arg, "-i")) { + filename = val; + } else if(!strcmp(arg, "--output") || !strcmp(arg, "-o")) { + directory = val; + } else if(!strcmp(arg, "--pagesize") || !strcmp(arg, "-p")) { + pagesize = strtoul(val, 0, 16); + } else { + return usage(); + } + } + + if (filename == NULL) { + return usage(); + } + + int total_read = 0; + FILE* f = fopen(filename, "rb"); + boot_img_hdr header; + + //printf("Reading header...\n"); + int i; + for (i = 0; i <= 512; i++) { + fseek(f, i, SEEK_SET); + fread(tmp, BOOT_MAGIC_SIZE, 1, f); + if (memcmp(tmp, BOOT_MAGIC, BOOT_MAGIC_SIZE) == 0) + break; + } + total_read = i; + if (i > 512) { + printf("Android boot magic not found.\n"); + return 1; + } + fseek(f, i, SEEK_SET); + printf("Android magic found at: %d\n", i); + + fread(&header, sizeof(header), 1, f); + printf("BOARD_KERNEL_CMDLINE %s\n", header.cmdline); + printf("BOARD_KERNEL_BASE %08x\n", header.kernel_addr - 0x00008000); + printf("BOARD_RAMDISK_OFFSET %08x\n", header.ramdisk_addr - header.kernel_addr + 0x00008000); + printf("BOARD_SECOND_OFFSET %08x\n", header.second_addr - header.kernel_addr + 0x00008000); + printf("BOARD_TAGS_OFFSET %08x\n",header.tags_addr - header.kernel_addr + 0x00008000); + printf("BOARD_PAGE_SIZE %d\n", header.page_size); + printf("BOARD_SECOND_SIZE %d\n", header.second_size); + printf("BOARD_DT_SIZE %d\n", header.dt_size); + + if (pagesize == 0) { + pagesize = header.page_size; + } + + //printf("cmdline...\n"); + sprintf(tmp, "%s/%s", directory, basename(filename)); + strcat(tmp, "-cmdline"); + write_string_to_file(tmp, header.cmdline); + + //printf("base...\n"); + sprintf(tmp, "%s/%s", directory, basename(filename)); + strcat(tmp, "-base"); + char basetmp[200]; + sprintf(basetmp, "%08x", header.kernel_addr - 0x00008000); + write_string_to_file(tmp, basetmp); + + //printf("ramdisk_offset...\n"); + sprintf(tmp, "%s/%s", directory, basename(filename)); + strcat(tmp, "-ramdisk_offset"); + char ramdisktmp[200]; + sprintf(ramdisktmp, "%08x", header.ramdisk_addr - header.kernel_addr + 0x00008000); + write_string_to_file(tmp, ramdisktmp); + + //printf("second_offset...\n"); + sprintf(tmp, "%s/%s", directory, basename(filename)); + strcat(tmp, "-second_offset"); + char secondtmp[200]; + sprintf(secondtmp, "%08x", header.second_addr - header.kernel_addr + 0x00008000); + write_string_to_file(tmp, secondtmp); + + //printf("tags_offset...\n"); + sprintf(tmp, "%s/%s", directory, basename(filename)); + strcat(tmp, "-tags_offset"); + char tagstmp[200]; + sprintf(tagstmp, "%08x", header.tags_addr - header.kernel_addr + 0x00008000); + write_string_to_file(tmp, tagstmp); + + //printf("pagesize...\n"); + sprintf(tmp, "%s/%s", directory, basename(filename)); + strcat(tmp, "-pagesize"); + char pagesizetmp[200]; + sprintf(pagesizetmp, "%d", header.page_size); + write_string_to_file(tmp, pagesizetmp); + + total_read += sizeof(header); + //printf("total read: %d\n", total_read); + total_read += read_padding(f, sizeof(header), pagesize); + + sprintf(tmp, "%s/%s", directory, basename(filename)); + strcat(tmp, "-zImage"); + FILE *k = fopen(tmp, "wb"); + byte* kernel = (byte*)malloc(header.kernel_size); + //printf("Reading kernel...\n"); + fread(kernel, header.kernel_size, 1, f); + total_read += header.kernel_size; + fwrite(kernel, header.kernel_size, 1, k); + fclose(k); + + //printf("total read: %d\n", header.kernel_size); + total_read += read_padding(f, header.kernel_size, pagesize); + + + byte* ramdisk = (byte*)malloc(header.ramdisk_size); + //printf("Reading ramdisk...\n"); + fread(ramdisk, header.ramdisk_size, 1, f); + total_read += header.ramdisk_size; + sprintf(tmp, "%s/%s", directory, basename(filename)); + if(ramdisk[0] == 0x02 && ramdisk[1]== 0x21) + strcat(tmp, "-ramdisk.lz4"); + else + strcat(tmp, "-ramdisk.gz"); + FILE *r = fopen(tmp, "wb"); + fwrite(ramdisk, header.ramdisk_size, 1, r); + fclose(r); + + total_read += read_padding(f, header.ramdisk_size, pagesize); + + sprintf(tmp, "%s/%s", directory, basename(filename)); + strcat(tmp, "-second"); + FILE *s = fopen(tmp, "wb"); + byte* second = (byte*)malloc(header.second_size); + //printf("Reading second...\n"); + fread(second, header.second_size, 1, f); + total_read += header.second_size; + fwrite(second, header.second_size, 1, r); + fclose(s); + + total_read += read_padding(f, header.second_size, pagesize); + + sprintf(tmp, "%s/%s", directory, basename(filename)); + strcat(tmp, "-dt"); + FILE *d = fopen(tmp, "wb"); + byte* dt = (byte*)malloc(header.dt_size); + //printf("Reading dt...\n"); + fread(dt, header.dt_size, 1, f); + total_read += header.dt_size; + fwrite(dt, header.dt_size, 1, r); + fclose(d); + + fclose(f); + + //printf("Total Read: %d\n", total_read); + return 0; +} diff --git a/rootdir/init.rc b/rootdir/init.rc index 317207c..5c6b606 100644 --- a/rootdir/init.rc +++ b/rootdir/init.rc @@ -10,6 +10,9 @@ import /init.${ro.hardware}.rc import /init.usb.configfs.rc import /init.${ro.zygote}.rc import /init.trace.rc +# Include CM's extra init file +import /init.cm.rc + on early-init # Set init and its forked children's oom_adj. @@ -47,6 +50,7 @@ on init write /sys/fs/cgroup/memory/sw/memory.move_charge_at_immigrate 1 chown root system /sys/fs/cgroup/memory/sw/tasks chmod 0660 /sys/fs/cgroup/memory/sw/tasks + chmod 0220 /sys/fs/cgroup/memory/cgroup.event_control mkdir /system mkdir /data 0771 system system @@ -390,6 +394,9 @@ on post-fs-data # Set SELinux security contexts on upgrade or policy update. restorecon_recursive /data + restorecon /data/data + restorecon /data/user + restorecon /data/user/0 # Check any timezone data in /data is newer than the copy in /system, delete if not. exec - system system -- /system/bin/tzdatacheck /system/usr/share/zoneinfo /data/misc/zoneinfo @@ -639,7 +646,7 @@ service ril-daemon /system/bin/rild socket sap_uim_socket1 stream 660 bluetooth bluetooth socket rild-debug stream 660 radio system user root - group radio cache inet misc audio log + group radio cache inet misc audio log qcom_diag service surfaceflinger /system/bin/surfaceflinger class core @@ -656,7 +663,7 @@ service drm /system/bin/drmserver service media /system/bin/mediaserver class main user media - group audio camera inet net_bt net_bt_admin net_bw_acct drmrpc mediadrm + group audio camera inet net_bt net_bt_admin net_bw_acct drmrpc mediadrm qcom_diag ioprio rt 4 # One shot invocation to deal with encrypted volume. @@ -691,6 +698,11 @@ service installd /system/bin/installd service flash_recovery /system/bin/install-recovery.sh class main oneshot + disabled + +# update recovery if enabled +on property:persist.sys.recovery_update=true + start flash_recovery service racoon /system/bin/racoon class main diff --git a/rootdir/ueventd.rc b/rootdir/ueventd.rc index b735dc3..f82d899 100644 --- a/rootdir/ueventd.rc +++ b/rootdir/ueventd.rc @@ -28,7 +28,7 @@ subsystem adf /dev/dri/* 0666 root graphics # these should not be world writable -/dev/diag 0660 radio radio +/dev/diag 0660 system qcom_diag /dev/diag_arm9 0660 radio radio /dev/android_adb 0660 adb adb /dev/android_adb_enable 0660 adb adb @@ -98,3 +98,43 @@ subsystem adf # DVB API device nodes /dev/dvb* 0660 root system + +# Governor permissions +/sys/devices/system/cpu/cpu* cpufreq/scaling_governor 0664 system system + +/sys/devices/system/cpu/cpufreq ondemand/boostfreq 0664 system system +/sys/devices/system/cpu/cpufreq ondemand/boostpulse 0664 system system +/sys/devices/system/cpu/cpufreq ondemand/boosttime 0664 system system +/sys/devices/system/cpu/cpufreq ondemand/down_differential 0664 system system +/sys/devices/system/cpu/cpufreq ondemand/down_differential_multi_core 0664 system system +/sys/devices/system/cpu/cpufreq ondemand/ignore_nice_load 0664 system system +/sys/devices/system/cpu/cpufreq ondemand/input_boost 0664 system system +/sys/devices/system/cpu/cpufreq ondemand/io_is_busy 0664 system system +/sys/devices/system/cpu/cpufreq ondemand/optimal_freq 0664 system system +/sys/devices/system/cpu/cpufreq ondemand/powersave_bias 0664 system system +/sys/devices/system/cpu/cpufreq ondemand/sampling_down_factor 0664 system system +/sys/devices/system/cpu/cpufreq ondemand/sampling_rate 0664 system system +/sys/devices/system/cpu/cpufreq ondemand/sampling_rate_min 0664 system system +/sys/devices/system/cpu/cpufreq ondemand/sync_freq 0664 system system +/sys/devices/system/cpu/cpufreq ondemand/up_threshold 0664 system system +/sys/devices/system/cpu/cpufreq ondemand/up_threshold_any_cpu_load 0664 system system +/sys/devices/system/cpu/cpufreq ondemand/up_threshold_multi_core 0664 system system + +/sys/devices/system/cpu/cpufreq interactive/above_hispeed_delay 0664 system system +/sys/devices/system/cpu/cpufreq interactive/align_windows 0664 system system +/sys/devices/system/cpu/cpufreq interactive/boost 0664 system system +/sys/devices/system/cpu/cpufreq interactive/boostpulse 0664 system system +/sys/devices/system/cpu/cpufreq interactive/boostpulse_duration 0664 system system +/sys/devices/system/cpu/cpufreq interactive/go_hispeed_load 0664 system system +/sys/devices/system/cpu/cpufreq interactive/hispeed_freq 0664 system system +/sys/devices/system/cpu/cpufreq interactive/io_is_busy 0664 system system +/sys/devices/system/cpu/cpufreq interactive/max_freq_hysteresis 0664 system system +/sys/devices/system/cpu/cpufreq interactive/min_sample_rate 0664 system system +/sys/devices/system/cpu/cpufreq interactive/min_sample_time 0664 system system +/sys/devices/system/cpu/cpufreq interactive/sampling_down_factor 0664 system system +/sys/devices/system/cpu/cpufreq interactive/sync_freq 0664 system system +/sys/devices/system/cpu/cpufreq interactive/target_loads 0664 system system +/sys/devices/system/cpu/cpufreq interactive/timer_rate 0664 system system +/sys/devices/system/cpu/cpufreq interactive/timer_slack 0664 system system +/sys/devices/system/cpu/cpufreq interactive/up_threshold_any_cpu_freq 0664 system system +/sys/devices/system/cpu/cpufreq interactive/up_threshold_any_cpu_load 0664 system system diff --git a/sdcard/Android.mk b/sdcard/Android.mk index cb3a8fb..b50a818 100644 --- a/sdcard/Android.mk +++ b/sdcard/Android.mk @@ -1,11 +1,21 @@ LOCAL_PATH := $(call my-dir) include $(CLEAR_VARS) +ifeq ($(call is-vendor-board-platform,QCOM),true) +LOCAL_C_INCLUDES += $(TARGET_OUT_INTERMEDIATES)/KERNEL_OBJ/usr/include +LOCAL_ADDITIONAL_DEPENDENCIES += $(TARGET_OUT_INTERMEDIATES)/KERNEL_OBJ/usr +endif LOCAL_SRC_FILES := sdcard.c -LOCAL_MODULE := sdcard +LOCAL_MODULE := libsdcard LOCAL_CFLAGS := -Wall -Wno-unused-parameter -Werror +LOCAL_MODULE_TAGS := optional +include $(BUILD_STATIC_LIBRARY) -LOCAL_SHARED_LIBRARIES := libcutils - +include $(CLEAR_VARS) +LOCAL_SRC_FILES := main.c +LOCAL_MODULE := sdcard +LOCAL_CFLAGS := -Wall -Wno-unused-parameter -Werror +LOCAL_STATIC_LIBRARIES := libsdcard +LOCAL_SHARED_LIBRARIES := libc libcutils include $(BUILD_EXECUTABLE) diff --git a/sdcard/main.c b/sdcard/main.c new file mode 100644 index 0000000..ad2405b --- /dev/null +++ b/sdcard/main.c @@ -0,0 +1,21 @@ +/* + * Copyright (C) 2010 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. + */ + +extern int sdcard_main(int argc, char **argv); + +int main(int argc, char **argv) { + return sdcard_main(argc, argv); +} diff --git a/sdcard/sdcard.c b/sdcard/sdcard.c index a79e2dd..13009aa 100644 --- a/sdcard/sdcard.c +++ b/sdcard/sdcard.c @@ -1202,7 +1202,13 @@ static int handle_open(struct fuse* fuse, struct fuse_handler* handler, } out.fh = ptr_to_id(h); out.open_flags = 0; - out.padding = 0; + + #ifdef FUSE_SHORTCIRCUIT + out.lower_fd = h->fd; + #else + out.padding = 0; + #endif + fuse_reply(fuse, hdr->unique, &out, sizeof(out)); return NO_STATUS; } @@ -1366,7 +1372,13 @@ static int handle_opendir(struct fuse* fuse, struct fuse_handler* handler, } out.fh = ptr_to_id(h); out.open_flags = 0; - out.padding = 0; + + #ifdef FUSE_SHORTCIRCUIT + out.lower_fd = -1; + #else + out.padding = 0; + #endif + fuse_reply(fuse, hdr->unique, &out, sizeof(out)); return NO_STATUS; } @@ -1448,6 +1460,11 @@ static int handle_init(struct fuse* fuse, struct fuse_handler* handler, out.major = FUSE_KERNEL_VERSION; out.max_readahead = req->max_readahead; out.flags = FUSE_ATOMIC_O_TRUNC | FUSE_BIG_WRITES; + + #ifdef FUSE_SHORTCIRCUIT + out.flags |= FUSE_SHORTCIRCUIT; + #endif + out.max_background = 32; out.congestion_threshold = 32; out.max_write = MAX_WRITE; @@ -1887,7 +1904,7 @@ static void run(const char* source_path, const char* label, uid_t uid, exit(1); } -int main(int argc, char **argv) { +int sdcard_main(int argc, char **argv) { const char *source_path = NULL; const char *label = NULL; uid_t uid = 0; diff --git a/toolbox/Android.mk b/toolbox/Android.mk index ad99a39..b17408a 100644 --- a/toolbox/Android.mk +++ b/toolbox/Android.mk @@ -25,40 +25,27 @@ LOCAL_CFLAGS += $(common_cflags) -Dmain=dd_main -DNO_CONV LOCAL_MODULE := libtoolbox_dd include $(BUILD_STATIC_LIBRARY) -include $(CLEAR_VARS) -LOCAL_SRC_FILES := upstream-netbsd/usr.bin/du/du.c -LOCAL_CFLAGS += $(common_cflags) -Dmain=du_main -LOCAL_MODULE := libtoolbox_du -include $(BUILD_STATIC_LIBRARY) - include $(CLEAR_VARS) BSD_TOOLS := \ dd \ - du \ OUR_TOOLS := \ - df \ getevent \ iftop \ ioctl \ - ionice \ log \ ls \ - lsof \ - mount \ nandread \ newfs_msdos \ ps \ prlimit \ - renice \ + restart \ sendevent \ start \ stop \ top \ - uptime \ - watchprops \ ALL_TOOLS = $(BSD_TOOLS) $(OUR_TOOLS) diff --git a/toolbox/df.c b/toolbox/df.c deleted file mode 100644 index 9cd0743..0000000 --- a/toolbox/df.c +++ /dev/null @@ -1,85 +0,0 @@ -#include <stdio.h> -#include <stdlib.h> -#include <string.h> -#include <errno.h> -#include <sys/statfs.h> - -static int ok = EXIT_SUCCESS; - -static void printsize(long long n) -{ - char unit = 'K'; - long long t; - - n *= 10; - - if (n > 1024*1024*10) { - n /= 1024; - unit = 'M'; - } - - if (n > 1024*1024*10) { - n /= 1024; - unit = 'G'; - } - - t = (n + 512) / 1024; - printf("%4lld.%1lld%c", t/10, t%10, unit); -} - -static void df(char *s, int always) { - struct statfs st; - - if (statfs(s, &st) < 0) { - fprintf(stderr, "%s: %s\n", s, strerror(errno)); - ok = EXIT_FAILURE; - } else { - if (st.f_blocks == 0 && !always) - return; - printf("%-20s ", s); - printsize((long long)st.f_blocks * (long long)st.f_bsize); - printf(" "); - printsize((long long)(st.f_blocks - (long long)st.f_bfree) * st.f_bsize); - printf(" "); - printsize((long long)st.f_bfree * (long long)st.f_bsize); - printf(" %d\n", (int) st.f_bsize); - } -} - -int df_main(int argc, char *argv[]) { - printf("Filesystem Size Used Free Blksize\n"); - if (argc == 1) { - char s[2000]; - FILE *f = fopen("/proc/mounts", "r"); - - while (fgets(s, 2000, f)) { - char *c, *e = s; - - for (c = s; *c; c++) { - if (*c == ' ') { - e = c + 1; - break; - } - } - - for (c = e; *c; c++) { - if (*c == ' ') { - *c = '\0'; - break; - } - } - - df(e, 0); - } - - fclose(f); - } else { - int i; - - for (i = 1; i < argc; i++) { - df(argv[i], 1); - } - } - - exit(ok); -} diff --git a/toolbox/ionice.c b/toolbox/ionice.c deleted file mode 100644 index 7abc261..0000000 --- a/toolbox/ionice.c +++ /dev/null @@ -1,58 +0,0 @@ -#include <stdio.h> -#include <stdlib.h> -#include <string.h> -#include <unistd.h> -#include <errno.h> - -#include <cutils/iosched_policy.h> - -static char *classes[] = {"none", "rt", "be", "idle", NULL}; - -int ionice_main(int argc, char *argv[]) -{ - IoSchedClass clazz = IoSchedClass_NONE; - int ioprio = 0; - int pid; - - if(argc != 2 && argc != 4) { - fprintf(stderr, "usage: ionice <pid> [none|rt|be|idle] [prio]\n"); - return 1; - } - - if (!(pid = atoi(argv[1]))) { - fprintf(stderr, "Invalid pid specified\n"); - return 1; - } - - if (argc == 2) { - if (android_get_ioprio(pid, &clazz, &ioprio)) { - fprintf(stderr, "Failed to read priority (%s)\n", strerror(errno)); - return 1; - } - fprintf(stdout, "Pid %d, class %s (%d), prio %d\n", pid, classes[clazz], clazz, ioprio); - return 0; - } - - if (!strcmp(argv[2], "none")) { - clazz = IoSchedClass_NONE; - } else if (!strcmp(argv[2], "rt")) { - clazz = IoSchedClass_RT; - } else if (!strcmp(argv[2], "be")) { - clazz = IoSchedClass_BE; - } else if (!strcmp(argv[2], "idle")) { - clazz = IoSchedClass_IDLE; - } else { - fprintf(stderr, "Unsupported class '%s'\n", argv[2]); - return 1; - } - - ioprio = atoi(argv[3]); - - printf("Setting pid %d i/o class to %d, prio %d\n", pid, clazz, ioprio); - if (android_set_ioprio(pid, clazz, ioprio)) { - fprintf(stderr, "Failed to set priority (%s)\n", strerror(errno)); - return 1; - } - - return 0; -} diff --git a/toolbox/lsof.c b/toolbox/lsof.c deleted file mode 100644 index 982f5aa..0000000 --- a/toolbox/lsof.c +++ /dev/null @@ -1,253 +0,0 @@ -/* - * Copyright (c) 2010, 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. - * * Neither the name of Google, 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 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. - */ - -#include <dirent.h> -#include <errno.h> -#include <fcntl.h> -#include <libgen.h> -#include <stdio.h> -#include <stdlib.h> -#include <string.h> -#include <unistd.h> - -#include <pwd.h> -#include <sys/stat.h> - -#define BUF_MAX 1024 -#define CMD_DISPLAY_MAX (9 + 1) -#define USER_DISPLAY_MAX (10 + 1) - -struct pid_info_t { - pid_t pid; - char user[USER_DISPLAY_MAX]; - - char cmdline[CMD_DISPLAY_MAX]; - - char path[PATH_MAX]; - ssize_t parent_length; -}; - -static void print_header() -{ - printf("%-9s %5s %10s %4s %9s %18s %9s %10s %s\n", - "COMMAND", - "PID", - "USER", - "FD", - "TYPE", - "DEVICE", - "SIZE/OFF", - "NODE", - "NAME"); -} - -static void print_type(char *type, struct pid_info_t* info) -{ - static ssize_t link_dest_size; - static char link_dest[PATH_MAX]; - - strlcat(info->path, type, sizeof(info->path)); - if ((link_dest_size = readlink(info->path, link_dest, sizeof(link_dest)-1)) < 0) { - if (errno == ENOENT) - goto out; - - snprintf(link_dest, sizeof(link_dest), "%s (readlink: %s)", info->path, strerror(errno)); - } else { - link_dest[link_dest_size] = '\0'; - } - - // Things that are just the root filesystem are uninteresting (we already know) - if (!strcmp(link_dest, "/")) - goto out; - - printf("%-9s %5d %10s %4s %9s %18s %9s %10s %s\n", - info->cmdline, info->pid, info->user, type, - "???", "???", "???", "???", link_dest); - -out: - info->path[info->parent_length] = '\0'; -} - -// Prints out all file that have been memory mapped -static void print_maps(struct pid_info_t* info) -{ - FILE *maps; - size_t offset; - char device[10]; - long int inode; - char file[PATH_MAX]; - - strlcat(info->path, "maps", sizeof(info->path)); - - maps = fopen(info->path, "r"); - if (!maps) - goto out; - - while (fscanf(maps, "%*x-%*x %*s %zx %s %ld %s\n", &offset, device, &inode, - file) == 4) { - // We don't care about non-file maps - if (inode == 0 || !strcmp(device, "00:00")) - continue; - - printf("%-9s %5d %10s %4s %9s %18s %9zd %10ld %s\n", - info->cmdline, info->pid, info->user, "mem", - "???", device, offset, inode, file); - } - - fclose(maps); - -out: - info->path[info->parent_length] = '\0'; -} - -// Prints out all open file descriptors -static void print_fds(struct pid_info_t* info) -{ - static char* fd_path = "fd/"; - strlcat(info->path, fd_path, sizeof(info->path)); - - int previous_length = info->parent_length; - info->parent_length += strlen(fd_path); - - DIR *dir = opendir(info->path); - if (dir == NULL) { - char msg[BUF_MAX]; - snprintf(msg, sizeof(msg), "%s (opendir: %s)", info->path, strerror(errno)); - printf("%-9s %5d %10s %4s %9s %18s %9s %10s %s\n", - info->cmdline, info->pid, info->user, "FDS", - "", "", "", "", msg); - goto out; - } - - struct dirent* de; - while ((de = readdir(dir))) { - if (!strcmp(de->d_name, ".") || !strcmp(de->d_name, "..")) - continue; - - print_type(de->d_name, info); - } - closedir(dir); - -out: - info->parent_length = previous_length; - info->path[info->parent_length] = '\0'; -} - -static void lsof_dumpinfo(pid_t pid) -{ - int fd; - struct pid_info_t info; - struct stat pidstat; - struct passwd *pw; - - info.pid = pid; - snprintf(info.path, sizeof(info.path), "/proc/%d/", pid); - info.parent_length = strlen(info.path); - - // Get the UID by calling stat on the proc/pid directory. - if (!stat(info.path, &pidstat)) { - pw = getpwuid(pidstat.st_uid); - if (pw) { - strlcpy(info.user, pw->pw_name, sizeof(info.user)); - } else { - snprintf(info.user, USER_DISPLAY_MAX, "%d", (int)pidstat.st_uid); - } - } else { - strcpy(info.user, "???"); - } - - // Read the command line information; each argument is terminated with NULL. - strlcat(info.path, "cmdline", sizeof(info.path)); - fd = open(info.path, O_RDONLY); - if (fd < 0) { - fprintf(stderr, "Couldn't read %s\n", info.path); - return; - } - - char cmdline[PATH_MAX]; - int numRead = read(fd, cmdline, sizeof(cmdline) - 1); - close(fd); - - if (numRead < 0) { - fprintf(stderr, "Error reading cmdline: %s: %s\n", info.path, strerror(errno)); - return; - } - - cmdline[numRead] = '\0'; - - // We only want the basename of the cmdline - strlcpy(info.cmdline, basename(cmdline), sizeof(info.cmdline)); - - // Read each of these symlinks - print_type("cwd", &info); - print_type("exe", &info); - print_type("root", &info); - - print_fds(&info); - print_maps(&info); -} - -int lsof_main(int argc, char *argv[]) -{ - long int pid = 0; - char* endptr; - if (argc == 2) { - pid = strtol(argv[1], &endptr, 10); - } - - print_header(); - - if (pid) { - lsof_dumpinfo(pid); - } else { - DIR *dir = opendir("/proc"); - if (dir == NULL) { - fprintf(stderr, "Couldn't open /proc\n"); - return -1; - } - - struct dirent* de; - while ((de = readdir(dir))) { - if (!strcmp(de->d_name, ".") || !strcmp(de->d_name, "..")) - continue; - - // Only inspect directories that are PID numbers - pid = strtol(de->d_name, &endptr, 10); - if (*endptr != '\0') - continue; - - lsof_dumpinfo(pid); - } - closedir(dir); - } - - return 0; -} diff --git a/toolbox/mount.c b/toolbox/mount.c deleted file mode 100644 index 66ae8b1..0000000 --- a/toolbox/mount.c +++ /dev/null @@ -1,360 +0,0 @@ -/* - * mount.c, by rmk - */ - -#include <sys/mount.h> -#include <sys/stat.h> -#include <fcntl.h> -#include <errno.h> -#include <stdio.h> -#include <stdlib.h> -#include <string.h> -#include <unistd.h> - -#include <linux/loop.h> - -#define ARRAY_SIZE(x) (sizeof(x) / sizeof(x[0])) - -#define DEFAULT_LOOP_DEVICE "/dev/block/loop0" -#define LOOPDEV_MAXLEN 64 - -struct mount_opts { - const char str[16]; - unsigned long rwmask; - unsigned long rwset; - unsigned long rwnoset; -}; - -struct extra_opts { - char *str; - char *end; - int used_size; - int alloc_size; -}; - -/* - * These options define the function of "mount(2)". - */ -#define MS_TYPE (MS_REMOUNT|MS_BIND|MS_MOVE) - - -static const struct mount_opts options[] = { - /* name mask set noset */ - { "async", MS_SYNCHRONOUS, 0, MS_SYNCHRONOUS }, - { "atime", MS_NOATIME, 0, MS_NOATIME }, - { "bind", MS_TYPE, MS_BIND, 0, }, - { "dev", MS_NODEV, 0, MS_NODEV }, - { "diratime", MS_NODIRATIME, 0, MS_NODIRATIME }, - { "dirsync", MS_DIRSYNC, MS_DIRSYNC, 0 }, - { "exec", MS_NOEXEC, 0, MS_NOEXEC }, - { "move", MS_TYPE, MS_MOVE, 0 }, - { "recurse", MS_REC, MS_REC, 0 }, - { "rec", MS_REC, MS_REC, 0 }, - { "remount", MS_TYPE, MS_REMOUNT, 0 }, - { "ro", MS_RDONLY, MS_RDONLY, 0 }, - { "rw", MS_RDONLY, 0, MS_RDONLY }, - { "suid", MS_NOSUID, 0, MS_NOSUID }, - { "sync", MS_SYNCHRONOUS, MS_SYNCHRONOUS, 0 }, - { "verbose", MS_VERBOSE, MS_VERBOSE, 0 }, - { "unbindable", MS_UNBINDABLE, MS_UNBINDABLE, 0 }, - { "private", MS_PRIVATE, MS_PRIVATE, 0 }, - { "slave", MS_SLAVE, MS_SLAVE, 0 }, - { "shared", MS_SHARED, MS_SHARED, 0 }, -}; - -static void add_extra_option(struct extra_opts *extra, char *s) -{ - int len = strlen(s); - int newlen; - - if (extra->str) - len++; /* +1 for ',' */ - newlen = extra->used_size + len; - - if (newlen >= extra->alloc_size) { - char *new; - - new = realloc(extra->str, newlen + 1); /* +1 for NUL */ - if (!new) - return; - - extra->str = new; - extra->end = extra->str + extra->used_size; - extra->alloc_size = newlen + 1; - } - - if (extra->used_size) { - *extra->end = ','; - extra->end++; - } - strcpy(extra->end, s); - extra->used_size += len; - -} - -static unsigned long -parse_mount_options(char *arg, unsigned long rwflag, struct extra_opts *extra, int* loop, char *loopdev) -{ - char *s; - - *loop = 0; - while ((s = strsep(&arg, ",")) != NULL) { - char *opt = s; - unsigned int i; - int res, no = s[0] == 'n' && s[1] == 'o'; - - if (no) - s += 2; - - if (strncmp(s, "loop=", 5) == 0) { - *loop = 1; - strlcpy(loopdev, s + 5, LOOPDEV_MAXLEN); - continue; - } - - if (strcmp(s, "loop") == 0) { - *loop = 1; - strlcpy(loopdev, DEFAULT_LOOP_DEVICE, LOOPDEV_MAXLEN); - continue; - } - for (i = 0, res = 1; i < ARRAY_SIZE(options); i++) { - res = strcmp(s, options[i].str); - - if (res == 0) { - rwflag &= ~options[i].rwmask; - if (no) - rwflag |= options[i].rwnoset; - else - rwflag |= options[i].rwset; - } - if (res <= 0) - break; - } - - if (res != 0 && s[0]) - add_extra_option(extra, opt); - } - - return rwflag; -} - -/* - * Mark the given block device as read-write, using the BLKROSET ioctl. - */ -static void fs_set_blk_rw(const char *blockdev) -{ - int fd; - int OFF = 0; - - fd = open(blockdev, O_RDONLY); - if (fd < 0) { - // should never happen - return; - } - - ioctl(fd, BLKROSET, &OFF); - close(fd); -} - -static char *progname; - -static struct extra_opts extra; -static unsigned long rwflag; - -static int -do_mount(char *dev, char *dir, char *type, unsigned long rwflag, void *data, int loop, - char *loopdev) -{ - char *s; - int error = 0; - - if (loop) { - int file_fd, device_fd; - int flags; - - flags = (rwflag & MS_RDONLY) ? O_RDONLY : O_RDWR; - - file_fd = open(dev, flags); - if (file_fd < 0) { - perror("open backing file failed"); - return 1; - } - device_fd = open(loopdev, flags); - if (device_fd < 0) { - perror("open loop device failed"); - close(file_fd); - return 1; - } - if (ioctl(device_fd, LOOP_SET_FD, file_fd) < 0) { - perror("ioctl LOOP_SET_FD failed"); - close(file_fd); - close(device_fd); - return 1; - } - - close(file_fd); - close(device_fd); - dev = loopdev; - } - - if ((rwflag & MS_RDONLY) == 0) { - fs_set_blk_rw(dev); - } - - while ((s = strsep(&type, ",")) != NULL) { -retry: - if (mount(dev, dir, s, rwflag, data) == -1) { - error = errno; - /* - * If the filesystem is not found, or the - * superblock is invalid, try the next. - */ - if (error == ENODEV || error == EINVAL) - continue; - - /* - * If we get EACCESS, and we're trying to - * mount readwrite and this isn't a remount, - * try read only. - */ - if (error == EACCES && - (rwflag & (MS_REMOUNT|MS_RDONLY)) == 0) { - rwflag |= MS_RDONLY; - goto retry; - } - break; - } - } - - if (error) { - errno = error; - perror("mount"); - return 255; - } - - return 0; -} - -static int print_mounts() -{ - FILE* f; - int length; - char buffer[100]; - - f = fopen("/proc/mounts", "r"); - if (!f) { - fprintf(stdout, "could not open /proc/mounts\n"); - return -1; - } - - do { - length = fread(buffer, 1, 100, f); - if (length > 0) - fwrite(buffer, 1, length, stdout); - } while (length > 0); - - fclose(f); - return 0; -} - -static int get_mounts_dev_dir(const char *arg, char **dev, char **dir) -{ - FILE *f; - char mount_dev[256]; - char mount_dir[256]; - char mount_type[256]; - char mount_opts[256]; - int mount_freq; - int mount_passno; - int match; - - f = fopen("/proc/mounts", "r"); - if (!f) { - fprintf(stdout, "could not open /proc/mounts\n"); - return -1; - } - - do { - match = fscanf(f, "%255s %255s %255s %255s %d %d\n", - mount_dev, mount_dir, mount_type, - mount_opts, &mount_freq, &mount_passno); - mount_dev[255] = 0; - mount_dir[255] = 0; - mount_type[255] = 0; - mount_opts[255] = 0; - if (match == 6 && - (strcmp(arg, mount_dev) == 0 || - strcmp(arg, mount_dir) == 0)) { - *dev = strdup(mount_dev); - *dir = strdup(mount_dir); - fclose(f); - return 0; - } - } while (match != EOF); - - fclose(f); - return -1; -} - -int mount_main(int argc, char *argv[]) -{ - char *type = NULL; - char *dev = NULL; - char *dir = NULL; - int c; - int loop = 0; - char loopdev[LOOPDEV_MAXLEN]; - - progname = argv[0]; - rwflag = MS_VERBOSE; - - // mount with no arguments is equivalent to "cat /proc/mounts" - if (argc == 1) return print_mounts(); - - do { - c = getopt(argc, argv, "o:rt:w"); - if (c == EOF) - break; - switch (c) { - case 'o': - rwflag = parse_mount_options(optarg, rwflag, &extra, &loop, loopdev); - break; - case 'r': - rwflag |= MS_RDONLY; - break; - case 't': - type = optarg; - break; - case 'w': - rwflag &= ~MS_RDONLY; - break; - case '?': - fprintf(stderr, "%s: invalid option -%c\n", - progname, optopt); - exit(1); - } - } while (1); - - /* - * If remount, bind or move was specified, then we don't - * have a "type" as such. Use the dummy "none" type. - */ - if (rwflag & MS_TYPE) - type = "none"; - - if (optind + 2 == argc) { - dev = argv[optind]; - dir = argv[optind + 1]; - } else if (optind + 1 == argc && rwflag & MS_REMOUNT) { - get_mounts_dev_dir(argv[optind], &dev, &dir); - } - - if (dev == NULL || dir == NULL || type == NULL) { - fprintf(stderr, "Usage: %s [-r] [-w] [-o options] [-t type] " - "device directory\n", progname); - exit(1); - } - - return do_mount(dev, dir, type, rwflag, extra.str, loop, loopdev); - /* We leak dev and dir in some cases, but we're about to exit */ -} diff --git a/toolbox/renice.c b/toolbox/renice.c deleted file mode 100644 index 99a06f4..0000000 --- a/toolbox/renice.c +++ /dev/null @@ -1,161 +0,0 @@ -/* - * Copyright (c) 2008, 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. - * * Neither the name of Google, 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 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. - */ - -#include <stdio.h> -#include <unistd.h> -#include <stdlib.h> -#include <string.h> -#include <sys/time.h> -#include <sys/resource.h> -#include <sched.h> -#include <getopt.h> - -static void -usage(const char *s) -{ - fprintf(stderr, "USAGE: %s [[-r] [-t TYPE] priority pids ...] [-g pid]\n", s); - exit(EXIT_FAILURE); -} - -void print_prio(pid_t pid) -{ - int sched; - struct sched_param sp; - - printf("pid %d's priority: %d\n", pid, getpriority(PRIO_PROCESS, pid)); - - printf("scheduling class: "); - sched = sched_getscheduler(pid); - switch (sched) { - case SCHED_FIFO: - printf("FIFO\n"); - break; - case SCHED_RR: - printf("RR\n"); - break; - case SCHED_OTHER: - printf("Normal\n"); - break; - case -1: - perror("sched_getscheduler"); - break; - default: - printf("Unknown\n"); - } - - sched_getparam(pid, &sp); - printf("RT prio: %d (of %d to %d)\n", sp.sched_priority, - sched_get_priority_min(sched), sched_get_priority_max(sched)); -} - -int get_sched(char *str) -{ - if (strcasecmp(str, "RR") == 0) - return SCHED_RR; - else if (strcasecmp(str, "FIFO") == 0) - return SCHED_FIFO; - else if (strcasecmp(str, "NORMAL") == 0) - return SCHED_OTHER; - else if (strcasecmp(str, "OTHER") == 0) - return SCHED_OTHER; - return SCHED_RR; -} - -int renice_main(int argc, char *argv[]) -{ - int prio; - int realtime = 0; - int opt; - int sched = SCHED_RR; - char *cmd = argv[0]; - - do { - opt = getopt(argc, argv, "rt:g:"); - if (opt == -1) - break; - switch (opt) { - case 'r': - // do realtime priority adjustment - realtime = 1; - break; - case 't': - sched = get_sched(optarg); - break; - case 'g': - print_prio(atoi(optarg)); - return 0; - default: - usage(cmd); - } - } while (1); - - argc -= optind; - argv += optind; - - if (argc < 1) - usage(cmd); - - prio = atoi(argv[0]); - argc--; - argv++; - - if (argc < 1) - usage(cmd); - - while(argc) { - pid_t pid; - - pid = atoi(argv[0]); - argc--; - argv++; - - if (realtime) { - struct sched_param sp = { .sched_priority = prio }; - int ret; - - ret = sched_setscheduler(pid, sched, &sp); - if (ret) { - perror("sched_set_scheduler"); - exit(EXIT_FAILURE); - } - } else { - int ret; - - ret = setpriority(PRIO_PROCESS, pid, prio); - if (ret) { - perror("setpriority"); - exit(EXIT_FAILURE); - } - } - } - - return 0; -} diff --git a/toolbox/restart.c b/toolbox/restart.c new file mode 100644 index 0000000..9d803de --- /dev/null +++ b/toolbox/restart.c @@ -0,0 +1,27 @@ +#include <string.h> +#include <stdio.h> +#include <stdlib.h> + +#include <cutils/properties.h> + +int restart_main(int argc, char *argv[]) +{ + char buf[1024]; + + if(argc > 1) { + property_set("ctl.stop", argv[1]); + property_set("ctl.start", argv[1]); + } else { + /* defaults to stopping and starting the common services */ + property_set("ctl.stop", "zygote_secondary"); + property_set("ctl.stop", "zygote"); + property_set("ctl.stop", "surfaceflinger"); + property_set("ctl.stop", "netd"); + property_set("ctl.start", "netd"); + property_set("ctl.start", "surfaceflinger"); + property_set("ctl.start", "zygote"); + property_set("ctl.start", "zygote_secondary"); + } + + return 0; +} diff --git a/toolbox/upstream-netbsd/usr.bin/du/du.c b/toolbox/upstream-netbsd/usr.bin/du/du.c deleted file mode 100644 index 086ac4a..0000000 --- a/toolbox/upstream-netbsd/usr.bin/du/du.c +++ /dev/null @@ -1,364 +0,0 @@ -/* $NetBSD: du.c,v 1.36 2012/03/11 11:23:20 shattered Exp $ */ - -/* - * Copyright (c) 1989, 1993, 1994 - * The Regents of the University of California. All rights reserved. - * - * This code is derived from software contributed to Berkeley by - * Chris Newcomb. - * - * 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 University 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 REGENTS 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 REGENTS 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. - */ - -#include <sys/cdefs.h> -#ifndef lint -__COPYRIGHT("@(#) Copyright (c) 1989, 1993, 1994\ - The Regents of the University of California. All rights reserved."); -#endif /* not lint */ - -#ifndef lint -#if 0 -static char sccsid[] = "@(#)du.c 8.5 (Berkeley) 5/4/95"; -#else -__RCSID("$NetBSD: du.c,v 1.36 2012/03/11 11:23:20 shattered Exp $"); -#endif -#endif /* not lint */ - -#include <sys/param.h> -#include <sys/types.h> -#include <sys/stat.h> - -#include <dirent.h> -#include <err.h> -#include <errno.h> -#include <fts.h> -#include <inttypes.h> -#include <util.h> -#include <stdio.h> -#include <stdlib.h> -#include <string.h> -#include <unistd.h> -#include <limits.h> - -/* Count inodes or file size */ -#define COUNT (iflag ? 1 : p->fts_statp->st_blocks) - -static int linkchk(dev_t, ino_t); -static void prstat(const char *, int64_t); -__dead static void usage(void); - -static int hflag, iflag; -static long blocksize; - -int -main(int argc, char *argv[]) -{ - FTS *fts; - FTSENT *p; - int64_t totalblocks; - int ftsoptions, listfiles; - int depth; - int Hflag, Lflag, aflag, ch, cflag, dflag, gkmflag, nflag, rval, sflag; - const char *noargv[2]; - - Hflag = Lflag = aflag = cflag = dflag = gkmflag = nflag = sflag = 0; - totalblocks = 0; - ftsoptions = FTS_PHYSICAL; - depth = INT_MAX; - while ((ch = getopt(argc, argv, "HLPacd:ghikmnrsx")) != -1) - switch (ch) { - case 'H': - Hflag = 1; - Lflag = 0; - break; - case 'L': - Lflag = 1; - Hflag = 0; - break; - case 'P': - Hflag = Lflag = 0; - break; - case 'a': - aflag = 1; - break; - case 'c': - cflag = 1; - break; - case 'd': - dflag = 1; - depth = atoi(optarg); - if (depth < 0 || depth > SHRT_MAX) { - warnx("invalid argument to option d: %s", - optarg); - usage(); - } - break; - case 'g': - blocksize = 1024 * 1024 * 1024; - gkmflag = 1; - break; - case 'h': - hflag = 1; - break; - case 'i': - iflag = 1; - break; - case 'k': - blocksize = 1024; - gkmflag = 1; - break; - case 'm': - blocksize = 1024 * 1024; - gkmflag = 1; - break; - case 'n': - nflag = 1; - break; - case 'r': - break; - case 's': - sflag = 1; - break; - case 'x': - ftsoptions |= FTS_XDEV; - break; - case '?': - default: - usage(); - } - argc -= optind; - argv += optind; - - /* - * XXX - * Because of the way that fts(3) works, logical walks will not count - * the blocks actually used by symbolic links. We rationalize this by - * noting that users computing logical sizes are likely to do logical - * copies, so not counting the links is correct. The real reason is - * that we'd have to re-implement the kernel's symbolic link traversing - * algorithm to get this right. If, for example, you have relative - * symbolic links referencing other relative symbolic links, it gets - * very nasty, very fast. The bottom line is that it's documented in - * the man page, so it's a feature. - */ - if (Hflag) - ftsoptions |= FTS_COMFOLLOW; - if (Lflag) { - ftsoptions &= ~FTS_PHYSICAL; - ftsoptions |= FTS_LOGICAL; - } - - listfiles = 0; - if (aflag) { - if (sflag || dflag) - usage(); - listfiles = 1; - } else if (sflag) { - if (dflag) - usage(); - depth = 0; - } - - if (!*argv) { - noargv[0] = "."; - noargv[1] = NULL; - argv = __UNCONST(noargv); - } - - if (!gkmflag) - (void)getbsize(NULL, &blocksize); - blocksize /= 512; - - if ((fts = fts_open(argv, ftsoptions, NULL)) == NULL) - err(1, "fts_open `%s'", *argv); - - for (rval = 0; (p = fts_read(fts)) != NULL;) { -#ifndef __ANDROID__ - if (nflag) { - switch (p->fts_info) { - case FTS_NS: - case FTS_SLNONE: - /* nothing */ - break; - default: - if (p->fts_statp->st_flags & UF_NODUMP) { - fts_set(fts, p, FTS_SKIP); - continue; - } - } - } -#endif - switch (p->fts_info) { - case FTS_D: /* Ignore. */ - break; - case FTS_DP: - p->fts_parent->fts_number += - p->fts_number += COUNT; - if (cflag) - totalblocks += COUNT; - /* - * If listing each directory, or not listing files - * or directories and this is post-order of the - * root of a traversal, display the total. - */ - if (p->fts_level <= depth - || (!listfiles && !p->fts_level)) - prstat(p->fts_path, p->fts_number); - break; - case FTS_DC: /* Ignore. */ - break; - case FTS_DNR: /* Warn, continue. */ - case FTS_ERR: - case FTS_NS: - warnx("%s: %s", p->fts_path, strerror(p->fts_errno)); - rval = 1; - break; - default: - if (p->fts_statp->st_nlink > 1 && - linkchk(p->fts_statp->st_dev, p->fts_statp->st_ino)) - break; - /* - * If listing each file, or a non-directory file was - * the root of a traversal, display the total. - */ - if (listfiles || !p->fts_level) - prstat(p->fts_path, COUNT); - p->fts_parent->fts_number += COUNT; - if (cflag) - totalblocks += COUNT; - } - } - if (errno) - err(1, "fts_read"); - if (cflag) - prstat("total", totalblocks); - exit(rval); -} - -static void -prstat(const char *fname, int64_t blocks) -{ - if (iflag) { - (void)printf("%" PRId64 "\t%s\n", blocks, fname); - return; - } - - if (hflag) { - char buf[5]; - int64_t sz = blocks * 512; - - humanize_number(buf, sizeof(buf), sz, "", HN_AUTOSCALE, - HN_B | HN_NOSPACE | HN_DECIMAL); - - (void)printf("%s\t%s\n", buf, fname); - } else - (void)printf("%" PRId64 "\t%s\n", - howmany(blocks, (int64_t)blocksize), - fname); -} - -static int -linkchk(dev_t dev, ino_t ino) -{ - static struct entry { - dev_t dev; - ino_t ino; - } *htable; - static int htshift; /* log(allocated size) */ - static int htmask; /* allocated size - 1 */ - static int htused; /* 2*number of insertions */ - static int sawzero; /* Whether zero is in table or not */ - int h, h2; - uint64_t tmp; - /* this constant is (1<<64)/((1+sqrt(5))/2) - * aka (word size)/(golden ratio) - */ - const uint64_t HTCONST = 11400714819323198485ULL; - const int HTBITS = CHAR_BIT * sizeof(tmp); - - /* Never store zero in hashtable */ - if (dev == 0 && ino == 0) { - h = sawzero; - sawzero = 1; - return h; - } - - /* Extend hash table if necessary, keep load under 0.5 */ - if (htused<<1 >= htmask) { - struct entry *ohtable; - - if (!htable) - htshift = 10; /* starting hashtable size */ - else - htshift++; /* exponential hashtable growth */ - - htmask = (1 << htshift) - 1; - htused = 0; - - ohtable = htable; - htable = calloc(htmask+1, sizeof(*htable)); - if (!htable) - err(1, "calloc"); - - /* populate newly allocated hashtable */ - if (ohtable) { - int i; - for (i = 0; i <= htmask>>1; i++) - if (ohtable[i].ino || ohtable[i].dev) - linkchk(ohtable[i].dev, ohtable[i].ino); - free(ohtable); - } - } - - /* multiplicative hashing */ - tmp = dev; - tmp <<= HTBITS>>1; - tmp |= ino; - tmp *= HTCONST; - h = tmp >> (HTBITS - htshift); - h2 = 1 | ( tmp >> (HTBITS - (htshift<<1) - 1)); /* must be odd */ - - /* open address hashtable search with double hash probing */ - while (htable[h].ino || htable[h].dev) { - if ((htable[h].ino == ino) && (htable[h].dev == dev)) - return 1; - h = (h + h2) & htmask; - } - - /* Insert the current entry into hashtable */ - htable[h].dev = dev; - htable[h].ino = ino; - htused++; - return 0; -} - -static void -usage(void) -{ - - (void)fprintf(stderr, - "usage: du [-H | -L | -P] [-a | -d depth | -s] [-cghikmnrx] [file ...]\n"); - exit(1); -} diff --git a/toolbox/uptime.c b/toolbox/uptime.c deleted file mode 100644 index ebfb15e..0000000 --- a/toolbox/uptime.c +++ /dev/null @@ -1,87 +0,0 @@ -/* - * Copyright (c) 2010, 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. - * * Neither the name of Google, 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 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. - */ - -#include <errno.h> -#include <stdio.h> -#include <string.h> -#include <time.h> - -static void format_time(int time, char* buffer) { - int seconds = time % 60; - time /= 60; - int minutes = time % 60; - time /= 60; - int hours = time % 24; - int days = time / 24; - - if (days > 0) { - sprintf(buffer, "%d day%s, %02d:%02d:%02d", days, (days == 1) ? "" : "s", hours, minutes, seconds); - } else { - sprintf(buffer, "%02d:%02d:%02d", hours, minutes, seconds); - } -} - -int uptime_main(int argc __attribute__((unused)), char *argv[] __attribute__((unused))) { - FILE* file = fopen("/proc/uptime", "r"); - if (!file) { - fprintf(stderr, "Could not open /proc/uptime\n"); - return -1; - } - float idle_time; - if (fscanf(file, "%*f %f", &idle_time) != 1) { - fprintf(stderr, "Could not parse /proc/uptime\n"); - fclose(file); - return -1; - } - fclose(file); - - struct timespec up_timespec; - if (clock_gettime(CLOCK_MONOTONIC, &up_timespec) == -1) { - fprintf(stderr, "Could not get monotonic time: %s\n", strerror(errno)); - return -1; - } - float up_time = up_timespec.tv_sec + up_timespec.tv_nsec / 1e9; - - struct timespec elapsed_timespec; - if (clock_gettime(CLOCK_BOOTTIME, &elapsed_timespec) == -1) { - fprintf(stderr, "Could not get boot time: %s\n", strerror(errno)); - return -1; - } - int elapsed = elapsed_timespec.tv_sec; - - char up_string[100], idle_string[100], sleep_string[100]; - format_time(elapsed, up_string); - format_time((int)idle_time, idle_string); - format_time((int)(elapsed - up_time), sleep_string); - printf("up time: %s, idle time: %s, sleep time: %s\n", up_string, idle_string, sleep_string); - - return 0; -} diff --git a/toolbox/watchprops.c b/toolbox/watchprops.c deleted file mode 100644 index cd62922..0000000 --- a/toolbox/watchprops.c +++ /dev/null @@ -1,92 +0,0 @@ -#include <stdio.h> -#include <stdlib.h> -#include <string.h> -#include <time.h> -#include <errno.h> - -#include <cutils/properties.h> -#include <cutils/hashmap.h> - -#define _REALLY_INCLUDE_SYS__SYSTEM_PROPERTIES_H_ -#include <sys/_system_properties.h> - -static int str_hash(void *key) -{ - return hashmapHash(key, strlen(key)); -} - -static bool str_equals(void *keyA, void *keyB) -{ - return strcmp(keyA, keyB) == 0; -} - -static void announce(char *name, char *value) -{ - unsigned char *x; - - for(x = (unsigned char *)value; *x; x++) { - if((*x < 32) || (*x > 127)) *x = '.'; - } - - fprintf(stderr,"%10d %s = '%s'\n", (int) time(0), name, value); -} - -static void add_to_watchlist(Hashmap *watchlist, const char *name, - const prop_info *pi) -{ - char *key = strdup(name); - unsigned *value = malloc(sizeof(unsigned)); - if (!key || !value) - exit(1); - - *value = __system_property_serial(pi); - hashmapPut(watchlist, key, value); -} - -static void populate_watchlist(const prop_info *pi, void *cookie) -{ - Hashmap *watchlist = cookie; - char name[PROP_NAME_MAX]; - char value_unused[PROP_VALUE_MAX]; - - __system_property_read(pi, name, value_unused); - add_to_watchlist(watchlist, name, pi); -} - -static void update_watchlist(const prop_info *pi, void *cookie) -{ - Hashmap *watchlist = cookie; - char name[PROP_NAME_MAX]; - char value[PROP_VALUE_MAX]; - unsigned *serial; - - __system_property_read(pi, name, value); - serial = hashmapGet(watchlist, name); - if (!serial) { - add_to_watchlist(watchlist, name, pi); - announce(name, value); - } else { - unsigned tmp = __system_property_serial(pi); - if (*serial != tmp) { - *serial = tmp; - announce(name, value); - } - } -} - -int watchprops_main(int argc, char *argv[]) -{ - unsigned serial; - - Hashmap *watchlist = hashmapCreate(1024, str_hash, str_equals); - if (!watchlist) - exit(1); - - __system_property_foreach(populate_watchlist, watchlist); - - for(serial = 0;;) { - serial = __system_property_wait_any(serial); - __system_property_foreach(update_watchlist, watchlist); - } - return 0; -} |