diff options
44 files changed, 2873 insertions, 661 deletions
diff --git a/adb/Android.mk b/adb/Android.mk index 36f595b..721b48d 100644 --- a/adb/Android.mk +++ b/adb/Android.mk @@ -130,7 +130,7 @@ LOCAL_FORCE_STATIC_EXECUTABLE := true LOCAL_MODULE_PATH := $(TARGET_ROOT_OUT_SBIN) LOCAL_UNSTRIPPED_PATH := $(TARGET_ROOT_OUT_SBIN_UNSTRIPPED) -LOCAL_STATIC_LIBRARIES := libcutils libc libmincrypt +LOCAL_STATIC_LIBRARIES := liblog libcutils libc libmincrypt include $(BUILD_EXECUTABLE) diff --git a/adb/log_service.c b/adb/log_service.c index 6e9bdee..af24356 100644 --- a/adb/log_service.c +++ b/adb/log_service.c @@ -22,7 +22,7 @@ #include <fcntl.h> #include <errno.h> #include <sys/socket.h> -#include <cutils/logger.h> +#include <log/logger.h> #include "sysdeps.h" #include "adb.h" diff --git a/adb/usb_vendors.c b/adb/usb_vendors.c index e132c67..68bb232 100644 --- a/adb/usb_vendors.c +++ b/adb/usb_vendors.c @@ -153,6 +153,8 @@ #define VENDOR_ID_NOOK 0x2080 // Qisda's USB Vendor ID #define VENDOR_ID_QISDA 0x1D45 +// ECS's USB Vendor ID +#define VENDOR_ID_ECS 0x03fc /** built-in vendor list */ @@ -216,6 +218,7 @@ int builtInVendorIds[] = { VENDOR_ID_MTK, VENDOR_ID_NOOK, VENDOR_ID_QISDA, + VENDOR_ID_ECS, }; #define BUILT_IN_VENDOR_COUNT (sizeof(builtInVendorIds)/sizeof(builtInVendorIds[0])) diff --git a/debuggerd/debuggerd.c b/debuggerd/debuggerd.c index 0028bda..756f7bb 100644 --- a/debuggerd/debuggerd.c +++ b/debuggerd/debuggerd.c @@ -31,9 +31,10 @@ #include <sys/stat.h> #include <sys/poll.h> +#include <log/logd.h> +#include <log/logger.h> + #include <cutils/sockets.h> -#include <cutils/logd.h> -#include <cutils/logger.h> #include <cutils/properties.h> #include <cutils/debugger.h> diff --git a/debuggerd/tombstone.c b/debuggerd/tombstone.c index 77f6ef1..7009a8e 100644 --- a/debuggerd/tombstone.c +++ b/debuggerd/tombstone.c @@ -29,7 +29,7 @@ #include <private/android_filesystem_config.h> -#include <cutils/logger.h> +#include <log/logger.h> #include <cutils/properties.h> #include <corkscrew/demangle.h> diff --git a/debuggerd/utility.c b/debuggerd/utility.c index 9bf3c18..41be982 100644 --- a/debuggerd/utility.c +++ b/debuggerd/utility.c @@ -22,7 +22,7 @@ #include <errno.h> #include <unistd.h> #include <signal.h> -#include <cutils/logd.h> +#include <log/logd.h> #include <sys/ptrace.h> #include <sys/wait.h> #include <arpa/inet.h> diff --git a/fastbootd/Android.mk b/fastbootd/Android.mk new file mode 100644 index 0000000..76b28e2 --- /dev/null +++ b/fastbootd/Android.mk @@ -0,0 +1,38 @@ +# Copyright (C) 2013 Google Inc. +# +# 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. + +LOCAL_PATH:= $(call my-dir) + +include $(CLEAR_VARS) + +LOCAL_SRC_FILES := \ + config.c \ + commands.c \ + fastbootd.c \ + protocol.c \ + transport.c \ + usb_linux_client.c + +LOCAL_MODULE := fastbootd +LOCAL_MODULE_TAGS := optional +LOCAL_CFLAGS := -Wall -Werror -Wno-unused-parameter + +LOCAL_STATIC_LIBRARIES := \ + libsparse_static \ + libc \ + libcutils + +LOCAL_FORCE_STATIC_EXECUTABLE := true + +include $(BUILD_EXECUTABLE) diff --git a/fastbootd/bootimg.h b/fastbootd/bootimg.h new file mode 100644 index 0000000..44fde92 --- /dev/null +++ b/fastbootd/bootimg.h @@ -0,0 +1,97 @@ +/* + * 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. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS + * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED + * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT + * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#ifndef _BOOT_IMAGE_H_ +#define _BOOT_IMAGE_H_ + +typedef struct boot_img_hdr boot_img_hdr; + +#define BOOT_MAGIC "ANDROID!" +#define BOOT_MAGIC_SIZE 8 +#define BOOT_NAME_SIZE 16 +#define BOOT_ARGS_SIZE 512 + +struct boot_img_hdr +{ + unsigned char magic[BOOT_MAGIC_SIZE]; + + unsigned kernel_size; /* size in bytes */ + unsigned kernel_addr; /* physical load addr */ + + unsigned ramdisk_size; /* size in bytes */ + unsigned ramdisk_addr; /* physical load addr */ + + unsigned second_size; /* size in bytes */ + unsigned second_addr; /* physical load addr */ + + unsigned tags_addr; /* physical addr for kernel tags */ + unsigned page_size; /* flash page size we assume */ + unsigned unused[2]; /* future expansion: should be 0 */ + + unsigned char name[BOOT_NAME_SIZE]; /* asciiz product name */ + + unsigned char cmdline[BOOT_ARGS_SIZE]; + + unsigned id[8]; /* timestamp / checksum / sha1 / etc */ +}; + +/* +** +-----------------+ +** | boot header | 1 page +** +-----------------+ +** | kernel | n pages +** +-----------------+ +** | ramdisk | m pages +** +-----------------+ +** | second stage | o 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 +** +** 0. all entities are page_size aligned in flash +** 1. kernel and ramdisk are required (size != 0) +** 2. second is optional (second_size == 0 -> no second) +** 3. load each element (kernel, ramdisk, second) at +** the specified physical address (kernel_addr, etc) +** 4. prepare tags at tag_addr. kernel_args[] is +** appended to the kernel commandline in the tags. +** 5. r0 = 0, r1 = MACHINE_TYPE, r2 = tags_addr +** 6. if second_size != 0: jump to second_addr +** else: jump to kernel_addr +*/ + +boot_img_hdr *mkbootimg(void *kernel, unsigned kernel_size, + void *ramdisk, unsigned ramdisk_size, + void *second, unsigned second_size, + unsigned page_size, + unsigned *bootimg_size); + +void bootimg_set_cmdline(boot_img_hdr *hdr, const char *cmdline); +#endif diff --git a/fastbootd/commands.c b/fastbootd/commands.c new file mode 100644 index 0000000..252f655 --- /dev/null +++ b/fastbootd/commands.c @@ -0,0 +1,206 @@ +/* + * Copyright (c) 2009-2013, Google Inc. + * 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 <stdlib.h> +#include <unistd.h> +#include <sys/types.h> + +#include "bootimg.h" +#include "debug.h" +#include "protocol.h" + +static void cmd_boot(struct protocol_handle *phandle, const char *arg) +{ +#if 0 + unsigned kernel_actual; + unsigned ramdisk_actual; + static struct boot_img_hdr hdr; + char *ptr = ((char*) data); + + if (sz < sizeof(hdr)) { + fastboot_fail(phandle, "invalid bootimage header"); + return; + } + + memcpy(&hdr, data, sizeof(hdr)); + + /* ensure commandline is terminated */ + hdr.cmdline[BOOT_ARGS_SIZE-1] = 0; + + kernel_actual = ROUND_TO_PAGE(hdr.kernel_size); + ramdisk_actual = ROUND_TO_PAGE(hdr.ramdisk_size); + + if (2048 + kernel_actual + ramdisk_actual < sz) { + fastboot_fail(phandle, "incomplete bootimage"); + return; + } + + /*memmove((void*) KERNEL_ADDR, ptr + 2048, hdr.kernel_size); + memmove((void*) RAMDISK_ADDR, ptr + 2048 + kernel_actual, hdr.ramdisk_size);*/ + + fastboot_okay(phandle, ""); + udc_stop(); + + + /*boot_linux((void*) KERNEL_ADDR, (void*) TAGS_ADDR, + (const char*) hdr.cmdline, LINUX_MACHTYPE, + (void*) RAMDISK_ADDR, hdr.ramdisk_size);*/ +#endif +} + +static void cmd_erase(struct protocol_handle *phandle, const char *arg) +{ +#if 0 + struct ptentry *ptn; + struct ptable *ptable; + + ptable = flash_get_ptable(); + if (ptable == NULL) { + fastboot_fail(phandle, "partition table doesn't exist"); + return; + } + + ptn = ptable_find(ptable, arg); + if (ptn == NULL) { + fastboot_fail(phandle, "unknown partition name"); + return; + } + + if (flash_erase(ptn)) { + fastboot_fail(phandle, "failed to erase partition"); + return; + } + fastboot_okay(phandle, ""); +#endif +} + +static void cmd_flash(struct protocol_handle *phandle, const char *arg) +{ +#if 0 + struct ptentry *ptn; + struct ptable *ptable; + unsigned extra = 0; + + ptable = flash_get_ptable(); + if (ptable == NULL) { + fastboot_fail(phandle, "partition table doesn't exist"); + return; + } + + ptn = ptable_find(ptable, arg); + if (ptn == NULL) { + fastboot_fail(phandle, "unknown partition name"); + return; + } + + if (!strcmp(ptn->name, "boot") || !strcmp(ptn->name, "recovery")) { + if (memcmp((void *)data, BOOT_MAGIC, BOOT_MAGIC_SIZE)) { + fastboot_fail(phandle, "image is not a boot image"); + return; + } + } + + if (!strcmp(ptn->name, "system") || !strcmp(ptn->name, "userdata")) + extra = 64; + else + sz = ROUND_TO_PAGE(sz); + + D(INFO, "writing %d bytes to '%s'\n", sz, ptn->name); + if (flash_write(ptn, extra, data, sz)) { + fastboot_fail(phandle, "flash write failure"); + return; + } + D(INFO, "partition '%s' updated\n", ptn->name); +#endif + fastboot_okay(phandle, ""); +} + +static void cmd_continue(struct protocol_handle *phandle, const char *arg) +{ + fastboot_okay(phandle, ""); +#if 0 + udc_stop(); + + boot_linux_from_flash(); +#endif +} + +static void cmd_getvar(struct protocol_handle *phandle, const char *arg) +{ + const char *value; + D(DEBUG, "cmd_getvar %s\n", arg); + + value = fastboot_getvar(arg); + + fastboot_okay(phandle, value); +} + +static void cmd_download(struct protocol_handle *phandle, const char *arg) +{ + unsigned len = strtoul(arg, NULL, 16); + int old_fd; + + if (len > 256 * 1024 * 1024) { + fastboot_fail(phandle, "data too large"); + return; + } + + fastboot_data(phandle, len); + + old_fd = protocol_get_download(phandle); + if (old_fd >= 0) { + off_t len = lseek(old_fd, 0, SEEK_END); + D(INFO, "disposing of unused fd %d, size %ld", old_fd, len); + close(old_fd); + } + + phandle->download_fd = protocol_handle_download(phandle, len); + if (phandle->download_fd < 0) { + //handle->state = STATE_ERROR; + fastboot_fail(phandle, "download failed"); + return; + } + + fastboot_okay(phandle, ""); +} + +void commands_init() +{ + fastboot_register("boot", cmd_boot); + fastboot_register("erase:", cmd_erase); + fastboot_register("flash:", cmd_flash); + fastboot_register("continue", cmd_continue); + fastboot_register("getvar:", cmd_getvar); + fastboot_register("download:", cmd_download); + //fastboot_publish("version", "0.5"); + //fastboot_publish("product", "swordfish"); + //fastboot_publish("kernel", "lk"); +} diff --git a/fastbootd/config.c b/fastbootd/config.c new file mode 100644 index 0000000..b8503fd --- /dev/null +++ b/fastbootd/config.c @@ -0,0 +1,161 @@ +/* + * Copyright (c) 2013, Google Inc. + * 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 <fcntl.h> +#include <string.h> +#include <unistd.h> +#include <sys/types.h> + +#include "protocol.h" + +#include "debug.h" + +// TODO: change config path +#define CONFIG_PATH "/data/fastboot.cfg" + +static char *strip(char *str) +{ + int n; + + n = strspn(str, " \t"); + str += n; + + for (n = strlen(str) - 1; n >= 0; n--) { + if (str[n] == ' ' || str[n] == '\t') + str[n] = '\0'; + else + break; + } + + return str; +} + +static int config_parse_line(char *line) +{ + char *c; + char *key; + char *value; + + c = strchr(line, '#'); + if (c) + *c = '\0'; + + if (strspn(line, " \t") == strlen(line)) + return 0; + + c = strchr(line, '='); + if (c == NULL) + return -1; + + key = line; + *c = '\0'; + value = c + 1; + + key = strip(key); + value = strip(value); + + key = strdup(key); + value = strdup(value); + + fastboot_publish(key, value); + + return 0; +} + +static void config_parse(char *buffer) +{ + char *saveptr; + char *str = buffer; + char *line = buffer; + int c; + int ret; + + for (c = 1; line != NULL; c++) { + line = strtok_r(str, "\r\n", &saveptr); + if (line != NULL) { + D(VERBOSE, "'%s'", line); + ret = config_parse_line(line); + if (ret < 0) { + D(WARN, "error parsing " CONFIG_PATH " line %d", c); + } + } + str = NULL; + } +} + +void config_init() +{ + int fd; + off_t len; + ssize_t ret; + size_t count = 0; + char *buffer; + + fd = open(CONFIG_PATH, O_RDONLY); + if (fd < 0) { + D(ERR, "failed to open " CONFIG_PATH); + return; + } + + len = lseek(fd, 0, SEEK_END); + if (len < 0) { + D(ERR, "failed to seek to end of " CONFIG_PATH); + return; + } + + lseek(fd, 0, SEEK_SET); + + buffer = malloc(len + 1); + if (buffer == NULL) { + D(ERR, "failed to allocate %ld bytes", len); + return; + } + + while (count < (size_t)len) { + ret = read(fd, buffer + count, len - count); + if (ret < 0 && errno != EINTR) { + D(ERR, "failed to read " CONFIG_PATH ": %d %s", errno, strerror(errno)); + return; + } + if (ret == 0) { + D(ERR, "early EOF reading " CONFIG_PATH); + return; + } + + count += ret; + } + + buffer[len] = '\0'; + + config_parse(buffer); + + free(buffer); +} diff --git a/fastbootd/debug.h b/fastbootd/debug.h new file mode 100644 index 0000000..74620b8 --- /dev/null +++ b/fastbootd/debug.h @@ -0,0 +1,42 @@ +/* + * Copyright (C) 2013 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef _FASTBOOTD_DEBUG_H_ +#define _FASTBOOTD_DEBUG_H_ + +#include <stdio.h> + +#include <cutils/klog.h> + +#define ERR 0 +#define WARN 1 +#define INFO 2 +#define VERBOSE 3 +#define DEBUG 4 + +extern unsigned int debug_level; + +//#define DLOG(fmt, ...) printf(fmt, ##__VA_ARGS__) +#define DLOG(fmt, ...) KLOG_INFO("fastbootd", fmt, ##__VA_ARGS__) + +#define D(level, fmt, ...) \ + do { \ + if (debug_level == level || debug_level > level) { \ + DLOG("%s:%d " fmt "\n", __BASE_FILE__, __LINE__, ##__VA_ARGS__); \ + } \ + } while (0) + +#endif diff --git a/fastbootd/fastbootd.c b/fastbootd/fastbootd.c new file mode 100644 index 0000000..98df0db --- /dev/null +++ b/fastbootd/fastbootd.c @@ -0,0 +1,45 @@ +/* + * Copyright (C) 2013 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include <stdio.h> +#include <unistd.h> + +#include <cutils/klog.h> + +#include "debug.h" + +unsigned int debug_level = DEBUG; + +void commands_init(); +void usb_init(); +void config_init(); + +int main(int argc, char **argv) +{ + (void)argc; + (void)argv; + + klog_init(); + klog_set_level(6); + + config_init(); + commands_init(); + usb_init(); + while (1) { + sleep(1); + } + return 0; +} diff --git a/fastbootd/protocol.c b/fastbootd/protocol.c new file mode 100644 index 0000000..0086b4a --- /dev/null +++ b/fastbootd/protocol.c @@ -0,0 +1,195 @@ +/* + * Copyright (c) 2009-2013, Google Inc. + * 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 <stddef.h> +#include <stdio.h> +#include <stdlib.h> +#include <string.h> + +#include "debug.h" +#include "protocol.h" +#include "transport.h" + +#define STATE_OFFLINE 0 +#define STATE_COMMAND 1 +#define STATE_COMPLETE 2 +#define STATE_ERROR 3 + +struct fastboot_cmd { + struct fastboot_cmd *next; + const char *prefix; + unsigned prefix_len; + void (*execute)(struct protocol_handle *phandle, const char *arg); +}; + +struct fastboot_var { + struct fastboot_var *next; + const char *name; + const char *value; +}; + +static struct fastboot_cmd *cmdlist; + +void fastboot_register(const char *prefix, + void (*phandle)(struct protocol_handle *phandle, const char *arg)) +{ + struct fastboot_cmd *cmd; + cmd = malloc(sizeof(*cmd)); + if (cmd) { + cmd->prefix = prefix; + cmd->prefix_len = strlen(prefix); + cmd->execute = phandle; + cmd->next = cmdlist; + cmdlist = cmd; + } +} + +static struct fastboot_var *varlist; + +void fastboot_publish(const char *name, const char *value) +{ + struct fastboot_var *var; + var = malloc(sizeof(*var)); + if (var) { + var->name = name; + var->value = value; + var->next = varlist; + varlist = var; + } +} + +const char *fastboot_getvar(const char *name) +{ + struct fastboot_var *var; + + for (var = varlist; var; var = var->next) { + if (!strcmp(var->name, name)) { + return var->value; + } + } + + return ""; +} + +int protocol_handle_download(struct protocol_handle *phandle, size_t len) +{ + return transport_handle_download(phandle->transport_handle, len); +} + +static ssize_t protocol_handle_write(struct protocol_handle *phandle, + char *buffer, size_t len) +{ + return transport_handle_write(phandle->transport_handle, buffer, len); +} + +static void fastboot_ack(struct protocol_handle *phandle, const char *code, + const char *reason) +{ + char response[64]; + + if (phandle->state != STATE_COMMAND) + return; + + if (reason == 0) + reason = ""; + + snprintf(response, 64, "%s%s", code, reason); + phandle->state = STATE_COMPLETE; + + protocol_handle_write(phandle, response, strlen(response)); +} + +void fastboot_fail(struct protocol_handle *phandle, const char *reason) +{ + fastboot_ack(phandle, "FAIL", reason); +} + +void fastboot_okay(struct protocol_handle *phandle, const char *info) +{ + fastboot_ack(phandle, "OKAY", info); +} + +void fastboot_data(struct protocol_handle *phandle, size_t len) +{ + char response[64]; + ssize_t ret; + + snprintf(response, 64, "DATA%08x", len); + ret = protocol_handle_write(phandle, response, strlen(response)); + if (ret < 0) + return; +} + +void protocol_handle_command(struct protocol_handle *phandle, char *buffer) +{ + D(INFO,"fastboot: %s\n", buffer); + + struct fastboot_cmd *cmd; + + for (cmd = cmdlist; cmd; cmd = cmd->next) { + if (memcmp(buffer, cmd->prefix, cmd->prefix_len)) + continue; + phandle->state = STATE_COMMAND; + cmd->execute(phandle, buffer + cmd->prefix_len); + if (phandle->state == STATE_COMMAND) + fastboot_fail(phandle, "unknown reason"); + return; + } + + fastboot_fail(phandle, "unknown command"); +} + +struct protocol_handle *create_protocol_handle(struct transport_handle *thandle) +{ + struct protocol_handle *phandle; + + phandle = calloc(sizeof(struct protocol_handle), 1); + + phandle->transport_handle = thandle; + phandle->state = STATE_OFFLINE; + phandle->download_fd = -1; + + pthread_mutex_init(&phandle->lock, NULL); + + return phandle; +} + +int protocol_get_download(struct protocol_handle *phandle) +{ + int fd; + + pthread_mutex_lock(&phandle->lock); + fd = phandle->download_fd; + phandle->download_fd = -1; + pthread_mutex_unlock(&phandle->lock); + + return fd; +} diff --git a/fastbootd/protocol.h b/fastbootd/protocol.h new file mode 100644 index 0000000..ea2a8df --- /dev/null +++ b/fastbootd/protocol.h @@ -0,0 +1,61 @@ +/* + * Copyright (c) 2013, Google Inc. + * 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. + */ + +#ifndef _FASTBOOTD_PROTOCOL_H_ +#define _FASTBOOTD_PROTOCOL_H_ + +#include <pthread.h> +#include <stddef.h> + +struct protocol_handle { + struct transport_handle *transport_handle; + unsigned int state; + int download_fd; + + pthread_mutex_t lock; +}; + +void fastboot_register(const char *prefix, + void (*handle)(struct protocol_handle *handle, const char *arg)); + +void fastboot_publish(const char *name, const char *value); +const char *fastboot_getvar(const char *name); + +struct protocol_handle *create_protocol_handle(struct transport_handle *t); +void protocol_handle_command(struct protocol_handle *handle, char *buffer); +int protocol_handle_download(struct protocol_handle *phandle, size_t len); +int protocol_get_download(struct protocol_handle *phandle); + +void fastboot_fail(struct protocol_handle *handle, const char *reason); +void fastboot_okay(struct protocol_handle *handle, const char *reason); +void fastboot_data(struct protocol_handle *handle, size_t len); + +#endif diff --git a/fastbootd/transport.c b/fastbootd/transport.c new file mode 100644 index 0000000..01a5a8a --- /dev/null +++ b/fastbootd/transport.c @@ -0,0 +1,149 @@ +/* + * Copyright (C) 2013 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include <pthread.h> +#include <stddef.h> +#include <stdio.h> +#include <stdlib.h> +#include <unistd.h> +#include <sys/mman.h> + +#include "debug.h" +#include "protocol.h" +#include "transport.h" + +#define COMMAND_BUF_SIZE 64 + +ssize_t transport_handle_write(struct transport_handle *thandle, char *buffer, size_t len) +{ + return thandle->transport->write(thandle, buffer, len); +} + +void transport_handle_close(struct transport_handle *thandle) +{ + thandle->transport->close(thandle); +} + +int transport_handle_download(struct transport_handle *thandle, size_t len) +{ + ssize_t ret; + size_t n = 0; + int fd; + // TODO: move out of /dev + char tempname[] = "/dev/fastboot_download_XXXXXX"; + char *buffer; + + fd = mkstemp(tempname); + if (fd < 0) + return -1; + + unlink(tempname); + + ftruncate(fd, len); + + buffer = mmap(NULL, len, PROT_READ | PROT_WRITE, MAP_SHARED, fd, 0); + if (buffer == NULL) { + D(ERR, "mmap(%u) failed: %d %s", len, errno, strerror(errno)); + goto err; + } + + while (n < len) { + ret = thandle->transport->read(thandle, buffer + n, len - n); + if (ret <= 0) { + D(WARN, "transport read failed, ret=%d %s", ret, strerror(-ret)); + break; + } + n += ret; + } + + munmap(buffer, len); + + if (n != len) + goto err; + + return fd; + +err: + close(fd); + transport_handle_close(thandle); + return -1; +} + +static void *transport_data_thread(void *arg) +{ + struct transport_handle *thandle = arg; + struct protocol_handle *phandle = create_protocol_handle(thandle); + + while (!thandle->stopped) { + int ret; + char buffer[COMMAND_BUF_SIZE + 1]; + D(VERBOSE, "transport_data_thread\n"); + + ret = thandle->transport->read(thandle, buffer, COMMAND_BUF_SIZE); + if (ret <= 0) { + D(DEBUG, "ret = %d\n", ret); + break; + } + if (ret > 0) { + buffer[ret] = 0; + protocol_handle_command(phandle, buffer); + } + } + + transport_handle_close(thandle); + free(thandle); + + return NULL; +} + +static void *transport_connect_thread(void *arg) +{ + struct transport *transport = arg; + while (!transport->stopped) { + struct transport_handle *thandle; + pthread_t thread; + pthread_attr_t attr; + + D(VERBOSE, "transport_connect_thread\n"); + thandle = transport->connect(transport); + if (thandle == NULL) { + D(ERR, "transport connect failed\n"); + sleep(1); + continue; + } + thandle->transport = transport; + + pthread_attr_init(&attr); + pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED); + + pthread_create(&thread, &attr, transport_data_thread, thandle); + + sleep(1); + } + + return NULL; +} + +void transport_register(struct transport *transport) +{ + pthread_t thread; + pthread_attr_t attr; + + pthread_attr_init(&attr); + pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED); + + pthread_create(&thread, &attr, transport_connect_thread, transport); +} diff --git a/fastbootd/transport.h b/fastbootd/transport.h new file mode 100644 index 0000000..209340d --- /dev/null +++ b/fastbootd/transport.h @@ -0,0 +1,41 @@ +/* + * Copyright (C) 2013 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef _FASTBOOTD_TRANSPORT_H_ +#define _FASTBOOTD_TRANSPORT_H_ + +#include <stdbool.h> + +struct transport_handle { + struct transport *transport; + + bool stopped; +}; + +struct transport { + void (*init)(); + void (*close)(struct transport_handle *thandle); + ssize_t (*read)(struct transport_handle *thandle, void *data, size_t len); + ssize_t (*write)(struct transport_handle *thandle, const void *data, size_t len); + struct transport_handle *(*connect)(struct transport *transport); + bool stopped; +}; + +void transport_register(struct transport *transport); +ssize_t transport_handle_write(struct transport_handle *handle, char *buffer, size_t len); +int transport_handle_download(struct transport_handle *handle, size_t len); + +#endif diff --git a/fastbootd/usb_linux_client.c b/fastbootd/usb_linux_client.c new file mode 100644 index 0000000..111cf35 --- /dev/null +++ b/fastbootd/usb_linux_client.c @@ -0,0 +1,353 @@ +/* + * Copyright (C) 2007 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include <endian.h> +#include <fcntl.h> +#include <pthread.h> +#include <stdio.h> +#include <stdlib.h> +#include <string.h> +#include <unistd.h> + +#include <sys/ioctl.h> +#include <sys/types.h> + +#include <linux/usb/ch9.h> +#include <linux/usb/functionfs.h> + +#include "debug.h" +#include "transport.h" + +#define TRACE_TAG TRACE_USB + +#define MAX_PACKET_SIZE_FS 64 +#define MAX_PACKET_SIZE_HS 512 + +#define cpu_to_le16(x) htole16(x) +#define cpu_to_le32(x) htole32(x) + +#define FASTBOOT_CLASS 0xff +#define FASTBOOT_SUBCLASS 0x42 +#define FASTBOOT_PROTOCOL 0x3 + +#define USB_FFS_FASTBOOT_PATH "/dev/usb-ffs/adb/" +#define USB_FFS_FASTBOOT_EP(x) USB_FFS_FASTBOOT_PATH#x + +#define USB_FFS_FASTBOOT_EP0 USB_FFS_FASTBOOT_EP(ep0) +#define USB_FFS_FASTBOOT_OUT USB_FFS_FASTBOOT_EP(ep1) +#define USB_FFS_FASTBOOT_IN USB_FFS_FASTBOOT_EP(ep2) + +#define READ_BUF_SIZE (16*1024) + +#define container_of(ptr, type, member) \ + ((type*)((char*)(ptr) - offsetof(type, member))) + +struct usb_transport { + struct transport transport; + + pthread_cond_t notify; + pthread_mutex_t lock; + + int control; + int bulk_out; /* "out" from the host's perspective => source for fastbootd */ + int bulk_in; /* "in" from the host's perspective => sink for fastbootd */ +}; + +struct usb_handle { + struct transport_handle handle; +}; + +static const struct { + struct usb_functionfs_descs_head header; + struct { + struct usb_interface_descriptor intf; + struct usb_endpoint_descriptor_no_audio source; + struct usb_endpoint_descriptor_no_audio sink; + } __attribute__((packed)) fs_descs, hs_descs; +} __attribute__((packed)) descriptors = { + .header = { + .magic = cpu_to_le32(FUNCTIONFS_DESCRIPTORS_MAGIC), + .length = cpu_to_le32(sizeof(descriptors)), + .fs_count = 3, + .hs_count = 3, + }, + .fs_descs = { + .intf = { + .bLength = sizeof(descriptors.fs_descs.intf), + .bDescriptorType = USB_DT_INTERFACE, + .bInterfaceNumber = 0, + .bNumEndpoints = 2, + .bInterfaceClass = FASTBOOT_CLASS, + .bInterfaceSubClass = FASTBOOT_SUBCLASS, + .bInterfaceProtocol = FASTBOOT_PROTOCOL, + .iInterface = 1, /* first string from the provided table */ + }, + .source = { + .bLength = sizeof(descriptors.fs_descs.source), + .bDescriptorType = USB_DT_ENDPOINT, + .bEndpointAddress = 1 | USB_DIR_OUT, + .bmAttributes = USB_ENDPOINT_XFER_BULK, + .wMaxPacketSize = MAX_PACKET_SIZE_FS, + }, + .sink = { + .bLength = sizeof(descriptors.fs_descs.sink), + .bDescriptorType = USB_DT_ENDPOINT, + .bEndpointAddress = 2 | USB_DIR_IN, + .bmAttributes = USB_ENDPOINT_XFER_BULK, + .wMaxPacketSize = MAX_PACKET_SIZE_FS, + }, + }, + .hs_descs = { + .intf = { + .bLength = sizeof(descriptors.hs_descs.intf), + .bDescriptorType = USB_DT_INTERFACE, + .bInterfaceNumber = 0, + .bNumEndpoints = 2, + .bInterfaceClass = FASTBOOT_CLASS, + .bInterfaceSubClass = FASTBOOT_SUBCLASS, + .bInterfaceProtocol = FASTBOOT_PROTOCOL, + .iInterface = 1, /* first string from the provided table */ + }, + .source = { + .bLength = sizeof(descriptors.hs_descs.source), + .bDescriptorType = USB_DT_ENDPOINT, + .bEndpointAddress = 1 | USB_DIR_OUT, + .bmAttributes = USB_ENDPOINT_XFER_BULK, + .wMaxPacketSize = MAX_PACKET_SIZE_HS, + }, + .sink = { + .bLength = sizeof(descriptors.hs_descs.sink), + .bDescriptorType = USB_DT_ENDPOINT, + .bEndpointAddress = 2 | USB_DIR_IN, + .bmAttributes = USB_ENDPOINT_XFER_BULK, + .wMaxPacketSize = MAX_PACKET_SIZE_HS, + }, + }, +}; + +#define STR_INTERFACE_ "Fastboot Interface" + +static const struct { + struct usb_functionfs_strings_head header; + struct { + __le16 code; + const char str1[sizeof(STR_INTERFACE_)]; + } __attribute__((packed)) lang0; +} __attribute__((packed)) strings = { + .header = { + .magic = cpu_to_le32(FUNCTIONFS_STRINGS_MAGIC), + .length = cpu_to_le32(sizeof(strings)), + .str_count = cpu_to_le32(1), + .lang_count = cpu_to_le32(1), + }, + .lang0 = { + cpu_to_le16(0x0409), /* en-us */ + STR_INTERFACE_, + }, +}; + +static int init_functionfs(struct usb_transport *usb_transport) +{ + ssize_t ret; + + D(VERBOSE, "OPENING %s", USB_FFS_FASTBOOT_EP0); + usb_transport->control = open(USB_FFS_FASTBOOT_EP0, O_RDWR); + if (usb_transport->control < 0) { + D(ERR, "[ %s: cannot open control endpoint: errno=%d]", USB_FFS_FASTBOOT_EP0, errno); + goto err; + } + + ret = write(usb_transport->control, &descriptors, sizeof(descriptors)); + if (ret < 0) { + D(ERR, "[ %s: write descriptors failed: errno=%d ]", USB_FFS_FASTBOOT_EP0, errno); + goto err; + } + + ret = write(usb_transport->control, &strings, sizeof(strings)); + if (ret < 0) { + D(ERR, "[ %s: writing strings failed: errno=%d]", USB_FFS_FASTBOOT_EP0, errno); + goto err; + } + + usb_transport->bulk_out = open(USB_FFS_FASTBOOT_OUT, O_RDWR); + if (usb_transport->bulk_out < 0) { + D(ERR, "[ %s: cannot open bulk-out ep: errno=%d ]", USB_FFS_FASTBOOT_OUT, errno); + goto err; + } + + usb_transport->bulk_in = open(USB_FFS_FASTBOOT_IN, O_RDWR); + if (usb_transport->bulk_in < 0) { + D(ERR, "[ %s: cannot open bulk-in ep: errno=%d ]", USB_FFS_FASTBOOT_IN, errno); + goto err; + } + + return 0; + +err: + if (usb_transport->bulk_in > 0) { + close(usb_transport->bulk_in); + usb_transport->bulk_in = -1; + } + if (usb_transport->bulk_out > 0) { + close(usb_transport->bulk_out); + usb_transport->bulk_out = -1; + } + if (usb_transport->control > 0) { + close(usb_transport->control); + usb_transport->control = -1; + } + return -1; +} + +static ssize_t bulk_write(int bulk_in, const char *buf, size_t length) +{ + size_t count = 0; + ssize_t ret; + + do { + ret = TEMP_FAILURE_RETRY(write(bulk_in, buf + count, length - count)); + if (ret < 0) { + D(WARN, "[ bulk_read failed fd=%d length=%d errno=%d %s ]", + bulk_in, length, errno, strerror(errno)); + return -1; + } else { + count += ret; + } + } while (count < length); + + D(VERBOSE, "[ bulk_write done fd=%d ]", bulk_in); + return count; +} + +static ssize_t usb_write(struct transport_handle *thandle, const void *data, size_t len) +{ + ssize_t ret; + struct transport *t = thandle->transport; + struct usb_transport *usb_transport = container_of(t, struct usb_transport, transport); + + D(DEBUG, "about to write (fd=%d, len=%d)", usb_transport->bulk_in, len); + ret = bulk_write(usb_transport->bulk_in, data, len); + if (ret < 0) { + D(ERR, "ERROR: fd = %d, ret = %zd", usb_transport->bulk_in, ret); + return -1; + } + D(DEBUG, "[ usb_write done fd=%d ]", usb_transport->bulk_in); + return ret; +} + +static ssize_t bulk_read(int bulk_out, char *buf, size_t length) +{ + ssize_t ret; + size_t n = 0; + + while (n < length) { + size_t to_read = (length - n > READ_BUF_SIZE) ? READ_BUF_SIZE : length - n; + ret = TEMP_FAILURE_RETRY(read(bulk_out, buf + n, to_read)); + if (ret < 0) { + D(WARN, "[ bulk_read failed fd=%d length=%d errno=%d %s ]", + bulk_out, length, errno, strerror(errno)); + return ret; + } + n += ret; + if (ret < (ssize_t)to_read) { + D(VERBOSE, "bulk_read short read, ret=%zd to_read=%u n=%u length=%u", + ret, to_read, n, length); + break; + } + } + + return n; +} + +ssize_t usb_read(struct transport_handle *thandle, void *data, size_t len) +{ + ssize_t ret; + struct transport *t = thandle->transport; + struct usb_transport *usb_transport = container_of(t, struct usb_transport, transport); + + D(DEBUG, "about to read (fd=%d, len=%d)", usb_transport->bulk_out, len); + ret = bulk_read(usb_transport->bulk_out, data, len); + if (ret < 0) { + D(ERR, "ERROR: fd = %d, ret = %zd", usb_transport->bulk_out, ret); + return -1; + } + D(DEBUG, "[ usb_read done fd=%d ret=%zd]", usb_transport->bulk_out, ret); + return ret; +} + +void usb_close(struct transport_handle *thandle) +{ + int err; + struct transport *t = thandle->transport; + struct usb_transport *usb_transport = container_of(t, struct usb_transport, transport); + + err = ioctl(usb_transport->bulk_in, FUNCTIONFS_CLEAR_HALT); + if (err < 0) + D(WARN, "[ kick: source (fd=%d) clear halt failed (%d) ]", usb_transport->bulk_in, errno); + + err = ioctl(usb_transport->bulk_out, FUNCTIONFS_CLEAR_HALT); + if (err < 0) + D(WARN, "[ kick: sink (fd=%d) clear halt failed (%d) ]", usb_transport->bulk_out, errno); + + pthread_mutex_lock(&usb_transport->lock); + close(usb_transport->control); + close(usb_transport->bulk_out); + close(usb_transport->bulk_in); + usb_transport->control = usb_transport->bulk_out = usb_transport->bulk_in = -1; + + pthread_cond_signal(&usb_transport->notify); + pthread_mutex_unlock(&usb_transport->lock); +} + +struct transport_handle *usb_connect(struct transport *transport) +{ + int ret; + struct usb_handle *usb_handle = calloc(sizeof(struct usb_handle), 1); + struct usb_transport *usb_transport = container_of(transport, struct usb_transport, transport); + + pthread_mutex_lock(&usb_transport->lock); + while (usb_transport->control != -1) + pthread_cond_wait(&usb_transport->notify, &usb_transport->lock); + pthread_mutex_unlock(&usb_transport->lock); + + ret = init_functionfs(usb_transport); + if (ret < 0) { + D(ERR, "usb connect: failed to initialize usb transport"); + return NULL; + } + + D(DEBUG, "[ usb_thread - registering device ]"); + return &usb_handle->handle; +} + +void usb_init() +{ + struct usb_transport *usb_transport = calloc(1, sizeof(struct usb_transport)); + + usb_transport->transport.connect = usb_connect; + usb_transport->transport.close = usb_close; + usb_transport->transport.read = usb_read; + usb_transport->transport.write = usb_write; + usb_transport->control = -1; + usb_transport->bulk_out = -1; + usb_transport->bulk_out = -1; + + pthread_cond_init(&usb_transport->notify, NULL); + pthread_mutex_init(&usb_transport->lock, NULL); + + transport_register(&usb_transport->transport); +} + diff --git a/healthd/Android.mk b/healthd/Android.mk new file mode 100644 index 0000000..910afb2 --- /dev/null +++ b/healthd/Android.mk @@ -0,0 +1,23 @@ +# Copyright 2013 The Android Open Source Project + +ifneq ($(BUILD_TINY_ANDROID),true) + +LOCAL_PATH := $(call my-dir) +include $(CLEAR_VARS) + +LOCAL_SRC_FILES := \ + healthd.cpp \ + BatteryMonitor.cpp \ + BatteryPropertiesRegistrar.cpp + +LOCAL_MODULE := healthd +LOCAL_MODULE_TAGS := optional +LOCAL_FORCE_STATIC_EXECUTABLE := true +LOCAL_MODULE_PATH := $(TARGET_ROOT_OUT_SBIN) +LOCAL_UNSTRIPPED_PATH := $(TARGET_ROOT_OUT_SBIN_UNSTRIPPED) + +LOCAL_STATIC_LIBRARIES := libbatteryservice libbinder libz libutils libstdc++ libcutils liblog libm libc + +include $(BUILD_EXECUTABLE) + +endif diff --git a/healthd/BatteryMonitor.cpp b/healthd/BatteryMonitor.cpp new file mode 100644 index 0000000..22f7713 --- /dev/null +++ b/healthd/BatteryMonitor.cpp @@ -0,0 +1,354 @@ +/* + * Copyright (C) 2013 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#define LOG_TAG "healthd" + +#include "BatteryMonitor.h" +#include "BatteryPropertiesRegistrar.h" + +#include <dirent.h> +#include <errno.h> +#include <fcntl.h> +#include <stdio.h> +#include <stdlib.h> +#include <unistd.h> +#include <batteryservice/BatteryService.h> +#include <cutils/klog.h> +#include <utils/String8.h> +#include <utils/Vector.h> + +#define POWER_SUPPLY_SUBSYSTEM "power_supply" +#define POWER_SUPPLY_SYSFS_PATH "/sys/class/" POWER_SUPPLY_SUBSYSTEM + +namespace android { + +struct sysfsStringEnumMap { + char* s; + int val; +}; + +static int mapSysfsString(const char* str, + struct sysfsStringEnumMap map[]) { + for (int i = 0; map[i].s; i++) + if (!strcmp(str, map[i].s)) + return map[i].val; + + return -1; +} + +int BatteryMonitor::getBatteryStatus(const char* status) { + int ret; + struct sysfsStringEnumMap batteryStatusMap[] = { + { "Unknown", BATTERY_STATUS_UNKNOWN }, + { "Charging", BATTERY_STATUS_CHARGING }, + { "Discharging", BATTERY_STATUS_DISCHARGING }, + { "Not charging", BATTERY_STATUS_NOT_CHARGING }, + { "Full", BATTERY_STATUS_FULL }, + { NULL, 0 }, + }; + + ret = mapSysfsString(status, batteryStatusMap); + if (ret < 0) { + KLOG_WARNING(LOG_TAG, "Unknown battery status '%s'\n", status); + ret = BATTERY_STATUS_UNKNOWN; + } + + return ret; +} + +int BatteryMonitor::getBatteryHealth(const char* status) { + int ret; + struct sysfsStringEnumMap batteryHealthMap[] = { + { "Unknown", BATTERY_HEALTH_UNKNOWN }, + { "Good", BATTERY_HEALTH_GOOD }, + { "Overheat", BATTERY_HEALTH_OVERHEAT }, + { "Dead", BATTERY_HEALTH_DEAD }, + { "Over voltage", BATTERY_HEALTH_OVER_VOLTAGE }, + { "Unspecified failure", BATTERY_HEALTH_UNSPECIFIED_FAILURE }, + { "Cold", BATTERY_HEALTH_COLD }, + { NULL, 0 }, + }; + + ret = mapSysfsString(status, batteryHealthMap); + if (ret < 0) { + KLOG_WARNING(LOG_TAG, "Unknown battery health '%s'\n", status); + ret = BATTERY_HEALTH_UNKNOWN; + } + + return ret; +} + +int BatteryMonitor::readFromFile(const String8& path, char* buf, size_t size) { + char *cp = NULL; + + if (path.isEmpty()) + return -1; + int fd = open(path.string(), O_RDONLY, 0); + if (fd == -1) { + KLOG_ERROR(LOG_TAG, "Could not open '%s'\n", path.string()); + return -1; + } + + ssize_t count = TEMP_FAILURE_RETRY(read(fd, buf, size)); + if (count > 0) + cp = (char *)memrchr(buf, '\n', count); + + if (cp) + *cp = '\0'; + else + buf[0] = '\0'; + + close(fd); + return count; +} + +BatteryMonitor::PowerSupplyType BatteryMonitor::readPowerSupplyType(const String8& path) { + const int SIZE = 128; + char buf[SIZE]; + int length = readFromFile(path, buf, SIZE); + BatteryMonitor::PowerSupplyType ret; + struct sysfsStringEnumMap supplyTypeMap[] = { + { "Unknown", ANDROID_POWER_SUPPLY_TYPE_UNKNOWN }, + { "Battery", ANDROID_POWER_SUPPLY_TYPE_BATTERY }, + { "UPS", ANDROID_POWER_SUPPLY_TYPE_AC }, + { "Mains", ANDROID_POWER_SUPPLY_TYPE_AC }, + { "USB", ANDROID_POWER_SUPPLY_TYPE_USB }, + { "USB_DCP", ANDROID_POWER_SUPPLY_TYPE_AC }, + { "USB_CDP", ANDROID_POWER_SUPPLY_TYPE_AC }, + { "USB_ACA", ANDROID_POWER_SUPPLY_TYPE_AC }, + { "Wireless", ANDROID_POWER_SUPPLY_TYPE_WIRELESS }, + { NULL, 0 }, + }; + + if (length <= 0) + return ANDROID_POWER_SUPPLY_TYPE_UNKNOWN; + + ret = (BatteryMonitor::PowerSupplyType)mapSysfsString(buf, supplyTypeMap); + if (ret < 0) + ret = ANDROID_POWER_SUPPLY_TYPE_UNKNOWN; + + return ret; +} + +bool BatteryMonitor::getBooleanField(const String8& path) { + const int SIZE = 16; + char buf[SIZE]; + + bool value = false; + if (readFromFile(path, buf, SIZE) > 0) { + if (buf[0] != '0') { + value = true; + } + } + + return value; +} + +int BatteryMonitor::getIntField(const String8& path) { + const int SIZE = 128; + char buf[SIZE]; + + int value = 0; + if (readFromFile(path, buf, SIZE) > 0) { + value = strtol(buf, NULL, 0); + } + return value; +} + +bool BatteryMonitor::update(void) { + struct BatteryProperties props; + + props.chargerAcOnline = false; + props.chargerUsbOnline = false; + props.chargerWirelessOnline = false; + props.batteryStatus = BATTERY_STATUS_UNKNOWN; + props.batteryHealth = BATTERY_HEALTH_UNKNOWN; + + if (!mBatteryPresentPath.isEmpty()) + props.batteryPresent = getBooleanField(mBatteryPresentPath); + else + props.batteryPresent = true; + + props.batteryLevel = getIntField(mBatteryCapacityPath); + props.batteryVoltage = getIntField(mBatteryVoltagePath) / 1000; + props.batteryTemperature = getIntField(mBatteryTemperaturePath); + + const int SIZE = 128; + char buf[SIZE]; + String8 btech; + + if (readFromFile(mBatteryStatusPath, buf, SIZE) > 0) + props.batteryStatus = getBatteryStatus(buf); + + if (readFromFile(mBatteryHealthPath, buf, SIZE) > 0) + props.batteryHealth = getBatteryHealth(buf); + + if (readFromFile(mBatteryTechnologyPath, buf, SIZE) > 0) + props.batteryTechnology = String8(buf); + + unsigned int i; + + for (i = 0; i < mChargerNames.size(); i++) { + String8 path; + path.appendFormat("%s/%s/online", POWER_SUPPLY_SYSFS_PATH, + mChargerNames[i].string()); + + 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()); + } + } + } + } + + KLOG_INFO(LOG_TAG, "battery l=%d v=%d t=%s%d.%d h=%d st=%d chg=%s%s%s\n", + props.batteryLevel, props.batteryVoltage, + props.batteryTemperature < 0 ? "-" : "", + abs(props.batteryTemperature / 10), + abs(props.batteryTemperature % 10), props.batteryHealth, + props.batteryStatus, + props.chargerAcOnline ? "a" : "", + props.chargerUsbOnline ? "u" : "", + props.chargerWirelessOnline ? "w" : ""); + + if (mBatteryPropertiesRegistrar != NULL) + mBatteryPropertiesRegistrar->notifyListeners(props); + + return props.chargerAcOnline | props.chargerUsbOnline | + props.chargerWirelessOnline; +} + +void BatteryMonitor::init(bool nosvcmgr) { + 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; + + while ((entry = readdir(dir))) { + const char* name = entry->d_name; + + if (!strcmp(name, ".") || !strcmp(name, "..")) + continue; + + char buf[20]; + // 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_AC: + case ANDROID_POWER_SUPPLY_TYPE_USB: + case ANDROID_POWER_SUPPLY_TYPE_WIRELESS: + path.clear(); + path.appendFormat("%s/%s/online", POWER_SUPPLY_SYSFS_PATH, name); + if (access(path.string(), R_OK) == 0) + mChargerNames.add(String8(name)); + break; + + case ANDROID_POWER_SUPPLY_TYPE_BATTERY: + path.clear(); + path.appendFormat("%s/%s/status", POWER_SUPPLY_SYSFS_PATH, name); + if (access(path, R_OK) == 0) + mBatteryStatusPath = path; + path.clear(); + path.appendFormat("%s/%s/health", POWER_SUPPLY_SYSFS_PATH, name); + if (access(path, R_OK) == 0) + mBatteryHealthPath = path; + path.clear(); + path.appendFormat("%s/%s/present", POWER_SUPPLY_SYSFS_PATH, name); + if (access(path, R_OK) == 0) + mBatteryPresentPath = path; + path.clear(); + path.appendFormat("%s/%s/capacity", POWER_SUPPLY_SYSFS_PATH, name); + if (access(path, R_OK) == 0) + mBatteryCapacityPath = path; + + path.clear(); + path.appendFormat("%s/%s/voltage_now", POWER_SUPPLY_SYSFS_PATH, name); + if (access(path, R_OK) == 0) { + mBatteryVoltagePath = path; + } else { + path.clear(); + path.appendFormat("%s/%s/batt_vol", POWER_SUPPLY_SYSFS_PATH, name); + if (access(path, R_OK) == 0) + mBatteryVoltagePath = path; + } + + path.clear(); + path.appendFormat("%s/%s/temp", POWER_SUPPLY_SYSFS_PATH, name); + if (access(path, R_OK) == 0) { + mBatteryTemperaturePath = path; + } else { + path.clear(); + path.appendFormat("%s/%s/batt_temp", POWER_SUPPLY_SYSFS_PATH, name); + if (access(path, R_OK) == 0) + mBatteryTemperaturePath = path; + } + + path.clear(); + path.appendFormat("%s/%s/technology", POWER_SUPPLY_SYSFS_PATH, name); + if (access(path, R_OK) == 0) + mBatteryTechnologyPath = path; + break; + + case ANDROID_POWER_SUPPLY_TYPE_UNKNOWN: + break; + } + } + closedir(dir); + } + + if (!mChargerNames.size()) + KLOG_ERROR(LOG_TAG, "No charger supplies found\n"); + if (mBatteryStatusPath.isEmpty()) + KLOG_WARNING(LOG_TAG, "BatteryStatusPath not found\n"); + if (mBatteryHealthPath.isEmpty()) + KLOG_WARNING("BatteryHealthPath not found\n"); + if (mBatteryPresentPath.isEmpty()) + KLOG_WARNING(LOG_TAG, "BatteryPresentPath not found\n"); + if (mBatteryCapacityPath.isEmpty()) + KLOG_WARNING(LOG_TAG, "BatteryCapacityPath not found\n"); + if (mBatteryVoltagePath.isEmpty()) + KLOG_WARNING(LOG_TAG, "BatteryVoltagePath not found\n"); + if (mBatteryTemperaturePath.isEmpty()) + KLOG_WARNING(LOG_TAG, "BatteryTemperaturePath not found\n"); + if (mBatteryTechnologyPath.isEmpty()) + KLOG_WARNING(LOG_TAG, "BatteryTechnologyPath not found\n"); + + if (nosvcmgr == false) { + mBatteryPropertiesRegistrar = new BatteryPropertiesRegistrar(this); + mBatteryPropertiesRegistrar->publish(); + } +} + +}; // namespace android diff --git a/healthd/BatteryMonitor.h b/healthd/BatteryMonitor.h new file mode 100644 index 0000000..df0920b --- /dev/null +++ b/healthd/BatteryMonitor.h @@ -0,0 +1,67 @@ +/* + * Copyright (C) 2013 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef HEALTHD_BATTERYMONITOR_H +#define HEALTHD_BATTERYMONITOR_H + +#include <binder/IInterface.h> +#include <utils/String8.h> +#include <utils/Vector.h> + +#include "BatteryPropertiesRegistrar.h" + +namespace android { + +class BatteryPropertiesRegistrar; + +class BatteryMonitor { + public: + + enum PowerSupplyType { + ANDROID_POWER_SUPPLY_TYPE_UNKNOWN = 0, + ANDROID_POWER_SUPPLY_TYPE_AC, + ANDROID_POWER_SUPPLY_TYPE_USB, + ANDROID_POWER_SUPPLY_TYPE_WIRELESS, + ANDROID_POWER_SUPPLY_TYPE_BATTERY + }; + + void init(bool nosvcmgr); + bool update(void); + + private: + String8 mBatteryStatusPath; + String8 mBatteryHealthPath; + String8 mBatteryPresentPath; + String8 mBatteryCapacityPath; + String8 mBatteryVoltagePath; + String8 mBatteryTemperaturePath; + String8 mBatteryTechnologyPath; + + Vector<String8> mChargerNames; + + sp<BatteryPropertiesRegistrar> mBatteryPropertiesRegistrar; + + int getBatteryStatus(const char* status); + int getBatteryHealth(const char* status); + int readFromFile(const String8& path, char* buf, size_t size); + PowerSupplyType readPowerSupplyType(const String8& path); + bool getBooleanField(const String8& path); + int getIntField(const String8& path); +}; + +}; // namespace android + +#endif // HEALTHD_BATTERY_MONTIOR_H diff --git a/healthd/BatteryPropertiesRegistrar.cpp b/healthd/BatteryPropertiesRegistrar.cpp new file mode 100644 index 0000000..6a33ad8 --- /dev/null +++ b/healthd/BatteryPropertiesRegistrar.cpp @@ -0,0 +1,81 @@ +/* + * Copyright (C) 2013 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "BatteryPropertiesRegistrar.h" +#include <batteryservice/BatteryService.h> +#include <batteryservice/IBatteryPropertiesListener.h> +#include <batteryservice/IBatteryPropertiesRegistrar.h> +#include <binder/IServiceManager.h> +#include <utils/Errors.h> +#include <utils/Mutex.h> +#include <utils/String16.h> + +namespace android { + +BatteryPropertiesRegistrar::BatteryPropertiesRegistrar(BatteryMonitor* monitor) { + mBatteryMonitor = monitor; +} + +void BatteryPropertiesRegistrar::publish() { + defaultServiceManager()->addService(String16("batterypropreg"), this); +} + +void BatteryPropertiesRegistrar::notifyListeners(struct BatteryProperties props) { + Mutex::Autolock _l(mRegistrationLock); + for (size_t i = 0; i < mListeners.size(); i++) { + mListeners[i]->batteryPropertiesChanged(props); + } +} + +void BatteryPropertiesRegistrar::registerListener(const sp<IBatteryPropertiesListener>& listener) { + { + Mutex::Autolock _l(mRegistrationLock); + // check whether this is a duplicate + for (size_t i = 0; i < mListeners.size(); i++) { + if (mListeners[i]->asBinder() == listener->asBinder()) { + return; + } + } + + mListeners.add(listener); + listener->asBinder()->linkToDeath(this); + } + mBatteryMonitor->update(); +} + +void BatteryPropertiesRegistrar::unregisterListener(const sp<IBatteryPropertiesListener>& listener) { + Mutex::Autolock _l(mRegistrationLock); + for (size_t i = 0; i < mListeners.size(); i++) { + if (mListeners[i]->asBinder() == listener->asBinder()) { + mListeners[i]->asBinder()->unlinkToDeath(this); + mListeners.removeAt(i); + break; + } + } +} + +void BatteryPropertiesRegistrar::binderDied(const wp<IBinder>& who) { + Mutex::Autolock _l(mRegistrationLock); + + for (size_t i = 0; i < mListeners.size(); i++) { + if (mListeners[i]->asBinder() == who) { + mListeners.removeAt(i); + break; + } + } +} + +} // namespace android diff --git a/healthd/BatteryPropertiesRegistrar.h b/healthd/BatteryPropertiesRegistrar.h new file mode 100644 index 0000000..793ddad --- /dev/null +++ b/healthd/BatteryPropertiesRegistrar.h @@ -0,0 +1,52 @@ +/* + * Copyright (C) 2013 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef HEALTHD_BATTERYPROPERTIES_REGISTRAR_H +#define HEALTHD_BATTERYPROPERTIES_REGISTRAR_H + +#include "BatteryMonitor.h" + +#include <binder/IBinder.h> +#include <utils/Mutex.h> +#include <utils/Vector.h> +#include <batteryservice/BatteryService.h> +#include <batteryservice/IBatteryPropertiesListener.h> +#include <batteryservice/IBatteryPropertiesRegistrar.h> + +namespace android { + +class BatteryMonitor; + +class BatteryPropertiesRegistrar : public BnBatteryPropertiesRegistrar, + public IBinder::DeathRecipient { +public: + BatteryPropertiesRegistrar(BatteryMonitor* monitor); + void publish(); + void notifyListeners(struct BatteryProperties props); + +private: + BatteryMonitor* mBatteryMonitor; + Mutex mRegistrationLock; + Vector<sp<IBatteryPropertiesListener> > mListeners; + + void registerListener(const sp<IBatteryPropertiesListener>& listener); + void unregisterListener(const sp<IBatteryPropertiesListener>& listener); + void binderDied(const wp<IBinder>& who); +}; + +}; // namespace android + +#endif // HEALTHD_BATTERYPROPERTIES_REGISTRAR_H diff --git a/healthd/healthd.cpp b/healthd/healthd.cpp new file mode 100644 index 0000000..1d79097 --- /dev/null +++ b/healthd/healthd.cpp @@ -0,0 +1,258 @@ +/* + * Copyright (C) 2013 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#define LOG_TAG "healthd" +#define KLOG_LEVEL 6 + +#include "BatteryMonitor.h" + +#include <errno.h> +#include <stdio.h> +#include <stdlib.h> +#include <unistd.h> +#include <batteryservice/BatteryService.h> +#include <binder/IPCThreadState.h> +#include <binder/ProcessState.h> +#include <cutils/klog.h> +#include <cutils/uevent.h> +#include <sys/epoll.h> +#include <sys/timerfd.h> + +using namespace android; + +// Periodic chores intervals in seconds +#define PERIODIC_CHORES_INTERVAL_FAST (60 * 1) +#define PERIODIC_CHORES_INTERVAL_SLOW (60 * 10) + +#define POWER_SUPPLY_SUBSYSTEM "power_supply" + +// epoll events: uevent, wakealarm, binder +#define MAX_EPOLL_EVENTS 3 +static int uevent_fd; +static int wakealarm_fd; +static int binder_fd; + +// -1 for no epoll timeout +static int awake_poll_interval = -1; + +static int wakealarm_wake_interval = PERIODIC_CHORES_INTERVAL_FAST; + +static BatteryMonitor* gBatteryMonitor; + +static bool nosvcmgr; + +static void wakealarm_set_interval(int interval) { + struct itimerspec itval; + + if (wakealarm_fd == -1) + return; + + wakealarm_wake_interval = interval; + itval.it_interval.tv_sec = interval; + itval.it_interval.tv_nsec = 0; + itval.it_value.tv_sec = interval; + itval.it_value.tv_nsec = 0; + + if (timerfd_settime(wakealarm_fd, 0, &itval, NULL) == -1) + KLOG_ERROR(LOG_TAG, "wakealarm_set_interval: timerfd_settime failed\n"); +} + +static void battery_update(void) { + // Fast wake interval when on charger (watch for overheat); + // slow wake interval when on battery (watch for drained battery). + + int new_wake_interval = gBatteryMonitor->update() ? + PERIODIC_CHORES_INTERVAL_FAST : PERIODIC_CHORES_INTERVAL_SLOW; + + if (new_wake_interval != wakealarm_wake_interval) + wakealarm_set_interval(new_wake_interval); + + // During awake periods poll at fast rate. If wake alarm is set at fast + // rate then just use the alarm; if wake alarm is set at slow rate then + // poll at fast rate while awake and let alarm wake up at slow rate when + // asleep. + + awake_poll_interval = + new_wake_interval == PERIODIC_CHORES_INTERVAL_FAST ? + -1 : PERIODIC_CHORES_INTERVAL_FAST * 1000; +} + +static void periodic_chores() { + battery_update(); +} + +static void uevent_init(void) { + uevent_fd = uevent_open_socket(64*1024, true); + + if (uevent_fd >= 0) + fcntl(uevent_fd, F_SETFL, O_NONBLOCK); + else + KLOG_ERROR(LOG_TAG, "uevent_init: uevent_open_socket failed\n"); +} + +#define UEVENT_MSG_LEN 1024 +static void uevent_event(void) { + char msg[UEVENT_MSG_LEN+2]; + char *cp; + int n; + + n = uevent_kernel_multicast_recv(uevent_fd, msg, UEVENT_MSG_LEN); + if (n <= 0) + return; + if (n >= UEVENT_MSG_LEN) /* overflow -- discard */ + return; + + msg[n] = '\0'; + msg[n+1] = '\0'; + cp = msg; + + while (*cp) { + if (!strcmp(cp, "SUBSYSTEM=" POWER_SUPPLY_SUBSYSTEM)) { + battery_update(); + break; + } + + /* advance to after the next \0 */ + while (*cp++) + ; + } +} + +static void wakealarm_init(void) { + wakealarm_fd = timerfd_create(CLOCK_BOOTTIME_ALARM, TFD_NONBLOCK); + if (wakealarm_fd == -1) { + KLOG_ERROR(LOG_TAG, "wakealarm_init: timerfd_create failed\n"); + return; + } + + wakealarm_set_interval(PERIODIC_CHORES_INTERVAL_FAST); +} + +static void wakealarm_event(void) { + unsigned long long wakeups; + + if (read(wakealarm_fd, &wakeups, sizeof(wakeups)) == -1) { + KLOG_ERROR(LOG_TAG, "wakealarm_event: read wakealarm_fd failed\n"); + return; + } + + periodic_chores(); +} + +static void binder_init(void) { + ProcessState::self()->setThreadPoolMaxThreadCount(0); + IPCThreadState::self()->disableBackgroundScheduling(true); + IPCThreadState::self()->setupPolling(&binder_fd); +} + +static void binder_event(void) { + IPCThreadState::self()->handlePolledCommands(); +} + +static void healthd_mainloop(void) { + struct epoll_event ev; + int epollfd; + int maxevents = 0; + + epollfd = epoll_create(MAX_EPOLL_EVENTS); + if (epollfd == -1) { + KLOG_ERROR(LOG_TAG, + "healthd_mainloop: epoll_create failed; errno=%d\n", + errno); + return; + } + + if (uevent_fd >= 0) { + ev.events = EPOLLIN | EPOLLWAKEUP; + ev.data.ptr = (void *)uevent_event; + if (epoll_ctl(epollfd, EPOLL_CTL_ADD, uevent_fd, &ev) == -1) + KLOG_ERROR(LOG_TAG, + "healthd_mainloop: epoll_ctl for uevent_fd failed; errno=%d\n", + errno); + else + maxevents++; + } + + if (wakealarm_fd >= 0) { + ev.events = EPOLLIN | EPOLLWAKEUP; + ev.data.ptr = (void *)wakealarm_event; + if (epoll_ctl(epollfd, EPOLL_CTL_ADD, wakealarm_fd, &ev) == -1) + KLOG_ERROR(LOG_TAG, + "healthd_mainloop: epoll_ctl for wakealarm_fd failed; errno=%d\n", + errno); + else + maxevents++; + } + + if (binder_fd >= 0) { + ev.events = EPOLLIN | EPOLLWAKEUP; + ev.data.ptr= (void *)binder_event; + if (epoll_ctl(epollfd, EPOLL_CTL_ADD, binder_fd, &ev) == -1) + KLOG_ERROR(LOG_TAG, + "healthd_mainloop: epoll_ctl for binder_fd failed; errno=%d\n", + errno); + else + maxevents++; + } + + while (1) { + struct epoll_event events[maxevents]; + int nevents; + + IPCThreadState::self()->flushCommands(); + nevents = epoll_wait(epollfd, events, maxevents, awake_poll_interval); + + if (nevents == -1) { + if (errno == EINTR) + continue; + KLOG_ERROR(LOG_TAG, "healthd_mainloop: epoll_wait failed\n"); + break; + } + + for (int n = 0; n < nevents; ++n) { + if (events[n].data.ptr) + (*(void (*)())events[n].data.ptr)(); + } + } + + return; +} + +int main(int argc, char **argv) { + int ch; + + klog_set_level(KLOG_LEVEL); + + while ((ch = getopt(argc, argv, "n")) != -1) { + switch (ch) { + case 'n': + nosvcmgr = true; + break; + case '?': + default: + KLOG_WARNING(LOG_TAG, "Unrecognized healthd option: %c\n", ch); + } + } + + wakealarm_init(); + uevent_init(); + binder_init(); + gBatteryMonitor = new BatteryMonitor(); + gBatteryMonitor->init(nosvcmgr); + + healthd_mainloop(); + return 0; +} diff --git a/include/cutils/log.h b/include/cutils/log.h index 8b045c7..0e0248e 100644 --- a/include/cutils/log.h +++ b/include/cutils/log.h @@ -1,563 +1 @@ -/* - * Copyright (C) 2005 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. - */ - -// -// C/C++ logging functions. See the logging documentation for API details. -// -// We'd like these to be available from C code (in case we import some from -// somewhere), so this has a C interface. -// -// The output will be correct when the log file is shared between multiple -// threads and/or multiple processes so long as the operating system -// supports O_APPEND. These calls have mutex-protected data structures -// and so are NOT reentrant. Do not use LOG in a signal handler. -// -#ifndef _LIBS_CUTILS_LOG_H -#define _LIBS_CUTILS_LOG_H - -#include <stdio.h> -#include <time.h> -#include <sys/types.h> -#include <unistd.h> -#ifdef HAVE_PTHREADS -#include <pthread.h> -#endif -#include <stdarg.h> - -#include <cutils/uio.h> -#include <cutils/logd.h> - -#ifdef __cplusplus -extern "C" { -#endif - -// --------------------------------------------------------------------- - -/* - * Normally we strip ALOGV (VERBOSE messages) from release builds. - * You can modify this (for example with "#define LOG_NDEBUG 0" - * at the top of your source file) to change that behavior. - */ -#ifndef LOG_NDEBUG -#ifdef NDEBUG -#define LOG_NDEBUG 1 -#else -#define LOG_NDEBUG 0 -#endif -#endif - -/* - * This is the local tag used for the following simplified - * logging macros. You can change this preprocessor definition - * before using the other macros to change the tag. - */ -#ifndef LOG_TAG -#define LOG_TAG NULL -#endif - -// --------------------------------------------------------------------- - -/* - * Simplified macro to send a verbose log message using the current LOG_TAG. - */ -#ifndef ALOGV -#if LOG_NDEBUG -#define ALOGV(...) ((void)0) -#else -#define ALOGV(...) ((void)ALOG(LOG_VERBOSE, LOG_TAG, __VA_ARGS__)) -#endif -#endif - -#define CONDITION(cond) (__builtin_expect((cond)!=0, 0)) - -#ifndef ALOGV_IF -#if LOG_NDEBUG -#define ALOGV_IF(cond, ...) ((void)0) -#else -#define ALOGV_IF(cond, ...) \ - ( (CONDITION(cond)) \ - ? ((void)ALOG(LOG_VERBOSE, LOG_TAG, __VA_ARGS__)) \ - : (void)0 ) -#endif -#endif - -/* - * Simplified macro to send a debug log message using the current LOG_TAG. - */ -#ifndef ALOGD -#define ALOGD(...) ((void)ALOG(LOG_DEBUG, LOG_TAG, __VA_ARGS__)) -#endif - -#ifndef ALOGD_IF -#define ALOGD_IF(cond, ...) \ - ( (CONDITION(cond)) \ - ? ((void)ALOG(LOG_DEBUG, LOG_TAG, __VA_ARGS__)) \ - : (void)0 ) -#endif - -/* - * Simplified macro to send an info log message using the current LOG_TAG. - */ -#ifndef ALOGI -#define ALOGI(...) ((void)ALOG(LOG_INFO, LOG_TAG, __VA_ARGS__)) -#endif - -#ifndef ALOGI_IF -#define ALOGI_IF(cond, ...) \ - ( (CONDITION(cond)) \ - ? ((void)ALOG(LOG_INFO, LOG_TAG, __VA_ARGS__)) \ - : (void)0 ) -#endif - -/* - * Simplified macro to send a warning log message using the current LOG_TAG. - */ -#ifndef ALOGW -#define ALOGW(...) ((void)ALOG(LOG_WARN, LOG_TAG, __VA_ARGS__)) -#endif - -#ifndef ALOGW_IF -#define ALOGW_IF(cond, ...) \ - ( (CONDITION(cond)) \ - ? ((void)ALOG(LOG_WARN, LOG_TAG, __VA_ARGS__)) \ - : (void)0 ) -#endif - -/* - * Simplified macro to send an error log message using the current LOG_TAG. - */ -#ifndef ALOGE -#define ALOGE(...) ((void)ALOG(LOG_ERROR, LOG_TAG, __VA_ARGS__)) -#endif - -#ifndef ALOGE_IF -#define ALOGE_IF(cond, ...) \ - ( (CONDITION(cond)) \ - ? ((void)ALOG(LOG_ERROR, LOG_TAG, __VA_ARGS__)) \ - : (void)0 ) -#endif - -// --------------------------------------------------------------------- - -/* - * Conditional based on whether the current LOG_TAG is enabled at - * verbose priority. - */ -#ifndef IF_ALOGV -#if LOG_NDEBUG -#define IF_ALOGV() if (false) -#else -#define IF_ALOGV() IF_ALOG(LOG_VERBOSE, LOG_TAG) -#endif -#endif - -/* - * Conditional based on whether the current LOG_TAG is enabled at - * debug priority. - */ -#ifndef IF_ALOGD -#define IF_ALOGD() IF_ALOG(LOG_DEBUG, LOG_TAG) -#endif - -/* - * Conditional based on whether the current LOG_TAG is enabled at - * info priority. - */ -#ifndef IF_ALOGI -#define IF_ALOGI() IF_ALOG(LOG_INFO, LOG_TAG) -#endif - -/* - * Conditional based on whether the current LOG_TAG is enabled at - * warn priority. - */ -#ifndef IF_ALOGW -#define IF_ALOGW() IF_ALOG(LOG_WARN, LOG_TAG) -#endif - -/* - * Conditional based on whether the current LOG_TAG is enabled at - * error priority. - */ -#ifndef IF_ALOGE -#define IF_ALOGE() IF_ALOG(LOG_ERROR, LOG_TAG) -#endif - - -// --------------------------------------------------------------------- - -/* - * Simplified macro to send a verbose system log message using the current LOG_TAG. - */ -#ifndef SLOGV -#if LOG_NDEBUG -#define SLOGV(...) ((void)0) -#else -#define SLOGV(...) ((void)__android_log_buf_print(LOG_ID_SYSTEM, ANDROID_LOG_VERBOSE, LOG_TAG, __VA_ARGS__)) -#endif -#endif - -#define CONDITION(cond) (__builtin_expect((cond)!=0, 0)) - -#ifndef SLOGV_IF -#if LOG_NDEBUG -#define SLOGV_IF(cond, ...) ((void)0) -#else -#define SLOGV_IF(cond, ...) \ - ( (CONDITION(cond)) \ - ? ((void)__android_log_buf_print(LOG_ID_SYSTEM, ANDROID_LOG_VERBOSE, LOG_TAG, __VA_ARGS__)) \ - : (void)0 ) -#endif -#endif - -/* - * Simplified macro to send a debug system log message using the current LOG_TAG. - */ -#ifndef SLOGD -#define SLOGD(...) ((void)__android_log_buf_print(LOG_ID_SYSTEM, ANDROID_LOG_DEBUG, LOG_TAG, __VA_ARGS__)) -#endif - -#ifndef SLOGD_IF -#define SLOGD_IF(cond, ...) \ - ( (CONDITION(cond)) \ - ? ((void)__android_log_buf_print(LOG_ID_SYSTEM, ANDROID_LOG_DEBUG, LOG_TAG, __VA_ARGS__)) \ - : (void)0 ) -#endif - -/* - * Simplified macro to send an info system log message using the current LOG_TAG. - */ -#ifndef SLOGI -#define SLOGI(...) ((void)__android_log_buf_print(LOG_ID_SYSTEM, ANDROID_LOG_INFO, LOG_TAG, __VA_ARGS__)) -#endif - -#ifndef SLOGI_IF -#define SLOGI_IF(cond, ...) \ - ( (CONDITION(cond)) \ - ? ((void)__android_log_buf_print(LOG_ID_SYSTEM, ANDROID_LOG_INFO, LOG_TAG, __VA_ARGS__)) \ - : (void)0 ) -#endif - -/* - * Simplified macro to send a warning system log message using the current LOG_TAG. - */ -#ifndef SLOGW -#define SLOGW(...) ((void)__android_log_buf_print(LOG_ID_SYSTEM, ANDROID_LOG_WARN, LOG_TAG, __VA_ARGS__)) -#endif - -#ifndef SLOGW_IF -#define SLOGW_IF(cond, ...) \ - ( (CONDITION(cond)) \ - ? ((void)__android_log_buf_print(LOG_ID_SYSTEM, ANDROID_LOG_WARN, LOG_TAG, __VA_ARGS__)) \ - : (void)0 ) -#endif - -/* - * Simplified macro to send an error system log message using the current LOG_TAG. - */ -#ifndef SLOGE -#define SLOGE(...) ((void)__android_log_buf_print(LOG_ID_SYSTEM, ANDROID_LOG_ERROR, LOG_TAG, __VA_ARGS__)) -#endif - -#ifndef SLOGE_IF -#define SLOGE_IF(cond, ...) \ - ( (CONDITION(cond)) \ - ? ((void)__android_log_buf_print(LOG_ID_SYSTEM, ANDROID_LOG_ERROR, LOG_TAG, __VA_ARGS__)) \ - : (void)0 ) -#endif - -// --------------------------------------------------------------------- - -/* - * Simplified macro to send a verbose radio log message using the current LOG_TAG. - */ -#ifndef RLOGV -#if LOG_NDEBUG -#define RLOGV(...) ((void)0) -#else -#define RLOGV(...) ((void)__android_log_buf_print(LOG_ID_RADIO, ANDROID_LOG_VERBOSE, LOG_TAG, __VA_ARGS__)) -#endif -#endif - -#define CONDITION(cond) (__builtin_expect((cond)!=0, 0)) - -#ifndef RLOGV_IF -#if LOG_NDEBUG -#define RLOGV_IF(cond, ...) ((void)0) -#else -#define RLOGV_IF(cond, ...) \ - ( (CONDITION(cond)) \ - ? ((void)__android_log_buf_print(LOG_ID_RADIO, ANDROID_LOG_VERBOSE, LOG_TAG, __VA_ARGS__)) \ - : (void)0 ) -#endif -#endif - -/* - * Simplified macro to send a debug radio log message using the current LOG_TAG. - */ -#ifndef RLOGD -#define RLOGD(...) ((void)__android_log_buf_print(LOG_ID_RADIO, ANDROID_LOG_DEBUG, LOG_TAG, __VA_ARGS__)) -#endif - -#ifndef RLOGD_IF -#define RLOGD_IF(cond, ...) \ - ( (CONDITION(cond)) \ - ? ((void)__android_log_buf_print(LOG_ID_RADIO, ANDROID_LOG_DEBUG, LOG_TAG, __VA_ARGS__)) \ - : (void)0 ) -#endif - -/* - * Simplified macro to send an info radio log message using the current LOG_TAG. - */ -#ifndef RLOGI -#define RLOGI(...) ((void)__android_log_buf_print(LOG_ID_RADIO, ANDROID_LOG_INFO, LOG_TAG, __VA_ARGS__)) -#endif - -#ifndef RLOGI_IF -#define RLOGI_IF(cond, ...) \ - ( (CONDITION(cond)) \ - ? ((void)__android_log_buf_print(LOG_ID_RADIO, ANDROID_LOG_INFO, LOG_TAG, __VA_ARGS__)) \ - : (void)0 ) -#endif - -/* - * Simplified macro to send a warning radio log message using the current LOG_TAG. - */ -#ifndef RLOGW -#define RLOGW(...) ((void)__android_log_buf_print(LOG_ID_RADIO, ANDROID_LOG_WARN, LOG_TAG, __VA_ARGS__)) -#endif - -#ifndef RLOGW_IF -#define RLOGW_IF(cond, ...) \ - ( (CONDITION(cond)) \ - ? ((void)__android_log_buf_print(LOG_ID_RADIO, ANDROID_LOG_WARN, LOG_TAG, __VA_ARGS__)) \ - : (void)0 ) -#endif - -/* - * Simplified macro to send an error radio log message using the current LOG_TAG. - */ -#ifndef RLOGE -#define RLOGE(...) ((void)__android_log_buf_print(LOG_ID_RADIO, ANDROID_LOG_ERROR, LOG_TAG, __VA_ARGS__)) -#endif - -#ifndef RLOGE_IF -#define RLOGE_IF(cond, ...) \ - ( (CONDITION(cond)) \ - ? ((void)__android_log_buf_print(LOG_ID_RADIO, ANDROID_LOG_ERROR, LOG_TAG, __VA_ARGS__)) \ - : (void)0 ) -#endif - - -// --------------------------------------------------------------------- - -/* - * Log a fatal error. If the given condition fails, this stops program - * execution like a normal assertion, but also generating the given message. - * It is NOT stripped from release builds. Note that the condition test - * is -inverted- from the normal assert() semantics. - */ -#ifndef LOG_ALWAYS_FATAL_IF -#define LOG_ALWAYS_FATAL_IF(cond, ...) \ - ( (CONDITION(cond)) \ - ? ((void)android_printAssert(#cond, LOG_TAG, ## __VA_ARGS__)) \ - : (void)0 ) -#endif - -#ifndef LOG_ALWAYS_FATAL -#define LOG_ALWAYS_FATAL(...) \ - ( ((void)android_printAssert(NULL, LOG_TAG, ## __VA_ARGS__)) ) -#endif - -/* - * Versions of LOG_ALWAYS_FATAL_IF and LOG_ALWAYS_FATAL that - * are stripped out of release builds. - */ -#if LOG_NDEBUG - -#ifndef LOG_FATAL_IF -#define LOG_FATAL_IF(cond, ...) ((void)0) -#endif -#ifndef LOG_FATAL -#define LOG_FATAL(...) ((void)0) -#endif - -#else - -#ifndef LOG_FATAL_IF -#define LOG_FATAL_IF(cond, ...) LOG_ALWAYS_FATAL_IF(cond, ## __VA_ARGS__) -#endif -#ifndef LOG_FATAL -#define LOG_FATAL(...) LOG_ALWAYS_FATAL(__VA_ARGS__) -#endif - -#endif - -/* - * Assertion that generates a log message when the assertion fails. - * Stripped out of release builds. Uses the current LOG_TAG. - */ -#ifndef ALOG_ASSERT -#define ALOG_ASSERT(cond, ...) LOG_FATAL_IF(!(cond), ## __VA_ARGS__) -//#define ALOG_ASSERT(cond) LOG_FATAL_IF(!(cond), "Assertion failed: " #cond) -#endif - -// --------------------------------------------------------------------- - -/* - * Basic log message macro. - * - * Example: - * ALOG(LOG_WARN, NULL, "Failed with error %d", errno); - * - * The second argument may be NULL or "" to indicate the "global" tag. - */ -#ifndef ALOG -#define ALOG(priority, tag, ...) \ - LOG_PRI(ANDROID_##priority, tag, __VA_ARGS__) -#endif - -/* - * Log macro that allows you to specify a number for the priority. - */ -#ifndef LOG_PRI -#define LOG_PRI(priority, tag, ...) \ - android_printLog(priority, tag, __VA_ARGS__) -#endif - -/* - * Log macro that allows you to pass in a varargs ("args" is a va_list). - */ -#ifndef LOG_PRI_VA -#define LOG_PRI_VA(priority, tag, fmt, args) \ - android_vprintLog(priority, NULL, tag, fmt, args) -#endif - -/* - * Conditional given a desired logging priority and tag. - */ -#ifndef IF_ALOG -#define IF_ALOG(priority, tag) \ - if (android_testLog(ANDROID_##priority, tag)) -#endif - -// --------------------------------------------------------------------- - -/* - * Event logging. - */ - -/* - * Event log entry types. These must match up with the declarations in - * java/android/android/util/EventLog.java. - */ -typedef enum { - EVENT_TYPE_INT = 0, - EVENT_TYPE_LONG = 1, - EVENT_TYPE_STRING = 2, - EVENT_TYPE_LIST = 3, -} AndroidEventLogType; - - -#ifndef LOG_EVENT_INT -#define LOG_EVENT_INT(_tag, _value) { \ - int intBuf = _value; \ - (void) android_btWriteLog(_tag, EVENT_TYPE_INT, &intBuf, \ - sizeof(intBuf)); \ - } -#endif -#ifndef LOG_EVENT_LONG -#define LOG_EVENT_LONG(_tag, _value) { \ - long long longBuf = _value; \ - (void) android_btWriteLog(_tag, EVENT_TYPE_LONG, &longBuf, \ - sizeof(longBuf)); \ - } -#endif -#ifndef LOG_EVENT_STRING -#define LOG_EVENT_STRING(_tag, _value) \ - ((void) 0) /* not implemented -- must combine len with string */ -#endif -/* TODO: something for LIST */ - -/* - * =========================================================================== - * - * The stuff in the rest of this file should not be used directly. - */ - -#define android_printLog(prio, tag, fmt...) \ - __android_log_print(prio, tag, fmt) - -#define android_vprintLog(prio, cond, tag, fmt...) \ - __android_log_vprint(prio, tag, fmt) - -/* XXX Macros to work around syntax errors in places where format string - * arg is not passed to ALOG_ASSERT, LOG_ALWAYS_FATAL or LOG_ALWAYS_FATAL_IF - * (happens only in debug builds). - */ - -/* Returns 2nd arg. Used to substitute default value if caller's vararg list - * is empty. - */ -#define __android_second(dummy, second, ...) second - -/* If passed multiple args, returns ',' followed by all but 1st arg, otherwise - * returns nothing. - */ -#define __android_rest(first, ...) , ## __VA_ARGS__ - -#define android_printAssert(cond, tag, fmt...) \ - __android_log_assert(cond, tag, \ - __android_second(0, ## fmt, NULL) __android_rest(fmt)) - -#define android_writeLog(prio, tag, text) \ - __android_log_write(prio, tag, text) - -#define android_bWriteLog(tag, payload, len) \ - __android_log_bwrite(tag, payload, len) -#define android_btWriteLog(tag, type, payload, len) \ - __android_log_btwrite(tag, type, payload, len) - -// TODO: remove these prototypes and their users -#define android_testLog(prio, tag) (1) -#define android_writevLog(vec,num) do{}while(0) -#define android_write1Log(str,len) do{}while (0) -#define android_setMinPriority(tag, prio) do{}while(0) -//#define android_logToCallback(func) do{}while(0) -#define android_logToFile(tag, file) (0) -#define android_logToFd(tag, fd) (0) - -typedef enum { - LOG_ID_MAIN = 0, - LOG_ID_RADIO = 1, - LOG_ID_EVENTS = 2, - LOG_ID_SYSTEM = 3, - - LOG_ID_MAX -} log_id_t; - -/* - * Send a simple string to the log. - */ -int __android_log_buf_write(int bufID, int prio, const char *tag, const char *text); -int __android_log_buf_print(int bufID, int prio, const char *tag, const char *fmt, ...); - - -#ifdef __cplusplus -} -#endif - -#endif // _LIBS_CUTILS_LOG_H +#include <log/log.h> diff --git a/include/cutils/event_tag_map.h b/include/log/event_tag_map.h index 1653c61..1653c61 100644 --- a/include/cutils/event_tag_map.h +++ b/include/log/event_tag_map.h diff --git a/include/log/log.h b/include/log/log.h new file mode 100644 index 0000000..7faddea --- /dev/null +++ b/include/log/log.h @@ -0,0 +1,563 @@ +/* + * Copyright (C) 2005 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. + */ + +// +// C/C++ logging functions. See the logging documentation for API details. +// +// We'd like these to be available from C code (in case we import some from +// somewhere), so this has a C interface. +// +// The output will be correct when the log file is shared between multiple +// threads and/or multiple processes so long as the operating system +// supports O_APPEND. These calls have mutex-protected data structures +// and so are NOT reentrant. Do not use LOG in a signal handler. +// +#ifndef _LIBS_LOG_LOG_H +#define _LIBS_LOG_LOG_H + +#include <stdio.h> +#include <time.h> +#include <sys/types.h> +#include <unistd.h> +#ifdef HAVE_PTHREADS +#include <pthread.h> +#endif +#include <stdarg.h> + +#include <log/uio.h> +#include <log/logd.h> + +#ifdef __cplusplus +extern "C" { +#endif + +// --------------------------------------------------------------------- + +/* + * Normally we strip ALOGV (VERBOSE messages) from release builds. + * You can modify this (for example with "#define LOG_NDEBUG 0" + * at the top of your source file) to change that behavior. + */ +#ifndef LOG_NDEBUG +#ifdef NDEBUG +#define LOG_NDEBUG 1 +#else +#define LOG_NDEBUG 0 +#endif +#endif + +/* + * This is the local tag used for the following simplified + * logging macros. You can change this preprocessor definition + * before using the other macros to change the tag. + */ +#ifndef LOG_TAG +#define LOG_TAG NULL +#endif + +// --------------------------------------------------------------------- + +/* + * Simplified macro to send a verbose log message using the current LOG_TAG. + */ +#ifndef ALOGV +#if LOG_NDEBUG +#define ALOGV(...) ((void)0) +#else +#define ALOGV(...) ((void)ALOG(LOG_VERBOSE, LOG_TAG, __VA_ARGS__)) +#endif +#endif + +#define CONDITION(cond) (__builtin_expect((cond)!=0, 0)) + +#ifndef ALOGV_IF +#if LOG_NDEBUG +#define ALOGV_IF(cond, ...) ((void)0) +#else +#define ALOGV_IF(cond, ...) \ + ( (CONDITION(cond)) \ + ? ((void)ALOG(LOG_VERBOSE, LOG_TAG, __VA_ARGS__)) \ + : (void)0 ) +#endif +#endif + +/* + * Simplified macro to send a debug log message using the current LOG_TAG. + */ +#ifndef ALOGD +#define ALOGD(...) ((void)ALOG(LOG_DEBUG, LOG_TAG, __VA_ARGS__)) +#endif + +#ifndef ALOGD_IF +#define ALOGD_IF(cond, ...) \ + ( (CONDITION(cond)) \ + ? ((void)ALOG(LOG_DEBUG, LOG_TAG, __VA_ARGS__)) \ + : (void)0 ) +#endif + +/* + * Simplified macro to send an info log message using the current LOG_TAG. + */ +#ifndef ALOGI +#define ALOGI(...) ((void)ALOG(LOG_INFO, LOG_TAG, __VA_ARGS__)) +#endif + +#ifndef ALOGI_IF +#define ALOGI_IF(cond, ...) \ + ( (CONDITION(cond)) \ + ? ((void)ALOG(LOG_INFO, LOG_TAG, __VA_ARGS__)) \ + : (void)0 ) +#endif + +/* + * Simplified macro to send a warning log message using the current LOG_TAG. + */ +#ifndef ALOGW +#define ALOGW(...) ((void)ALOG(LOG_WARN, LOG_TAG, __VA_ARGS__)) +#endif + +#ifndef ALOGW_IF +#define ALOGW_IF(cond, ...) \ + ( (CONDITION(cond)) \ + ? ((void)ALOG(LOG_WARN, LOG_TAG, __VA_ARGS__)) \ + : (void)0 ) +#endif + +/* + * Simplified macro to send an error log message using the current LOG_TAG. + */ +#ifndef ALOGE +#define ALOGE(...) ((void)ALOG(LOG_ERROR, LOG_TAG, __VA_ARGS__)) +#endif + +#ifndef ALOGE_IF +#define ALOGE_IF(cond, ...) \ + ( (CONDITION(cond)) \ + ? ((void)ALOG(LOG_ERROR, LOG_TAG, __VA_ARGS__)) \ + : (void)0 ) +#endif + +// --------------------------------------------------------------------- + +/* + * Conditional based on whether the current LOG_TAG is enabled at + * verbose priority. + */ +#ifndef IF_ALOGV +#if LOG_NDEBUG +#define IF_ALOGV() if (false) +#else +#define IF_ALOGV() IF_ALOG(LOG_VERBOSE, LOG_TAG) +#endif +#endif + +/* + * Conditional based on whether the current LOG_TAG is enabled at + * debug priority. + */ +#ifndef IF_ALOGD +#define IF_ALOGD() IF_ALOG(LOG_DEBUG, LOG_TAG) +#endif + +/* + * Conditional based on whether the current LOG_TAG is enabled at + * info priority. + */ +#ifndef IF_ALOGI +#define IF_ALOGI() IF_ALOG(LOG_INFO, LOG_TAG) +#endif + +/* + * Conditional based on whether the current LOG_TAG is enabled at + * warn priority. + */ +#ifndef IF_ALOGW +#define IF_ALOGW() IF_ALOG(LOG_WARN, LOG_TAG) +#endif + +/* + * Conditional based on whether the current LOG_TAG is enabled at + * error priority. + */ +#ifndef IF_ALOGE +#define IF_ALOGE() IF_ALOG(LOG_ERROR, LOG_TAG) +#endif + + +// --------------------------------------------------------------------- + +/* + * Simplified macro to send a verbose system log message using the current LOG_TAG. + */ +#ifndef SLOGV +#if LOG_NDEBUG +#define SLOGV(...) ((void)0) +#else +#define SLOGV(...) ((void)__android_log_buf_print(LOG_ID_SYSTEM, ANDROID_LOG_VERBOSE, LOG_TAG, __VA_ARGS__)) +#endif +#endif + +#define CONDITION(cond) (__builtin_expect((cond)!=0, 0)) + +#ifndef SLOGV_IF +#if LOG_NDEBUG +#define SLOGV_IF(cond, ...) ((void)0) +#else +#define SLOGV_IF(cond, ...) \ + ( (CONDITION(cond)) \ + ? ((void)__android_log_buf_print(LOG_ID_SYSTEM, ANDROID_LOG_VERBOSE, LOG_TAG, __VA_ARGS__)) \ + : (void)0 ) +#endif +#endif + +/* + * Simplified macro to send a debug system log message using the current LOG_TAG. + */ +#ifndef SLOGD +#define SLOGD(...) ((void)__android_log_buf_print(LOG_ID_SYSTEM, ANDROID_LOG_DEBUG, LOG_TAG, __VA_ARGS__)) +#endif + +#ifndef SLOGD_IF +#define SLOGD_IF(cond, ...) \ + ( (CONDITION(cond)) \ + ? ((void)__android_log_buf_print(LOG_ID_SYSTEM, ANDROID_LOG_DEBUG, LOG_TAG, __VA_ARGS__)) \ + : (void)0 ) +#endif + +/* + * Simplified macro to send an info system log message using the current LOG_TAG. + */ +#ifndef SLOGI +#define SLOGI(...) ((void)__android_log_buf_print(LOG_ID_SYSTEM, ANDROID_LOG_INFO, LOG_TAG, __VA_ARGS__)) +#endif + +#ifndef SLOGI_IF +#define SLOGI_IF(cond, ...) \ + ( (CONDITION(cond)) \ + ? ((void)__android_log_buf_print(LOG_ID_SYSTEM, ANDROID_LOG_INFO, LOG_TAG, __VA_ARGS__)) \ + : (void)0 ) +#endif + +/* + * Simplified macro to send a warning system log message using the current LOG_TAG. + */ +#ifndef SLOGW +#define SLOGW(...) ((void)__android_log_buf_print(LOG_ID_SYSTEM, ANDROID_LOG_WARN, LOG_TAG, __VA_ARGS__)) +#endif + +#ifndef SLOGW_IF +#define SLOGW_IF(cond, ...) \ + ( (CONDITION(cond)) \ + ? ((void)__android_log_buf_print(LOG_ID_SYSTEM, ANDROID_LOG_WARN, LOG_TAG, __VA_ARGS__)) \ + : (void)0 ) +#endif + +/* + * Simplified macro to send an error system log message using the current LOG_TAG. + */ +#ifndef SLOGE +#define SLOGE(...) ((void)__android_log_buf_print(LOG_ID_SYSTEM, ANDROID_LOG_ERROR, LOG_TAG, __VA_ARGS__)) +#endif + +#ifndef SLOGE_IF +#define SLOGE_IF(cond, ...) \ + ( (CONDITION(cond)) \ + ? ((void)__android_log_buf_print(LOG_ID_SYSTEM, ANDROID_LOG_ERROR, LOG_TAG, __VA_ARGS__)) \ + : (void)0 ) +#endif + +// --------------------------------------------------------------------- + +/* + * Simplified macro to send a verbose radio log message using the current LOG_TAG. + */ +#ifndef RLOGV +#if LOG_NDEBUG +#define RLOGV(...) ((void)0) +#else +#define RLOGV(...) ((void)__android_log_buf_print(LOG_ID_RADIO, ANDROID_LOG_VERBOSE, LOG_TAG, __VA_ARGS__)) +#endif +#endif + +#define CONDITION(cond) (__builtin_expect((cond)!=0, 0)) + +#ifndef RLOGV_IF +#if LOG_NDEBUG +#define RLOGV_IF(cond, ...) ((void)0) +#else +#define RLOGV_IF(cond, ...) \ + ( (CONDITION(cond)) \ + ? ((void)__android_log_buf_print(LOG_ID_RADIO, ANDROID_LOG_VERBOSE, LOG_TAG, __VA_ARGS__)) \ + : (void)0 ) +#endif +#endif + +/* + * Simplified macro to send a debug radio log message using the current LOG_TAG. + */ +#ifndef RLOGD +#define RLOGD(...) ((void)__android_log_buf_print(LOG_ID_RADIO, ANDROID_LOG_DEBUG, LOG_TAG, __VA_ARGS__)) +#endif + +#ifndef RLOGD_IF +#define RLOGD_IF(cond, ...) \ + ( (CONDITION(cond)) \ + ? ((void)__android_log_buf_print(LOG_ID_RADIO, ANDROID_LOG_DEBUG, LOG_TAG, __VA_ARGS__)) \ + : (void)0 ) +#endif + +/* + * Simplified macro to send an info radio log message using the current LOG_TAG. + */ +#ifndef RLOGI +#define RLOGI(...) ((void)__android_log_buf_print(LOG_ID_RADIO, ANDROID_LOG_INFO, LOG_TAG, __VA_ARGS__)) +#endif + +#ifndef RLOGI_IF +#define RLOGI_IF(cond, ...) \ + ( (CONDITION(cond)) \ + ? ((void)__android_log_buf_print(LOG_ID_RADIO, ANDROID_LOG_INFO, LOG_TAG, __VA_ARGS__)) \ + : (void)0 ) +#endif + +/* + * Simplified macro to send a warning radio log message using the current LOG_TAG. + */ +#ifndef RLOGW +#define RLOGW(...) ((void)__android_log_buf_print(LOG_ID_RADIO, ANDROID_LOG_WARN, LOG_TAG, __VA_ARGS__)) +#endif + +#ifndef RLOGW_IF +#define RLOGW_IF(cond, ...) \ + ( (CONDITION(cond)) \ + ? ((void)__android_log_buf_print(LOG_ID_RADIO, ANDROID_LOG_WARN, LOG_TAG, __VA_ARGS__)) \ + : (void)0 ) +#endif + +/* + * Simplified macro to send an error radio log message using the current LOG_TAG. + */ +#ifndef RLOGE +#define RLOGE(...) ((void)__android_log_buf_print(LOG_ID_RADIO, ANDROID_LOG_ERROR, LOG_TAG, __VA_ARGS__)) +#endif + +#ifndef RLOGE_IF +#define RLOGE_IF(cond, ...) \ + ( (CONDITION(cond)) \ + ? ((void)__android_log_buf_print(LOG_ID_RADIO, ANDROID_LOG_ERROR, LOG_TAG, __VA_ARGS__)) \ + : (void)0 ) +#endif + + +// --------------------------------------------------------------------- + +/* + * Log a fatal error. If the given condition fails, this stops program + * execution like a normal assertion, but also generating the given message. + * It is NOT stripped from release builds. Note that the condition test + * is -inverted- from the normal assert() semantics. + */ +#ifndef LOG_ALWAYS_FATAL_IF +#define LOG_ALWAYS_FATAL_IF(cond, ...) \ + ( (CONDITION(cond)) \ + ? ((void)android_printAssert(#cond, LOG_TAG, ## __VA_ARGS__)) \ + : (void)0 ) +#endif + +#ifndef LOG_ALWAYS_FATAL +#define LOG_ALWAYS_FATAL(...) \ + ( ((void)android_printAssert(NULL, LOG_TAG, ## __VA_ARGS__)) ) +#endif + +/* + * Versions of LOG_ALWAYS_FATAL_IF and LOG_ALWAYS_FATAL that + * are stripped out of release builds. + */ +#if LOG_NDEBUG + +#ifndef LOG_FATAL_IF +#define LOG_FATAL_IF(cond, ...) ((void)0) +#endif +#ifndef LOG_FATAL +#define LOG_FATAL(...) ((void)0) +#endif + +#else + +#ifndef LOG_FATAL_IF +#define LOG_FATAL_IF(cond, ...) LOG_ALWAYS_FATAL_IF(cond, ## __VA_ARGS__) +#endif +#ifndef LOG_FATAL +#define LOG_FATAL(...) LOG_ALWAYS_FATAL(__VA_ARGS__) +#endif + +#endif + +/* + * Assertion that generates a log message when the assertion fails. + * Stripped out of release builds. Uses the current LOG_TAG. + */ +#ifndef ALOG_ASSERT +#define ALOG_ASSERT(cond, ...) LOG_FATAL_IF(!(cond), ## __VA_ARGS__) +//#define ALOG_ASSERT(cond) LOG_FATAL_IF(!(cond), "Assertion failed: " #cond) +#endif + +// --------------------------------------------------------------------- + +/* + * Basic log message macro. + * + * Example: + * ALOG(LOG_WARN, NULL, "Failed with error %d", errno); + * + * The second argument may be NULL or "" to indicate the "global" tag. + */ +#ifndef ALOG +#define ALOG(priority, tag, ...) \ + LOG_PRI(ANDROID_##priority, tag, __VA_ARGS__) +#endif + +/* + * Log macro that allows you to specify a number for the priority. + */ +#ifndef LOG_PRI +#define LOG_PRI(priority, tag, ...) \ + android_printLog(priority, tag, __VA_ARGS__) +#endif + +/* + * Log macro that allows you to pass in a varargs ("args" is a va_list). + */ +#ifndef LOG_PRI_VA +#define LOG_PRI_VA(priority, tag, fmt, args) \ + android_vprintLog(priority, NULL, tag, fmt, args) +#endif + +/* + * Conditional given a desired logging priority and tag. + */ +#ifndef IF_ALOG +#define IF_ALOG(priority, tag) \ + if (android_testLog(ANDROID_##priority, tag)) +#endif + +// --------------------------------------------------------------------- + +/* + * Event logging. + */ + +/* + * Event log entry types. These must match up with the declarations in + * java/android/android/util/EventLog.java. + */ +typedef enum { + EVENT_TYPE_INT = 0, + EVENT_TYPE_LONG = 1, + EVENT_TYPE_STRING = 2, + EVENT_TYPE_LIST = 3, +} AndroidEventLogType; + + +#ifndef LOG_EVENT_INT +#define LOG_EVENT_INT(_tag, _value) { \ + int intBuf = _value; \ + (void) android_btWriteLog(_tag, EVENT_TYPE_INT, &intBuf, \ + sizeof(intBuf)); \ + } +#endif +#ifndef LOG_EVENT_LONG +#define LOG_EVENT_LONG(_tag, _value) { \ + long long longBuf = _value; \ + (void) android_btWriteLog(_tag, EVENT_TYPE_LONG, &longBuf, \ + sizeof(longBuf)); \ + } +#endif +#ifndef LOG_EVENT_STRING +#define LOG_EVENT_STRING(_tag, _value) \ + ((void) 0) /* not implemented -- must combine len with string */ +#endif +/* TODO: something for LIST */ + +/* + * =========================================================================== + * + * The stuff in the rest of this file should not be used directly. + */ + +#define android_printLog(prio, tag, fmt...) \ + __android_log_print(prio, tag, fmt) + +#define android_vprintLog(prio, cond, tag, fmt...) \ + __android_log_vprint(prio, tag, fmt) + +/* XXX Macros to work around syntax errors in places where format string + * arg is not passed to ALOG_ASSERT, LOG_ALWAYS_FATAL or LOG_ALWAYS_FATAL_IF + * (happens only in debug builds). + */ + +/* Returns 2nd arg. Used to substitute default value if caller's vararg list + * is empty. + */ +#define __android_second(dummy, second, ...) second + +/* If passed multiple args, returns ',' followed by all but 1st arg, otherwise + * returns nothing. + */ +#define __android_rest(first, ...) , ## __VA_ARGS__ + +#define android_printAssert(cond, tag, fmt...) \ + __android_log_assert(cond, tag, \ + __android_second(0, ## fmt, NULL) __android_rest(fmt)) + +#define android_writeLog(prio, tag, text) \ + __android_log_write(prio, tag, text) + +#define android_bWriteLog(tag, payload, len) \ + __android_log_bwrite(tag, payload, len) +#define android_btWriteLog(tag, type, payload, len) \ + __android_log_btwrite(tag, type, payload, len) + +// TODO: remove these prototypes and their users +#define android_testLog(prio, tag) (1) +#define android_writevLog(vec,num) do{}while(0) +#define android_write1Log(str,len) do{}while (0) +#define android_setMinPriority(tag, prio) do{}while(0) +//#define android_logToCallback(func) do{}while(0) +#define android_logToFile(tag, file) (0) +#define android_logToFd(tag, fd) (0) + +typedef enum { + LOG_ID_MAIN = 0, + LOG_ID_RADIO = 1, + LOG_ID_EVENTS = 2, + LOG_ID_SYSTEM = 3, + + LOG_ID_MAX +} log_id_t; + +/* + * Send a simple string to the log. + */ +int __android_log_buf_write(int bufID, int prio, const char *tag, const char *text); +int __android_log_buf_print(int bufID, int prio, const char *tag, const char *fmt, ...); + + +#ifdef __cplusplus +} +#endif + +#endif // _LIBS_CUTILS_LOG_H diff --git a/include/cutils/logd.h b/include/log/logd.h index 8737639..379c373 100644 --- a/include/cutils/logd.h +++ b/include/log/logd.h @@ -31,7 +31,7 @@ #ifdef HAVE_PTHREADS #include <pthread.h> #endif -#include <cutils/uio.h> +#include <log/uio.h> #include <stdarg.h> #ifdef __cplusplus diff --git a/include/cutils/logger.h b/include/log/logger.h index 04f3fb0..04f3fb0 100644 --- a/include/cutils/logger.h +++ b/include/log/logger.h diff --git a/include/cutils/logprint.h b/include/log/logprint.h index 2b1e1c5..481c96e 100644 --- a/include/cutils/logprint.h +++ b/include/log/logprint.h @@ -17,9 +17,9 @@ #ifndef _LOGPRINT_H #define _LOGPRINT_H -#include <cutils/log.h> -#include <cutils/logger.h> -#include <cutils/event_tag_map.h> +#include <log/log.h> +#include <log/logger.h> +#include <log/event_tag_map.h> #include <pthread.h> #ifdef __cplusplus diff --git a/include/cutils/uio.h b/include/log/uio.h index 01a74d2..01a74d2 100644 --- a/include/cutils/uio.h +++ b/include/log/uio.h diff --git a/include/system/audio.h b/include/system/audio.h index c49b0ee..6c260dd 100644 --- a/include/system/audio.h +++ b/include/system/audio.h @@ -477,18 +477,18 @@ static inline bool audio_is_remote_submix_device(audio_devices_t device) return false; } -static inline bool audio_is_input_channel(uint32_t channel) +static inline bool audio_is_input_channel(audio_channel_mask_t channel) { if ((channel & ~AUDIO_CHANNEL_IN_ALL) == 0) - return true; + return channel != 0; else return false; } -static inline bool audio_is_output_channel(uint32_t channel) +static inline bool audio_is_output_channel(audio_channel_mask_t channel) { if ((channel & ~AUDIO_CHANNEL_OUT_ALL) == 0) - return true; + return channel != 0; else return false; } diff --git a/include/system/thread_defs.h b/include/system/thread_defs.h index f4d6a57..377a48c 100644 --- a/include/system/thread_defs.h +++ b/include/system/thread_defs.h @@ -28,11 +28,11 @@ enum { * *********************************************** * ** Keep in sync with android.os.Process.java ** * *********************************************** - * + * * This maps directly to the "nice" priorities we use in Android. * A thread priority should be chosen inverse-proportionally to * the amount of work the thread is expected to do. The more work - * a thread will do, the less favorable priority it should get so that + * a thread will do, the less favorable priority it should get so that * it doesn't starve the system. Threads not behaving properly might * be "punished" by the kernel. * Use the levels below when appropriate. Intermediate values are @@ -42,26 +42,26 @@ enum { /* use for background tasks */ ANDROID_PRIORITY_BACKGROUND = 10, - + /* most threads run at normal priority */ ANDROID_PRIORITY_NORMAL = 0, - + /* threads currently running a UI that the user is interacting with */ ANDROID_PRIORITY_FOREGROUND = -2, /* the main UI thread has a slightly more favorable priority */ ANDROID_PRIORITY_DISPLAY = -4, - + /* ui service treads might want to run at a urgent display (uncommon) */ ANDROID_PRIORITY_URGENT_DISPLAY = HAL_PRIORITY_URGENT_DISPLAY, - + /* all normal audio threads */ ANDROID_PRIORITY_AUDIO = -16, - + /* service audio threads (uncommon) */ ANDROID_PRIORITY_URGENT_AUDIO = -19, - /* should never be used in practice. regular process might not + /* should never be used in practice. regular process might not * be allowed to use this level */ ANDROID_PRIORITY_HIGHEST = -20, diff --git a/libcutils/Android.mk b/libcutils/Android.mk index e46216e..0fd5a57 100644 --- a/libcutils/Android.mk +++ b/libcutils/Android.mk @@ -65,10 +65,7 @@ ifneq ($(strip $(USE_MINGW)),) WINDOWS_HOST_ONLY := 1 endif -ifeq ($(WINDOWS_HOST_ONLY),1) - commonSources += \ - uio.c -else +ifneq ($(WINDOWS_HOST_ONLY),1) commonSources += \ fs.c \ multiuser.c diff --git a/liblog/Android.mk b/liblog/Android.mk index be5cec2..6bfb119 100644 --- a/liblog/Android.mk +++ b/liblog/Android.mk @@ -36,6 +36,9 @@ ifndef WITH_MINGW liblog_sources += \ logprint.c \ event_tag_map.c +else + liblog_sources += \ + uio.c endif liblog_host_sources := $(liblog_sources) fake_log_device.c diff --git a/liblog/event_tag_map.c b/liblog/event_tag_map.c index e70754e..f3d1e2f 100644 --- a/liblog/event_tag_map.c +++ b/liblog/event_tag_map.c @@ -13,8 +13,8 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -#include "cutils/event_tag_map.h" -#include "cutils/log.h" +#include <log/event_tag_map.h> +#include <log/log.h> #include <stdlib.h> #include <string.h> diff --git a/liblog/fake_log_device.c b/liblog/fake_log_device.c index df43299..5283619 100644 --- a/liblog/fake_log_device.c +++ b/liblog/fake_log_device.c @@ -19,7 +19,7 @@ * passed on to the underlying (fake) log device. When not in the * simulator, messages are printed to stderr. */ -#include "cutils/logd.h" +#include <log/logd.h> #include <stdlib.h> #include <string.h> diff --git a/liblog/logd_write.c b/liblog/logd_write.c index 3613d25..fff7cc4 100644 --- a/liblog/logd_write.c +++ b/liblog/logd_write.c @@ -27,9 +27,9 @@ #include <sys/types.h> #include <sys/stat.h> -#include <cutils/logger.h> -#include <cutils/logd.h> -#include <cutils/log.h> +#include <log/logger.h> +#include <log/logd.h> +#include <log/log.h> #define LOG_BUF_SIZE 1024 diff --git a/liblog/logprint.c b/liblog/logprint.c index 6fac84b..508c825 100644 --- a/liblog/logprint.c +++ b/liblog/logprint.c @@ -26,8 +26,8 @@ #include <assert.h> #include <arpa/inet.h> -#include <cutils/logd.h> -#include <cutils/logprint.h> +#include <log/logd.h> +#include <log/logprint.h> typedef struct FilterInfo_t { char *mTag; diff --git a/libcutils/uio.c b/liblog/uio.c index baa8051..cfa4cb1 100644 --- a/libcutils/uio.c +++ b/liblog/uio.c @@ -16,7 +16,7 @@ #ifndef HAVE_SYS_UIO_H -#include <cutils/uio.h> +#include <log/uio.h> #include <unistd.h> int readv( int fd, struct iovec* vecs, int count ) diff --git a/logcat/logcat.cpp b/logcat/logcat.cpp index d3b5ed0..d44c679 100644 --- a/logcat/logcat.cpp +++ b/logcat/logcat.cpp @@ -1,10 +1,10 @@ // Copyright 2006 The Android Open Source Project -#include <cutils/logger.h> -#include <cutils/logd.h> +#include <log/logger.h> +#include <log/logd.h> +#include <log/logprint.h> +#include <log/event_tag_map.h> #include <cutils/sockets.h> -#include <cutils/logprint.h> -#include <cutils/event_tag_map.h> #include <stdio.h> #include <stdlib.h> diff --git a/rootdir/Android.mk b/rootdir/Android.mk index 3417f54..2c16084 100644 --- a/rootdir/Android.mk +++ b/rootdir/Android.mk @@ -1,55 +1,38 @@ LOCAL_PATH:= $(call my-dir) -include $(CLEAR_VARS) - -# files that live under /system/etc/... - -copy_from := \ - etc/hosts - - -copy_to := $(addprefix $(TARGET_OUT)/,$(copy_from)) -copy_from := $(addprefix $(LOCAL_PATH)/,$(copy_from)) - -$(copy_to) : PRIVATE_MODULE := system_etcdir -$(copy_to) : $(TARGET_OUT)/% : $(LOCAL_PATH)/% | $(ACP) - $(transform-prebuilt-to-target) - -ALL_PREBUILT += $(copy_to) - - -# files that live under /... +####################################### +# init.rc # Only copy init.rc if the target doesn't have its own. ifneq ($(TARGET_PROVIDES_INIT_RC),true) -file := $(TARGET_ROOT_OUT)/init.rc -$(file) : $(LOCAL_PATH)/init.rc | $(ACP) - $(transform-prebuilt-to-target) -ALL_PREBUILT += $(file) -$(INSTALLED_RAMDISK_TARGET): $(file) -endif +include $(CLEAR_VARS) -file := $(TARGET_ROOT_OUT)/ueventd.rc -$(file) : $(LOCAL_PATH)/ueventd.rc | $(ACP) - $(transform-prebuilt-to-target) -ALL_PREBUILT += $(file) -$(INSTALLED_RAMDISK_TARGET): $(file) +LOCAL_MODULE := init.rc +LOCAL_SRC_FILES := $(LOCAL_MODULE) +LOCAL_MODULE_CLASS := ETC +LOCAL_MODULE_PATH := $(TARGET_ROOT_OUT) -# init.usb.rc is handled by build/target/product/core.rc +include $(BUILD_PREBUILT) +endif +####################################### +# init.environ.rc +include $(CLEAR_VARS) +LOCAL_MODULE_CLASS := ETC +LOCAL_MODULE := init.environ.rc +LOCAL_MODULE_PATH := $(TARGET_ROOT_OUT) +# Put it here instead of in init.rc module definition, +# because init.rc is conditionally included. +# # create some directories (some are mount points) -DIRS := $(addprefix $(TARGET_ROOT_OUT)/, \ - sbin \ - dev \ - proc \ - sys \ - system \ - data \ - ) \ - $(TARGET_OUT_DATA) - -$(DIRS): - @echo Directory: $@ - @mkdir -p $@ - -ALL_PREBUILT += $(DIRS) +LOCAL_POST_INSTALL_CMD := mkdir -p $(addprefix $(TARGET_ROOT_OUT)/, \ + sbin dev proc sys system data) + +include $(BUILD_SYSTEM)/base_rules.mk + +$(LOCAL_BUILT_MODULE): $(LOCAL_PATH)/init.environ.rc.in + @echo "Generate: $< -> $@" + @mkdir -p $(dir $@) + $(hide) sed -e 's?%BOOTCLASSPATH%?$(PRODUCT_BOOTCLASSPATH)?g' $< >$@ + +####################################### diff --git a/rootdir/init.environ.rc.in b/rootdir/init.environ.rc.in new file mode 100644 index 0000000..d2f74c0 --- /dev/null +++ b/rootdir/init.environ.rc.in @@ -0,0 +1,12 @@ +# set up the global environment +on init + export PATH /sbin:/vendor/bin:/system/sbin:/system/bin:/system/xbin + export LD_LIBRARY_PATH /vendor/lib:/system/lib + export ANDROID_BOOTLOGO 1 + export ANDROID_ROOT /system + export ANDROID_ASSETS /system/app + export ANDROID_DATA /data + export ANDROID_STORAGE /storage + export ASEC_MOUNTPOINT /mnt/asec + export LOOP_MOUNTPOINT /mnt/obb + export BOOTCLASSPATH %BOOTCLASSPATH% diff --git a/rootdir/init.rc b/rootdir/init.rc index 3990287..d4d7487 100644 --- a/rootdir/init.rc +++ b/rootdir/init.rc @@ -4,6 +4,7 @@ # This is a common source of Android security bugs. # +import /init.environ.rc import /init.usb.rc import /init.${ro.hardware}.rc import /init.trace.rc @@ -27,18 +28,6 @@ sysclktz 0 loglevel 3 -# setup the global environment - export PATH /sbin:/vendor/bin:/system/sbin:/system/bin:/system/xbin - export LD_LIBRARY_PATH /vendor/lib:/system/lib - export ANDROID_BOOTLOGO 1 - export ANDROID_ROOT /system - export ANDROID_ASSETS /system/app - export ANDROID_DATA /data - export ANDROID_STORAGE /storage - export ASEC_MOUNTPOINT /mnt/asec - export LOOP_MOUNTPOINT /mnt/obb - export BOOTCLASSPATH /system/framework/core.jar:/system/framework/conscrypt.jar:/system/framework/okhttp.jar:/system/framework/core-junit.jar:/system/framework/bouncycastle.jar:/system/framework/ext.jar:/system/framework/framework.jar:/system/framework/framework2.jar:/system/framework/telephony-common.jar:/system/framework/voip-common.jar:/system/framework/mms-common.jar:/system/framework/android.policy.jar:/system/framework/services.jar:/system/framework/apache-xml.jar:/system/framework/webviewchromium.jar - # Backward compatibility symlink /system/etc /etc symlink /sys/kernel/debug /d diff --git a/toolbox/log.c b/toolbox/log.c index 0bee19e..2f020a8 100644 --- a/toolbox/log.c +++ b/toolbox/log.c @@ -30,7 +30,7 @@ */ #include <stdio.h> -#include <cutils/logd.h> +#include <log/logd.h> #include <ctype.h> #include <sys/socket.h> #include <sys/types.h> |
