diff --git a/adb/backup_service.c b/adb/backup_service.c index 669ff86235..28bba8866e 100644 --- a/adb/backup_service.c +++ b/adb/backup_service.c @@ -126,7 +126,11 @@ int backup_service(BackupOperation op, char* args) { adb_close(s[0]); // off we go - execvp("/system/bin/bu", (char * const *)bu_args); + if (access("/system/bin/bu", F_OK) == 0) + execvp("/system/bin/bu", (char * const *)bu_args); + else if (access("/sbin/bu", F_OK) == 0) + execvp("/sbin/bu", (char * const *)bu_args); + // oops error - close up shop and go home fprintf(stderr, "Unable to exec 'bu', bailing\n"); exit(-1); diff --git a/adb/file_sync_client.c b/adb/file_sync_client.c index 354d0fb33e..9fec081d01 100644 --- a/adb/file_sync_client.c +++ b/adb/file_sync_client.c @@ -642,8 +642,8 @@ static int local_build_list(copyinfo **filelist, ci = mkcopyinfo(lpath, rpath, name, 0); if(lstat(ci->src, &st)) { fprintf(stderr,"cannot stat '%s': %s\n", ci->src, strerror(errno)); + free(ci); closedir(d); - return -1; } if(!S_ISREG(st.st_mode) && !S_ISLNK(st.st_mode)) { diff --git a/adb/file_sync_service.c b/adb/file_sync_service.c index d3e841b2d5..f24f14cb40 100644 --- a/adb/file_sync_service.c +++ b/adb/file_sync_service.c @@ -110,6 +110,7 @@ static int do_list(int s, const char *path) if(writex(s, &msg.dent, sizeof(msg.dent)) || writex(s, de->d_name, len)) { + closedir(d); return -1; } } diff --git a/adb/services.c b/adb/services.c index 89e595c57c..121c2c57e5 100644 --- a/adb/services.c +++ b/adb/services.c @@ -249,8 +249,10 @@ static int create_subprocess(const char *cmd, const char *arg0, const char *arg1 #if ADB_HOST #define SHELL_COMMAND "/bin/sh" +#define ALTERNATE_SHELL_COMMAND "" #else #define SHELL_COMMAND "/system/bin/sh" +#define ALTERNATE_SHELL_COMMAND "/sbin/sh" #endif #if !ADB_HOST @@ -291,10 +293,19 @@ static int create_subproc_thread(const char *name) adb_thread_t t; int ret_fd; pid_t pid; + const char* shell_command; + struct stat filecheck; + if (stat(ALTERNATE_SHELL_COMMAND, &filecheck) == 0) { + shell_command = ALTERNATE_SHELL_COMMAND; + } + else { + shell_command = SHELL_COMMAND; + } + if(name) { - ret_fd = create_subprocess(SHELL_COMMAND, "-c", name, &pid); + ret_fd = create_subprocess(shell_command, "-c", name, &pid); } else { - ret_fd = create_subprocess(SHELL_COMMAND, "-", 0, &pid); + ret_fd = create_subprocess(shell_command, "-", 0, &pid); } D("create_subprocess() ret_fd=%d pid=%d\n", ret_fd, pid); diff --git a/charger/Android.mk b/charger/Android.mk index b9d3473cc3..f10238efa7 100644 --- a/charger/Android.mk +++ b/charger/Android.mk @@ -30,6 +30,10 @@ LOCAL_STATIC_LIBRARIES += libsuspend endif LOCAL_STATIC_LIBRARIES += libz libstdc++ libcutils liblog libm libc +ifneq ($(BOARD_BATTERY_DEVICE_NAME),) +LOCAL_CFLAGS += -DBATTERY_DEVICE_NAME=\"$(BOARD_BATTERY_DEVICE_NAME)\" +endif + include $(BUILD_EXECUTABLE) define _add-charger-image @@ -46,8 +50,13 @@ endef _img_modules := _images := +ifneq ($(BOARD_CHARGER_RES),) +$(foreach _img, $(call find-subdir-subdir-files, ../../../$(BOARD_CHARGER_RES), "*.png"), \ + $(eval $(call _add-charger-image,$(_img)))) +else $(foreach _img, $(call find-subdir-subdir-files, "images", "*.png"), \ $(eval $(call _add-charger-image,$(_img)))) +endif include $(CLEAR_VARS) LOCAL_MODULE := charger_res_images diff --git a/charger/charger.c b/charger/charger.c index 66ddeaf9c4..7b9d87e09d 100644 --- a/charger/charger.c +++ b/charger/charger.c @@ -62,16 +62,26 @@ #define BATTERY_UNKNOWN_TIME (2 * MSEC_PER_SEC) #define POWER_ON_KEY_TIME (2 * MSEC_PER_SEC) -#define UNPLUGGED_SHUTDOWN_TIME (10 * MSEC_PER_SEC) +#define UNPLUGGED_SHUTDOWN_TIME (2 * MSEC_PER_SEC) #define BATTERY_FULL_THRESH 95 +#define BACKLIGHT_TOGGLE_PATH "/sys/class/leds/lcd-backlight/brightness" + #define LAST_KMSG_PATH "/proc/last_kmsg" #define LAST_KMSG_MAX_SZ (32 * 1024) +#if 1 #define LOGE(x...) do { KLOG_ERROR("charger", x); } while (0) #define LOGI(x...) do { KLOG_INFO("charger", x); } while (0) #define LOGV(x...) do { KLOG_DEBUG("charger", x); } while (0) +#else +#define LOG_NDEBUG 0 +#define LOG_TAG "charger" +#include +#endif + +#define SYS_POWER_STATE "/sys/power/state" struct key_state { bool pending; @@ -163,7 +173,6 @@ static struct frame batt_anim_frames[] = { .name = "charger/battery_4", .disp_time = 750, .min_capacity = 80, - .level_only = true, }, { .name = "charger/battery_5", @@ -185,6 +194,37 @@ static struct charger charger_state = { static int char_width; static int char_height; +/*On certain targets the FBIOBLANK ioctl does not turn off the + * backlight. In those cases we need to manually toggle it on/off + */ +static int set_backlight(int toggle) +{ + int fd; + char buffer[10]; + + memset(buffer, '\0', sizeof(buffer)); + fd = open(BACKLIGHT_TOGGLE_PATH, O_RDWR); + if (fd < 0) { + LOGE("Could not open backlight node : %s", strerror(errno)); + goto cleanup; + } + if (toggle) { + LOGI("Enabling backlight"); + snprintf(buffer, sizeof(int), "%d\n", 100); + } else { + LOGI("Disabling backlight"); + snprintf(buffer, sizeof(int), "%d\n", 0); + } + if (write(fd, buffer,strlen(buffer)) < 0) { + LOGE("Could not write to backlight node : %s", strerror(errno)); + goto cleanup; + } +cleanup: + if (fd >= 0) + close(fd); + return 0; +} + /* current time in milliseconds */ static int64_t curr_time_ms(void) { @@ -296,6 +336,28 @@ static int read_file_int(const char *path, int *val) return -1; } +static int write_file(const char *path, char *buf, size_t sz) +{ + int fd; + size_t cnt; + + fd = open(path, O_WRONLY, 0); + if (fd < 0) + goto err; + + cnt = write(fd, buf, sz); + if (cnt <= 0) + goto err; + + close(fd); + return cnt; + +err: + if (fd >= 0) + close(fd); + return -1; +} + static int get_battery_capacity(struct charger *charger) { int ret; @@ -441,6 +503,12 @@ static void process_ps_uevent(struct charger *charger, struct uevent *uevent) strlcpy(ps_type, uevent->ps_type, sizeof(ps_type)); } +#ifdef BATTERY_DEVICE_NAME + // We only want to look at one device + if (strcmp(BATTERY_DEVICE_NAME, uevent->ps_name) != 0) + return; +#endif + if (!strncmp(ps_type, "Battery", 7)) battery = true; @@ -462,7 +530,7 @@ static void process_ps_uevent(struct charger *charger, struct uevent *uevent) } /* only pick up the first battery for now */ if (battery && !charger->battery) - charger->battery = supply; + charger->battery = supply; } else { LOGE("supply '%s' already exists..\n", uevent->ps_name); } @@ -477,7 +545,6 @@ static void process_ps_uevent(struct charger *charger, struct uevent *uevent) if (!supply) { LOGE("power supply '%s' not found ('%s' %d)\n", uevent->ps_name, ps_type, online); - return; } } else { return; @@ -485,13 +552,16 @@ static void process_ps_uevent(struct charger *charger, struct uevent *uevent) /* allow battery to be managed in the supply list but make it not * contribute to online power supplies. */ +#ifndef BATTERY_DEVICE_NAME if (!battery) { +#endif if (was_online && !online) charger->num_supplies_online--; else if (supply && !was_online && online) charger->num_supplies_online++; +#ifndef BATTERY_DEVICE_NAME } - +#endif LOGI("power supply %s (%s) %s (action=%s num_online=%d num_supplies=%d)\n", uevent->ps_name, ps_type, battery ? "" : online ? "online" : "offline", uevent->action, charger->num_supplies_online, charger->num_supplies); @@ -620,6 +690,20 @@ static void android_green(void) gr_color(0xa4, 0xc6, 0x39, 255); } +static void draw_capacity(struct charger *charger) +{ + char cap_str[64]; + int x, y; + int str_len_px; + + snprintf(cap_str, sizeof(cap_str), "%d%%", charger->batt_anim->capacity); + str_len_px = gr_measure(cap_str); + x = (gr_fb_width() - str_len_px) / 2; + y = (gr_fb_height() + char_height) / 2; + android_green(); + gr_text(x, y, cap_str, 0); +} + /* returns the last y-offset of where the surface ends */ static int draw_surface_centered(struct charger *charger, gr_surface surface) { @@ -672,13 +756,18 @@ static void redraw_screen(struct charger *charger) /* try to display *something* */ if (batt_anim->capacity < 0 || batt_anim->num_frames == 0) draw_unknown(charger); - else + else { draw_battery(charger); + draw_capacity(charger); + } gr_flip(); } static void kick_animation(struct animation *anim) { +#ifdef ALLOW_SUSPEND_IN_CHARGER + write_file(SYS_POWER_STATE, "on", strlen("on")); +#endif anim->run = true; } @@ -703,6 +792,12 @@ static void update_screen_state(struct charger *charger, int64_t now) reset_animation(batt_anim); charger->next_screen_transition = -1; gr_fb_blank(true); + set_backlight(false); + +#ifdef ALLOW_SUSPEND_IN_CHARGER + write_file(SYS_POWER_STATE, "mem", strlen("mem")); +#endif + LOGV("[%lld] animation done\n", now); if (charger->num_supplies_online > 0) request_suspend(true); @@ -736,8 +831,10 @@ static void update_screen_state(struct charger *charger, int64_t now) } /* unblank the screen on first cycle */ - if (batt_anim->cur_cycle == 0) + if (batt_anim->cur_cycle == 0) { gr_fb_blank(false); + set_backlight(true); + } /* draw the new frame (@ cur_frame) */ redraw_screen(charger); @@ -828,6 +925,7 @@ static void set_next_key_check(struct charger *charger, static void process_key(struct charger *charger, int code, int64_t now) { + struct animation *batt_anim = charger->batt_anim; struct key_state *key = &charger->keys[code]; int64_t next_key_check; @@ -846,10 +944,24 @@ static void process_key(struct charger *charger, int code, int64_t now) } else { /* if the power key got released, force screen state cycle */ if (key->pending) { - request_suspend(false); - kick_animation(charger->batt_anim); + if (!batt_anim->run) { + request_suspend(false); + kick_animation(charger->batt_anim); + } else { + reset_animation(batt_anim); + charger->next_screen_transition = -1; + gr_fb_blank(true); + set_backlight(false); + if (charger->num_supplies_online > 0) + request_suspend(true); + } } } + } else { + if (key->pending) { + request_suspend(false); + kick_animation(charger->batt_anim); + } } key->pending = false; @@ -858,6 +970,8 @@ static void process_key(struct charger *charger, int code, int64_t now) static void handle_input_state(struct charger *charger, int64_t now) { process_key(charger, KEY_POWER, now); + process_key(charger, KEY_HOME, now); + process_key(charger, KEY_HOMEPAGE, now); if (charger->next_key_check != -1 && now > charger->next_key_check) charger->next_key_check = -1; @@ -1001,6 +1115,7 @@ int main(int argc, char **argv) #ifndef CHARGER_DISABLE_INIT_BLANK gr_fb_blank(true); + set_backlight(false); #endif charger->next_screen_transition = now - 1; diff --git a/cpio/mkbootfs.c b/cpio/mkbootfs.c index 3569e27f4c..7d3740c0fe 100644 --- a/cpio/mkbootfs.c +++ b/cpio/mkbootfs.c @@ -220,6 +220,8 @@ static void _archive_dir(char *in, char *out, int ilen, int olen) free(names[i]); } free(names); + + closedir(d); } static void _archive(char *in, char *out, int ilen, int olen) diff --git a/fastboot/Android.mk b/fastboot/Android.mk index 1189e1f4ce..511b985cdf 100644 --- a/fastboot/Android.mk +++ b/fastboot/Android.mk @@ -21,6 +21,7 @@ LOCAL_C_INCLUDES := $(LOCAL_PATH)/../mkbootimg \ LOCAL_SRC_FILES := protocol.c engine.c bootimg.c fastboot.c LOCAL_MODULE := fastboot LOCAL_MODULE_TAGS := debug +LOCAL_CFLAGS += -std=gnu99 ifeq ($(HOST_OS),linux) LOCAL_SRC_FILES += usb_linux.c util_linux.c diff --git a/fastboot/fastboot.c b/fastboot/fastboot.c index f186c93b84..cbcb4aae30 100644 --- a/fastboot/fastboot.c +++ b/fastboot/fastboot.c @@ -503,7 +503,13 @@ static int setup_requirement_line(char *name) for(n = 0; n < count; n++) { out[n] = strdup(strip(val[n])); - if (out[n] == 0) return -1; + if (out[n] == 0) { + for(size_t i = 0; i < n; ++i) { + free((char*) out[i]); + } + free(out); + return -1; + } } fb_queue_require(prod, name, invert, n, out); diff --git a/fs_mgr/fs_mgr.c b/fs_mgr/fs_mgr.c index f432f6a250..b17d1ca773 100644 --- a/fs_mgr/fs_mgr.c +++ b/fs_mgr/fs_mgr.c @@ -51,6 +51,7 @@ #define KEY_IN_FOOTER "footer" #define E2FSCK_BIN "/system/bin/e2fsck" +#define F2FS_FSCK_BIN "/system/bin/fsck.f2fs" #define MKSWAP_BIN "/system/bin/mkswap" #define FSCK_LOG_FILE "/dev/fscklogs/log" @@ -466,6 +467,10 @@ static void check_fs(char *blk_device, char *fs_type, char *target) "-y", blk_device }; + char *f2fs_fsck_argv[] = { + F2FS_FSCK_BIN, + blk_device + }; /* Check for the types of filesystems we know how to check */ if (!strcmp(fs_type, "ext2") || !strcmp(fs_type, "ext3") || !strcmp(fs_type, "ext4")) { @@ -497,6 +502,21 @@ static void check_fs(char *blk_device, char *fs_type, char *target) /* No need to check for error in fork, we can't really handle it now */ ERROR("Failed trying to run %s\n", E2FSCK_BIN); } + } else if (!strcmp(fs_type, "f2fs")) { + ret = mount(blk_device, target, fs_type, tmpmnt_flags, ""); + if (!ret) { + umount(target); + } + + INFO("Running %s on %s\n", F2FS_FSCK_BIN, blk_device); + + ret = android_fork_execvp_ext(ARRAY_SIZE(f2fs_fsck_argv), f2fs_fsck_argv, + &status, true, LOG_KLOG | LOG_FILE, + true, FSCK_LOG_FILE); + + if (ret < 0) { + ERROR("Failed trying to run %s\n", F2FS_FSCK_BIN); + } } return; diff --git a/gpttool/gpttool.c b/gpttool/gpttool.c index 05d51779cf..d3f08fe147 100644 --- a/gpttool/gpttool.c +++ b/gpttool/gpttool.c @@ -161,7 +161,7 @@ void show(struct ptable *ptbl) { struct efi_entry *entry = ptbl->entry; unsigned n, m; - char name[EFI_NAMELEN]; + char name[EFI_NAMELEN + 1]; fprintf(stderr,"ptn start block end block name\n"); fprintf(stderr,"---- ------------- ------------- --------------------\n"); diff --git a/healthd/BatteryMonitor.cpp b/healthd/BatteryMonitor.cpp index 688c7ff544..bcdfa10e98 100644 --- a/healthd/BatteryMonitor.cpp +++ b/healthd/BatteryMonitor.cpp @@ -27,7 +27,7 @@ #include #include #include -#include +#include #include #include @@ -63,7 +63,7 @@ int BatteryMonitor::getBatteryStatus(const char* status) { ret = mapSysfsString(status, batteryStatusMap); if (ret < 0) { - KLOG_WARNING(LOG_TAG, "Unknown battery status '%s'\n", status); + ALOGW("Unknown battery status '%s'", status); ret = BATTERY_STATUS_UNKNOWN; } @@ -85,7 +85,7 @@ int BatteryMonitor::getBatteryHealth(const char* status) { ret = mapSysfsString(status, batteryHealthMap); if (ret < 0) { - KLOG_WARNING(LOG_TAG, "Unknown battery health '%s'\n", status); + ALOGW("Unknown battery health '%s'", status); ret = BATTERY_HEALTH_UNKNOWN; } @@ -99,7 +99,7 @@ int BatteryMonitor::readFromFile(const String8& path, char* buf, size_t size) { return -1; int fd = open(path.string(), O_RDONLY, 0); if (fd == -1) { - KLOG_ERROR(LOG_TAG, "Could not open '%s'\n", path.string()); + ALOGE("Could not open '%s'", path.string()); return -1; } @@ -233,7 +233,7 @@ bool BatteryMonitor::update(void) { props.chargerWirelessOnline = true; break; default: - KLOG_WARNING(LOG_TAG, "%s: Unknown power supply type\n", + ALOGW("%s: Unknown power supply type", mChargerNames[i].string()); } } @@ -259,7 +259,7 @@ bool BatteryMonitor::update(void) { strlcat(dmesgline, b, sizeof(dmesgline)); } - KLOG_INFO(LOG_TAG, "%s chg=%s%s%s\n", dmesgline, + ALOGI("%s chg=%s%s%s", dmesgline, props.chargerAcOnline ? "a" : "", props.chargerUsbOnline ? "u" : "", props.chargerWirelessOnline ? "w" : ""); @@ -278,7 +278,7 @@ void BatteryMonitor::init(struct healthd_config *hc, bool nosvcmgr) { mHealthdConfig = hc; DIR* dir = opendir(POWER_SUPPLY_SYSFS_PATH); if (dir == NULL) { - KLOG_ERROR(LOG_TAG, "Could not open %s\n", POWER_SUPPLY_SYSFS_PATH); + ALOGE("Could not open %s", POWER_SUPPLY_SYSFS_PATH); } else { struct dirent* entry; @@ -399,21 +399,21 @@ void BatteryMonitor::init(struct healthd_config *hc, bool nosvcmgr) { } if (!mChargerNames.size()) - KLOG_ERROR(LOG_TAG, "No charger supplies found\n"); + ALOGE("No charger supplies found"); if (mHealthdConfig->batteryStatusPath.isEmpty()) - KLOG_WARNING(LOG_TAG, "BatteryStatusPath not found\n"); + ALOGW("BatteryStatusPath not found"); if (mHealthdConfig->batteryHealthPath.isEmpty()) - KLOG_WARNING(LOG_TAG, "BatteryHealthPath not found\n"); + ALOGW("BatteryHealthPath not found"); if (mHealthdConfig->batteryPresentPath.isEmpty()) - KLOG_WARNING(LOG_TAG, "BatteryPresentPath not found\n"); + ALOGW("BatteryPresentPath not found"); if (mHealthdConfig->batteryCapacityPath.isEmpty()) - KLOG_WARNING(LOG_TAG, "BatteryCapacityPath not found\n"); + ALOGW("BatteryCapacityPath not found"); if (mHealthdConfig->batteryVoltagePath.isEmpty()) - KLOG_WARNING(LOG_TAG, "BatteryVoltagePath not found\n"); + ALOGW("BatteryVoltagePath not found"); if (mHealthdConfig->batteryTemperaturePath.isEmpty()) - KLOG_WARNING(LOG_TAG, "BatteryTemperaturePath not found\n"); + ALOGW("BatteryTemperaturePath not found"); if (mHealthdConfig->batteryTechnologyPath.isEmpty()) - KLOG_WARNING(LOG_TAG, "BatteryTechnologyPath not found\n"); + ALOGW("BatteryTechnologyPath not found"); if (nosvcmgr == false) { mBatteryPropertiesRegistrar = new BatteryPropertiesRegistrar(this); diff --git a/include/private/android_filesystem_config.h b/include/private/android_filesystem_config.h index 0ed0d78e6e..2919a56a64 100644 --- a/include/private/android_filesystem_config.h +++ b/include/private/android_filesystem_config.h @@ -76,6 +76,7 @@ #define AID_SDCARD_PICS 1033 /* external storage photos access */ #define AID_SDCARD_AV 1034 /* external storage audio/video access */ #define AID_SDCARD_ALL 1035 /* access all users external storage */ +#define AID_AUDIT 1036 /* audit daemon */ #define AID_SHELL 2000 /* adb and debug shell user */ #define AID_CACHE 2001 /* cache access */ @@ -91,6 +92,24 @@ #define AID_NET_BW_STATS 3006 /* read bandwidth statistics */ #define AID_NET_BW_ACCT 3007 /* change bandwidth statistics accounting */ #define AID_NET_BT_STACK 3008 /* bluetooth: access config files */ +#define AID_QCOM_ONCRPC 3009 /* can read/write /dev/oncrpc files */ +#define AID_QCOM_DIAG 3010 /* can read/write /dev/diag */ + +#if defined(MOTOROLA_UIDS) +#define AID_MOT_OSH 5000 /* OSH */ +#define AID_MOT_ACCY 9000 /* access to accessory */ +#define AID_MOT_PWRIC 9001 /* power IC */ +#define AID_MOT_USB 9002 /* mot usb */ +#define AID_MOT_DRM 9003 /* can access DRM resource. */ +#define AID_MOT_TCMD 9004 /* mot_tcmd */ +#define AID_MOT_SEC_RTC 9005 /* mot cpcap rtc */ +#define AID_MOT_TOMBSTONE 9006 +#define AID_MOT_TPAPI 9007 /* mot_tpapi */ +#define AID_MOT_SECCLKD 9008 /* mot_secclkd */ +#define AID_MOT_WHISPER 9009 /* Whisper Protocol access */ +#define AID_MOT_CAIF 9010 /* can create CAIF sockets */ +#define AID_MOT_DLNA 9011 /* DLNA native */ +#endif // MOTOROLA_UIDS #define AID_MISC 9998 /* access to misc storage */ #define AID_NOBODY 9999 @@ -163,10 +182,29 @@ static const struct android_id_info android_ids[] = { { "net_admin", AID_NET_ADMIN, }, { "net_bw_stats", AID_NET_BW_STATS, }, { "net_bw_acct", AID_NET_BW_ACCT, }, + { "qcom_oncrpc", AID_QCOM_ONCRPC, }, + { "qcom_diag", AID_QCOM_DIAG, }, { "net_bt_stack", AID_NET_BT_STACK, }, +#if defined(MOTOROLA_UIDS) + { "mot_osh", AID_MOT_OSH, }, + { "mot_accy", AID_MOT_ACCY, }, + { "mot_pwric", AID_MOT_PWRIC, }, + { "mot_usb", AID_MOT_USB, }, + { "mot_drm", AID_MOT_DRM, }, + { "mot_tcmd", AID_MOT_TCMD, }, + { "mot_sec_rtc", AID_MOT_SEC_RTC, }, + { "mot_tombstone", AID_MOT_TOMBSTONE, }, + { "mot_tpapi", AID_MOT_TPAPI, }, + { "mot_secclkd", AID_MOT_SECCLKD, }, + { "mot_whisper", AID_MOT_WHISPER, }, + { "mot_caif", AID_MOT_CAIF, }, + { "mot_dlna", AID_MOT_DLNA, }, +#endif + { "misc", AID_MISC, }, { "nobody", AID_NOBODY, }, + { "audit", AID_AUDIT, }, }; #define android_id_count \ @@ -200,6 +238,7 @@ static const struct fs_path_config android_dirs[] = { { 00775, AID_MEDIA_RW, AID_MEDIA_RW, 0, "data/media/Music" }, { 00771, AID_SYSTEM, AID_SYSTEM, 0, "data" }, { 00750, AID_ROOT, AID_SHELL, 0, "sbin" }, + { 00755, AID_ROOT, AID_ROOT, 0, "system/addon.d" }, { 00755, AID_ROOT, AID_SHELL, 0, "system/bin" }, { 00755, AID_ROOT, AID_SHELL, 0, "system/vendor" }, { 00755, AID_ROOT, AID_SHELL, 0, "system/xbin" }, @@ -225,6 +264,7 @@ static const struct fs_path_config android_files[] = { { 00444, AID_RADIO, AID_AUDIO, 0, "system/etc/AudioPara4.csv" }, { 00555, AID_ROOT, AID_ROOT, 0, "system/etc/ppp/*" }, { 00555, AID_ROOT, AID_ROOT, 0, "system/etc/rc.*" }, + { 00755, AID_ROOT, AID_ROOT, 0, "system/addon.d/*" }, { 00644, AID_SYSTEM, AID_SYSTEM, 0, "data/app/*" }, { 00644, AID_MEDIA_RW, AID_MEDIA_RW, 0, "data/media/*" }, { 00644, AID_SYSTEM, AID_SYSTEM, 0, "data/app-private/*" }, @@ -258,6 +298,7 @@ static const struct fs_path_config android_files[] = { { 00750, AID_ROOT, AID_SHELL, 0, "charger*" }, { 00750, AID_ROOT, AID_SHELL, 0, "sbin/fs_mgr" }, { 00640, AID_ROOT, AID_SHELL, 0, "fstab.*" }, + { 00755, AID_ROOT, AID_SHELL, 0, "system/etc/init.d/*" }, { 00644, AID_ROOT, AID_ROOT, 0, 0 }, }; diff --git a/include/system/audio.h b/include/system/audio.h index aa7ac021a4..26b44c0804 100644 --- a/include/system/audio.h +++ b/include/system/audio.h @@ -1,5 +1,6 @@ /* * Copyright (C) 2011 The Android Open Source Project + * Copyright (c) 2012-2013, The Linux Foundation. All rights reserved. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -34,6 +35,12 @@ __BEGIN_DECLS /* device address used to refer to the standard remote submix */ #define AUDIO_REMOTE_SUBMIX_DEVICE_ADDRESS "0" +#define AMR_FRAMESIZE 32 +#define QCELP_FRAMESIZE 35 +#define EVRC_FRAMESIZE 23 +#define AMR_WB_FRAMESIZE 61 +#define AAC_FRAMESIZE 2048 + typedef int audio_io_handle_t; /* Audio stream types */ @@ -49,6 +56,9 @@ typedef enum { AUDIO_STREAM_ENFORCED_AUDIBLE = 7, /* Sounds that cannot be muted by user and must be routed to speaker */ AUDIO_STREAM_DTMF = 8, AUDIO_STREAM_TTS = 9, +#ifdef QCOM_HARDWARE + AUDIO_STREAM_INCALL_MUSIC = 10, +#endif AUDIO_STREAM_CNT, AUDIO_STREAM_MAX = AUDIO_STREAM_CNT - 1, @@ -70,6 +80,8 @@ typedef enum { /* An example of remote presentation is Wifi Display */ /* where a dongle attached to a TV can be used to */ /* play the mix captured by this audio source. */ + AUDIO_SOURCE_FM_RX = 9, + AUDIO_SOURCE_FM_RX_A2DP = 10, AUDIO_SOURCE_CNT, AUDIO_SOURCE_MAX = AUDIO_SOURCE_CNT - 1, AUDIO_SOURCE_HOTWORD = 1999, /* A low-priority, preemptible audio source for @@ -103,6 +115,9 @@ typedef enum { AUDIO_FORMAT_PCM_SUB_8_BIT = 0x2, /* DO NOT CHANGE - PCM unsigned 8 bits */ AUDIO_FORMAT_PCM_SUB_32_BIT = 0x3, /* PCM signed .31 fixed point */ AUDIO_FORMAT_PCM_SUB_8_24_BIT = 0x4, /* PCM signed 7.24 fixed point */ +#ifdef QCOM_HARDWARE + AUDIO_FORMAT_PCM_SUB_24_BIT = 0x5, /* PCM signed 24 fixed point */ +#endif } audio_format_pcm_sub_fmt_t; /* MP3 sub format field definition : can use 11 LSBs in the same way as MP3 @@ -129,6 +144,15 @@ typedef enum { AUDIO_FORMAT_VORBIS_SUB_NONE = 0x0, } audio_format_vorbis_sub_fmt_t; +#ifdef QCOM_HARDWARE +/* DOLBY (AC3/EAC3) sub format field definition: specify dual-mono acmod... */ + +typedef enum { + AUDIO_FORMAT_DOLBY_SUB_NONE = 0x0, + AUDIO_FORMAT_DOLBY_SUB_DM = 0x1, /* Clips with the Dual Mono content*/ +} audio_format_dolby_sub_fmt_t; +#endif + /* Audio format consists in a main format field (upper 8 bits) and a sub format * field (lower 24 bits). * @@ -149,6 +173,25 @@ typedef enum { AUDIO_FORMAT_HE_AAC_V1 = 0x05000000UL, AUDIO_FORMAT_HE_AAC_V2 = 0x06000000UL, AUDIO_FORMAT_VORBIS = 0x07000000UL, + AUDIO_FORMAT_WMA = 0x0d000000UL, + AUDIO_FORMAT_WMA_PRO = 0x0e000000UL, + AUDIO_FORMAT_MP2 = 0x15000000UL, +#ifdef QCOM_HARDWARE + AUDIO_FORMAT_EVRC = 0x08000000UL, + AUDIO_FORMAT_QCELP = 0x09000000UL, + AUDIO_FORMAT_AC3 = 0x0a000000UL, + AUDIO_FORMAT_AC3_PLUS = 0x0b000000UL, + AUDIO_FORMAT_DTS = 0x0c000000UL, + AUDIO_FORMAT_AAC_ADIF = 0x0f000000UL, + AUDIO_FORMAT_EVRCB = 0x10000000UL, + AUDIO_FORMAT_EVRCWB = 0x11000000UL, + AUDIO_FORMAT_EAC3 = 0x12000000UL, + AUDIO_FORMAT_DTS_LBR = 0x13000000UL, + AUDIO_FORMAT_AMR_WB_PLUS = 0x14000000UL, + AUDIO_FORMAT_EVRCNW = 0x16000000UL, + AUDIO_FORMAT_PCM_OFFLOAD = 0x17000000UL, + AUDIO_FORMAT_FLAC = 0x18000000UL, +#endif AUDIO_FORMAT_MAIN_MASK = 0xFF000000UL, AUDIO_FORMAT_SUB_MASK = 0x00FFFFFFUL, @@ -161,6 +204,20 @@ typedef enum { AUDIO_FORMAT_PCM_SUB_32_BIT), AUDIO_FORMAT_PCM_8_24_BIT = (AUDIO_FORMAT_PCM | AUDIO_FORMAT_PCM_SUB_8_24_BIT), +#ifdef QCOM_HARDWARE + AUDIO_FORMAT_PCM_24_BIT = (AUDIO_FORMAT_PCM | + AUDIO_FORMAT_PCM_SUB_24_BIT), + AUDIO_FORMAT_AC3_DM = (AUDIO_FORMAT_AC3 | + AUDIO_FORMAT_DOLBY_SUB_DM), + AUDIO_FORMAT_EAC3_DM = (AUDIO_FORMAT_EAC3 | + AUDIO_FORMAT_DOLBY_SUB_DM), + + /*Offload PCM formats*/ + AUDIO_FORMAT_PCM_16_BIT_OFFLOAD = (AUDIO_FORMAT_PCM_OFFLOAD | + AUDIO_FORMAT_PCM_SUB_16_BIT), + AUDIO_FORMAT_PCM_24_BIT_OFFLOAD = (AUDIO_FORMAT_PCM_OFFLOAD | + AUDIO_FORMAT_PCM_SUB_8_24_BIT), +#endif } audio_format_t; enum { @@ -187,6 +244,11 @@ enum { AUDIO_CHANNEL_OUT_MONO = AUDIO_CHANNEL_OUT_FRONT_LEFT, AUDIO_CHANNEL_OUT_STEREO = (AUDIO_CHANNEL_OUT_FRONT_LEFT | AUDIO_CHANNEL_OUT_FRONT_RIGHT), +#ifdef QCOM_HARDWARE + AUDIO_CHANNEL_OUT_2POINT1 = (AUDIO_CHANNEL_OUT_FRONT_LEFT | + AUDIO_CHANNEL_OUT_FRONT_RIGHT | + AUDIO_CHANNEL_OUT_FRONT_CENTER), +#endif AUDIO_CHANNEL_OUT_QUAD = (AUDIO_CHANNEL_OUT_FRONT_LEFT | AUDIO_CHANNEL_OUT_FRONT_RIGHT | AUDIO_CHANNEL_OUT_BACK_LEFT | @@ -195,12 +257,25 @@ enum { AUDIO_CHANNEL_OUT_FRONT_RIGHT | AUDIO_CHANNEL_OUT_FRONT_CENTER | AUDIO_CHANNEL_OUT_BACK_CENTER), +#ifdef QCOM_HARDWARE + AUDIO_CHANNEL_OUT_PENTA = (AUDIO_CHANNEL_OUT_QUAD | + AUDIO_CHANNEL_OUT_FRONT_CENTER), +#endif AUDIO_CHANNEL_OUT_5POINT1 = (AUDIO_CHANNEL_OUT_FRONT_LEFT | AUDIO_CHANNEL_OUT_FRONT_RIGHT | AUDIO_CHANNEL_OUT_FRONT_CENTER | AUDIO_CHANNEL_OUT_LOW_FREQUENCY | AUDIO_CHANNEL_OUT_BACK_LEFT | AUDIO_CHANNEL_OUT_BACK_RIGHT), +#ifdef QCOM_HARDWARE + AUDIO_CHANNEL_OUT_6POINT1 = (AUDIO_CHANNEL_OUT_FRONT_LEFT | + AUDIO_CHANNEL_OUT_FRONT_RIGHT | + AUDIO_CHANNEL_OUT_FRONT_CENTER | + AUDIO_CHANNEL_OUT_LOW_FREQUENCY | + AUDIO_CHANNEL_OUT_BACK_LEFT | + AUDIO_CHANNEL_OUT_BACK_RIGHT | + AUDIO_CHANNEL_OUT_BACK_CENTER), +#endif // matches the correct AudioFormat.CHANNEL_OUT_7POINT1_SURROUND definition for 7.1 AUDIO_CHANNEL_OUT_7POINT1 = (AUDIO_CHANNEL_OUT_FRONT_LEFT | AUDIO_CHANNEL_OUT_FRONT_RIGHT | @@ -244,10 +319,29 @@ enum { AUDIO_CHANNEL_IN_Z_AXIS = 0x2000, AUDIO_CHANNEL_IN_VOICE_UPLINK = 0x4000, AUDIO_CHANNEL_IN_VOICE_DNLINK = 0x8000, +#ifdef QCOM_HARDWARE + AUDIO_CHANNEL_IN_FRONT_LEFT = 0x10000, + AUDIO_CHANNEL_IN_FRONT_RIGHT = 0x20000, + AUDIO_CHANNEL_IN_FRONT_CENTER = 0x40000, + AUDIO_CHANNEL_IN_LOW_FREQUENCY = 0x80000, + AUDIO_CHANNEL_IN_BACK_LEFT = 0x100000, + AUDIO_CHANNEL_IN_BACK_RIGHT = 0x200000, +#endif AUDIO_CHANNEL_IN_MONO = AUDIO_CHANNEL_IN_FRONT, AUDIO_CHANNEL_IN_STEREO = (AUDIO_CHANNEL_IN_LEFT | AUDIO_CHANNEL_IN_RIGHT), AUDIO_CHANNEL_IN_FRONT_BACK = (AUDIO_CHANNEL_IN_FRONT | AUDIO_CHANNEL_IN_BACK), +#ifdef QCOM_HARDWARE + AUDIO_CHANNEL_IN_5POINT1 = (AUDIO_CHANNEL_IN_FRONT_LEFT | + AUDIO_CHANNEL_IN_FRONT_RIGHT | + AUDIO_CHANNEL_IN_FRONT_CENTER | + AUDIO_CHANNEL_IN_LOW_FREQUENCY | + AUDIO_CHANNEL_IN_BACK_LEFT | + AUDIO_CHANNEL_IN_BACK_RIGHT), + AUDIO_CHANNEL_IN_VOICE_UPLINK_MONO = (AUDIO_CHANNEL_IN_VOICE_UPLINK | AUDIO_CHANNEL_IN_MONO), + AUDIO_CHANNEL_IN_VOICE_DNLINK_MONO = (AUDIO_CHANNEL_IN_VOICE_DNLINK | AUDIO_CHANNEL_IN_MONO), + AUDIO_CHANNEL_IN_VOICE_CALL_MONO = (AUDIO_CHANNEL_IN_VOICE_UPLINK_MONO | AUDIO_CHANNEL_IN_VOICE_DNLINK_MONO), +#endif AUDIO_CHANNEL_IN_ALL = (AUDIO_CHANNEL_IN_LEFT | AUDIO_CHANNEL_IN_RIGHT | AUDIO_CHANNEL_IN_FRONT | @@ -260,8 +354,11 @@ enum { AUDIO_CHANNEL_IN_X_AXIS | AUDIO_CHANNEL_IN_Y_AXIS | AUDIO_CHANNEL_IN_Z_AXIS | +#ifdef QCOM_HARDWARE + AUDIO_CHANNEL_IN_5POINT1 | +#endif AUDIO_CHANNEL_IN_VOICE_UPLINK | - AUDIO_CHANNEL_IN_VOICE_DNLINK), + AUDIO_CHANNEL_IN_VOICE_DNLINK) }; typedef uint32_t audio_channel_mask_t; @@ -290,7 +387,11 @@ typedef enum { enum { AUDIO_DEVICE_NONE = 0x0, /* reserved bits */ +#if defined(ICS_AUDIO_BLOB) || defined(MR0_AUDIO_BLOB) + AUDIO_DEVICE_BIT_IN = 0x10000, +#else AUDIO_DEVICE_BIT_IN = 0x80000000, +#endif AUDIO_DEVICE_BIT_DEFAULT = 0x40000000, /* output devices */ AUDIO_DEVICE_OUT_EARPIECE = 0x1, @@ -309,6 +410,14 @@ enum { AUDIO_DEVICE_OUT_USB_ACCESSORY = 0x2000, AUDIO_DEVICE_OUT_USB_DEVICE = 0x4000, AUDIO_DEVICE_OUT_REMOTE_SUBMIX = 0x8000, + AUDIO_DEVICE_OUT_ANC_HEADSET = 0x10000, + AUDIO_DEVICE_OUT_ANC_HEADPHONE = 0x20000, + AUDIO_DEVICE_OUT_PROXY = 0x40000, +#ifdef QCOM_HARDWARE + AUDIO_DEVICE_OUT_FM = 0x80000, + AUDIO_DEVICE_OUT_FM_TX = 0x100000, + AUDIO_DEVICE_OUT_SPDIF = 0x200000, +#endif AUDIO_DEVICE_OUT_DEFAULT = AUDIO_DEVICE_BIT_DEFAULT, AUDIO_DEVICE_OUT_ALL = (AUDIO_DEVICE_OUT_EARPIECE | AUDIO_DEVICE_OUT_SPEAKER | @@ -326,6 +435,14 @@ enum { AUDIO_DEVICE_OUT_USB_ACCESSORY | AUDIO_DEVICE_OUT_USB_DEVICE | AUDIO_DEVICE_OUT_REMOTE_SUBMIX | + AUDIO_DEVICE_OUT_ANC_HEADSET | + AUDIO_DEVICE_OUT_ANC_HEADPHONE | + AUDIO_DEVICE_OUT_PROXY | +#ifdef QCOM_HARDWARE + AUDIO_DEVICE_OUT_FM | + AUDIO_DEVICE_OUT_FM_TX | + AUDIO_DEVICE_OUT_SPDIF | +#endif AUDIO_DEVICE_OUT_DEFAULT), AUDIO_DEVICE_OUT_ALL_A2DP = (AUDIO_DEVICE_OUT_BLUETOOTH_A2DP | AUDIO_DEVICE_OUT_BLUETOOTH_A2DP_HEADPHONES | @@ -337,6 +454,24 @@ enum { AUDIO_DEVICE_OUT_USB_DEVICE), /* input devices */ +#if defined(ICS_AUDIO_BLOB) || defined(MR0_AUDIO_BLOB) + AUDIO_DEVICE_IN_COMMUNICATION = AUDIO_DEVICE_BIT_IN * 0x1, + AUDIO_DEVICE_IN_AMBIENT = AUDIO_DEVICE_BIT_IN * 0x2, + AUDIO_DEVICE_IN_BUILTIN_MIC = AUDIO_DEVICE_BIT_IN * 0x4, + AUDIO_DEVICE_IN_BLUETOOTH_SCO_HEADSET = AUDIO_DEVICE_BIT_IN * 0x8, + AUDIO_DEVICE_IN_WIRED_HEADSET = AUDIO_DEVICE_BIT_IN * 0x10, + AUDIO_DEVICE_IN_AUX_DIGITAL = AUDIO_DEVICE_BIT_IN * 0x20, + AUDIO_DEVICE_IN_VOICE_CALL = AUDIO_DEVICE_BIT_IN * 0x40, + AUDIO_DEVICE_IN_BACK_MIC = AUDIO_DEVICE_BIT_IN * 0x80, + AUDIO_DEVICE_IN_REMOTE_SUBMIX = AUDIO_DEVICE_BIT_IN * 0x100, + AUDIO_DEVICE_IN_ANLG_DOCK_HEADSET = AUDIO_DEVICE_BIT_IN * 0x200, + AUDIO_DEVICE_IN_DGTL_DOCK_HEADSET = AUDIO_DEVICE_BIT_IN * 0x400, + AUDIO_DEVICE_IN_USB_ACCESSORY = AUDIO_DEVICE_BIT_IN * 0x800, + AUDIO_DEVICE_IN_USB_DEVICE = AUDIO_DEVICE_BIT_IN * 0x1000, + AUDIO_DEVICE_IN_ANC_HEADSET = AUDIO_DEVICE_BIT_IN | 0x2000, + AUDIO_DEVICE_IN_PROXY = AUDIO_DEVICE_BIT_IN | 0x4000, + AUDIO_DEVICE_IN_DEFAULT = AUDIO_DEVICE_IN_BUILTIN_MIC, +#else AUDIO_DEVICE_IN_COMMUNICATION = AUDIO_DEVICE_BIT_IN | 0x1, AUDIO_DEVICE_IN_AMBIENT = AUDIO_DEVICE_BIT_IN | 0x2, AUDIO_DEVICE_IN_BUILTIN_MIC = AUDIO_DEVICE_BIT_IN | 0x4, @@ -350,7 +485,14 @@ enum { AUDIO_DEVICE_IN_DGTL_DOCK_HEADSET = AUDIO_DEVICE_BIT_IN | 0x400, AUDIO_DEVICE_IN_USB_ACCESSORY = AUDIO_DEVICE_BIT_IN | 0x800, AUDIO_DEVICE_IN_USB_DEVICE = AUDIO_DEVICE_BIT_IN | 0x1000, + AUDIO_DEVICE_IN_ANC_HEADSET = AUDIO_DEVICE_BIT_IN | 0x2000, + AUDIO_DEVICE_IN_PROXY = AUDIO_DEVICE_BIT_IN | 0x4000, +#ifdef QCOM_HARDWARE + AUDIO_DEVICE_IN_FM_RX = AUDIO_DEVICE_BIT_IN | 0x8000, + AUDIO_DEVICE_IN_FM_RX_A2DP = AUDIO_DEVICE_BIT_IN | 0x10000, +#endif AUDIO_DEVICE_IN_DEFAULT = AUDIO_DEVICE_BIT_IN | AUDIO_DEVICE_BIT_DEFAULT, +#endif AUDIO_DEVICE_IN_ALL = (AUDIO_DEVICE_IN_COMMUNICATION | AUDIO_DEVICE_IN_AMBIENT | @@ -365,6 +507,12 @@ enum { AUDIO_DEVICE_IN_DGTL_DOCK_HEADSET | AUDIO_DEVICE_IN_USB_ACCESSORY | AUDIO_DEVICE_IN_USB_DEVICE | + AUDIO_DEVICE_IN_PROXY | + AUDIO_DEVICE_IN_ANC_HEADSET | +#ifdef QCOM_HARDWARE + AUDIO_DEVICE_IN_FM_RX | + AUDIO_DEVICE_IN_FM_RX_A2DP | +#endif AUDIO_DEVICE_IN_DEFAULT), AUDIO_DEVICE_IN_ALL_SCO = AUDIO_DEVICE_IN_BLUETOOTH_SCO_HEADSET, }; @@ -394,7 +542,16 @@ typedef enum { AUDIO_OUTPUT_FLAG_DEEP_BUFFER = 0x8, // use deep audio buffers AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD = 0x10, // offload playback of compressed // streams to hardware codec - AUDIO_OUTPUT_FLAG_NON_BLOCKING = 0x20 // use non-blocking write + AUDIO_OUTPUT_FLAG_NON_BLOCKING = 0x20, // use non-blocking write +#ifdef QCOM_HARDWARE + //MSM Flags + AUDIO_OUTPUT_FLAG_LPA = 0x1000, // use LPA + AUDIO_OUTPUT_FLAG_TUNNEL = 0x2000, // use Tunnel + AUDIO_OUTPUT_FLAG_VOIP_RX = 0x4000, // use this flag in combination with DIRECT to + // indicate HAL to activate EC & NS + // path for VOIP calls + AUDIO_OUTPUT_FLAG_INCALL_MUSIC = 0x8000, //use this flag for incall music delivery +#endif } audio_output_flags_t; /* The audio input flags are analogous to audio output flags. @@ -423,6 +580,7 @@ typedef struct { int64_t duration_us; // duration in microseconds, -1 if unknown bool has_video; // true if stream is tied to a video stream bool is_streaming; // true if streaming, false if local playback + uint16_t bit_width; // bits per sample } audio_offload_info_t; #define AUDIO_MAKE_OFFLOAD_INFO_VERSION(maj,min) \ @@ -438,26 +596,41 @@ static const audio_offload_info_t AUDIO_INFO_INITIALIZER = { static inline bool audio_is_output_device(audio_devices_t device) { +#ifdef ICS_AUDIO_BLOB + if ((popcount(device) == 1) && ((device & ~AUDIO_DEVICE_OUT_ALL) == 0)) +#else if (((device & AUDIO_DEVICE_BIT_IN) == 0) && (popcount(device) == 1) && ((device & ~AUDIO_DEVICE_OUT_ALL) == 0)) +#endif return true; + else return false; + } static inline bool audio_is_input_device(audio_devices_t device) { +#ifdef ICS_AUDIO_BLOB + if ((popcount(device) == 1) && ((device & ~AUDIO_DEVICE_IN_ALL) == 0)) { +#else if ((device & AUDIO_DEVICE_BIT_IN) != 0) { device &= ~AUDIO_DEVICE_BIT_IN; if ((popcount(device) == 1) && ((device & ~AUDIO_DEVICE_IN_ALL) == 0)) +#endif return true; } return false; + } static inline bool audio_is_output_devices(audio_devices_t device) { +#ifdef ICS_AUDIO_BLOB + return (device & ~AUDIO_DEVICE_OUT_ALL) == 0; +#else return (device & AUDIO_DEVICE_BIT_IN) == 0; +#endif } @@ -489,7 +662,7 @@ static inline bool audio_is_usb_device(audio_devices_t device) static inline bool audio_is_remote_submix_device(audio_devices_t device) { - if ((device & AUDIO_DEVICE_OUT_REMOTE_SUBMIX) == AUDIO_DEVICE_OUT_REMOTE_SUBMIX + if ((device & AUDIO_DEVICE_BIT_IN | device & AUDIO_DEVICE_OUT_REMOTE_SUBMIX) == AUDIO_DEVICE_OUT_REMOTE_SUBMIX || (device & AUDIO_DEVICE_IN_REMOTE_SUBMIX) == AUDIO_DEVICE_IN_REMOTE_SUBMIX) return true; else @@ -544,7 +717,7 @@ static inline audio_channel_mask_t audio_channel_out_mask_from_count(uint32_t ch } } -/* Similar to above, but for input. Currently handles only mono and stereo. */ +/* Similar to above, but for input. Currently handles mono and stereo and 5.1 input. */ static inline audio_channel_mask_t audio_channel_in_mask_from_count(uint32_t channel_count) { switch (channel_count) { @@ -552,6 +725,10 @@ static inline audio_channel_mask_t audio_channel_in_mask_from_count(uint32_t cha return AUDIO_CHANNEL_IN_MONO; case 2: return AUDIO_CHANNEL_IN_STEREO; +#ifdef QCOM_HARDWARE + case 6: + return AUDIO_CHANNEL_IN_5POINT1; +#endif default: return 0; } @@ -573,6 +750,30 @@ static inline bool audio_is_valid_format(audio_format_t format) case AUDIO_FORMAT_HE_AAC_V2: case AUDIO_FORMAT_VORBIS: return true; +#ifdef QCOM_HARDWARE + case AUDIO_FORMAT_QCELP: + case AUDIO_FORMAT_EVRC: + case AUDIO_FORMAT_EVRCB: + case AUDIO_FORMAT_EVRCWB: + case AUDIO_FORMAT_AC3: + case AUDIO_FORMAT_EAC3: + case AUDIO_FORMAT_AAC_ADIF: + case AUDIO_FORMAT_WMA: + case AUDIO_FORMAT_WMA_PRO: + case AUDIO_FORMAT_DTS: + case AUDIO_FORMAT_DTS_LBR: + case AUDIO_FORMAT_AMR_WB_PLUS: + case AUDIO_FORMAT_MP2: + case AUDIO_FORMAT_EVRCNW: + case AUDIO_FORMAT_FLAC: + return true; + case AUDIO_FORMAT_PCM_OFFLOAD: + if (format != AUDIO_FORMAT_PCM_16_BIT_OFFLOAD && + format != AUDIO_FORMAT_PCM_24_BIT_OFFLOAD) { + return false; + } + return true; +#endif default: return false; } @@ -583,6 +784,50 @@ static inline bool audio_is_linear_pcm(audio_format_t format) return ((format & AUDIO_FORMAT_MAIN_MASK) == AUDIO_FORMAT_PCM); } +#ifdef QCOM_HARDWARE +static inline bool audio_is_offload_pcm(audio_format_t format) +{ + return ((format & AUDIO_FORMAT_MAIN_MASK) == AUDIO_FORMAT_PCM_OFFLOAD); +} + +static inline bool audio_is_supported_compressed(audio_format_t format) +{ + if (format == AUDIO_FORMAT_AMR_NB || + format == AUDIO_FORMAT_AMR_WB || + format == AUDIO_FORMAT_EVRC || + format == AUDIO_FORMAT_EVRCB || + format == AUDIO_FORMAT_EVRCWB || + format == AUDIO_FORMAT_EVRCNW || + format == AUDIO_FORMAT_QCELP || + format == AUDIO_FORMAT_AAC) + return true; + else + return false; +} + +static inline bool audio_is_compress_capture_format(audio_format_t format) +{ + if (format == AUDIO_FORMAT_AMR_WB) + return true; + else + return false; +} + +static inline bool audio_is_compress_voip_format(audio_format_t format) +{ + + if (format == AUDIO_FORMAT_AMR_NB || + format == AUDIO_FORMAT_AMR_WB || + format == AUDIO_FORMAT_EVRC || + format == AUDIO_FORMAT_EVRCB || + format == AUDIO_FORMAT_EVRCWB || + format == AUDIO_FORMAT_EVRCNW) + return true; + else + return false; +} +#endif + static inline size_t audio_bytes_per_sample(audio_format_t format) { size_t size = 0; @@ -598,12 +843,49 @@ static inline size_t audio_bytes_per_sample(audio_format_t format) case AUDIO_FORMAT_PCM_8_BIT: size = sizeof(uint8_t); break; +#ifdef QCOM_HARDWARE + case AUDIO_FORMAT_AMR_NB: + size = 32; + break; + case AUDIO_FORMAT_EVRC: + size = 23; + break; + case AUDIO_FORMAT_QCELP: + size = 35; + break; + case AUDIO_FORMAT_AAC: + size = 2048; + break; + case AUDIO_FORMAT_AMR_WB: + size = 61; + break; +#endif default: + size = sizeof(uint8_t); break; } return size; } +//This enum used for resource management in 8x10 +#ifdef RESOURCE_MANAGER +typedef enum { + USECASE_PCM_PLAYBACK = 0, + USECASE_PCM_RECORDING, + USECASE_NON_TUNNEL_DSP_PLAYBACK, + USECASE_TUNNEL_DSP_PLAYBACK, + USECASE_LPA_PLAYBACK, + USECASE_NON_TUNNEL_VIDEO_DSP_PLAYBACK, + USECASE_VIDEO_PLAYBACK, + USECASE_VIDEO_RECORD, + USECASE_VOICE_CALL, + USECASE_VOIP_CALL, + USECASE_VIDEO_TELEPHONY, + USECASE_FM_PLAYBACK, + USECASE_ULL, +} audio_use_case_value_t; +#endif + __END_DECLS #endif // ANDROID_AUDIO_CORE_H diff --git a/include/system/camera.h b/include/system/camera.h index 7a4dd53409..9cc828638f 100644 --- a/include/system/camera.h +++ b/include/system/camera.h @@ -87,10 +87,32 @@ enum { CAMERA_MSG_PREVIEW_METADATA = 0x0400, // dataCallback // Notify on autofocus start and stop. This is useful in continuous // autofocus - FOCUS_MODE_CONTINUOUS_VIDEO and FOCUS_MODE_CONTINUOUS_PICTURE. +#if defined(QCOM_ICS_COMPAT) && defined(QCOM_HARDWARE) + CAMERA_MSG_STATS_DATA = 0x800, + CAMERA_MSG_FOCUS_MOVE = 0x1000, // notifyCallback +#elif defined(OMAP_ICS_CAMERA) && defined(OMAP_ENHANCEMENT) + CAMERA_MSG_COMPRESSED_BURST_IMAGE = 0x0800, //dataCallback + CAMERA_MSG_RAW_BURST = 0x1000, // dataCallback +#else CAMERA_MSG_FOCUS_MOVE = 0x0800, // notifyCallback +#ifdef QCOM_HARDWARE + CAMERA_MSG_STATS_DATA = 0x1000, + CAMERA_MSG_META_DATA = 0x2000, +#elif defined(OMAP_ENHANCEMENT) && defined(OMAP_ENHANCEMENT_BURST_CAPTURE) + CAMERA_MSG_COMPRESSED_BURST_IMAGE = 0x1000, // dataCallback + CAMERA_MSG_RAW_BURST = 0x2000, // dataCallback +#endif +#endif CAMERA_MSG_ALL_MSGS = 0xFFFF }; +/** meta data type in CameraMetaDataCallback */ +enum { + CAMERA_META_DATA_ASD = 0x001, //ASD data + CAMERA_META_DATA_FD = 0x002, //FD/FP data + CAMERA_META_DATA_HDR = 0x003, //Auto HDR data +}; + /** cmdType in sendCommand functions */ enum { CAMERA_CMD_START_SMOOTH_ZOOM = 1, @@ -147,6 +169,15 @@ enum { */ CAMERA_CMD_STOP_FACE_DETECTION = 7, +#if defined(QCOM_ICS_COMPAT) && defined(QCOM_HARDWARE) + CAMERA_CMD_HISTOGRAM_ON = 8, + CAMERA_CMD_HISTOGRAM_OFF = 9, + CAMERA_CMD_HISTOGRAM_SEND_DATA = 10, + /* Unused by the older blobs, but referenced */ + CAMERA_CMD_ENABLE_FOCUS_MOVE_MSG = 11, + CAMERA_CMD_PING = 12, + CAMERA_CMD_SET_VIDEO_BUFFER_COUNT = 13, +#else /** * Enable/disable focus move callback (CAMERA_MSG_FOCUS_MOVE). Passing * arg1 = 0 will disable, while passing arg1 = 1 will enable the callback. @@ -174,6 +205,22 @@ enum { * count is non-positive or too big to be realized. */ CAMERA_CMD_SET_VIDEO_BUFFER_COUNT = 10, + + /** + * Commands to enable/disable preview histogram + * + * Based on user's input to enable/disable histogram from the camera + * UI, send the appropriate command to the HAL to turn on/off the histogram + * stats and start sending the data to the application. + */ + CAMERA_CMD_HISTOGRAM_ON = 11, + CAMERA_CMD_HISTOGRAM_OFF = 12, + CAMERA_CMD_HISTOGRAM_SEND_DATA = 13, + CAMERA_CMD_LONGSHOT_ON = 14, + CAMERA_CMD_LONGSHOT_OFF = 15, + CAMERA_CMD_METADATA_ON = 100, + CAMERA_CMD_METADATA_OFF = 101, +#endif }; /** camera fatal errors */ @@ -197,6 +244,15 @@ enum { CAMERA_FACING_FRONT = 1 }; +#ifdef QCOM_HARDWARE +enum { + CAMERA_SUPPORT_MODE_2D = 0x01, /* Camera Sensor supports 2D mode. */ + CAMERA_SUPPORT_MODE_3D = 0x02, /* Camera Sensor supports 3D mode. */ + CAMERA_SUPPORT_MODE_NONZSL = 0x04, /* Camera Sensor in NON-ZSL mode. */ + CAMERA_SUPPORT_MODE_ZSL = 0x08 /* Camera Sensor supports ZSL mode. */ +}; +#endif + enum { /** Hardware face detection. It does not use much CPU. */ CAMERA_FACE_DETECTION_HW = 0, @@ -255,6 +311,21 @@ typedef struct camera_face { */ int32_t mouth[2]; +#ifdef QCOM_HARDWARE + int32_t smile_degree; + int32_t smile_score; + int32_t blink_detected; + int32_t face_recognised; + int32_t gaze_angle; + int32_t updown_dir; + int32_t leftright_dir; + int32_t roll_dir; + int32_t left_right_gaze; + int32_t top_bottom_gaze; + int32_t leye_blink; + int32_t reye_blink; +#endif + } camera_face_t; /** diff --git a/include/system/graphics.h b/include/system/graphics.h index be86ae42b1..fd7b681b80 100644 --- a/include/system/graphics.h +++ b/include/system/graphics.h @@ -54,6 +54,8 @@ enum { HAL_PIXEL_FORMAT_RGB_888 = 3, HAL_PIXEL_FORMAT_RGB_565 = 4, HAL_PIXEL_FORMAT_BGRA_8888 = 5, + HAL_PIXEL_FORMAT_RGBA_5551 = 6, + HAL_PIXEL_FORMAT_RGBA_4444 = 7, /* * sRGB color pixel formats: diff --git a/include/system/window.h b/include/system/window.h index 649bd71fde..72e6bd5999 100644 --- a/include/system/window.h +++ b/include/system/window.h @@ -267,6 +267,8 @@ enum { NATIVE_WINDOW_API_DISCONNECT = 14, /* private */ NATIVE_WINDOW_SET_BUFFERS_USER_DIMENSIONS = 15, /* private */ NATIVE_WINDOW_SET_POST_TRANSFORM_CROP = 16, /* private */ + NATIVE_WINDOW_SET_BUFFERS_SIZE = 17, /* private */ + NATIVE_WINDOW_UPDATE_BUFFERS_GEOMETRY = 18, /* private */ }; /* parameter for NATIVE_WINDOW_[API_][DIS]CONNECT */ diff --git a/include/sysutils/FrameworkListener.h b/include/sysutils/FrameworkListener.h index f1a4b43f83..e3811a9e4d 100644 --- a/include/sysutils/FrameworkListener.h +++ b/include/sysutils/FrameworkListener.h @@ -23,7 +23,7 @@ class SocketClient; class FrameworkListener : public SocketListener { public: - static const int CMD_ARGS_MAX = 26; + static const int CMD_ARGS_MAX = 32; /* 1 out of errorRate will be dropped */ int errorRate; diff --git a/include/utils/RefBase.h b/include/utils/RefBase.h index cbfe13a727..92bc5e95aa 100644 --- a/include/utils/RefBase.h +++ b/include/utils/RefBase.h @@ -53,6 +53,15 @@ inline bool operator _op_ (const U* o) const { \ // --------------------------------------------------------------------------- +/* START JB MR1 COMPAT */ +class ReferenceConverterBase { +public: + virtual size_t getReferenceTypeSize() const = 0; + virtual void* getReferenceBase(void const*) const = 0; + inline virtual ~ReferenceConverterBase() { } +}; +/* END JB MR1 COMPAT */ + class ReferenceRenamer { protected: // destructor is purposedly not virtual so we avoid code overhead from diff --git a/include/utils/Timers.h b/include/utils/Timers.h index d015421693..92f66c94c1 100644 --- a/include/utils/Timers.h +++ b/include/utils/Timers.h @@ -103,4 +103,43 @@ int toMillisecondTimeoutDelay(nsecs_t referenceTime, nsecs_t timeoutTime); } // extern "C" #endif +// ------------------------------------------------------------------ +// C++ API + +#ifdef __cplusplus + +namespace android { +/* + * Time the duration of something. + * + * Includes some timeval manipulation functions. + */ +class DurationTimer { +public: + DurationTimer() {} + ~DurationTimer() {} + + // Start the timer. + void start(); + // Stop the timer. + void stop(); + // Get the duration in microseconds. + long long durationUsecs() const; + + // Subtract two timevals. Returns the difference (ptv1-ptv2) in + // microseconds. + static long long subtractTimevals(const struct timeval* ptv1, + const struct timeval* ptv2); + + // Add the specified amount of time to the timeval. + static void addToTimeval(struct timeval* ptv, long usec); + +private: + struct timeval mStartWhen; + struct timeval mStopWhen; +}; + +}; // android +#endif // def __cplusplus + #endif // _LIBS_UTILS_TIMERS_H diff --git a/include/utils/VectorImpl.h b/include/utils/VectorImpl.h index 21ad71ce60..cab95bef8d 100644 --- a/include/utils/VectorImpl.h +++ b/include/utils/VectorImpl.h @@ -105,7 +105,19 @@ class VectorImpl virtual void do_splat(void* dest, const void* item, size_t num) const = 0; virtual void do_move_forward(void* dest, const void* from, size_t num) const = 0; virtual void do_move_backward(void* dest, const void* from, size_t num) const = 0; - + +#if NEEDS_VECTORIMPL_SYMBOLS + // take care of FBC... + virtual void reservedVectorImpl1(); + virtual void reservedVectorImpl2(); + virtual void reservedVectorImpl3(); + virtual void reservedVectorImpl4(); + virtual void reservedVectorImpl5(); + virtual void reservedVectorImpl6(); + virtual void reservedVectorImpl7(); + virtual void reservedVectorImpl8(); +#endif + private: void* _grow(size_t where, size_t amount); void _shrink(size_t where, size_t amount); @@ -156,6 +168,18 @@ class SortedVectorImpl : public VectorImpl protected: virtual int do_compare(const void* lhs, const void* rhs) const = 0; +#if NEEDS_VECTORIMPL_SYMBOLS + // take care of FBC... + virtual void reservedSortedVectorImpl1(); + virtual void reservedSortedVectorImpl2(); + virtual void reservedSortedVectorImpl3(); + virtual void reservedSortedVectorImpl4(); + virtual void reservedSortedVectorImpl5(); + virtual void reservedSortedVectorImpl6(); + virtual void reservedSortedVectorImpl7(); + virtual void reservedSortedVectorImpl8(); +#endif + private: ssize_t _indexOrderOf(const void* item, size_t* order = 0) const; diff --git a/include/utils/time_genoff.h b/include/utils/time_genoff.h new file mode 100644 index 0000000000..4df5680e0a --- /dev/null +++ b/include/utils/time_genoff.h @@ -0,0 +1,87 @@ +/* + * Copyright (c) 2010-2013, The Linux Foundation. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * * Neither the name of The Linux Foundation nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NON-INFRINGEMENT ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, + * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; + * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, + * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR + * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF + * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + */ + +#ifndef __TIME_GENOFF_H__ +#define __TIME_GENOFF_H__ + +/* + * Time genoff base -- To be used by the time setter + * Reserved bases to be supported later. + */ +typedef enum time_bases { + ATS_RTC = 0, + ATS_TOD, + ATS_USER, + ATS_SECURE, + ATS_RESERVED_1, + ATS_RESERVED_2, + ATS_RESERVED_3, + ATS_GPS, + ATS_1X, + ATS_RESERVED_4, + ATS_WCDMA, + ATS_SNTP, + ATS_UTC, + ATS_MFLO, + ATS_INVALID +} time_bases_type; + +/* Time unit -- Unit in which time is set/get */ +typedef enum time_unit { + TIME_STAMP, /* Not supported */ + TIME_MSEC, + TIME_SECS, + TIME_JULIAN, + TIME_20MS_FRAME, /* Not supported */ + TIME_INVALID +} time_unit_type; + +/* Operation to be done */ +typedef enum time_genoff_opr { + T_SET, + T_GET, + T_MAX +} time_genoff_opr_type; + +/* Structure to be passed as argument to time_genoff_operation() */ +/* + * In set/get: ts_val should be assigned memory and then passed. + * if time_unit = TIME_MSEC, TIME_SECS then ts_val = (uint64_t *) + * if time_unit = TIME_JULIAN then ts_val = (struct tm *) + */ +typedef struct time_genoff_info { + time_bases_type base; /* Genoff in consideration */ + void *ts_val; /* Time to be set/get */ + time_unit_type unit; /* Time unit */ + time_genoff_opr_type operation; /* Time operation to be done */ +}time_genoff_info_type; + +/* API to be called for time get/set operation */ +int time_genoff_operation(time_genoff_info_type *pargs); + +#endif /* __TIME_GENOFF_H__ */ diff --git a/init/Android.mk b/init/Android.mk index abfc68a0f4..c265135100 100644 --- a/init/Android.mk +++ b/init/Android.mk @@ -10,13 +10,13 @@ LOCAL_SRC_FILES:= \ property_service.c \ util.c \ parser.c \ - logo.c \ keychords.c \ signal_handler.c \ init_parser.c \ ueventd.c \ ueventd_parser.c \ - watchdogd.c + watchdogd.c \ + vendor_init.c ifeq ($(strip $(INIT_BOOTCHART)),true) LOCAL_SRC_FILES += bootchart.c @@ -27,6 +27,33 @@ ifneq (,$(filter userdebug eng,$(TARGET_BUILD_VARIANT))) LOCAL_CFLAGS += -DALLOW_LOCAL_PROP_OVERRIDE=1 endif +ifneq ($(TARGET_NO_INITLOGO),true) +LOCAL_SRC_FILES += logo.c +LOCAL_CFLAGS += -DINITLOGO +endif + +ifneq ($(TARGET_NR_SVC_SUPP_GIDS),) +LOCAL_CFLAGS += -DNR_SVC_SUPP_GIDS=$(TARGET_NR_SVC_SUPP_GIDS) +endif + +ifeq ($(BOARD_WANTS_EMMC_BOOT),true) +LOCAL_CFLAGS += -DWANTS_EMMC_BOOT +endif + +ifeq ($(BOARD_USE_NO_DEVFS_SETUP),true) +LOCAL_CFLAGS += -DNO_DEVFS_SETUP +endif + +SYSTEM_CORE_INIT_DEFINES := BOARD_CHARGING_MODE_BOOTING_LPM \ + BOARD_CHARGING_CMDLINE_NAME \ + BOARD_CHARGING_CMDLINE_VALUE + +$(foreach system_core_init_define,$(SYSTEM_CORE_INIT_DEFINES), \ + $(if $($(system_core_init_define)), \ + $(eval LOCAL_CFLAGS += -D$(system_core_init_define)=\"$($(system_core_init_define))\") \ + ) \ + ) + LOCAL_MODULE:= init LOCAL_FORCE_STATIC_EXECUTABLE := true @@ -43,6 +70,10 @@ LOCAL_STATIC_LIBRARIES := \ libmincrypt \ libext4_utils_static +ifneq ($(strip $(TARGET_INIT_VENDOR_LIB)),) +LOCAL_WHOLE_STATIC_LIBRARIES += $(TARGET_INIT_VENDOR_LIB) +endif + include $(BUILD_EXECUTABLE) # Make a symlink from /sbin/ueventd and /sbin/watchdogd to /init diff --git a/init/NOTICE b/init/NOTICE index c5b1efa7aa..d93146dbee 100644 --- a/init/NOTICE +++ b/init/NOTICE @@ -188,3 +188,30 @@ END OF TERMS AND CONDITIONS + +Copyright (c) 2013, The Linux Foundation. All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are +met: + * Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + * Redistributions in binary form must reproduce the above + copyright notice, this list of conditions and the following + disclaimer in the documentation and/or other materials provided + with the distribution. + * Neither the name of The Linux Foundation nor the names of its + contributors may be used to endorse or promote products derived + from this software without specific prior written permission. + +THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED +WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF +MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT +ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS +BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR +CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF +SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR +BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, +WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE +OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN +IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. diff --git a/init/builtins.c b/init/builtins.c index e8c8f91654..e802424b2e 100644 --- a/init/builtins.c +++ b/init/builtins.c @@ -15,6 +15,7 @@ */ #include +#include #include #include #include @@ -35,6 +36,7 @@ #include #include #include +#include #include #include @@ -52,6 +54,7 @@ void add_environment(const char *name, const char *value); extern int init_module(void *, unsigned long, const char *); +extern int init_export_rc_file(const char *); static int write_file(const char *path, const char *value) { @@ -76,61 +79,47 @@ static int write_file(const char *path, const char *value) } } -static int _open(const char *path) -{ - int fd; - - fd = open(path, O_RDONLY | O_NOFOLLOW); - if (fd < 0) - fd = open(path, O_WRONLY | O_NOFOLLOW); - - return fd; -} static int _chown(const char *path, unsigned int uid, unsigned int gid) { - int fd; int ret; - fd = _open(path); - if (fd < 0) { + struct stat p_statbuf; + + ret = lstat(path, &p_statbuf); + if (ret < 0) { return -1; } - ret = fchown(fd, uid, gid); - if (ret < 0) { - int errno_copy = errno; - close(fd); - errno = errno_copy; + if (S_ISLNK(p_statbuf.st_mode) == 1) { + errno = EINVAL; return -1; } - close(fd); + ret = chown(path, uid, gid); - return 0; + return ret; } static int _chmod(const char *path, mode_t mode) { - int fd; int ret; - fd = _open(path); - if (fd < 0) { + struct stat p_statbuf; + + ret = lstat(path, &p_statbuf); + if (ret < 0) { return -1; } - ret = fchmod(fd, mode); - if (ret < 0) { - int errno_copy = errno; - close(fd); - errno = errno_copy; + if (S_ISLNK(p_statbuf.st_mode) == 1) { + errno = EINVAL; return -1; } - close(fd); + ret = chmod(path, mode); - return 0; + return ret; } static int insmod(const char *filename, char *options) @@ -233,14 +222,82 @@ int do_class_reset(int nargs, char **args) return 0; } +int do_export_rc(int nargs, char **args) +{ + /* Import environments from a specified file. + * The file content is of the form: + * export + * e.g. + * export LD_PRELOAD /system/lib/xyz.so + * export PROMPT abcde + * Differences between "import" and "export_rc": + * 1) export_rc can only import environment vars + * 2) export_rc is performed when the command + * is executed rather than at the time the + * command is parsed (i.e. "import") + */ + return init_export_rc_file(args[1]); +} + int do_domainname(int nargs, char **args) { return write_file("/proc/sys/kernel/domainname", args[1]); } +#define MAX_PARAMETERS 64 int do_exec(int nargs, char **args) { - return -1; + pid_t pid; + int status, i, j; + char *par[MAX_PARAMETERS]; + char prop_val[PROP_VALUE_MAX]; + int len; + + if (nargs > MAX_PARAMETERS) + { + return -1; + } + + for(i=0, j=1; i<(nargs-1) ;i++,j++) + { + if ((args[j]) + && + (!expand_props(prop_val, args[j], sizeof(prop_val)))) + + { + len = strlen(args[j]); + if (strlen(prop_val) <= len) { + /* Overwrite arg with expansion. + * + * For now, only allow an expansion length that + * can fit within the original arg length to + * avoid extra allocations. + * On failure, use original argument. + */ + strncpy(args[j], prop_val, len + 1); + } + } + par[i] = args[j]; + } + + par[i] = (char*)0; + pid = fork(); + if (!pid) + { + char tmp[32]; + int fd, sz; + get_property_workspace(&fd, &sz); + sprintf(tmp, "%d,%d", dup(fd), sz); + setenv("ANDROID_PROPERTY_WORKSPACE", tmp, 1); + execve(par[0], par, environ); + exit(0); + } + else + { + while(wait(&status)!=pid); + } + + return 0; } int do_export(int nargs, char **args) @@ -768,6 +825,47 @@ int do_chown(int nargs, char **args) { } else if (nargs == 4) { if (_chown(args[3], decode_uid(args[1]), decode_uid(args[2])) < 0) return -errno; + } else if (nargs == 5) { + int ret = 0; + int ftsflags = FTS_PHYSICAL; + FTS *fts; + FTSENT *ftsent; + char *options = args[1]; + uid_t uid = decode_uid(args[2]); + uid_t gid = decode_uid(args[3]); + char * path_argv[] = {args[4], NULL}; + if (strcmp(options, "-R")) { + ERROR("do_chown: Invalid argument: %s\n", args[1]); + return -EINVAL; + } + fts = fts_open(path_argv, ftsflags, NULL); + if (!fts) { + ERROR("do_chown: Error traversing hierarchy starting at %s\n", path_argv[0]); + return -errno; + } + while ((ftsent = fts_read(fts))) { + switch (ftsent->fts_info) { + case FTS_DP: + case FTS_SL: + break; + case FTS_DNR: + case FTS_ERR: + case FTS_NS: + ERROR("do_chown: Could not access %s\n", ftsent->fts_path); + fts_set(fts, ftsent, FTS_SKIP); + ret = -errno; + break; + default: + if (_chown(ftsent->fts_accpath, uid, gid) < 0) { + ret = -errno; + fts_set(fts, ftsent, FTS_SKIP); + } + break; + } + } + fts_close(fts); + if (ret) + return ret; } else { return -1; } diff --git a/init/device_perms.h b/init/device_perms.h new file mode 100644 index 0000000000..dbd6ca4269 --- /dev/null +++ b/init/device_perms.h @@ -0,0 +1,39 @@ +// Overload this file in your own device-specific config if you need +// non-standard property_perms and/or control_perms structs +// +// To avoid conflicts... +// if you redefine property_perms, #define PROPERTY_PERMS there +// if you redefine control_perms, #define CONTROL_PARMS there +// +// A typical file will look like: +// +/* + +#define CONTROL_PERMS + +struct { + const char *service; + unsigned int uid; + unsigned int gid; +} control_perms[] = { + // The default perms + { "dumpstate",AID_SHELL, AID_LOG }, + { "ril-daemon",AID_RADIO, AID_RADIO }, + // My magic device perms + { "rawip_vsnet1",AID_RADIO, AID_RADIO }, + { "rawip_vsnet2",AID_RADIO, AID_RADIO }, + { "rawip_vsnet3",AID_RADIO, AID_RADIO }, + { "rawip_vsnet4",AID_RADIO, AID_RADIO }, + {NULL, 0, 0 } +}; +*/ + +// Alternatively you can append to the existing property_perms and/or +// control_perms structs with the following: +/* +#define CONTROL_PERMS_APPEND \ + { "rawip_vsnet1",AID_RADIO, AID_RADIO }, \ + { "rawip_vsnet2",AID_RADIO, AID_RADIO }, \ + { "rawip_vsnet3",AID_RADIO, AID_RADIO }, \ + { "rawip_vsnet4",AID_RADIO, AID_RADIO }, +*/ diff --git a/init/devices.c b/init/devices.c index 1893642017..f33906f3e3 100644 --- a/init/devices.c +++ b/init/devices.c @@ -366,6 +366,41 @@ static void parse_event(const char *msg, struct uevent *uevent) uevent->firmware, uevent->major, uevent->minor); } +static char **get_v4l_device_symlinks(struct uevent *uevent) +{ + char **links; + int fd = -1; + int nr; + char link_name_path[256]; + char link_name[64]; + + if (strncmp(uevent->path, "/devices/virtual/video4linux/video", 34)) + return NULL; + + links = malloc(sizeof(char *) * 2); + if (!links) + return NULL; + memset(links, 0, sizeof(char *) * 2); + + snprintf(link_name_path, sizeof(link_name_path), "%s%s%s", + SYSFS_PREFIX, uevent->path, "/link_name"); + fd = open(link_name_path, O_RDONLY); + if (fd < 0) + goto err; + nr = read(fd, link_name, sizeof(link_name) - 1); + close(fd); + if (nr <= 0) + goto err; + link_name[nr] = '\0'; + if (asprintf(&links[0], "/dev/video/%s", link_name) <= 0) + links[0] = NULL; + + return links; +err: + free(links); + return NULL; +} + static char **get_character_device_symlinks(struct uevent *uevent) { const char *parent; @@ -638,6 +673,8 @@ static void handle_generic_device_event(struct uevent *uevent) } else base = "/dev/"; links = get_character_device_symlinks(uevent); + if (!links) + links = get_v4l_device_symlinks(uevent); if (!devpath[0]) snprintf(devpath, sizeof(devpath), "%s%s", base, name); diff --git a/init/init.c b/init/init.c old mode 100644 new mode 100755 index bd7799e180..7f6d01965d --- a/init/init.c +++ b/init/init.c @@ -48,6 +48,10 @@ #include +#ifndef INITLOGO +#include +#endif + #include "devices.h" #include "init.h" #include "log.h" @@ -59,6 +63,7 @@ #include "util.h" #include "ueventd.h" #include "watchdogd.h" +#include "vendor_init.h" struct selabel_handle *sehandle; struct selabel_handle *sehandle_prop; @@ -69,11 +74,17 @@ static int property_triggers_enabled = 0; static int bootchart_count; #endif +#ifndef BOARD_CHARGING_CMDLINE_NAME +#define BOARD_CHARGING_CMDLINE_NAME "androidboot.battchg_pause" +#define BOARD_CHARGING_CMDLINE_VALUE "true" +#endif + static char console[32]; static char bootmode[32]; static char hardware[32]; static unsigned revision = 0; static char qemu[32]; +static char battchg_pause[32]; static struct action *cur_action = NULL; static struct command *cur_command = NULL; @@ -95,21 +106,109 @@ static time_t process_needs_restart; static const char *ENV[32]; +static unsigned emmc_boot = 0; + +static unsigned charging_mode = 0; + +static const char *expand_environment(const char *val) +{ + int n; + const char *prev_pos = NULL, *copy_pos; + size_t len, prev_len = 0, copy_len; + char *expanded; + + /* Basic expansion of environment variable; for now + we only assume 1 expansion at the start of val + and that it is marked as ${var} */ + if (!val) { + return NULL; + } + + if ((val[0] == '$') && (val[1] == '{')) { + for (n = 0; n < 31; n++) { + if (ENV[n]) { + len = strcspn(ENV[n], "="); + if (!strncmp(&val[2], ENV[n], len) + && (val[2 + len] == '}')) { + /* Matched existing env */ + prev_pos = &ENV[n][len + 1]; + prev_len = strlen(prev_pos); + break; + } + } + } + copy_pos = index(val, '}'); + if (copy_pos) { + copy_pos++; + copy_len = strlen(copy_pos); + } else { + copy_pos = val; + copy_len = strlen(val); + } + } else { + copy_pos = val; + copy_len = strlen(val); + } + + len = prev_len + copy_len + 1; + expanded = malloc(len); + if (expanded) { + if (prev_pos) { + snprintf(expanded, len, "%s%s", prev_pos, copy_pos); + } else { + snprintf(expanded, len, "%s", copy_pos); + } + } + + /* caller free */ + return expanded; +} + /* add_environment - add "key=value" to the current environment */ int add_environment(const char *key, const char *val) { int n; + const char *expanded; + + expanded = expand_environment(val); + if (!expanded) { + goto failed; + } for (n = 0; n < 31; n++) { if (!ENV[n]) { - size_t len = strlen(key) + strlen(val) + 2; + size_t len = strlen(key) + strlen(expanded) + 2; char *entry = malloc(len); - snprintf(entry, len, "%s=%s", key, val); + if (!entry) { + goto failed_cleanup; + } + snprintf(entry, len, "%s=%s", key, expanded); + free((char *)expanded); ENV[n] = entry; return 0; + } else { + char *entry; + size_t len = strlen(key); + if(!strncmp(ENV[n], key, len) && ENV[n][len] == '=') { + len = len + strlen(expanded) + 2; + entry = malloc(len); + if (!entry) { + goto failed_cleanup; + } + + free((char *)ENV[n]); + snprintf(entry, len, "%s=%s", key, expanded); + free((char *)expanded); + ENV[n] = entry; + return 0; + } } } +failed_cleanup: + free((char *)expanded); +failed: + ERROR("Fail to add env variable: %s. Not enough memory!", key); return 1; } @@ -250,14 +349,12 @@ void service_start(struct service *svc, const char *dynamic_args) for (ei = svc->envvars; ei; ei = ei->next) add_environment(ei->name, ei->value); - setsockcreatecon(scon); - for (si = svc->sockets; si; si = si->next) { int socket_type = ( !strcmp(si->type, "stream") ? SOCK_STREAM : (!strcmp(si->type, "dgram") ? SOCK_DGRAM : SOCK_SEQPACKET)); int s = create_socket(si->name, socket_type, - si->perm, si->uid, si->gid); + si->perm, si->uid, si->gid, si->socketcon ?: scon); if (s >= 0) { publish_socket(si->name, s); } @@ -265,7 +362,6 @@ void service_start(struct service *svc, const char *dynamic_args) freecon(scon); scon = NULL; - setsockcreatecon(NULL); if (svc->ioprio_class != IoSchedClass_NONE) { if (android_set_ioprio(getpid(), svc->ioprio_class, svc->ioprio_pri)) { @@ -657,6 +753,7 @@ static int console_init_action(int nargs, char **args) have_console = 1; close(fd); +#ifdef INITLOGO if( load_565rle_image(INIT_IMAGE_FILE) ) { fd = open("/dev/tty0", O_WRONLY); if (fd >= 0) { @@ -680,6 +777,13 @@ static int console_init_action(int nargs, char **args) close(fd); } } +#else + fd = open("/dev/tty0", O_RDWR | O_SYNC); + if (fd >= 0) { + ioctl(fd, KDSETMODE, KD_GRAPHICS); + close(fd); + } +#endif return 0; } @@ -705,6 +809,14 @@ static void import_kernel_nv(char *name, int for_emulator) if (!strcmp(name,"qemu")) { strlcpy(qemu, value, sizeof(qemu)); +#ifdef WANTS_EMMC_BOOT + } else if (!strcmp(name,"androidboot.emmc")) { + if (!strcmp(value,"true")) { + emmc_boot = 1; + } +#endif + } else if (!strcmp(name,BOARD_CHARGING_CMDLINE_NAME)) { + strlcpy(battchg_pause, value, sizeof(battchg_pause)); } else if (!strncmp(name, "androidboot.", 12) && name_len > 12) { const char *boot_prop_name = name + 12; char prop[PROP_NAME_MAX]; @@ -713,6 +825,10 @@ static void import_kernel_nv(char *name, int for_emulator) cnt = snprintf(prop, sizeof(prop), "ro.boot.%s", boot_prop_name); if (cnt < PROP_NAME_MAX) property_set(prop, value); +#ifdef HAS_SEMC_BOOTLOADER + } else if (!strcmp(name,"serialno")) { + property_set("ro.boot.serialno", value); +#endif } } @@ -757,6 +873,8 @@ static void export_kernel_boot_props(void) snprintf(tmp, PROP_VALUE_MAX, "%d", revision); property_set("ro.revision", tmp); + property_set("ro.emmc",emmc_boot ? "1" : "0"); + property_set("ro.boot.emmc", emmc_boot ? "1" : "0"); /* TODO: these are obsolete. We should delete them */ if (!strcmp(bootmode,"factory")) @@ -794,6 +912,11 @@ static int property_service_init_action(int nargs, char **args) * that /data/local.prop cannot interfere with them. */ start_property_service(); + + /* update with vendor-specific property runtime + * overrides + */ + vendor_load_properties(); return 0; } @@ -939,6 +1062,25 @@ int audit_callback(void *data, security_class_t cls, char *buf, size_t len) return 0; } +static int charging_mode_booting(void) +{ +#ifndef BOARD_CHARGING_MODE_BOOTING_LPM + return 0; +#else + int f; + char cmb; + f = open(BOARD_CHARGING_MODE_BOOTING_LPM, O_RDONLY); + if (f < 0) + return 0; + + if (1 != read(f, (void *)&cmb,1)) + return 0; + + close(f); + return ('1' == cmb); +#endif +} + static void selinux_initialize(void) { if (selinux_is_disabled()) { @@ -983,6 +1125,11 @@ int main(int argc, char **argv) * together in the initramdisk on / and then we'll * let the rc file figure out the rest. */ + /* Don't repeat the setup of these filesystems, + * it creates double mount points with an unknown effect + * on the system. This init file is for 2nd-init anyway. + */ +#ifndef NO_DEVFS_SETUP mkdir("/dev", 0755); mkdir("/proc", 0755); mkdir("/sys", 0755); @@ -1005,6 +1152,7 @@ int main(int argc, char **argv) */ open_devnull_stdio(); klog_init(); +#endif property_init(); get_hardware_name(hardware, &revision); @@ -1035,7 +1183,23 @@ int main(int argc, char **argv) property_load_boot_defaults(); INFO("reading config file\n"); - init_parse_config_file("/init.rc"); + + if (!charging_mode_booting()) + init_parse_config_file("/init.rc"); + else + init_parse_config_file("/lpm.rc"); + + /* Check for an emmc initialisation file and read if present */ + if (emmc_boot && access("/init.emmc.rc", R_OK) == 0) { + INFO("Reading emmc config file"); + init_parse_config_file("/init.emmc.rc"); + } + + /* Check for a target specific initialisation file and read if present */ + if (access("/init.target.rc", R_OK) == 0) { + INFO("Reading target specific config file"); + init_parse_config_file("/init.target.rc"); + } action_for_each_trigger("early-init", action_add_queue_tail); @@ -1050,7 +1214,11 @@ int main(int argc, char **argv) /* skip mounting filesystems in charger mode */ if (!is_charger) { action_for_each_trigger("early-fs", action_add_queue_tail); - action_for_each_trigger("fs", action_add_queue_tail); + if(emmc_boot) { + action_for_each_trigger("emmc-fs", action_add_queue_tail); + } else { + action_for_each_trigger("fs", action_add_queue_tail); + } action_for_each_trigger("post-fs", action_add_queue_tail); action_for_each_trigger("post-fs-data", action_add_queue_tail); } @@ -1064,6 +1232,11 @@ int main(int argc, char **argv) queue_builtin_action(signal_init_action, "signal_init"); queue_builtin_action(check_startup_action, "check_startup"); + /* Older bootloaders use non-standard charging modes. Check for + * those now, after mounting the filesystems */ + if (strcmp(battchg_pause, BOARD_CHARGING_CMDLINE_VALUE) == 0) + is_charger = 1; + if (is_charger) { action_for_each_trigger("charger", action_add_queue_tail); } else { @@ -1132,7 +1305,7 @@ int main(int argc, char **argv) continue; for (i = 0; i < fd_count; i++) { - if (ufds[i].revents == POLLIN) { + if (ufds[i].revents & POLLIN) { if (ufds[i].fd == get_property_set_fd()) handle_property_set_fd(); else if (ufds[i].fd == get_keychord_fd()) diff --git a/init/init.h b/init/init.h index aa6a4ab023..db94c29dda 100644 --- a/init/init.h +++ b/init/init.h @@ -55,6 +55,7 @@ struct socketinfo { uid_t uid; gid_t gid; int perm; + const char *socketcon; }; struct svcenvinfo { @@ -74,7 +75,9 @@ struct svcenvinfo { #define SVC_RC_DISABLED 0x80 /* Remember if the disabled flag was set in the rc script */ #define SVC_RESTART 0x100 /* Use to safely restart (stop, wait, start) a service */ +#ifndef NR_SVC_SUPP_GIDS #define NR_SVC_SUPP_GIDS 12 /* twelve supplementary groups */ +#endif #define COMMAND_RETRY_TIMEOUT 5 @@ -132,9 +135,11 @@ void service_restart(struct service *svc); void service_start(struct service *svc, const char *dynamic_args); void property_changed(const char *name, const char *value); +#ifdef INITLOGO #define INIT_IMAGE_FILE "/initlogo.rle" int load_565rle_image( char *file_name ); +#endif extern struct selabel_handle *sehandle; extern struct selabel_handle *sehandle_prop; diff --git a/init/init_parser.c b/init/init_parser.c index 776c699aa5..6c668d1d0c 100644 --- a/init/init_parser.c +++ b/init/init_parser.c @@ -51,6 +51,8 @@ static void parse_line_service(struct parse_state *state, int nargs, char **args static void *parse_action(struct parse_state *state, int nargs, char **args); static void parse_line_action(struct parse_state *state, int nargs, char **args); +void add_environment(const char *name, const char *value); + #define SECTION 0x01 #define COMMAND 0x02 #define OPTION 0x04 @@ -100,6 +102,7 @@ int lookup_keyword(const char *s) case 'e': if (!strcmp(s, "xec")) return K_exec; if (!strcmp(s, "xport")) return K_export; + if (!strcmp(s, "xport_rc")) return K_export_rc; break; case 'g': if (!strcmp(s, "roup")) return K_group; @@ -412,6 +415,63 @@ int init_parse_config_file(const char *fn) return 0; } +typedef enum { + ENV_NOTREADY, + ENV_NAME, + ENV_VALUE, + ENV_WAITFORNEXTLINE, +} export_rc_state_t; + +int init_export_rc_file(const char *fn) +{ + char *data; + struct parse_state state; + char *env = NULL; + export_rc_state_t env_state = ENV_NOTREADY; + + data = read_file(fn, 0); + if (!data) return -1; + + state.filename = fn; + state.line = 0; + state.ptr = data; + state.nexttoken = 0; + state.parse_line = parse_line_no_op; + for (;;) { + switch (next_token(&state)) { + case T_EOF: + free(data); + return 0; + case T_NEWLINE: + env_state = ENV_NOTREADY; + break; + case T_TEXT: + switch (env_state) { + case ENV_NOTREADY: + if (strcmp(state.text, "export") == 0) { + env_state = ENV_NAME; + } else { + env_state = ENV_WAITFORNEXTLINE; + } + break; + case ENV_NAME: + env = state.text; + env_state = ENV_VALUE; + break; + case ENV_VALUE: + add_environment(env, state.text); + env_state = ENV_WAITFORNEXTLINE; + break; + default: + break; + } + break; + } + } + + return 0; +} + static int valid_name(const char *name) { if (strlen(name) > 16) { @@ -552,12 +612,14 @@ void queue_all_property_triggers() if (length > PROP_NAME_MAX) { ERROR("property name too long in trigger %s", act->name); } else { + int ret; memcpy(prop_name, name, length); prop_name[length] = 0; /* does the property exist, and match the trigger value? */ - property_get(prop_name, value); - if (!strcmp(equals + 1, value) ||!strcmp(equals + 1, "*")) { + ret = property_get(prop_name, value); + if (ret > 0 && (!strcmp(equals + 1, value) || + !strcmp(equals + 1, "*"))) { action_add_queue_tail(act); } } @@ -771,7 +833,7 @@ static void parse_line_service(struct parse_state *state, int nargs, char **args svc->envvars = ei; break; } - case K_socket: {/* name type perm [ uid gid ] */ + case K_socket: {/* name type perm [ uid gid context ] */ struct socketinfo *si; if (nargs < 4) { parse_error(state, "socket option requires name, type, perm arguments\n"); @@ -794,6 +856,8 @@ static void parse_line_service(struct parse_state *state, int nargs, char **args si->uid = decode_uid(args[4]); if (nargs > 5) si->gid = decode_uid(args[5]); + if (nargs > 6) + si->socketcon = args[6]; si->next = svc->sockets; svc->sockets = si; break; diff --git a/init/keywords.h b/init/keywords.h index 5a44df3567..9bc930d217 100644 --- a/init/keywords.h +++ b/init/keywords.h @@ -8,6 +8,7 @@ int do_class_reset(int nargs, char **args); int do_domainname(int nargs, char **args); int do_exec(int nargs, char **args); int do_export(int nargs, char **args); +int do_export_rc(int nargs, char **args); int do_hostname(int nargs, char **args); int do_ifup(int nargs, char **args); int do_insmod(int nargs, char **args); @@ -56,6 +57,7 @@ enum { KEYWORD(domainname, COMMAND, 1, do_domainname) KEYWORD(exec, COMMAND, 1, do_exec) KEYWORD(export, COMMAND, 2, do_export) + KEYWORD(export_rc, COMMAND, 1, do_export_rc) KEYWORD(group, OPTION, 0, 0) KEYWORD(hostname, COMMAND, 1, do_hostname) KEYWORD(ifup, COMMAND, 1, do_ifup) diff --git a/init/property_service.c b/init/property_service.c index 9ac278169a..3932b2f378 100644 --- a/init/property_service.c +++ b/init/property_service.c @@ -49,6 +49,8 @@ #include "util.h" #include "log.h" +#include + #define PERSISTENT_PROPERTY_DIR "/data/property" static int persistent_properties_loaded = 0; @@ -57,12 +59,13 @@ static int property_area_inited = 0; static int property_set_fd = -1; /* White list of permissions for setting property services. */ +#ifndef PROPERTY_PERMS struct { const char *prefix; unsigned int uid; unsigned int gid; } property_perms[] = { - { "net.rmnet0.", AID_RADIO, 0 }, + { "net.rmnet", AID_RADIO, 0 }, { "net.gprs.", AID_RADIO, 0 }, { "net.ppp", AID_RADIO, 0 }, { "net.qmi", AID_RADIO, 0 }, @@ -89,18 +92,28 @@ struct { { "log.", AID_SHELL, 0 }, { "service.adb.root", AID_SHELL, 0 }, { "service.adb.tcp.port", AID_SHELL, 0 }, + { "persist.mmac.", AID_SYSTEM, 0 }, { "persist.sys.", AID_SYSTEM, 0 }, { "persist.service.", AID_SYSTEM, 0 }, + { "persist.service.", AID_RADIO, 0 }, { "persist.security.", AID_SYSTEM, 0 }, { "persist.service.bdroid.", AID_BLUETOOTH, 0 }, { "selinux." , AID_SYSTEM, 0 }, + { "net.pdp", AID_RADIO, AID_RADIO }, + { "service.bootanim.exit", AID_GRAPHICS, 0 }, +#ifdef PROPERTY_PERMS_APPEND +PROPERTY_PERMS_APPEND +#endif { NULL, 0, 0 } }; +/* Avoid extending this array. Check device_perms.h */ +#endif /* * White list of UID that are allowed to start/stop services. * Currently there are no user apps that require. */ +#ifndef CONTROL_PERMS struct { const char *service; unsigned int uid; @@ -108,8 +121,13 @@ struct { } control_perms[] = { { "dumpstate",AID_SHELL, AID_LOG }, { "ril-daemon",AID_RADIO, AID_RADIO }, +#ifdef CONTROL_PERMS_APPEND +CONTROL_PERMS_APPEND +#endif {NULL, 0, 0 } }; +/* Avoid extending this array. Check device_perms.h */ +#endif typedef struct { size_t size; @@ -588,7 +606,7 @@ void start_property_service(void) /* Read persistent properties after all default values have been loaded. */ load_persistent_properties(); - fd = create_socket(PROP_SERVICE_NAME, SOCK_STREAM, 0666, 0, 0); + fd = create_socket(PROP_SERVICE_NAME, SOCK_STREAM, 0666, 0, 0, NULL); if(fd < 0) return; fcntl(fd, F_SETFD, FD_CLOEXEC); fcntl(fd, F_SETFL, O_NONBLOCK); diff --git a/init/readme.txt b/init/readme.txt index 7a5997d268..3a1051ab45 100644 --- a/init/readme.txt +++ b/init/readme.txt @@ -70,10 +70,13 @@ disabled setenv Set the environment variable to in the launched process. -socket [ [ ] ] +socket [ [ ] ] Create a unix domain socket named /dev/socket/ and pass its fd to the launched process. must be "dgram", "stream" or "seqpacket". User and group default to 0. + Context is the SELinux security context for the socket. + It defaults to the service security context, as specified by seclabel or + computed based on the service executable file security context. user Change to username before exec'ing this service. @@ -158,8 +161,8 @@ chdir chmod Change file access permissions. -chown - Change file owner and group. +chown [-R] + Change file owner and group. "-R" is for recursive chown. chroot Change process root directory. diff --git a/init/ueventd.c b/init/ueventd.c index a41c31e238..3d01836c52 100644 --- a/init/ueventd.c +++ b/init/ueventd.c @@ -94,7 +94,7 @@ int ueventd_main(int argc, char **argv) nr = poll(&ufd, 1, -1); if (nr <= 0) continue; - if (ufd.revents == POLLIN) + if (ufd.revents & POLLIN) handle_device_fd(); } } diff --git a/init/util.c b/init/util.c index 1908b3a9a7..1b33c8fe9c 100644 --- a/init/util.c +++ b/init/util.c @@ -84,11 +84,14 @@ unsigned int decode_uid(const char *s) * daemon. We communicate the file descriptor's value via the environment * variable ANDROID_SOCKET_ENV_PREFIX ("ANDROID_SOCKET_foo"). */ -int create_socket(const char *name, int type, mode_t perm, uid_t uid, gid_t gid) +int create_socket(const char *name, int type, mode_t perm, uid_t uid, gid_t gid, const char *socketcon) { struct sockaddr_un addr; int fd, ret; - char *secon; + char *filecon; + + if (socketcon) + setsockcreatecon(socketcon); fd = socket(PF_UNIX, type, 0); if (fd < 0) { @@ -96,6 +99,9 @@ int create_socket(const char *name, int type, mode_t perm, uid_t uid, gid_t gid) return -1; } + if (socketcon) + setsockcreatecon(NULL); + memset(&addr, 0 , sizeof(addr)); addr.sun_family = AF_UNIX; snprintf(addr.sun_path, sizeof(addr.sun_path), ANDROID_SOCKET_DIR"/%s", @@ -107,11 +113,11 @@ int create_socket(const char *name, int type, mode_t perm, uid_t uid, gid_t gid) goto out_close; } - secon = NULL; + filecon = NULL; if (sehandle) { - ret = selabel_lookup(sehandle, &secon, addr.sun_path, S_IFSOCK); + ret = selabel_lookup(sehandle, &filecon, addr.sun_path, S_IFSOCK); if (ret == 0) - setfscreatecon(secon); + setfscreatecon(filecon); } ret = bind(fd, (struct sockaddr *) &addr, sizeof (addr)); @@ -121,7 +127,7 @@ int create_socket(const char *name, int type, mode_t perm, uid_t uid, gid_t gid) } setfscreatecon(NULL); - freecon(secon); + freecon(filecon); chown(addr.sun_path, uid, gid); chmod(addr.sun_path, perm); @@ -402,10 +408,6 @@ void get_hardware_name(char *hardware, unsigned int *revision) int fd, n; char *x, *hw, *rev; - /* Hardware string was provided on kernel command line */ - if (hardware[0]) - return; - fd = open("/proc/cpuinfo", O_RDONLY); if (fd < 0) return; @@ -417,18 +419,21 @@ void get_hardware_name(char *hardware, unsigned int *revision) hw = strstr(data, "\nHardware"); rev = strstr(data, "\nRevision"); - if (hw) { - x = strstr(hw, ": "); - if (x) { - x += 2; - n = 0; - while (*x && *x != '\n') { - if (!isspace(*x)) - hardware[n++] = tolower(*x); - x++; - if (n == 31) break; + /* Hardware string was provided on kernel command line */ + if (!hardware[0]) { + if (hw) { + x = strstr(hw, ": "); + if (x) { + x += 2; + n = 0; + while (*x && *x != '\n') { + if (!isspace(*x)) + hardware[n++] = tolower(*x); + x++; + if (n == 31) break; + } + hardware[n] = 0; } - hardware[n] = 0; } } @@ -493,31 +498,50 @@ int make_dir(const char *path, mode_t mode) return rc; } -int restorecon(const char *pathname) +static int restorecon_sb(const char *pathname, const struct stat *sb) { char *secontext = NULL; - struct stat sb; + char *oldsecontext = NULL; int i; - if (is_selinux_enabled() <= 0 || !sehandle) - return 0; - - if (lstat(pathname, &sb) < 0) + if (selabel_lookup(sehandle, &secontext, pathname, sb->st_mode) < 0) return -errno; - if (selabel_lookup(sehandle, &secontext, pathname, sb.st_mode) < 0) - return -errno; - if (lsetfilecon(pathname, secontext) < 0) { + + if (lgetfilecon(pathname, &oldsecontext) < 0) { freecon(secontext); return -errno; } + + if (strcmp(oldsecontext, secontext) != 0) { + if (lsetfilecon(pathname, secontext) < 0) { + freecon(oldsecontext); + freecon(secontext); + return -errno; + } + } + freecon(oldsecontext); freecon(secontext); return 0; } +int restorecon(const char *pathname) +{ + struct stat sb; + + if (is_selinux_enabled() <= 0 || !sehandle) + return 0; + + if (lstat(pathname, &sb) < 0) + return -errno; + + return restorecon_sb(pathname, &sb); +} + static int nftw_restorecon(const char* filename, const struct stat* statptr, - int fileflags, struct FTW* pftw) + int fileflags __attribute__((unused)), + struct FTW* pftw __attribute__((unused))) { - restorecon(filename); + restorecon_sb(filename, statptr); return 0; } @@ -525,5 +549,9 @@ int restorecon_recursive(const char* pathname) { int fd_limit = 20; int flags = FTW_DEPTH | FTW_MOUNT | FTW_PHYS; + + if (is_selinux_enabled() <= 0 || !sehandle) + return 0; + return nftw(pathname, nftw_restorecon, fd_limit, flags); } diff --git a/init/util.h b/init/util.h index 6bca4e6891..04b8129bae 100644 --- a/init/util.h +++ b/init/util.h @@ -26,7 +26,7 @@ static const char *coldboot_done = "/dev/.coldboot_done"; int mtd_name_to_number(const char *name); int create_socket(const char *name, int type, mode_t perm, - uid_t uid, gid_t gid); + uid_t uid, gid_t gid, const char *socketcon); void *read_file(const char *fn, unsigned *_sz); time_t gettime(void); unsigned int decode_uid(const char *s); diff --git a/init/vendor_init.c b/init/vendor_init.c new file mode 100644 index 0000000000..d3fd5ffe2b --- /dev/null +++ b/init/vendor_init.c @@ -0,0 +1,37 @@ +/* +Copyright (c) 2013, The Linux Foundation. All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are +met: + * Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + * Redistributions in binary form must reproduce the above + copyright notice, this list of conditions and the following + disclaimer in the documentation and/or other materials provided + with the distribution. + * Neither the name of The Linux Foundation nor the names of its + contributors may be used to endorse or promote products derived + from this software without specific prior written permission. + +THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED +WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF +MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT +ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS +BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR +CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF +SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR +BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, +WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE +OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN +IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#include "vendor_init.h" + +/* init vendor override stubs */ + +__attribute__ ((weak)) +void vendor_load_properties() +{ +} diff --git a/init/vendor_init.h b/init/vendor_init.h new file mode 100644 index 0000000000..9afb449be0 --- /dev/null +++ b/init/vendor_init.h @@ -0,0 +1,33 @@ +/* +Copyright (c) 2013, The Linux Foundation. All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are +met: + * Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + * Redistributions in binary form must reproduce the above + copyright notice, this list of conditions and the following + disclaimer in the documentation and/or other materials provided + with the distribution. + * Neither the name of The Linux Foundation nor the names of its + contributors may be used to endorse or promote products derived + from this software without specific prior written permission. + +THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED +WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF +MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT +ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS +BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR +CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF +SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR +BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, +WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE +OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN +IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#ifndef __INIT_VENDOR__H__ +#define __INIT_VENDOR__H__ +extern void vendor_load_properties(void); +#endif /* __INIT_VENDOR__H__ */ diff --git a/libcutils/dir_hash.c b/libcutils/dir_hash.c index be14af65c5..098b5db5a2 100644 --- a/libcutils/dir_hash.c +++ b/libcutils/dir_hash.c @@ -159,6 +159,7 @@ static int recurse(HashAlgorithm algorithm, const char *directory_path, free(name); free(node); + closedir(d); return -1; } diff --git a/libdiskconfig/Android.mk b/libdiskconfig/Android.mk index b5d83fad9e..5cd8355c07 100644 --- a/libdiskconfig/Android.mk +++ b/libdiskconfig/Android.mk @@ -14,6 +14,13 @@ LOCAL_MODULE_TAGS := optional LOCAL_SYSTEM_SHARED_LIBRARIES := libcutils liblog libc include $(BUILD_SHARED_LIBRARY) +include $(CLEAR_VARS) +LOCAL_SRC_FILES := $(commonSources) +LOCAL_MODULE := libdiskconfig +LOCAL_MODULE_TAGS := optional +#LOCAL_STATIC_LIBRARIES := libcutils liblog libc +include $(BUILD_STATIC_LIBRARY) + ifeq ($(HOST_OS),linux) include $(CLEAR_VARS) LOCAL_SRC_FILES := $(commonSources) diff --git a/liblog/Android.mk b/liblog/Android.mk index 6bfb119668..19f880bae0 100644 --- a/liblog/Android.mk +++ b/liblog/Android.mk @@ -67,15 +67,20 @@ LOCAL_LDLIBS := -lpthread LOCAL_CFLAGS := -DFAKE_LOG_DEVICE=1 -m64 include $(BUILD_HOST_STATIC_LIBRARY) +ifeq ($(TARGET_USES_MOTOROLA_LOG),true) +LIBLOG_CFLAGS := -DMOTOROLA_LOG +endif # Shared and static library for target # ======================================================== include $(CLEAR_VARS) +LOCAL_CFLAGS += $(LIBLOG_CFLAGS) LOCAL_MODULE := liblog LOCAL_SRC_FILES := $(liblog_sources) include $(BUILD_STATIC_LIBRARY) include $(CLEAR_VARS) +LOCAL_CFLAGS += $(LIBLOG_CFLAGS) LOCAL_MODULE := liblog LOCAL_WHOLE_STATIC_LIBRARIES := liblog include $(BUILD_SHARED_LIBRARY) diff --git a/liblog/logd_write.c b/liblog/logd_write.c index fff7cc4ddc..65a2202869 100644 --- a/liblog/logd_write.c +++ b/liblog/logd_write.c @@ -31,6 +31,12 @@ #include #include +#ifdef MOTOROLA_LOG +#if HAVE_LIBC_SYSTEM_PROPERTIES +#include +#endif +#endif + #define LOG_BUF_SIZE 1024 #if FAKE_LOG_DEVICE @@ -72,6 +78,112 @@ int __android_log_dev_available(void) return (g_log_status == kLogAvailable); } +#ifdef HTCLOG +signed int __htclog_read_masks(char *buf, signed int len) +{ + return 0; +} + +int __htclog_init_mask(const char *a1, unsigned int a2, int a3) +{ + return 0; +} + +int __htclog_print_private(int a1, const char *a2, const char *fmt, ...) +{ + return 0; +} +#endif + +#ifdef MOTOROLA_LOG +/* Fallback when there is neither log.tag. nor log.tag.DEFAULT. + * this is compile-time defaulted to "info". The log startup code + * looks at the build tags to see about whether it should be DEBUG... + * -- just as is done in frameworks/base/core/jni/android_util_Log.cpp + */ +static int prio_fallback = ANDROID_LOG_INFO; + +/* + * public interface so native code can see "should i log this" + * and behave similar to java Log.isLoggable() calls. + * + * NB: we have (level,tag) here to match the other __android_log entries. + * The Java side uses (tag,level) for its ordering. + * since the args are (int,char*) vs (char*,char*) we won't get strange + * swapped-the-strings errors. + */ + +#define LOGGING_PREFIX "log.tag." +#define LOGGING_DEFAULT "log.tag.DEFAULT" + +int __android_log_loggable(int prio, const char *tag) +{ + int nprio; + +#if HAVE_LIBC_SYSTEM_PROPERTIES + char keybuf[PROP_NAME_MAX]; + char results[PROP_VALUE_MAX]; + int n; + + /* we can NOT cache the log.tag. and log.tag.DEFAULT + * values because either one can be changed dynamically. + * + * damn, says the performance compulsive. + */ + + n = 0; + results[0] = '\0'; + if (tag) { + memcpy (keybuf, LOGGING_PREFIX, strlen (LOGGING_PREFIX) + 1); + /* watch out for buffer overflow */ + strncpy (keybuf + strlen (LOGGING_PREFIX), tag, + sizeof (keybuf) - strlen (LOGGING_PREFIX)); + keybuf[sizeof (keybuf) - 1] = '\0'; + n = __system_property_get (keybuf, results); + } + if (n == 0) { + /* nothing yet, look for the global */ + memcpy (keybuf, LOGGING_DEFAULT, sizeof (LOGGING_DEFAULT)); + n = __system_property_get (keybuf, results); + } + + if (n == 0) { + nprio = prio_fallback; + } else { + switch (results[0]) + { + case 'E': + nprio = ANDROID_LOG_ERROR; + break; + case 'W': + nprio = ANDROID_LOG_WARN; + break; + case 'I': + nprio = ANDROID_LOG_INFO; + break; + case 'D': + nprio = ANDROID_LOG_DEBUG; + break; + case 'V': + nprio = ANDROID_LOG_VERBOSE; + break; + case 'S': + nprio = ANDROID_LOG_SILENT; + break; + default: + /* unspecified or invalid */ + nprio = prio_fallback; + break; + } + } +#else + /* no system property routines, fallback to a default */ + nprio = prio_fallback; +#endif + return ((prio >= nprio) ? 1 : 0); +} +#endif + static int __write_to_log_null(log_id_t log_fd, struct iovec *vec, size_t nr) { return -1; diff --git a/libmincrypt/Android.mk b/libmincrypt/Android.mk index 090d0e591e..da53296b61 100644 --- a/libmincrypt/Android.mk +++ b/libmincrypt/Android.mk @@ -7,6 +7,13 @@ LOCAL_MODULE := libmincrypt LOCAL_SRC_FILES := rsa.c sha.c sha256.c include $(BUILD_STATIC_LIBRARY) +## Crippled version without an RSA implementation +## to coexist with libcrypto_static and provide SHA_hash +include $(CLEAR_VARS) +LOCAL_MODULE := libminshacrypt +LOCAL_SRC_FILES := sha.c sha256.c +include $(BUILD_STATIC_LIBRARY) + include $(CLEAR_VARS) LOCAL_MODULE := libmincrypt diff --git a/libnetutils/ifc_utils.c b/libnetutils/ifc_utils.c index eb33d0695d..ad1a0c9b4b 100644 --- a/libnetutils/ifc_utils.c +++ b/libnetutils/ifc_utils.c @@ -1,16 +1,17 @@ /* + * Copyright (c) 2011-2013 The Linux Foundation. All rights reserved. * Copyright 2008, 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 + * 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 + * 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 + * 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. */ @@ -801,11 +802,6 @@ ifc_configure(const char *ifname, ifc_close(); return -1; } - if (ifc_create_default_route(ifname, gateway)) { - printerr("failed to set default route %s: %s\n", ipaddr_to_string(gateway), strerror(errno)); - ifc_close(); - return -1; - } ifc_close(); @@ -813,6 +809,8 @@ ifc_configure(const char *ifname, property_set(dns_prop_name, dns1 ? ipaddr_to_string(dns1) : ""); snprintf(dns_prop_name, sizeof(dns_prop_name), "net.%s.dns2", ifname); property_set(dns_prop_name, dns2 ? ipaddr_to_string(dns2) : ""); + snprintf(dns_prop_name, sizeof(dns_prop_name), "net.%s.gw", ifname); + property_set(dns_prop_name, gateway ? ipaddr_to_string(gateway) : ""); return 0; } diff --git a/libsparse/backed_block.c b/libsparse/backed_block.c index dfb217b309..3e72b57c71 100644 --- a/libsparse/backed_block.c +++ b/libsparse/backed_block.c @@ -370,7 +370,7 @@ int backed_block_split(struct backed_block_list *bbl, struct backed_block *bb, } new_bb = malloc(sizeof(struct backed_block)); - if (bb == NULL) { + if (new_bb == NULL) { return -ENOMEM; } diff --git a/libsparse/output_file.c b/libsparse/output_file.c index 5014e4a87e..2cadd0edf2 100644 --- a/libsparse/output_file.c +++ b/libsparse/output_file.c @@ -731,10 +731,12 @@ int write_fd_chunk(struct output_file *out, unsigned int len, } pos = lseek64(fd, offset, SEEK_SET); if (pos < 0) { + free(data); return -errno; } ret = read_all(fd, data, len); if (ret < 0) { + free(data); return ret; } ptr = data; diff --git a/libsysutils/Android.mk b/libsysutils/Android.mk index 1d396b2ad2..9b05798142 100644 --- a/libsysutils/Android.mk +++ b/libsysutils/Android.mk @@ -2,9 +2,7 @@ ifneq ($(BUILD_TINY_ANDROID),true) LOCAL_PATH:= $(call my-dir) -include $(CLEAR_VARS) - -LOCAL_SRC_FILES:= \ +common_src_files := \ src/SocketListener.cpp \ src/FrameworkListener.cpp \ src/NetlinkListener.cpp \ @@ -14,14 +12,20 @@ LOCAL_SRC_FILES:= \ src/ServiceManager.cpp \ EventLogTags.logtags -LOCAL_MODULE:= libsysutils +include $(CLEAR_VARS) +LOCAL_SRC_FILES:= $(common_src_files) +LOCAL_MODULE:= libsysutils LOCAL_C_INCLUDES := $(KERNEL_HEADERS) - LOCAL_CFLAGS := - LOCAL_SHARED_LIBRARIES := libcutils liblog - include $(BUILD_SHARED_LIBRARY) +include $(CLEAR_VARS) +LOCAL_SRC_FILES:= $(common_src_files) +LOCAL_MODULE:= libsysutils +LOCAL_C_INCLUDES := $(KERNEL_HEADERS) +LOCAL_CFLAGS := +include $(BUILD_STATIC_LIBRARY) + endif diff --git a/libutils/Android.mk b/libutils/Android.mk index 720443e88a..be5977eca4 100644 --- a/libutils/Android.mk +++ b/libutils/Android.mk @@ -120,6 +120,13 @@ LOCAL_SHARED_LIBRARIES := \ liblog \ libdl +ifeq ($(BOARD_USES_QC_TIME_SERVICES),true) +LOCAL_CFLAGS += -DHAVE_QC_TIME_SERVICES=1 +LOCAL_SHARED_LIBRARIES += libtime_genoff +$(shell mkdir -p $(OUT)/obj/SHARED_LIBRARIES/libtime_genoff_intermediates/) +$(shell touch $(OUT)/obj/SHARED_LIBRARIES/libtime_genoff_intermediates/export_includes) +endif + LOCAL_MODULE:= libutils include $(BUILD_STATIC_LIBRARY) @@ -134,6 +141,13 @@ LOCAL_SHARED_LIBRARIES := \ libdl \ libcorkscrew +ifeq ($(BOARD_USES_QC_TIME_SERVICES),true) +LOCAL_CFLAGS += -DHAVE_QC_TIME_SERVICES=1 +LOCAL_SHARED_LIBRARIES += libtime_genoff +$(shell mkdir -p $(OUT)/obj/SHARED_LIBRARIES/libtime_genoff_intermediates/) +$(shell touch $(OUT)/obj/SHARED_LIBRARIES/libtime_genoff_intermediates/export_includes) +endif + include $(BUILD_SHARED_LIBRARY) # Include subdirectory makefiles diff --git a/libutils/RefBase.cpp b/libutils/RefBase.cpp index f398a82cef..604951d828 100644 --- a/libutils/RefBase.cpp +++ b/libutils/RefBase.cpp @@ -626,6 +626,13 @@ void RefBase::onLastWeakRef(const void* /*id*/) // --------------------------------------------------------------------------- +/* START JB MR1 COMPAT */ +extern "C" void _ZN7android7RefBase14moveReferencesEPvPKvjRKNS_22ReferenceConverterBaseE(void* dst, void const* src, size_t n, + const ReferenceConverterBase& caster) +{ +} +/* END JB MR1 COMPAT */ + void RefBase::renameRefs(size_t n, const ReferenceRenamer& renamer) { #if DEBUG_REFS for (size_t i=0 ; i +#if HAVE_QC_TIME_SERVICES +extern "C" { +#include +} +#endif + namespace android { +#if HAVE_QC_TIME_SERVICES +int setTimeServicesTime(time_bases_type base, int64_t millis) +{ + int rc = 0; + time_genoff_info_type time_set; + uint64_t value = millis; + time_set.base = base; + time_set.unit = TIME_MSEC; + time_set.operation = T_SET; + time_set.ts_val = &value; + rc = time_genoff_operation(&time_set); + if (rc) { + ALOGE("Error setting generic offset: %d. Still setting system time\n", rc); + rc = -1; + } + return rc; +} +#endif +/* + * Set the current time. This only works when running as root. + */ +int setCurrentTimeMillis(int64_t millis) +{ +#if WIN32 + // not implemented + return -1; +#else + struct timeval tv; +#ifdef HAVE_ANDROID_OS + struct timespec ts; + int fd; + int res; +#endif + int ret = 0; + +#if HAVE_QC_TIME_SERVICES + int rc; + rc = setTimeServicesTime(ATS_USER, millis); + if (rc) { + ALOGE("Error setting generic offset: %d. Still setting system time\n", rc); + } +#endif + + if (millis <= 0 || millis / 1000LL >= INT_MAX) { + return -1; + } + + tv.tv_sec = (time_t) (millis / 1000LL); + tv.tv_usec = (suseconds_t) ((millis % 1000LL) * 1000LL); + + ALOGD("Setting time of day to sec=%d\n", (int) tv.tv_sec); + +#ifdef HAVE_ANDROID_OS + fd = open("/dev/alarm", O_RDWR); + if(fd < 0) { + ALOGW("Unable to open alarm driver: %s\n", strerror(errno)); + return -1; + } + ts.tv_sec = tv.tv_sec; + ts.tv_nsec = tv.tv_usec * 1000; + res = ioctl(fd, ANDROID_ALARM_SET_RTC, &ts); + if(res < 0) { + ALOGW("Unable to set rtc to %ld: %s\n", tv.tv_sec, strerror(errno)); + ret = -1; + } + close(fd); +#else + if (settimeofday(&tv, NULL) != 0) { + ALOGW("Unable to set clock to %d.%d: %s\n", + (int) tv.tv_sec, (int) tv.tv_usec, strerror(errno)); + ret = -1; + } +#endif + + return ret; +#endif // WIN32 +} + /* * native public static long uptimeMillis(); */ diff --git a/libutils/Timers.cpp b/libutils/Timers.cpp index 5293cd2a82..d4f85164af 100644 --- a/libutils/Timers.cpp +++ b/libutils/Timers.cpp @@ -70,3 +70,65 @@ int toMillisecondTimeoutDelay(nsecs_t referenceTime, nsecs_t timeoutTime) } return timeoutDelayMillis; } + + +/* + * =========================================================================== + * DurationTimer + * =========================================================================== + */ + +using namespace android; + +// Start the timer. +void DurationTimer::start(void) +{ + gettimeofday(&mStartWhen, NULL); +} + +// Stop the timer. +void DurationTimer::stop(void) +{ + gettimeofday(&mStopWhen, NULL); +} + +// Get the duration in microseconds. +long long DurationTimer::durationUsecs(void) const +{ + return (long) subtractTimevals(&mStopWhen, &mStartWhen); +} + +// Subtract two timevals. Returns the difference (ptv1-ptv2) in +// microseconds. +/*static*/ long long DurationTimer::subtractTimevals(const struct timeval* ptv1, + const struct timeval* ptv2) +{ + long long stop = ((long long) ptv1->tv_sec) * 1000000LL + + ((long long) ptv1->tv_usec); + long long start = ((long long) ptv2->tv_sec) * 1000000LL + + ((long long) ptv2->tv_usec); + return stop - start; +} + +// Add the specified amount of time to the timeval. +/*static*/ void DurationTimer::addToTimeval(struct timeval* ptv, long usec) +{ + if (usec < 0) { + ALOG(LOG_WARN, "", "Negative values not supported in addToTimeval\n"); + return; + } + + // normalize tv_usec if necessary + if (ptv->tv_usec >= 1000000) { + ptv->tv_sec += ptv->tv_usec / 1000000; + ptv->tv_usec %= 1000000; + } + + ptv->tv_usec += usec % 1000000; + if (ptv->tv_usec >= 1000000) { + ptv->tv_usec -= 1000000; + ptv->tv_sec++; + } + ptv->tv_sec += usec / 1000000; +} + diff --git a/libutils/VectorImpl.cpp b/libutils/VectorImpl.cpp index 5a79647cb2..275f19aa89 100644 --- a/libutils/VectorImpl.cpp +++ b/libutils/VectorImpl.cpp @@ -504,6 +504,17 @@ void VectorImpl::_do_move_backward(void* dest, const void* from, size_t num) con do_move_backward(dest, from, num); } +#if NEEDS_VECTORIMPL_SYMBOLS +void VectorImpl::reservedVectorImpl1() { } +void VectorImpl::reservedVectorImpl2() { } +void VectorImpl::reservedVectorImpl3() { } +void VectorImpl::reservedVectorImpl4() { } +void VectorImpl::reservedVectorImpl5() { } +void VectorImpl::reservedVectorImpl6() { } +void VectorImpl::reservedVectorImpl7() { } +void VectorImpl::reservedVectorImpl8() { } +#endif + /*****************************************************************************/ SortedVectorImpl::SortedVectorImpl(size_t itemSize, uint32_t flags) @@ -619,6 +630,17 @@ ssize_t SortedVectorImpl::remove(const void* item) return i; } +#if NEEDS_VECTORIMPL_SYMBOLS +void SortedVectorImpl::reservedSortedVectorImpl1() { }; +void SortedVectorImpl::reservedSortedVectorImpl2() { }; +void SortedVectorImpl::reservedSortedVectorImpl3() { }; +void SortedVectorImpl::reservedSortedVectorImpl4() { }; +void SortedVectorImpl::reservedSortedVectorImpl5() { }; +void SortedVectorImpl::reservedSortedVectorImpl6() { }; +void SortedVectorImpl::reservedSortedVectorImpl7() { }; +void SortedVectorImpl::reservedSortedVectorImpl8() { }; +#endif + /*****************************************************************************/ }; // namespace android diff --git a/mkbootimg/Android.mk b/mkbootimg/Android.mk index 2a97c26e14..153b25ea13 100644 --- a/mkbootimg/Android.mk +++ b/mkbootimg/Android.mk @@ -9,4 +9,35 @@ LOCAL_MODULE := mkbootimg include $(BUILD_HOST_EXECUTABLE) +include $(CLEAR_VARS) +LOCAL_MODULE_TAGS := eng +LOCAL_SRC_FILES := unpackbootimg.c +LOCAL_MODULE := unpackbootimg +include $(BUILD_HOST_EXECUTABLE) + +include $(CLEAR_VARS) +LOCAL_SRC_FILES := mkbootimg.c +LOCAL_STATIC_LIBRARIES := libmincrypt libcutils libc +LOCAL_MODULE := utility_mkbootimg +LOCAL_MODULE_TAGS := eng +LOCAL_MODULE_STEM := mkbootimg +LOCAL_MODULE_CLASS := UTILITY_EXECUTABLES +LOCAL_UNSTRIPPED_PATH := $(PRODUCT_OUT)/symbols/utilities +LOCAL_MODULE_PATH := $(PRODUCT_OUT)/utilities +LOCAL_FORCE_STATIC_EXECUTABLE := true +include $(BUILD_EXECUTABLE) + +include $(CLEAR_VARS) +LOCAL_SRC_FILES := unpackbootimg.c +LOCAL_STATIC_LIBRARIES := libcutils libc +LOCAL_MODULE := utility_unpackbootimg +LOCAL_MODULE_TAGS := eng +LOCAL_MODULE_STEM := unpackbootimg +LOCAL_MODULE_CLASS := UTILITY_EXECUTABLES +LOCAL_UNSTRIPPED_PATH := $(PRODUCT_OUT)/symbols/utilities +LOCAL_MODULE_PATH := $(PRODUCT_OUT)/utilities +LOCAL_FORCE_STATIC_EXECUTABLE := true +include $(BUILD_EXECUTABLE) + $(call dist-for-goals,dist_files,$(LOCAL_BUILT_MODULE)) + diff --git a/mkbootimg/bootimg.h b/mkbootimg/bootimg.h index 242ab35db8..4692f0cf9d 100644 --- a/mkbootimg/bootimg.h +++ b/mkbootimg/bootimg.h @@ -40,8 +40,8 @@ struct boot_img_hdr 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 dt_size; /* device tree in bytes */ + unsigned unused; /* future expansion: should be 0 */ unsigned char name[BOOT_NAME_SIZE]; /* asciiz product name */ unsigned char cmdline[BOOT_ARGS_SIZE]; @@ -59,10 +59,13 @@ struct boot_img_hdr ** +-----------------+ ** | second stage | o pages ** +-----------------+ +** | device tree | p pages +** +-----------------+ ** ** n = (kernel_size + page_size - 1) / page_size ** m = (ramdisk_size + page_size - 1) / page_size ** o = (second_size + page_size - 1) / page_size +** p = (dt_size + page_size - 1) / page_size ** ** 0. all entities are page_size aligned in flash ** 1. kernel and ramdisk are required (size != 0) diff --git a/mkbootimg/mkbootimg.c b/mkbootimg/mkbootimg.c index 34a879b5ac..ebeba97b60 100644 --- a/mkbootimg/mkbootimg.c +++ b/mkbootimg/mkbootimg.c @@ -65,6 +65,8 @@ int usage(void) " [ --board ]\n" " [ --base
]\n" " [ --pagesize ]\n" + " [ --ramdisk_offset
]\n" + " [ --dt ]\n" " -o|--output \n" ); return 1; @@ -105,6 +107,8 @@ int main(int argc, char **argv) char *cmdline = ""; char *bootimg = 0; char *board = ""; + char *dt_fn = 0; + void *dt_data = 0; unsigned pagesize = 2048; int fd; SHA_CTX ctx; @@ -157,6 +161,8 @@ int main(int argc, char **argv) fprintf(stderr,"error: unsupported page size %d\n", pagesize); return -1; } + } else if(!strcmp(arg, "--dt")) { + dt_fn = val; } else { return usage(); } @@ -223,6 +229,14 @@ int main(int argc, char **argv) } } + if(dt_fn) { + dt_data = load_file(dt_fn, &hdr.dt_size); + if (dt_data == 0) { + fprintf(stderr,"error: could not load device tree image '%s'\n", dt_fn); + return 1; + } + } + /* put a hash of the contents in the header so boot images can be * differentiated based on their first 2k. */ @@ -233,6 +247,10 @@ int main(int argc, char **argv) SHA_update(&ctx, &hdr.ramdisk_size, sizeof(hdr.ramdisk_size)); SHA_update(&ctx, second_data, hdr.second_size); SHA_update(&ctx, &hdr.second_size, sizeof(hdr.second_size)); + if(dt_data) { + SHA_update(&ctx, dt_data, hdr.dt_size); + SHA_update(&ctx, &hdr.dt_size, sizeof(hdr.dt_size)); + } sha = SHA_final(&ctx); memcpy(hdr.id, sha, SHA_DIGEST_SIZE > sizeof(hdr.id) ? sizeof(hdr.id) : SHA_DIGEST_SIZE); @@ -257,6 +275,10 @@ int main(int argc, char **argv) if(write_padding(fd, pagesize, hdr.ramdisk_size)) goto fail; } + if(dt_data) { + if(write(fd, dt_data, hdr.dt_size) != hdr.dt_size) goto fail; + if(write_padding(fd, pagesize, hdr.dt_size)) goto fail; + } return 0; fail: diff --git a/mkbootimg/unpackbootimg.c b/mkbootimg/unpackbootimg.c new file mode 100644 index 0000000000..8be0405482 --- /dev/null +++ b/mkbootimg/unpackbootimg.c @@ -0,0 +1,170 @@ +#include +#include +#include +#include +#include +#include +#include +#include + +#include "mincrypt/sha.h" +#include "bootimg.h" + +typedef unsigned char byte; + +int read_padding(FILE* f, unsigned itemsize, int pagesize) +{ + byte* buf = (byte*)malloc(sizeof(byte) * pagesize); + unsigned pagemask = pagesize - 1; + unsigned count; + + if((itemsize & pagemask) == 0) { + free(buf); + return 0; + } + + count = pagesize - (itemsize & pagemask); + + fread(buf, count, 1, f); + free(buf); + return count; +} + +void write_string_to_file(char* file, char* string) +{ + FILE* f = fopen(file, "w"); + fwrite(string, strlen(string), 1, f); + fwrite("\n", 1, 1, f); + fclose(f); +} + +int usage() { + printf("usage: unpackbootimg\n"); + printf("\t-i|--input boot.img\n"); + printf("\t[ -o|--output output_directory]\n"); + printf("\t[ -p|--pagesize ]\n"); + return 0; +} + +int main(int argc, char** argv) +{ + char tmp[PATH_MAX]; + char* directory = "./"; + char* filename = NULL; + int pagesize = 0; + + argc--; + argv++; + while(argc > 0){ + char *arg = argv[0]; + char *val = argv[1]; + argc -= 2; + argv += 2; + if(!strcmp(arg, "--input") || !strcmp(arg, "-i")) { + filename = val; + } else if(!strcmp(arg, "--output") || !strcmp(arg, "-o")) { + directory = val; + } else if(!strcmp(arg, "--pagesize") || !strcmp(arg, "-p")) { + pagesize = strtoul(val, 0, 16); + } else { + return usage(); + } + } + + if (filename == NULL) { + return usage(); + } + + int total_read = 0; + FILE* f = fopen(filename, "rb"); + boot_img_hdr header; + + //printf("Reading header...\n"); + int i; + for (i = 0; i <= 512; i++) { + fseek(f, i, SEEK_SET); + fread(tmp, BOOT_MAGIC_SIZE, 1, f); + if (memcmp(tmp, BOOT_MAGIC, BOOT_MAGIC_SIZE) == 0) + break; + } + total_read = i; + if (i > 512) { + printf("Android boot magic not found.\n"); + return 1; + } + fseek(f, i, SEEK_SET); + printf("Android magic found at: %d\n", i); + + fread(&header, sizeof(header), 1, f); + printf("BOARD_KERNEL_CMDLINE %s\n", header.cmdline); + printf("BOARD_KERNEL_BASE %08x\n", header.kernel_addr - 0x00008000); + printf("BOARD_PAGE_SIZE %d\n", header.page_size); + printf("BOARD_DT_SIZE %d\n", header.dt_size); + + if (pagesize == 0) { + pagesize = header.page_size; + } + + //printf("cmdline...\n"); + sprintf(tmp, "%s/%s", directory, basename(filename)); + strcat(tmp, "-cmdline"); + write_string_to_file(tmp, header.cmdline); + + //printf("base...\n"); + sprintf(tmp, "%s/%s", directory, basename(filename)); + strcat(tmp, "-base"); + char basetmp[200]; + sprintf(basetmp, "%08x", header.kernel_addr - 0x00008000); + write_string_to_file(tmp, basetmp); + + //printf("pagesize...\n"); + sprintf(tmp, "%s/%s", directory, basename(filename)); + strcat(tmp, "-pagesize"); + char pagesizetmp[200]; + sprintf(pagesizetmp, "%d", header.page_size); + write_string_to_file(tmp, pagesizetmp); + + total_read += sizeof(header); + //printf("total read: %d\n", total_read); + total_read += read_padding(f, sizeof(header), pagesize); + + sprintf(tmp, "%s/%s", directory, basename(filename)); + strcat(tmp, "-zImage"); + FILE *k = fopen(tmp, "wb"); + byte* kernel = (byte*)malloc(header.kernel_size); + //printf("Reading kernel...\n"); + fread(kernel, header.kernel_size, 1, f); + total_read += header.kernel_size; + fwrite(kernel, header.kernel_size, 1, k); + fclose(k); + + //printf("total read: %d\n", header.kernel_size); + total_read += read_padding(f, header.kernel_size, pagesize); + + sprintf(tmp, "%s/%s", directory, basename(filename)); + strcat(tmp, "-ramdisk.gz"); + FILE *r = fopen(tmp, "wb"); + byte* ramdisk = (byte*)malloc(header.ramdisk_size); + //printf("Reading ramdisk...\n"); + fread(ramdisk, header.ramdisk_size, 1, f); + total_read += header.ramdisk_size; + fwrite(ramdisk, header.ramdisk_size, 1, r); + fclose(r); + + total_read += read_padding(f, header.ramdisk_size, pagesize); + + sprintf(tmp, "%s/%s", directory, basename(filename)); + strcat(tmp, "-dt.img"); + FILE *d = fopen(tmp, "wb"); + byte* dt = (byte*)malloc(header.dt_size); + //printf("Reading dt...\n"); + fread(dt, header.dt_size, 1, f); + total_read += header.dt_size; + fwrite(dt, header.dt_size, 1, r); + fclose(d); + + fclose(f); + + //printf("Total Read: %d\n", total_read); + return 0; +} diff --git a/rootdir/init.rc b/rootdir/init.rc index 1ee9fbf4ac..eef4527b31 100644 --- a/rootdir/init.rc +++ b/rootdir/init.rc @@ -1,3 +1,6 @@ +# Copyright (c) 2013, The Linux Foundation. All rights reserved. +# Not a Contribution. +# # Copyright (C) 2012 The Android Open Source Project # # IMPORTANT: Do not create world writable files or directories. @@ -82,6 +85,10 @@ loglevel 3 mkdir /mnt/obb 0700 root system mount tmpfs tmpfs /mnt/obb mode=0755,gid=1000 + # Fuse public mount points. + mkdir /mnt/fuse 0700 root system + mount tmpfs tmpfs /mnt/fuse mode=0775,gid=1000 + write /proc/sys/kernel/panic_on_oops 1 write /proc/sys/kernel/hung_task_timeout_secs 0 write /proc/cpu/alignment 4 @@ -232,6 +239,7 @@ on post-fs-data mkdir /data/property 0700 root root mkdir /data/ssh 0750 root shell mkdir /data/ssh/empty 0700 root root + mkdir /data/radio 0770 radio radio # create dalvik-cache, so as to enforce our permissions mkdir /data/dalvik-cache 0771 system system @@ -264,6 +272,9 @@ on post-fs-data # Set indication (checked by vold) that we have finished this action #setprop vold.post_fs_data_done 1 +# Include extra init file + import /init.ose.rc + on boot # basic network init ifup lo @@ -327,8 +338,15 @@ on boot chmod 0660 /sys/devices/system/cpu/cpufreq/interactive/io_is_busy # Assume SMP uses shared cpufreq policy for all CPUs + chown system system /sys/devices/system/cpu/cpu0/cpufreq/scaling_governor + chmod 0664 /sys/devices/system/cpu/cpu0/cpufreq/scaling_governor chown system system /sys/devices/system/cpu/cpu0/cpufreq/scaling_max_freq - chmod 0660 /sys/devices/system/cpu/cpu0/cpufreq/scaling_max_freq + chmod 0664 /sys/devices/system/cpu/cpu0/cpufreq/scaling_max_freq + chown system system /sys/devices/system/cpu/cpu0/cpufreq/scaling_min_freq + chmod 0664 /sys/devices/system/cpu/cpu0/cpufreq/scaling_min_freq + + chown system system /sys/block/mmcblk0/queue/scheduler + chmod 0664 /sys/block/mmcblk0/queue/scheduler chown system system /sys/class/timed_output/vibrator/enable chown system system /sys/class/leds/keyboard-backlight/brightness @@ -485,9 +503,9 @@ service ril-daemon /system/bin/rild class main socket rild stream 660 root radio socket rild-debug stream 660 radio system + socket cutback stream 660 media radio user root - group radio cache inet misc audio log - + group radio cache inet misc audio sdcard_rw qcom_oncrpc qcom_diag log net_raw diag service surfaceflinger /system/bin/surfaceflinger class main user system @@ -510,7 +528,7 @@ service drm /system/bin/drmserver service media /system/bin/mediaserver class main user media - group audio camera inet net_bt net_bt_admin net_bw_acct drmrpc mediadrm + group audio camera inet net_bt net_bt_admin net_bw_acct drmrpc mediadrm qcom_diag ioprio rt 4 service bootanim /system/bin/bootanimation @@ -547,7 +565,7 @@ service mtpd /system/bin/mtpd service keystore /system/bin/keystore /data/misc/keystore class main user keystore - group keystore drmrpc + group keystore drmrpc system service dumpstate /system/bin/dumpstate -s class main diff --git a/rootdir/ueventd.rc b/rootdir/ueventd.rc index 2cf02650bb..e38c4d1456 100644 --- a/rootdir/ueventd.rc +++ b/rootdir/ueventd.rc @@ -5,6 +5,8 @@ /dev/tty 0666 root root /dev/random 0666 root root /dev/urandom 0666 root root +# Make HW RNG readable by group system to let EntropyMixer read it. +/dev/hw_random 0660 system system /dev/ashmem 0666 root root /dev/binder 0666 root root @@ -15,6 +17,9 @@ # the msm hw3d client device node is world writable/readable. /dev/msm_hw3dc 0666 root root +# the DIAG device node is not world writable/readable. +/dev/diag 0660 system qcom_diag + # gpu driver for adreno200 is globally accessible /dev/kgsl 0666 root root @@ -22,7 +27,6 @@ /dev/dri/* 0666 root graphics # these should not be world writable -/dev/diag 0660 radio radio /dev/diag_arm9 0660 radio radio /dev/android_adb 0660 adb adb /dev/android_adb_enable 0660 adb adb @@ -43,7 +47,7 @@ /dev/adsp/* 0660 system audio /dev/snd/* 0660 system audio /dev/mt9t013 0660 system system -/dev/msm_camera/* 0660 system system +/dev/msm_camera/* 0660 system camera /dev/akm8976_daemon 0640 compass system /dev/akm8976_aot 0640 compass system /dev/akm8973_daemon 0640 compass system @@ -85,3 +89,27 @@ /sys/devices/virtual/input/input* enable 0660 root input /sys/devices/virtual/input/input* poll_delay 0660 root input /sys/devices/virtual/usb_composite/* enable 0664 root system + +/sys/devices/system/cpu/cpufreq ondemand/boostfreq 0664 system system +/sys/devices/system/cpu/cpufreq ondemand/boostpulse 0664 system system +/sys/devices/system/cpu/cpufreq ondemand/boosttime 0664 system system +/sys/devices/system/cpu/cpufreq ondemand/sampling_rate 0664 system system +/sys/devices/system/cpu/cpufreq ondemand/io_is_busy 0664 system system +/sys/devices/system/cpu/cpufreq ondemand/down_differential 0664 system system +/sys/devices/system/cpu/cpufreq ondemand/powersave_bias 0664 system system +/sys/devices/system/cpu/cpufreq ondemand/sampling_down_factor 0664 system system +/sys/devices/system/cpu/cpufreq ondemand/up_threshold 0664 system system +/sys/devices/system/cpu/cpufreq ondemand/up_threshold_multi_core 0664 system system +/sys/devices/system/cpu/cpufreq ondemand/down_differential_multi_core 0664 system system +/sys/devices/system/cpu/cpufreq ondemand/optimal_freq 0664 system system +/sys/devices/system/cpu/cpufreq ondemand/sync_freq 0664 system system +/sys/devices/system/cpu/cpufreq ondemand/up_threshold_any_cpu_load 0664 system system + +/sys/devices/system/cpu/cpufreq interactive/boostpulse 0664 system system +/sys/devices/system/cpu/cpufreq interactive/timer_rate 0664 system system +/sys/devices/system/cpu/cpufreq interactive/min_sample_rate 0664 system system +/sys/devices/system/cpu/cpufreq interactive/min_sample_time 0664 system system +/sys/devices/system/cpu/cpufreq interactive/hispeed_freq 0664 system system +/sys/devices/system/cpu/cpufreq interactive/go_hispeed_load 0664 system system +/sys/devices/system/cpu/cpufreq interactive/above_hispeed_delay 0664 system system +/sys/devices/system/cpu/cpufreq interactive/io_is_busy 0664 system system