system/core
Revision | 14a57a3a34c111a6afd0ca779e70c44ba7361b18 (tree) |
---|---|
Time | 2017-10-26 00:43:43 |
Author | meijjaa <jjmeijer88@gmai...> |
Commiter | meijjaa |
Merge remote-tracking branch 'x86/nougat-x86' into cm-14.1-x86
@@ -51,7 +51,48 @@ ADB_MUTEX_DEFINE(local_transports_lock); | ||
51 | 51 | * trying to connect twice to a given local transport. |
52 | 52 | */ |
53 | 53 | static atransport* local_transports[ ADB_LOCAL_TRANSPORT_MAX ]; |
54 | -#endif /* ADB_HOST */ | |
54 | +#else /* !ADB_HOST */ | |
55 | + | |
56 | +#define WAKE_LOCK_NAME "adb-socket-connection" | |
57 | +#define WAKE_LOCK_ACQUIRE "/sys/power/wake_lock" | |
58 | +#define WAKE_LOCK_RELEASE "/sys/power/wake_unlock" | |
59 | + | |
60 | +static int sysfs_write(const char *node, const char *message) | |
61 | +{ | |
62 | + int fd; | |
63 | + ssize_t to_write; | |
64 | + int ret = 0; | |
65 | + | |
66 | + fd = adb_open(node, O_RDWR); | |
67 | + if (!fd) { | |
68 | + D("open '%s' failed: %s", node, strerror(errno)); | |
69 | + return -1; | |
70 | + } | |
71 | + | |
72 | + to_write = strlen(message); | |
73 | + if (adb_write(fd, message, to_write) != to_write) { | |
74 | + D("write '%s' failed: %s", node, strerror(errno)); | |
75 | + ret = -1; | |
76 | + } | |
77 | + adb_close(fd); | |
78 | + return ret; | |
79 | +} | |
80 | + | |
81 | +static void get_wakelock(void) | |
82 | +{ | |
83 | + if (sysfs_write(WAKE_LOCK_ACQUIRE, WAKE_LOCK_NAME)) { | |
84 | + D("couldn't reserve wakelock for socket connection"); | |
85 | + } | |
86 | +} | |
87 | + | |
88 | +static void release_wakelock(void) | |
89 | +{ | |
90 | + if (sysfs_write(WAKE_LOCK_RELEASE, WAKE_LOCK_NAME)) { | |
91 | + D("couldn't release wakelock for socket connection"); | |
92 | + } | |
93 | +} | |
94 | + | |
95 | +#endif /* !ADB_HOST */ | |
55 | 96 | |
56 | 97 | static int remote_read(apacket *p, atransport *t) |
57 | 98 | { |
@@ -171,6 +212,9 @@ static void server_socket_thread(void* arg) { | ||
171 | 212 | fd = adb_socket_accept(serverfd, addrp, &alen); |
172 | 213 | if(fd >= 0) { |
173 | 214 | D("server: new connection on fd %d", fd); |
215 | +#if !ADB_HOST | |
216 | + get_wakelock(); | |
217 | +#endif | |
174 | 218 | close_on_exec(fd); |
175 | 219 | disable_tcp_nagle(fd); |
176 | 220 | register_socket_transport(fd, "host", port, 1); |
@@ -340,6 +384,9 @@ static void remote_kick(atransport *t) | ||
340 | 384 | |
341 | 385 | static void remote_close(atransport *t) |
342 | 386 | { |
387 | +#if !ADB_HOST | |
388 | + release_wakelock(); | |
389 | +#endif | |
343 | 390 | int fd = t->sfd; |
344 | 391 | if (fd != -1) { |
345 | 392 | t->sfd = -1; |
@@ -131,8 +131,13 @@ static const char* get_sigcode(int signo, int code) { | ||
131 | 131 | #if defined(SEGV_BNDERR) |
132 | 132 | case SEGV_BNDERR: return "SEGV_BNDERR"; |
133 | 133 | #endif |
134 | +#if defined(SEGV_PKUERR) | |
135 | + case SEGV_PKUERR: return "SEGV_PKUERR"; | |
136 | +#endif | |
134 | 137 | } |
135 | -#if defined(SEGV_BNDERR) | |
138 | +#if defined(SEGV_PKUERR) | |
139 | + static_assert(NSIGSEGV == SEGV_PKUERR, "missing SEGV_* si_code"); | |
140 | +#elif defined(SEGV_BNDERR) | |
136 | 141 | static_assert(NSIGSEGV == SEGV_BNDERR, "missing SEGV_* si_code"); |
137 | 142 | #else |
138 | 143 | static_assert(NSIGSEGV == SEGV_ACCERR, "missing SEGV_* si_code"); |
@@ -36,7 +36,7 @@ static int format_ext4(char *fs_blkdev, char *fs_mnt_point, long long fs_length) | ||
36 | 36 | uint64_t dev_sz; |
37 | 37 | int fd, rc = 0; |
38 | 38 | |
39 | - if ((fd = open(fs_blkdev, O_WRONLY, 0644)) < 0) { | |
39 | + if ((fd = open(fs_blkdev, O_WRONLY)) < 0) { | |
40 | 40 | ERROR("Cannot open block device. %s\n", strerror(errno)); |
41 | 41 | return -1; |
42 | 42 | } |
@@ -76,7 +76,7 @@ public: | ||
76 | 76 | |
77 | 77 | void store_sid(uint32_t uid, uint64_t sid) { |
78 | 78 | char filename[21]; |
79 | - sprintf(filename, "%u", uid); | |
79 | + snprintf(filename, sizeof(filename), "%u", uid); | |
80 | 80 | int fd = open(filename, O_WRONLY | O_TRUNC | O_CREAT, S_IRUSR | S_IWUSR); |
81 | 81 | if (fd < 0) { |
82 | 82 | ALOGE("could not open file: %s: %s", filename, strerror(errno)); |
@@ -102,7 +102,7 @@ public: | ||
102 | 102 | |
103 | 103 | void maybe_store_sid(uint32_t uid, uint64_t sid) { |
104 | 104 | char filename[21]; |
105 | - sprintf(filename, "%u", uid); | |
105 | + snprintf(filename, sizeof(filename), "%u", uid); | |
106 | 106 | if (access(filename, F_OK) == -1) { |
107 | 107 | store_sid(uid, sid); |
108 | 108 | } |
@@ -111,7 +111,7 @@ public: | ||
111 | 111 | uint64_t read_sid(uint32_t uid) { |
112 | 112 | char filename[21]; |
113 | 113 | uint64_t sid; |
114 | - sprintf(filename, "%u", uid); | |
114 | + snprintf(filename, sizeof(filename), "%u", uid); | |
115 | 115 | int fd = open(filename, O_RDONLY); |
116 | 116 | if (fd < 0) return 0; |
117 | 117 | read(fd, &sid, sizeof(sid)); |
@@ -121,7 +121,7 @@ public: | ||
121 | 121 | |
122 | 122 | void clear_sid(uint32_t uid) { |
123 | 123 | char filename[21]; |
124 | - sprintf(filename, "%u", uid); | |
124 | + snprintf(filename, sizeof(filename), "%u", uid); | |
125 | 125 | if (remove(filename) < 0) { |
126 | 126 | ALOGE("%s: could not remove file [%s], attempting 0 write", __func__, strerror(errno)); |
127 | 127 | store_sid(uid, 0); |
@@ -0,0 +1,103 @@ | ||
1 | +/* | |
2 | + * Copyright (C) 2012 The Android Open Source Project | |
3 | + * | |
4 | + * Licensed under the Apache License, Version 2.0 (the "License"); | |
5 | + * you may not use this file except in compliance with the License. | |
6 | + * You may obtain a copy of the License at | |
7 | + * | |
8 | + * http://www.apache.org/licenses/LICENSE-2.0 | |
9 | + * | |
10 | + * Unless required by applicable law or agreed to in writing, software | |
11 | + * distributed under the License is distributed on an "AS IS" BASIS, | |
12 | + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | |
13 | + * See the License for the specific language governing permissions and | |
14 | + * limitations under the License. | |
15 | + */ | |
16 | + | |
17 | +#ifndef _LIBS_CUTILS_PROBEMODULE_H | |
18 | +#define _LIBS_CUTILS_PROBEMODULE_H | |
19 | + | |
20 | +#ifdef __cplusplus | |
21 | +extern "C" { | |
22 | +#endif | |
23 | + | |
24 | +/* get_default_mod_path() - get the default modules path | |
25 | + * It checks /system/lib/modules/$(uname -r)/ first. If it doesn't exist, | |
26 | + * fall back to /system/lib/modules/. | |
27 | + * | |
28 | + * def_mod_path: The buffer to be filled | |
29 | + * | |
30 | + * return : def_mod_path | |
31 | + */ | |
32 | +extern char *get_default_mod_path(char *def_mod_path); | |
33 | + | |
34 | +/* insmod() - load a kernel module (target) from a file | |
35 | + * | |
36 | + * filename : Filename of the target module. | |
37 | + * | |
38 | + * args : A string of target module's parameters. NOTE: we only | |
39 | + * support parameters of the target module. | |
40 | + * | |
41 | + */ | |
42 | +extern int insmod(const char *filename, const char *args); | |
43 | + | |
44 | +/* insmod_by_dep() - load a kernel module (target) with its dependency | |
45 | + * The module's dependency must be described in the provided dependency file. | |
46 | + * other modules in the dependency chain will be loaded prior to the target. | |
47 | + * | |
48 | + * module_name: Name of the target module. e.g. name "MyModule" is for | |
49 | + * module file MyModule.ko. | |
50 | + * | |
51 | + * args : A string of target module's parameters. NOTE: we only | |
52 | + * support parameters of the target module. | |
53 | + * | |
54 | + * dep_name : Name of dependency file. If it is NULL, we will look | |
55 | + * up /system/lib/modules/modules.dep by default. | |
56 | + * | |
57 | + * strip : Non-zero values remove paths of modules in dependency. | |
58 | + * before loading them. The final path of a module will be | |
59 | + * base/MyModule.ko. This is for devices which put every | |
60 | + * modules into a single directory. | |
61 | + * | |
62 | + * Passing 0 to strip keeps module paths in dependency file. | |
63 | + * e.g. "kernel/drivers/.../MyModule.ko" in dep file will | |
64 | + * be loaded as base/kernel/drivers/.../MyModule.ko . | |
65 | + * | |
66 | + * base : Base dir, a prefix to be added to module's path prior to | |
67 | + * loading. The last character prior to base string's terminator | |
68 | + * must be a '/'. If it is NULL, we will take | |
69 | + * /system/lib/modules/modules.dep by default. | |
70 | + * | |
71 | + * return : 0 for success; non-zero for any errors. | |
72 | + * | |
73 | + * Note: | |
74 | + * When loading modules, function will not fail for any modules which are | |
75 | + * already in kernel. The module parameters passed to function will not be | |
76 | + * effective in this case if target module is already loaded into kernel. | |
77 | + */ | |
78 | +extern int insmod_by_dep( | |
79 | + const char *module_name, | |
80 | + const char *args, | |
81 | + const char *dep_name, | |
82 | + int strip, | |
83 | + const char * base); | |
84 | + | |
85 | +/* rmmod_by_dep() - remove a module (target) from kernel with its dependency | |
86 | + * The module's dependency must be described in the provided dependency file. | |
87 | + * This function will try to remove other modules in the dependency chain too | |
88 | + * | |
89 | + * module_name: Name of the target module. e.g. name "MyModule" is for | |
90 | + * module file MyModule.ko. | |
91 | + * | |
92 | + * dep_name : Name of dependency file. If it is NULL, we will look | |
93 | + * up /system/lib/modules/modules.dep by default. | |
94 | + * | |
95 | + * return : 0 for success; non-zero for any errors. | |
96 | + */ | |
97 | +extern int rmmod_by_dep(const char *module_name, const char *dep_name); | |
98 | + | |
99 | +#ifdef __cplusplus | |
100 | +} | |
101 | +#endif | |
102 | + | |
103 | +#endif /*_LIBS_CUTILS_PROBEMODULE_H*/ |
@@ -21,6 +21,11 @@ | ||
21 | 21 | #include <stdint.h> |
22 | 22 | #include <sys/types.h> |
23 | 23 | |
24 | +#ifdef __APPLE__ | |
25 | +typedef int64_t loff_t; | |
26 | +#define lseek64 lseek | |
27 | +#endif | |
28 | + | |
24 | 29 | #ifdef __cplusplus |
25 | 30 | extern "C" { |
26 | 31 | #endif |
@@ -68,6 +68,7 @@ include $(BUILD_STATIC_LIBRARY) | ||
68 | 68 | |
69 | 69 | include $(CLEAR_VARS) |
70 | 70 | LOCAL_CPPFLAGS := $(init_cflags) |
71 | +LOCAL_CPPFLAGS += -DTARGET_PRODUCT=\"$(TARGET_PRODUCT)\" | |
71 | 72 | LOCAL_SRC_FILES:= \ |
72 | 73 | bootchart.cpp \ |
73 | 74 | builtins.cpp \ |
@@ -142,6 +143,7 @@ LOCAL_STATIC_LIBRARIES := \ | ||
142 | 143 | |
143 | 144 | # Create symlinks |
144 | 145 | LOCAL_POST_INSTALL_CMD := $(hide) mkdir -p $(TARGET_ROOT_OUT)/sbin; \ |
146 | + ln -sf ../init $(TARGET_ROOT_OUT)/sbin/modprobe; \ | |
145 | 147 | ln -sf ../init $(TARGET_ROOT_OUT)/sbin/ueventd; \ |
146 | 148 | ln -sf ../init $(TARGET_ROOT_OUT)/sbin/watchdogd |
147 | 149 |
@@ -29,9 +29,6 @@ | ||
29 | 29 | #include <sys/socket.h> |
30 | 30 | #include <sys/mount.h> |
31 | 31 | #include <sys/resource.h> |
32 | -#ifndef NO_FINIT_MODULE | |
33 | -#include <sys/syscall.h> | |
34 | -#endif | |
35 | 32 | #include <sys/time.h> |
36 | 33 | #include <sys/types.h> |
37 | 34 | #include <sys/stat.h> |
@@ -51,6 +48,7 @@ | ||
51 | 48 | #include <bootloader_message/bootloader_message.h> |
52 | 49 | #include <cutils/partition_utils.h> |
53 | 50 | #include <cutils/android_reboot.h> |
51 | +#include <cutils/probe_module.h> | |
54 | 52 | #include <logwrap/logwrap.h> |
55 | 53 | #include <private/android_filesystem_config.h> |
56 | 54 |
@@ -78,29 +76,6 @@ extern "C" int init_module(void *, unsigned long, const char *); | ||
78 | 76 | |
79 | 77 | static const int kTerminateServiceDelayMicroSeconds = 50000; |
80 | 78 | |
81 | -static int insmod(const char *filename, const char *options) { | |
82 | -#ifndef NO_FINIT_MODULE | |
83 | - int fd = open(filename, O_RDONLY | O_NOFOLLOW | O_CLOEXEC); | |
84 | - if (fd == -1) { | |
85 | - ERROR("insmod: open(\"%s\") failed: %s", filename, strerror(errno)); | |
86 | -#else | |
87 | - std::string module; | |
88 | - if (!read_file(filename, &module)) { | |
89 | -#endif | |
90 | - return -1; | |
91 | - } | |
92 | -#ifndef NO_FINIT_MODULE | |
93 | - int rc = syscall(__NR_finit_module, fd, options, 0); | |
94 | - if (rc == -1) { | |
95 | - ERROR("finit_module for \"%s\" failed: %s", filename, strerror(errno)); | |
96 | - } | |
97 | - close(fd); | |
98 | - return rc; | |
99 | -#else | |
100 | - return init_module(&module[0], module.size(), options); | |
101 | -#endif | |
102 | -} | |
103 | - | |
104 | 79 | static int __ifupdown(const char *interface, int up) { |
105 | 80 | struct ifreq ifr; |
106 | 81 | int s, ret; |
@@ -573,9 +548,14 @@ static int mount_fstab(const char* fstabfile, int mount_mode) { | ||
573 | 548 | ret = -1; |
574 | 549 | } |
575 | 550 | } else if (pid == 0) { |
551 | + std::string filename_val; | |
552 | + if (!expand_props(fstabfile, &filename_val)) { | |
553 | + ERROR("mount_all: cannot expand '%s'\n", fstabfile); | |
554 | + _exit(-1); | |
555 | + } | |
576 | 556 | /* child, call fs_mgr_mount_all() */ |
577 | 557 | klog_set_level(6); /* So we can see what fs_mgr_mount_all() does */ |
578 | - fstab = fs_mgr_read_fstab(fstabfile); | |
558 | + fstab = fs_mgr_read_fstab(filename_val.c_str()); | |
579 | 559 | child_ret = fs_mgr_mount_all(fstab, mount_mode); |
580 | 560 | fs_mgr_free_fstab(fstab); |
581 | 561 | if (child_ret == -1) { |
@@ -649,14 +629,13 @@ static int queue_fs_event(int code) { | ||
649 | 629 | * not return. |
650 | 630 | */ |
651 | 631 | static int do_mount_all(const std::vector<std::string>& args) { |
652 | - std::size_t na = 0; | |
653 | 632 | bool import_rc = true; |
654 | 633 | bool queue_event = true; |
655 | 634 | int mount_mode = MOUNT_MODE_DEFAULT; |
656 | 635 | const char* fstabfile = args[1].c_str(); |
657 | 636 | std::size_t path_arg_end = args.size(); |
658 | 637 | |
659 | - for (na = args.size() - 1; na > 1; --na) { | |
638 | + for (std::size_t na = args.size() - 1; na > 1; --na) { | |
660 | 639 | if (args[na] == "--early") { |
661 | 640 | path_arg_end = na; |
662 | 641 | queue_event = false; |
@@ -834,13 +813,96 @@ static int do_rmdir(const std::vector<std::string>& args) { | ||
834 | 813 | return rmdir(args[1].c_str()); |
835 | 814 | } |
836 | 815 | |
816 | +// read persist property from /data/property directly, because it maybe has not loaded | |
817 | +// if the file not found, try to call property_get, the default value could be saved | |
818 | +// into /default.prop | |
819 | +static std::string persist_property_get(const char *name) | |
820 | +{ | |
821 | + const char *filename_template = "/data/property/%s"; | |
822 | + size_t max_file_name_len = strlen(filename_template) + PROP_NAME_MAX; | |
823 | + char filename[max_file_name_len]; | |
824 | + snprintf(filename, max_file_name_len, filename_template, name); | |
825 | + | |
826 | + if (access(filename, 0) == 0) { | |
827 | + char *line = NULL; | |
828 | + size_t len; | |
829 | + FILE *fp = fopen(filename, "r+"); | |
830 | + if (fp == NULL) { | |
831 | + ERROR("failed to read file for property:%s\n", filename); | |
832 | + return 0; | |
833 | + } | |
834 | + | |
835 | + std::string result; | |
836 | + if (getline(&line, &len, fp) == -1) { | |
837 | + len = 0; | |
838 | + } else { | |
839 | + for (len = 0; *(line+len) != '\n' && *(line+len) != 0; len++); | |
840 | + *(line + len) = '\0'; | |
841 | + result = line; | |
842 | + free(line); | |
843 | + } | |
844 | + fclose(fp); | |
845 | + return result; | |
846 | + } | |
847 | + | |
848 | + return property_get(name); | |
849 | +} | |
850 | + | |
837 | 851 | static int do_sysclktz(const std::vector<std::string>& args) { |
838 | 852 | struct timezone tz; |
853 | + struct timeval tv; | |
854 | + struct tm tm; | |
855 | + time_t t; | |
839 | 856 | |
840 | 857 | memset(&tz, 0, sizeof(tz)); |
841 | - tz.tz_minuteswest = std::stoi(args[1]); | |
842 | - if (settimeofday(NULL, &tz)) | |
858 | + memset(&tv, 0, sizeof(tv)); | |
859 | + memset(&tm, 0, sizeof(tm)); | |
860 | + | |
861 | + INFO("sysclktz: the arg %s is ignored, only persist.rtc_local_time matters\n", args[1].c_str()); | |
862 | + | |
863 | + if (gettimeofday(&tv, NULL)) { | |
864 | + ERROR("sysclktz: failed to call gettimeofday"); | |
843 | 865 | return -1; |
866 | + } | |
867 | + | |
868 | + if (persist_property_get("persist.rtc_local_time") == "1") { | |
869 | + /* Notify kernel that hwtime use local time */ | |
870 | + write_file("/sys/class/misc/alarm/rtc_local_time", "1"); | |
871 | + /* | |
872 | + * If ro.hwtime.mode is local, set system time | |
873 | + * and saved system zone in case of network not | |
874 | + * available and auto syncing time not available. | |
875 | + */ | |
876 | + | |
877 | + std::string time_zone = persist_property_get("persist.sys.timezone"); | |
878 | + if (time_zone.empty()) { | |
879 | + INFO("sysclktz: persist.sys.timezone not found\n"); | |
880 | + tz.tz_minuteswest = 0; | |
881 | + } else { | |
882 | + const char *timezone_prop = time_zone.c_str(); | |
883 | + INFO("sysclktz: persist.sys.timezone: %s\n", timezone_prop); | |
884 | + // localtime_r need the property, we need to set it | |
885 | + property_set("persist.sys.timezone", timezone_prop); | |
886 | + t = tv.tv_sec; | |
887 | + localtime_r(&t, &tm); | |
888 | + tz.tz_minuteswest = -(tm.tm_gmtoff / 60); | |
889 | + INFO("sysclktz: tz.tz_minuteswest: %d\n", tz.tz_minuteswest); | |
890 | + } | |
891 | + | |
892 | + /* | |
893 | + * At this moment, system time should be local | |
894 | + * time too, set it back to utc which linux required. | |
895 | + */ | |
896 | + tv.tv_sec += tz.tz_minuteswest * 60; | |
897 | + if (settimeofday(&tv, &tz)) { | |
898 | + ERROR("sysclktz: failed to call settimeofdays\n"); | |
899 | + return -1; | |
900 | + } | |
901 | + } else { | |
902 | + tz.tz_minuteswest = std::stoi(args[1]); | |
903 | + return settimeofday(NULL, &tz); | |
904 | + } | |
905 | + | |
844 | 906 | return 0; |
845 | 907 | } |
846 | 908 |
@@ -42,18 +42,28 @@ | ||
42 | 42 | |
43 | 43 | #include <android-base/file.h> |
44 | 44 | #include <cutils/list.h> |
45 | +#include <cutils/probe_module.h> | |
45 | 46 | #include <cutils/uevent.h> |
46 | 47 | |
47 | 48 | #include "devices.h" |
48 | 49 | #include "ueventd_parser.h" |
49 | 50 | #include "util.h" |
50 | 51 | #include "log.h" |
52 | +#include "parser.h" | |
51 | 53 | #include "property_service.h" |
52 | 54 | |
53 | 55 | #define SYSFS_PREFIX "/sys" |
56 | +#if defined(__i386__) || defined(__x86_64__) | |
57 | +static const char *firmware_dirs[] = { "/system/lib/firmware" }; | |
58 | +#else | |
54 | 59 | static const char *firmware_dirs[] = { "/etc/firmware", |
55 | 60 | "/vendor/firmware", |
56 | 61 | "/firmware/image" }; |
62 | +#endif | |
63 | + | |
64 | +#define MODULES_BLKLST "/system/etc/modules.blacklist" | |
65 | +#define READ_MODULES_ALIAS 1 | |
66 | +#define READ_MODULES_BLKLST 2 | |
57 | 67 | |
58 | 68 | extern struct selabel_handle *sehandle; |
59 | 69 |
@@ -68,6 +78,7 @@ struct uevent { | ||
68 | 78 | const char *firmware; |
69 | 79 | const char *partition_name; |
70 | 80 | const char *device_name; |
81 | + const char *modalias; | |
71 | 82 | int partition_num; |
72 | 83 | int major; |
73 | 84 | int minor; |
@@ -95,9 +106,27 @@ struct platform_node { | ||
95 | 106 | struct listnode list; |
96 | 107 | }; |
97 | 108 | |
109 | +struct module_alias_node { | |
110 | + char *name; | |
111 | + char *pattern; | |
112 | + struct listnode list; | |
113 | +}; | |
114 | + | |
115 | +struct module_blacklist_node { | |
116 | + char *name; | |
117 | + bool deferred; | |
118 | + struct listnode list; | |
119 | +}; | |
120 | + | |
98 | 121 | static list_declare(sys_perms); |
99 | 122 | static list_declare(dev_perms); |
100 | 123 | static list_declare(platform_names); |
124 | +static list_declare(modules_aliases_map); | |
125 | +static list_declare(modules_blacklist); | |
126 | +static list_declare(deferred_module_loading_list); | |
127 | + | |
128 | +static int read_modules_aliases(); | |
129 | +static int read_modules_blacklist(); | |
101 | 130 | |
102 | 131 | int add_dev_perms(const char *name, const char *attr, |
103 | 132 | mode_t perm, unsigned int uid, unsigned int gid, |
@@ -405,6 +434,7 @@ static void parse_event(const char *msg, struct uevent *uevent) | ||
405 | 434 | uevent->partition_name = NULL; |
406 | 435 | uevent->partition_num = -1; |
407 | 436 | uevent->device_name = NULL; |
437 | + uevent->modalias = NULL; | |
408 | 438 | |
409 | 439 | /* currently ignoring SEQNUM */ |
410 | 440 | while(*msg) { |
@@ -435,6 +465,9 @@ static void parse_event(const char *msg, struct uevent *uevent) | ||
435 | 465 | } else if(!strncmp(msg, "DEVNAME=", 8)) { |
436 | 466 | msg += 8; |
437 | 467 | uevent->device_name = msg; |
468 | + } else if(!strncmp(msg, "MODALIAS=", 9)) { | |
469 | + msg += 9; | |
470 | + uevent->modalias = msg; | |
438 | 471 | } |
439 | 472 | |
440 | 473 | /* advance to after the next \0 */ |
@@ -761,7 +794,7 @@ static void handle_generic_device_event(struct uevent *uevent) | ||
761 | 794 | return; |
762 | 795 | mkdir_recursive_for_devpath(devpath); |
763 | 796 | } else if (!strncmp(uevent->subsystem, "usb", 3)) { |
764 | - if (!strcmp(uevent->subsystem, "usb")) { | |
797 | + if (!strcmp(uevent->subsystem, "usb") || !strcmp(uevent->subsystem, "usbmisc")) { | |
765 | 798 | if (uevent->device_name) { |
766 | 799 | if (!assemble_devpath(devpath, "/dev", uevent->device_name)) |
767 | 800 | return; |
@@ -848,8 +881,186 @@ static void handle_generic_device_event(struct uevent *uevent) | ||
848 | 881 | uevent->major, uevent->minor, links); |
849 | 882 | } |
850 | 883 | |
884 | +static int is_module_blacklisted_or_deferred(const char *name, bool need_deferred) | |
885 | +{ | |
886 | + struct listnode *blklst_node; | |
887 | + struct module_blacklist_node *blacklist; | |
888 | + int ret = 0; | |
889 | + | |
890 | + if (!name) goto out; | |
891 | + | |
892 | + /* See if module is blacklisted, skip if it is */ | |
893 | + list_for_each(blklst_node, &modules_blacklist) { | |
894 | + blacklist = node_to_item(blklst_node, | |
895 | + struct module_blacklist_node, | |
896 | + list); | |
897 | + if (!strcmp(name, blacklist->name)) { | |
898 | + INFO("modules %s is blacklisted\n", name); | |
899 | + ret = blacklist->deferred ? (need_deferred ? 2 : 0) : 1; | |
900 | + goto out; | |
901 | + } | |
902 | + } | |
903 | + | |
904 | +out: | |
905 | + return ret; | |
906 | +} | |
907 | + | |
908 | +static int load_module_by_device_modalias(const char *id, bool need_deferred) | |
909 | +{ | |
910 | + struct listnode *alias_node; | |
911 | + struct module_alias_node *alias; | |
912 | + int ret = -1; | |
913 | + | |
914 | + list_for_each(alias_node, &modules_aliases_map) { | |
915 | + alias = node_to_item(alias_node, struct module_alias_node, list); | |
916 | + | |
917 | + if (alias && alias->name && alias->pattern) { | |
918 | + if (fnmatch(alias->pattern, id, 0) == 0) { | |
919 | + INFO("trying to load module %s due to uevents\n", alias->name); | |
920 | + | |
921 | + ret = is_module_blacklisted_or_deferred(alias->name, need_deferred); | |
922 | + if (ret == 0) { | |
923 | + if ((ret = insmod_by_dep(alias->name, "", NULL, 0, NULL))) { | |
924 | + /* cannot load module. try another one since | |
925 | + * there may be another match. | |
926 | + */ | |
927 | + NOTICE("failed to load %s for modalias %s\n", | |
928 | + alias->name, id); | |
929 | + } else { | |
930 | + /* loading was successful */ | |
931 | + INFO("loaded module %s due to uevents\n", alias->name); | |
932 | + } | |
933 | + } else { | |
934 | + NOTICE("blacklisted module %s: %d\n", alias->name, ret); | |
935 | + } | |
936 | + } | |
937 | + } | |
938 | + } | |
939 | + | |
940 | + return ret; | |
941 | +} | |
942 | + | |
943 | +static void handle_deferred_module_loading() | |
944 | +{ | |
945 | + /* try to read the module alias mapping if map is empty | |
946 | + * if succeed, loading all the modules in the queue | |
947 | + */ | |
948 | + if (!list_empty(&modules_aliases_map)) { | |
949 | + struct listnode *node = NULL; | |
950 | + struct listnode *next = NULL; | |
951 | + struct module_alias_node *alias = NULL; | |
952 | + | |
953 | + list_for_each_safe(node, next, &deferred_module_loading_list) { | |
954 | + alias = node_to_item(node, struct module_alias_node, list); | |
955 | + | |
956 | + if (alias && alias->pattern) { | |
957 | + INFO("deferred loading of module for %s\n", alias->pattern); | |
958 | + load_module_by_device_modalias(alias->pattern, false); | |
959 | + free(alias->pattern); | |
960 | + list_remove(node); | |
961 | + free(alias); | |
962 | + } | |
963 | + } | |
964 | + } | |
965 | +} | |
966 | + | |
967 | +static int module_probe(int argc, char **argv) | |
968 | +{ | |
969 | + if (list_empty(&modules_aliases_map)) { | |
970 | + read_modules_aliases(); | |
971 | + read_modules_blacklist(); | |
972 | + } | |
973 | + | |
974 | + // is it a modalias? | |
975 | + int ret = load_module_by_device_modalias(argv[1], false); | |
976 | + if (ret) { | |
977 | + // treat it as a module name | |
978 | + std::string options; | |
979 | + if (argc > 2) { | |
980 | + options = argv[2]; | |
981 | + for (int i = 3; i < argc; ++i) { | |
982 | + options += ' '; | |
983 | + options += argv[i]; | |
984 | + } | |
985 | + } | |
986 | + ret = insmod_by_dep(argv[1], options.c_str(), NULL, 0, NULL); | |
987 | + } | |
988 | + return ret; | |
989 | +} | |
990 | + | |
991 | +int modprobe_main(int argc, char **argv) | |
992 | +{ | |
993 | + const char *prog = argv[0]; | |
994 | + | |
995 | + /* We only accept requests from root user (kernel) */ | |
996 | + if (getuid()) | |
997 | + return -EPERM; | |
998 | + | |
999 | + /* Kernel will launch a user space program specified by | |
1000 | + * /proc/sys/kernel/modprobe to load modules. | |
1001 | + * No deferred loading in this case. | |
1002 | + */ | |
1003 | + while (argc > 1 && (!strcmp(argv[1], "-q") || !strcmp(argv[1], "--"))) { | |
1004 | + klog_set_level(KLOG_NOTICE_LEVEL); | |
1005 | + argc--, argv++; | |
1006 | + } | |
1007 | + | |
1008 | + if (argc < 2) { | |
1009 | + /* it is called without enough arguments */ | |
1010 | + return -EINVAL; | |
1011 | + } | |
1012 | + | |
1013 | + NOTICE("%s %s\n", prog, argv[1]); | |
1014 | + return module_probe(argc, argv); | |
1015 | +} | |
1016 | + | |
1017 | +static int is_booting(void) | |
1018 | +{ | |
1019 | + return access("/dev/.booting", F_OK) == 0; | |
1020 | +} | |
1021 | + | |
1022 | +static void handle_module_loading(const char *modalias) | |
1023 | +{ | |
1024 | + struct module_alias_node *node; | |
1025 | + | |
1026 | + /* once modules.alias can be read, | |
1027 | + * we load all the deferred ones | |
1028 | + */ | |
1029 | + if (list_empty(&modules_aliases_map)) { | |
1030 | + if (read_modules_aliases() == 0) { | |
1031 | + read_modules_blacklist(); | |
1032 | + } | |
1033 | + } | |
1034 | + | |
1035 | + if (!modalias) return; | |
1036 | + | |
1037 | + if (list_empty(&modules_aliases_map) || | |
1038 | + load_module_by_device_modalias(modalias, is_booting()) == 2) { | |
1039 | + /* if module alias mapping is empty, | |
1040 | + * queue it for loading later | |
1041 | + */ | |
1042 | + node = (module_alias_node *) calloc(1, sizeof(*node)); | |
1043 | + if (node) { | |
1044 | + node->pattern = strdup(modalias); | |
1045 | + if (!node->pattern) { | |
1046 | + free(node); | |
1047 | + } else { | |
1048 | + list_add_tail(&deferred_module_loading_list, &node->list); | |
1049 | + INFO("add to queue for deferred module loading: %s", | |
1050 | + node->pattern); | |
1051 | + } | |
1052 | + } else { | |
1053 | + ERROR("failed to allocate memory to store device id for deferred module loading.\n"); | |
1054 | + } | |
1055 | + } | |
1056 | +} | |
1057 | + | |
851 | 1058 | static void handle_device_event(struct uevent *uevent) |
852 | 1059 | { |
1060 | + if (!strcmp(uevent->action,"add")) { | |
1061 | + handle_module_loading(uevent->modalias); | |
1062 | + } | |
1063 | + | |
853 | 1064 | if (!strcmp(uevent->action,"add") || !strcmp(uevent->action, "change") || !strcmp(uevent->action, "online")) |
854 | 1065 | fixup_sys_perms(uevent->path); |
855 | 1066 |
@@ -915,11 +1126,6 @@ static int load_firmware(int fw_fd, int loading_fd, int data_fd) | ||
915 | 1126 | return ret; |
916 | 1127 | } |
917 | 1128 | |
918 | -static int is_booting(void) | |
919 | -{ | |
920 | - return access("/dev/.booting", F_OK) == 0; | |
921 | -} | |
922 | - | |
923 | 1129 | static void process_firmware_event(struct uevent *uevent) |
924 | 1130 | { |
925 | 1131 | char *root, *loading, *data; |
@@ -927,7 +1133,7 @@ static void process_firmware_event(struct uevent *uevent) | ||
927 | 1133 | size_t i; |
928 | 1134 | int booting = is_booting(); |
929 | 1135 | |
930 | - INFO("firmware: loading '%s' for '%s'\n", | |
1136 | + NOTICE("firmware: loading '%s' for '%s'\n", | |
931 | 1137 | uevent->firmware, uevent->path); |
932 | 1138 | |
933 | 1139 | l = asprintf(&root, SYSFS_PREFIX"%s/", uevent->path); |
@@ -995,26 +1201,162 @@ root_free_out: | ||
995 | 1201 | |
996 | 1202 | static void handle_firmware_event(struct uevent *uevent) |
997 | 1203 | { |
998 | - pid_t pid; | |
999 | - | |
1000 | 1204 | if(strcmp(uevent->subsystem, "firmware")) |
1001 | 1205 | return; |
1002 | 1206 | |
1003 | 1207 | if(strcmp(uevent->action, "add")) |
1004 | 1208 | return; |
1005 | 1209 | |
1006 | - /* we fork, to avoid making large memory allocations in init proper */ | |
1007 | - pid = fork(); | |
1008 | - if (!pid) { | |
1009 | - process_firmware_event(uevent); | |
1010 | - _exit(EXIT_SUCCESS); | |
1011 | - } else if (pid < 0) { | |
1012 | - ERROR("could not fork to process firmware event: %s\n", strerror(errno)); | |
1210 | + process_firmware_event(uevent); | |
1211 | +} | |
1212 | + | |
1213 | +static void parse_line_module_alias(struct parse_state *state, int nargs, char **args) | |
1214 | +{ | |
1215 | + struct module_alias_node *node; | |
1216 | + | |
1217 | + if (!args || | |
1218 | + (nargs != 3) || | |
1219 | + !args[0] || !args[1] || !args[2]) { | |
1220 | + /* empty line or not enough arguments */ | |
1221 | + return; | |
1222 | + } | |
1223 | + | |
1224 | + node = (module_alias_node *) calloc(1, sizeof(*node)); | |
1225 | + if (!node) return; | |
1226 | + | |
1227 | + node->name = strdup(args[2]); | |
1228 | + if (!node->name) { | |
1229 | + free(node); | |
1230 | + return; | |
1231 | + } | |
1232 | + | |
1233 | + node->pattern = strdup(args[1]); | |
1234 | + if (!node->pattern) { | |
1235 | + free(node->name); | |
1236 | + free(node); | |
1237 | + return; | |
1238 | + } | |
1239 | + | |
1240 | + list_add_tail(&modules_aliases_map, &node->list); | |
1241 | +} | |
1242 | + | |
1243 | +static void parse_line_module_blacklist(struct parse_state *state, int nargs, char **args) | |
1244 | +{ | |
1245 | + struct module_blacklist_node *node; | |
1246 | + bool deferred; | |
1247 | + | |
1248 | + if (!args || | |
1249 | + (nargs != 2) || | |
1250 | + !args[0] || !args[1]) { | |
1251 | + /* empty line or not enough arguments */ | |
1252 | + return; | |
1253 | + } | |
1254 | + | |
1255 | + /* this line does not being with "blacklist" or "deferred" */ | |
1256 | + if (!strncmp(args[0], "blacklist", 9)) | |
1257 | + deferred = false; | |
1258 | + else if (!strncmp(args[0], "deferred", 8)) | |
1259 | + deferred = true; | |
1260 | + else | |
1261 | + return; | |
1262 | + | |
1263 | + node = (module_blacklist_node *) calloc(1, sizeof(*node)); | |
1264 | + if (!node) return; | |
1265 | + | |
1266 | + node->name = strdup(args[1]); | |
1267 | + if (!node->name) { | |
1268 | + free(node); | |
1269 | + return; | |
1270 | + } | |
1271 | + node->deferred = deferred; | |
1272 | + | |
1273 | + list_add_tail(&modules_blacklist, &node->list); | |
1274 | +} | |
1275 | + | |
1276 | +static int __read_modules_desc_file(int mode) | |
1277 | +{ | |
1278 | + struct parse_state state; | |
1279 | + char *args[3]; | |
1280 | + int nargs; | |
1281 | + char fn[PATH_MAX]; | |
1282 | + int fd = -1; | |
1283 | + int ret = -1; | |
1284 | + int args_to_read = 0; | |
1285 | + std::string data; | |
1286 | + | |
1287 | + if (mode == READ_MODULES_ALIAS) { | |
1288 | + /* read modules.alias */ | |
1289 | + strcat(get_default_mod_path(fn), "modules.alias"); | |
1290 | + } else if (mode == READ_MODULES_BLKLST) { | |
1291 | + /* read modules.blacklist */ | |
1292 | + strcpy(fn, MODULES_BLKLST); | |
1293 | + } else { | |
1294 | + /* unknown mode */ | |
1295 | + goto out; | |
1296 | + } | |
1297 | + | |
1298 | + fd = open(fn, O_RDONLY); | |
1299 | + if (fd == -1) { | |
1300 | + goto out; | |
1301 | + } | |
1302 | + | |
1303 | + /* read the whole file */ | |
1304 | + if (!read_file(fn, &data)) { | |
1305 | + goto out; | |
1306 | + } | |
1307 | + | |
1308 | + /* invoke tokenizer */ | |
1309 | + nargs = 0; | |
1310 | + state.filename = fn; | |
1311 | + state.line = 1; | |
1312 | + state.ptr = &data[0]; | |
1313 | + state.nexttoken = 0; | |
1314 | + if (mode == READ_MODULES_ALIAS) { | |
1315 | + state.parse_line = parse_line_module_alias; | |
1316 | + args_to_read = 3; | |
1317 | + } else if (mode == READ_MODULES_BLKLST) { | |
1318 | + state.parse_line = parse_line_module_blacklist; | |
1319 | + args_to_read = 2; | |
1320 | + } | |
1321 | + for (;;) { | |
1322 | + int token = next_token(&state); | |
1323 | + switch (token) { | |
1324 | + case T_EOF: | |
1325 | + state.parse_line(&state, 0, 0); | |
1326 | + ret = 0; | |
1327 | + goto out; | |
1328 | + case T_NEWLINE: | |
1329 | + if (nargs) { | |
1330 | + state.parse_line(&state, nargs, args); | |
1331 | + nargs = 0; | |
1332 | + } | |
1333 | + break; | |
1334 | + case T_TEXT: | |
1335 | + if (nargs < args_to_read) { | |
1336 | + args[nargs++] = state.text; | |
1337 | + } | |
1338 | + break; | |
1339 | + } | |
1340 | + } | |
1341 | + ret = 0; | |
1342 | + | |
1343 | +out: | |
1344 | + if (fd != -1) { | |
1345 | + close(fd); | |
1013 | 1346 | } |
1347 | + return ret; | |
1348 | +} | |
1349 | + | |
1350 | +static int read_modules_aliases() { | |
1351 | + return __read_modules_desc_file(READ_MODULES_ALIAS); | |
1352 | +} | |
1353 | + | |
1354 | +static int read_modules_blacklist() { | |
1355 | + return __read_modules_desc_file(READ_MODULES_BLKLST); | |
1014 | 1356 | } |
1015 | 1357 | |
1016 | 1358 | #define UEVENT_MSG_LEN 2048 |
1017 | -void handle_device_fd() | |
1359 | +void handle_device_fd(bool child) | |
1018 | 1360 | { |
1019 | 1361 | char msg[UEVENT_MSG_LEN+2]; |
1020 | 1362 | int n; |
@@ -1037,8 +1379,11 @@ void handle_device_fd() | ||
1037 | 1379 | } |
1038 | 1380 | } |
1039 | 1381 | |
1040 | - handle_device_event(&uevent); | |
1041 | - handle_firmware_event(&uevent); | |
1382 | + if (child) { | |
1383 | + handle_firmware_event(&uevent); | |
1384 | + } else { | |
1385 | + handle_device_event(&uevent); | |
1386 | + } | |
1042 | 1387 | } |
1043 | 1388 | } |
1044 | 1389 |
@@ -1094,17 +1439,21 @@ static void coldboot(const char *path) | ||
1094 | 1439 | } |
1095 | 1440 | } |
1096 | 1441 | |
1097 | -void device_init() { | |
1442 | +void device_init(bool child) | |
1443 | +{ | |
1098 | 1444 | sehandle = selinux_android_file_context_handle(); |
1099 | 1445 | selinux_status_open(true); |
1100 | 1446 | |
1101 | - /* is 256K enough? udev uses 16MB! */ | |
1102 | - device_fd = uevent_open_socket(256*1024, true); | |
1447 | + /* is 8MB enough? udev uses 16MB! */ | |
1448 | + device_fd = uevent_open_socket(8 * 1024 * 1024, true); | |
1103 | 1449 | if (device_fd == -1) { |
1104 | 1450 | return; |
1105 | 1451 | } |
1106 | 1452 | fcntl(device_fd, F_SETFL, O_NONBLOCK); |
1107 | 1453 | |
1454 | + if (child) { | |
1455 | + return; // don't do coldboot in child | |
1456 | + } | |
1108 | 1457 | if (access(COLDBOOT_DONE, F_OK) == 0) { |
1109 | 1458 | NOTICE("Skipping coldboot, already done!\n"); |
1110 | 1459 | return; |
@@ -1114,6 +1463,7 @@ void device_init() { | ||
1114 | 1463 | coldboot("/sys/class"); |
1115 | 1464 | coldboot("/sys/block"); |
1116 | 1465 | coldboot("/sys/devices"); |
1466 | + handle_deferred_module_loading(); | |
1117 | 1467 | close(open(COLDBOOT_DONE, O_WRONLY|O_CREAT|O_CLOEXEC, 0000)); |
1118 | 1468 | NOTICE("Coldboot took %.2fs.\n", t.duration()); |
1119 | 1469 | } |
@@ -19,8 +19,9 @@ | ||
19 | 19 | |
20 | 20 | #include <sys/stat.h> |
21 | 21 | |
22 | -extern void handle_device_fd(); | |
23 | -extern void device_init(void); | |
22 | +extern void handle_device_fd(bool = false); | |
23 | +extern void device_init(bool); | |
24 | +extern int modprobe_main(int argc, char **argv); | |
24 | 25 | extern int add_dev_perms(const char *name, const char *attr, |
25 | 26 | mode_t perm, unsigned int uid, |
26 | 27 | unsigned int gid, unsigned short prefix, |
@@ -177,10 +177,10 @@ static int wait_for_coldboot_done_action(const std::vector<std::string>& args) { | ||
177 | 177 | timeout = 5; |
178 | 178 | #endif |
179 | 179 | NOTICE("Waiting for %s...\n", COLDBOOT_DONE); |
180 | - // Any longer than 1s is an unreasonable length of time to delay booting. | |
180 | + // Any longer than 10s is an unreasonable length of time to delay booting. | |
181 | 181 | // If you're hitting this timeout, check that you didn't make your |
182 | 182 | // sepolicy regular expressions too expensive (http://b/19899875). |
183 | - if (wait_for_file(COLDBOOT_DONE, timeout)) { | |
183 | + if (wait_for_file(COLDBOOT_DONE, 10)) { | |
184 | 184 | ERROR("Timed out waiting for %s\n", COLDBOOT_DONE); |
185 | 185 | } |
186 | 186 | NOTICE("Waiting for %s took %.2fs.\n", COLDBOOT_DONE, t.duration()); |
@@ -300,8 +300,8 @@ static int console_init_action(const std::vector<std::string>& args) | ||
300 | 300 | |
301 | 301 | fd = open("/dev/tty0", O_WRONLY | O_CLOEXEC); |
302 | 302 | if (fd >= 0) { |
303 | - const char *msg; | |
304 | - msg = "\n" | |
303 | + const char *msg = | |
304 | + "\033[9;0]\n" | |
305 | 305 | "\n" |
306 | 306 | "\n" |
307 | 307 | "\n" |
@@ -366,7 +366,7 @@ static void export_kernel_boot_props() { | ||
366 | 366 | { "ro.boot.mode", "ro.bootmode", "unknown", }, |
367 | 367 | { "ro.boot.baseband", "ro.baseband", "unknown", }, |
368 | 368 | { "ro.boot.bootloader", "ro.bootloader", "unknown", }, |
369 | - { "ro.boot.hardware", "ro.hardware", "unknown", }, | |
369 | + { "ro.boot.hardware", "ro.hardware", TARGET_PRODUCT, }, | |
370 | 370 | #ifndef IGNORE_RO_BOOT_REVISION |
371 | 371 | { "ro.boot.revision", "ro.revision", "0", }, |
372 | 372 | #endif |
@@ -558,6 +558,10 @@ static int charging_mode_booting(void) { | ||
558 | 558 | } |
559 | 559 | |
560 | 560 | int main(int argc, char** argv) { |
561 | + if (strstr(argv[0], "modprobe")) { | |
562 | + return modprobe_main(argc, argv); | |
563 | + } | |
564 | + | |
561 | 565 | if (!strcmp(basename(argv[0]), "ueventd")) { |
562 | 566 | return ueventd_main(argc, argv); |
563 | 567 | } |
@@ -12,7 +12,7 @@ void parse_error(struct parse_state *state, const char *fmt, ...) | ||
12 | 12 | char buf[128]; |
13 | 13 | int off; |
14 | 14 | |
15 | - snprintf(buf, 128, "%s: %d: ", state->filename, state->line); | |
15 | + snprintf(buf, sizeof(buf), "%s: %d: ", state->filename, state->line); | |
16 | 16 | buf[127] = 0; |
17 | 17 | off = strlen(buf); |
18 | 18 |
@@ -373,9 +373,11 @@ bool Service::Start() { | ||
373 | 373 | } |
374 | 374 | if (rc == 0 && scon == mycon) { |
375 | 375 | ERROR("Service %s does not have a SELinux domain defined.\n", name_.c_str()); |
376 | +#if 0 | |
376 | 377 | free(mycon); |
377 | 378 | free(fcon); |
378 | 379 | return false; |
380 | +#endif | |
379 | 381 | } |
380 | 382 | free(mycon); |
381 | 383 | free(fcon); |
@@ -15,12 +15,14 @@ | ||
15 | 15 | */ |
16 | 16 | |
17 | 17 | #include <ctype.h> |
18 | +#include <errno.h> | |
18 | 19 | #include <fcntl.h> |
19 | 20 | #include <poll.h> |
20 | 21 | #include <signal.h> |
21 | 22 | #include <stdio.h> |
22 | 23 | #include <stdlib.h> |
23 | 24 | #include <string.h> |
25 | +#include <unistd.h> | |
24 | 26 | |
25 | 27 | #include <android-base/stringprintf.h> |
26 | 28 | #include <private/android_filesystem_config.h> |
@@ -66,10 +68,12 @@ int ueventd_main(int argc, char **argv) | ||
66 | 68 | ueventd_parse_config_file("/ueventd.rc"); |
67 | 69 | ueventd_parse_config_file(android::base::StringPrintf("/ueventd.%s.rc", hardware.c_str()).c_str()); |
68 | 70 | |
69 | - boot_device = property_get("ro.boot.bootdevice"); | |
70 | - | |
71 | - device_init(); | |
71 | + pid_t pid = fork(); | |
72 | + if (pid < 0) { | |
73 | + ERROR("could not fork to process firmware event: %s\n", strerror(errno)); | |
74 | + } | |
72 | 75 | |
76 | + device_init(pid == 0); | |
73 | 77 | pollfd ufd; |
74 | 78 | ufd.events = POLLIN; |
75 | 79 | ufd.fd = get_device_fd(); |
@@ -81,7 +85,7 @@ int ueventd_main(int argc, char **argv) | ||
81 | 85 | continue; |
82 | 86 | } |
83 | 87 | if (ufd.revents & POLLIN) { |
84 | - handle_device_fd(); | |
88 | + handle_device_fd(pid == 0); | |
85 | 89 | } |
86 | 90 | } |
87 | 91 |
@@ -113,7 +113,7 @@ static void *parse_subsystem(parse_state* state, int /*nargs*/, char** args) { | ||
113 | 113 | parse_error(state, "out of memory\n"); |
114 | 114 | return 0; |
115 | 115 | } |
116 | - s->name = args[1]; | |
116 | + s->name = strdup(args[1]); | |
117 | 117 | s->dirname = "/dev"; |
118 | 118 | list_add_tail(&subsystem_list, &s->slist); |
119 | 119 | return s; |
@@ -142,7 +142,7 @@ static void parse_line_subsystem(struct parse_state *state, int nargs, | ||
142 | 142 | |
143 | 143 | case K_dirname: |
144 | 144 | if (args[1][0] == '/') |
145 | - s->dirname = args[1]; | |
145 | + s->dirname = strdup(args[1]); | |
146 | 146 | else |
147 | 147 | parse_error(state, "dirname '%s' does not start with '/'\n", |
148 | 148 | args[1]); |
@@ -191,7 +191,7 @@ static void parse_line(struct parse_state *state, char **args, int nargs) | ||
191 | 191 | } |
192 | 192 | } |
193 | 193 | |
194 | -static void parse_config(const char *fn, const std::string& data) | |
194 | +static void parse_config(const char *fn, std::string& data) | |
195 | 195 | { |
196 | 196 | char *args[UEVENTD_PARSER_MAXARGS]; |
197 | 197 |
@@ -199,7 +199,7 @@ static void parse_config(const char *fn, const std::string& data) | ||
199 | 199 | parse_state state; |
200 | 200 | state.filename = fn; |
201 | 201 | state.line = 1; |
202 | - state.ptr = strdup(data.c_str()); // TODO: fix this code! | |
202 | + state.ptr = &data[0]; | |
203 | 203 | state.nexttoken = 0; |
204 | 204 | state.parse_line = parse_line_no_op; |
205 | 205 | for (;;) { |
@@ -98,6 +98,7 @@ LOCAL_SRC_FILES := $(libcutils_common_sources) \ | ||
98 | 98 | debugger.c \ |
99 | 99 | klog.c \ |
100 | 100 | partition_utils.c \ |
101 | + probe_module.c \ | |
101 | 102 | properties.c \ |
102 | 103 | qtaguid.c \ |
103 | 104 | trace-dev.c \ |
@@ -0,0 +1,387 @@ | ||
1 | +/* | |
2 | + * Copyright (C) 2012 The Android Open Source Project | |
3 | + * | |
4 | + * Licensed under the Apache License, Version 2.0 (the "License"); | |
5 | + * you may not use this file except in compliance with the License. | |
6 | + * You may obtain a copy of the License at | |
7 | + * | |
8 | + * http://www.apache.org/licenses/LICENSE-2.0 | |
9 | + * | |
10 | + * Unless required by applicable law or agreed to in writing, software | |
11 | + * distributed under the License is distributed on an "AS IS" BASIS, | |
12 | + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | |
13 | + * See the License for the specific language governing permissions and | |
14 | + * limitations under the License. | |
15 | + */ | |
16 | + | |
17 | +#include <stdio.h> | |
18 | +#include <stdlib.h> | |
19 | +#include <string.h> | |
20 | +#include <limits.h> | |
21 | +#include <errno.h> | |
22 | +#include <fcntl.h> | |
23 | +#include <cutils/misc.h> | |
24 | +#include <sys/syscall.h> | |
25 | +#include <sys/utsname.h> | |
26 | + | |
27 | +#define LOG_TAG "ProbeModule" | |
28 | +#include <cutils/log.h> | |
29 | + | |
30 | +#define LDM_DEFAULT_MOD_PATH "/system/lib/modules/" | |
31 | + | |
32 | +extern int delete_module(const char *, unsigned int); | |
33 | + | |
34 | +/* get_default_mod_path() interface to outside, | |
35 | + * refer to its description in probe_module.h | |
36 | + */ | |
37 | +char *get_default_mod_path(char *def_mod_path) | |
38 | +{ | |
39 | + int len; | |
40 | + struct utsname buf; | |
41 | + uname(&buf); | |
42 | + len = snprintf(def_mod_path, PATH_MAX, "%s", LDM_DEFAULT_MOD_PATH); | |
43 | + strcpy(def_mod_path + len, buf.release); | |
44 | + if (access(def_mod_path, F_OK)) | |
45 | + def_mod_path[len] = '\0'; | |
46 | + else | |
47 | + strcat(def_mod_path, "/"); | |
48 | + return def_mod_path; | |
49 | +} | |
50 | + | |
51 | +int insmod(const char *filename, const char *options) | |
52 | +{ | |
53 | + int fd = open(filename, O_RDONLY | O_NOFOLLOW | O_CLOEXEC); | |
54 | + if (fd == -1) { | |
55 | + ALOGE("insmod: open(\"%s\") failed: %s", filename, strerror(errno)); | |
56 | + return -1; | |
57 | + } | |
58 | + int rc = syscall(__NR_finit_module, fd, options, 0); | |
59 | + if (rc == -1) { | |
60 | + if (errno == EEXIST) { | |
61 | + rc = 0; | |
62 | + } else { | |
63 | + ALOGE("finit_module for \"%s\" failed: %s", filename, strerror(errno)); | |
64 | + } | |
65 | + } | |
66 | + close(fd); | |
67 | + return rc; | |
68 | +} | |
69 | + | |
70 | +static char *strip_path(char *str) | |
71 | +{ | |
72 | + char *ptr = strrchr(str, '/'); | |
73 | + return ptr ? ptr + 1 : str; | |
74 | +} | |
75 | + | |
76 | +static void hyphen_to_underscore(char *str) | |
77 | +{ | |
78 | + while (str && *str != '\0') { | |
79 | + if (*str == '-') | |
80 | + *str = '_'; | |
81 | + str++; | |
82 | + } | |
83 | +} | |
84 | + | |
85 | +/* Compare module names, but don't differentiate '_' and '-'. | |
86 | + * return: 0 when s1 is matched to s2 or size is zero. | |
87 | + * non-zero in any other cases. | |
88 | + */ | |
89 | +static int match_name(const char *s1, const char *s2, const size_t size) | |
90 | +{ | |
91 | + size_t i; | |
92 | + | |
93 | + if (!size) | |
94 | + return 0; | |
95 | + | |
96 | + for (i = 0; i < size; i++, s1++, s2++) { | |
97 | + | |
98 | + if ((*s1 == '_' || *s1 == '-') && (*s2 == '_' || *s2 == '-')) | |
99 | + continue; | |
100 | + | |
101 | + if (*s1 != *s2) | |
102 | + return -1; | |
103 | + | |
104 | + if (*s1 == '\0') | |
105 | + return 0; | |
106 | + } | |
107 | + | |
108 | + return 0; | |
109 | +} | |
110 | + | |
111 | +/* check if a line in dep file is target module's dependency. | |
112 | + * return 1 when it is, otherwise 0 in any other cases. | |
113 | + */ | |
114 | +static int is_target_module(char *line, const char *target) | |
115 | +{ | |
116 | + char *token; | |
117 | + char name[PATH_MAX]; | |
118 | + const char *delimiter = ":"; | |
119 | + int ret = 0; | |
120 | + | |
121 | + /* search token */ | |
122 | + token = strstr(line, delimiter); | |
123 | + | |
124 | + if (!token) { | |
125 | + ALOGE("invalid line: no token"); | |
126 | + return 0; | |
127 | + } | |
128 | + | |
129 | + /* only take stuff before the token */ | |
130 | + *token = '\0'; | |
131 | + | |
132 | + /* use "module.ko" in comparision */ | |
133 | + strcat(strcpy(name, target), ".ko"); | |
134 | + | |
135 | + ret = !match_name(strip_path(line), name, strlen(name)); | |
136 | + | |
137 | + /* restore [single] token, keep line unchanged until we parse it later */ | |
138 | + *token = *delimiter; | |
139 | + | |
140 | + return ret; | |
141 | + | |
142 | +} | |
143 | + | |
144 | +/* turn a single string into an array of dependency. | |
145 | + * | |
146 | + * return: dependency array's address if it succeeded. Caller | |
147 | + * is responsible to free the array's memory. | |
148 | + * NULL when any error happens. | |
149 | + */ | |
150 | +static char **setup_dep(char *line) | |
151 | +{ | |
152 | + char *tmp = line; | |
153 | + char *brk; | |
154 | + int i; | |
155 | + char **dep; | |
156 | + | |
157 | + for (i = 2; (tmp = strchr(tmp, ' ')); i++) | |
158 | + tmp++; | |
159 | + | |
160 | + dep = malloc(sizeof(char *) * i); | |
161 | + if (dep) { | |
162 | + i = 0; | |
163 | + do { | |
164 | + tmp = strtok_r(i ? NULL : line, ": ", &brk); | |
165 | + } while ((dep[i++] = tmp)); | |
166 | + } | |
167 | + | |
168 | + return dep; | |
169 | +} | |
170 | + | |
171 | +/* install all modules in the dependency chain | |
172 | + * deps : A array of module file names, must be terminated by a NULL pointer | |
173 | + * args : The module parameters for target module. | |
174 | + * strip : Non-zero to strip out path info in the file name; | |
175 | + * 0 to keep path info when loading modules. | |
176 | + * base : a prefix to module path, it will NOT be affected by strip flag. | |
177 | + * return : 0 for success or nothing to do; non-zero when any error occurs. | |
178 | + */ | |
179 | +static int insmod_s(char *dep[], const char *args, int strip, const char *base) | |
180 | +{ | |
181 | + char *name; | |
182 | + int cnt; | |
183 | + size_t len; | |
184 | + int ret = 0; | |
185 | + char path_name[PATH_MAX]; | |
186 | + char def_mod_path[PATH_MAX]; | |
187 | + const char *base_dir; | |
188 | + | |
189 | + if (base && strlen(base)) | |
190 | + base_dir = base; | |
191 | + else | |
192 | + base_dir = get_default_mod_path(def_mod_path); | |
193 | + | |
194 | + /* load modules in reversed order */ | |
195 | + for (cnt = 0; dep[cnt]; cnt++) | |
196 | + ; | |
197 | + | |
198 | + len = strlen(strcpy(path_name, base_dir)); | |
199 | + | |
200 | + while (!ret && cnt--) { | |
201 | + | |
202 | + name = strip ? strip_path(dep[cnt]) : dep[cnt]; | |
203 | + | |
204 | + strcpy(path_name + len, name); | |
205 | + | |
206 | + ret = insmod(path_name, cnt ? "" : args); | |
207 | + } | |
208 | + | |
209 | + return ret; | |
210 | +} | |
211 | + | |
212 | +/* remove all modules in a dependency chain | |
213 | + * NOTE: We assume module name in kernel is same as the file name without .ko | |
214 | + */ | |
215 | +static int rmmod_s(char *dep[], int flags) | |
216 | +{ | |
217 | + int i; | |
218 | + int ret = 0; | |
219 | + | |
220 | + for (i = 0; dep[i]; i++) { | |
221 | + char *mod_name = strip_path(dep[i]); | |
222 | + size_t len = strlen(mod_name); | |
223 | + | |
224 | + if (len > 3 && strstr(mod_name, ".ko") == (mod_name + len - 3)) { | |
225 | + mod_name[len - 3] = '\0'; | |
226 | + | |
227 | + hyphen_to_underscore(mod_name); | |
228 | + | |
229 | + ret = delete_module(mod_name, flags); | |
230 | + | |
231 | + if (ret) { | |
232 | + ALOGE("%s: Failed to remove module [%s] error (%s)", | |
233 | + __FUNCTION__, mod_name, strerror(errno)); | |
234 | + break; | |
235 | + | |
236 | + } | |
237 | + } | |
238 | + } | |
239 | + | |
240 | + return ret; | |
241 | +} | |
242 | + | |
243 | +/* look_up_dep() find and setup target module's dependency in modules.dep | |
244 | + * | |
245 | + * dep_file: a pointer to module's dep file loaded in memory, its content | |
246 | + * will be CHANGED during parsing. | |
247 | + * | |
248 | + * return: a pointer to an array which holds the dependency strings and | |
249 | + * terminated by a NULL pointer. Caller is responsible to free the | |
250 | + * array's memory. | |
251 | + * | |
252 | + * non-zero in any other cases. Content of dep array is invalid. | |
253 | + */ | |
254 | +static char **look_up_dep(const char *module_name, void *dep_file) | |
255 | +{ | |
256 | + char *line; | |
257 | + char *saved_pos; | |
258 | + char *start; | |
259 | + char **dep = NULL; | |
260 | + | |
261 | + if (!dep_file || !module_name || *module_name == '\0') | |
262 | + return NULL; | |
263 | + | |
264 | + start = (char *)dep_file; | |
265 | + | |
266 | + /* We expect modules.dep file has a new line char before EOF. */ | |
267 | + while ((line = strtok_r(start, "\n", &saved_pos)) != NULL) { | |
268 | + | |
269 | + start = NULL; | |
270 | + | |
271 | + if (is_target_module(line, module_name)) { | |
272 | + | |
273 | + dep = setup_dep(line); | |
274 | + /* job done */ | |
275 | + break; | |
276 | + } | |
277 | + } | |
278 | + | |
279 | + return dep; | |
280 | +} | |
281 | + | |
282 | +/* load_dep_file() load a dep file (usually it is modules.dep) | |
283 | + * into memory. Caller is responsible to free the memory. | |
284 | + * | |
285 | + * file_name: dep file's name, if it is NULL or an empty string, | |
286 | + * This function will try to load a dep file in the | |
287 | + * default path defined in LDM_DEFAULT_DEP_FILE | |
288 | + * | |
289 | + * return: a pointer to the allocated mem which holds all | |
290 | + * content of the depfile. a zero pointer will be | |
291 | + * returned for any errors. | |
292 | + * */ | |
293 | +static void *load_dep_file(const char *file_name) | |
294 | +{ | |
295 | + unsigned int len; | |
296 | + char def_mod_path[PATH_MAX]; | |
297 | + if (!file_name || *file_name == '\0') { | |
298 | + file_name = get_default_mod_path(def_mod_path); | |
299 | + strcat(def_mod_path, "modules.dep"); | |
300 | + } | |
301 | + | |
302 | + return load_file(file_name, &len); | |
303 | +} | |
304 | + | |
305 | +/* insmod_by_dep() interface to outside, | |
306 | + * refer to its description in probe_module.h | |
307 | + */ | |
308 | +int insmod_by_dep(const char *module_name, | |
309 | + const char *args, | |
310 | + const char *dep_name, | |
311 | + int strip, | |
312 | + const char *base) | |
313 | +{ | |
314 | + void *dep_file; | |
315 | + char **dep = NULL; | |
316 | + int ret = -1; | |
317 | + | |
318 | + if (!module_name || *module_name == '\0') { | |
319 | + ALOGE("need valid module name"); | |
320 | + return ret; | |
321 | + } | |
322 | + | |
323 | + dep_file = load_dep_file(dep_name); | |
324 | + | |
325 | + if (!dep_file) { | |
326 | + ALOGE("cannot load dep file : %s", dep_name); | |
327 | + return ret; | |
328 | + } | |
329 | + | |
330 | + dep = look_up_dep(module_name, dep_file); | |
331 | + | |
332 | + if (!dep) { | |
333 | + ALOGE("%s: cannot load module: [%s]", __FUNCTION__, module_name); | |
334 | + goto free_file; | |
335 | + } | |
336 | + | |
337 | + ret = insmod_s(dep, args, strip, base); | |
338 | + | |
339 | + free(dep); | |
340 | + | |
341 | +free_file: | |
342 | + free(dep_file); | |
343 | + | |
344 | + return ret; | |
345 | + | |
346 | +} | |
347 | + | |
348 | +/* rmmod_by_dep() interface to outside, | |
349 | + * refer to its description in probe_module.h | |
350 | + */ | |
351 | +int rmmod_by_dep(const char *module_name, | |
352 | + const char *dep_name) | |
353 | +{ | |
354 | + void *dep_file; | |
355 | + char **dep = NULL; | |
356 | + int ret = -1; | |
357 | + | |
358 | + if (!module_name || *module_name == '\0') { | |
359 | + ALOGE("need valid module name"); | |
360 | + return ret; | |
361 | + } | |
362 | + | |
363 | + dep_file = load_dep_file(dep_name); | |
364 | + | |
365 | + if (!dep_file) { | |
366 | + ALOGE("cannot load dep file : %s", dep_name); | |
367 | + return ret; | |
368 | + } | |
369 | + | |
370 | + dep = look_up_dep(module_name, dep_file); | |
371 | + | |
372 | + if (!dep) { | |
373 | + ALOGE("%s: cannot remove module: [%s]", __FUNCTION__, module_name); | |
374 | + goto free_file; | |
375 | + } | |
376 | + | |
377 | + ret = rmmod_s(dep, O_NONBLOCK); | |
378 | + | |
379 | + free(dep); | |
380 | + | |
381 | +free_file: | |
382 | + free(dep_file); | |
383 | + | |
384 | + return ret; | |
385 | +} | |
386 | + | |
387 | +/* end of file */ |
@@ -27,6 +27,6 @@ include $(CLEAR_VARS) | ||
27 | 27 | LOCAL_SRC_FILES := $(commonSources) |
28 | 28 | LOCAL_MODULE := libdiskconfig_host |
29 | 29 | LOCAL_MODULE_TAGS := optional |
30 | -LOCAL_CFLAGS := -O2 -g -W -Wall -Werror -D_LARGEFILE64_SOURCE | |
30 | +LOCAL_CFLAGS := -O2 -g -W -Wall -Werror -D_LARGEFILE64_SOURCE -DHOST_BUILD | |
31 | 31 | include $(BUILD_HOST_STATIC_LIBRARY) |
32 | -endif # HOST_OS == linux | |
32 | +endif |
@@ -260,11 +260,11 @@ config_mbr(struct disk_info *dinfo) | ||
260 | 260 | } |
261 | 261 | |
262 | 262 | /* if extended, need 1 lba for ebr */ |
263 | - if ((cur_lba + extended) >= dinfo->num_lba) | |
263 | + if (dinfo->num_lba && (cur_lba + extended) >= dinfo->num_lba) | |
264 | 264 | goto nospace; |
265 | 265 | else if (pinfo->len_kb != (uint32_t)-1) { |
266 | 266 | uint32_t sz_lba = (pinfo->len_kb / dinfo->sect_size) * 1024; |
267 | - if ((cur_lba + sz_lba + extended) > dinfo->num_lba) | |
267 | + if (dinfo->num_lba && (cur_lba + sz_lba + extended) > dinfo->num_lba) | |
268 | 268 | goto nospace; |
269 | 269 | } |
270 | 270 |
@@ -27,7 +27,9 @@ | ||
27 | 27 | #include <sys/ioctl.h> |
28 | 28 | #include <sys/stat.h> |
29 | 29 | |
30 | +#ifndef HOST_BUILD | |
30 | 31 | #include <linux/fs.h> |
32 | +#endif | |
31 | 33 | |
32 | 34 | #include <cutils/config_utils.h> |
33 | 35 | #include <log/log.h> |
@@ -76,7 +78,7 @@ parse_len(const char *str, uint64_t *plen) | ||
76 | 78 | } |
77 | 79 | } else { |
78 | 80 | /* convert len to kilobytes */ |
79 | - if (multiple > 1024) | |
81 | + if (multiple >= 1024) | |
80 | 82 | multiple >>= 10; |
81 | 83 | *plen *= multiple; |
82 | 84 |
@@ -236,6 +238,7 @@ fail: | ||
236 | 238 | return NULL; |
237 | 239 | } |
238 | 240 | |
241 | +#ifndef HOST_BUILD | |
239 | 242 | static int |
240 | 243 | sync_ptable(int fd) |
241 | 244 | { |
@@ -256,6 +259,13 @@ sync_ptable(int fd) | ||
256 | 259 | |
257 | 260 | return 0; |
258 | 261 | } |
262 | +#else | |
263 | +static int sync_ptable(int fd) | |
264 | +{ | |
265 | + (void)fd; | |
266 | + return 0; | |
267 | +} | |
268 | +#endif | |
259 | 269 | |
260 | 270 | /* This function verifies that the disk info provided is valid, and if so, |
261 | 271 | * returns an open file descriptor. |
@@ -272,7 +282,6 @@ static int | ||
272 | 282 | validate(struct disk_info *dinfo) |
273 | 283 | { |
274 | 284 | int fd; |
275 | - int sect_sz; | |
276 | 285 | uint64_t disk_size; |
277 | 286 | uint64_t total_size; |
278 | 287 | int cnt; |
@@ -298,6 +307,12 @@ validate(struct disk_info *dinfo) | ||
298 | 307 | /* Verify that we can operate on the device that was requested. |
299 | 308 | * We presently only support block devices and regular file images. */ |
300 | 309 | if (S_ISBLK(stat.st_mode)) { |
310 | +#ifdef HOST_BUILD | |
311 | + ALOGE("Block device manipulation on host forbidden"); | |
312 | + goto fail; | |
313 | +#else | |
314 | + int sect_sz; | |
315 | + | |
301 | 316 | /* get the sector size and make sure we agree */ |
302 | 317 | if (ioctl(fd, BLKSSZGET, §_sz) < 0) { |
303 | 318 | ALOGE("Cannot get sector size (errno=%d)", errno); |
@@ -319,6 +334,7 @@ validate(struct disk_info *dinfo) | ||
319 | 334 | dinfo->num_lba = (uint32_t)(disk_size / (uint64_t)dinfo->sect_size); |
320 | 335 | } else |
321 | 336 | disk_size = (uint64_t)dinfo->num_lba * (uint64_t)dinfo->sect_size; |
337 | +#endif | |
322 | 338 | } else if (S_ISREG(stat.st_mode)) { |
323 | 339 | ALOGI("Requesting operation on a regular file, not block device."); |
324 | 340 | if (!dinfo->sect_size) { |
@@ -36,6 +36,7 @@ write_raw_image(const char *dst, const char *src, loff_t offset, int test) | ||
36 | 36 | int dst_fd = -1; |
37 | 37 | int src_fd = -1; |
38 | 38 | uint8_t buffer[2048]; |
39 | + ssize_t buf_offset; | |
39 | 40 | ssize_t nr_bytes; |
40 | 41 | ssize_t tmp; |
41 | 42 | int done = 0; |
@@ -80,8 +81,9 @@ write_raw_image(const char *dst, const char *src, loff_t offset, int test) | ||
80 | 81 | if (test) |
81 | 82 | nr_bytes = 0; |
82 | 83 | |
84 | + buf_offset = 0; | |
83 | 85 | while (nr_bytes > 0) { |
84 | - if ((tmp = write(dst_fd, buffer, nr_bytes)) < 0) { | |
86 | + if ((tmp = write(dst_fd, &buffer[buf_offset], nr_bytes)) < 0) { | |
85 | 87 | /* XXX: Should we not even bother with EINTR? */ |
86 | 88 | if (errno == EINTR) |
87 | 89 | continue; |
@@ -91,6 +93,7 @@ write_raw_image(const char *dst, const char *src, loff_t offset, int test) | ||
91 | 93 | if (!tmp) |
92 | 94 | continue; |
93 | 95 | nr_bytes -= tmp; |
96 | + buf_offset += tmp; | |
94 | 97 | } |
95 | 98 | } |
96 | 99 |
@@ -1,7 +1,7 @@ | ||
1 | 1 | LOCAL_PATH:= $(call my-dir) |
2 | 2 | include $(CLEAR_VARS) |
3 | 3 | |
4 | -ifeq ($(TARGET_ARCH),x86) | |
4 | +ifneq ($(filter x86%,$(TARGET_ARCH)),) | |
5 | 5 | LOCAL_SRC_FILES:= \ |
6 | 6 | codegen.cpp |
7 | 7 | else |
@@ -16,7 +16,7 @@ LOCAL_SHARED_LIBRARIES := \ | ||
16 | 16 | LOCAL_C_INCLUDES := \ |
17 | 17 | $(LOCAL_PATH)/../.. |
18 | 18 | |
19 | -ifeq ($(TARGET_ARCH),x86) | |
19 | +ifneq ($(filter x86%,$(TARGET_ARCH)),) | |
20 | 20 | LOCAL_STATIC_LIBRARIES := libenc |
21 | 21 | endif |
22 | 22 |
@@ -14,26 +14,38 @@ | ||
14 | 14 | * limitations under the License. |
15 | 15 | */ |
16 | 16 | |
17 | +#include <errno.h> | |
18 | +#include <fcntl.h> | |
17 | 19 | #include <stdbool.h> |
20 | +#include <string.h> | |
18 | 21 | |
19 | 22 | #define LOG_TAG "libsuspend" |
20 | 23 | #include <cutils/log.h> |
24 | +#include <cutils/properties.h> | |
21 | 25 | |
22 | 26 | #include <suspend/autosuspend.h> |
23 | 27 | |
24 | 28 | #include "autosuspend_ops.h" |
25 | 29 | |
30 | +static const char *default_sleep_state = "mem"; | |
31 | +static const char *fallback_sleep_state = "freeze"; | |
32 | + | |
26 | 33 | static struct autosuspend_ops *autosuspend_ops; |
27 | 34 | static bool autosuspend_enabled; |
28 | 35 | static bool autosuspend_inited; |
29 | 36 | |
30 | 37 | static int autosuspend_init(void) |
31 | 38 | { |
39 | + char buf[PROPERTY_VALUE_MAX]; | |
40 | + | |
32 | 41 | if (autosuspend_inited) { |
33 | 42 | return 0; |
34 | 43 | } |
35 | 44 | |
36 | - autosuspend_ops = autosuspend_earlysuspend_init(); | |
45 | + property_get("sleep.earlysuspend", buf, "0"); | |
46 | + if (buf[0] == '1') { | |
47 | + autosuspend_ops = autosuspend_earlysuspend_init(); | |
48 | + } | |
37 | 49 | if (autosuspend_ops) { |
38 | 50 | goto out; |
39 | 51 | } |
@@ -110,3 +122,34 @@ int autosuspend_disable(void) | ||
110 | 122 | autosuspend_enabled = false; |
111 | 123 | return 0; |
112 | 124 | } |
125 | + | |
126 | +static bool sleep_state_available(const char *state) | |
127 | +{ | |
128 | + char buf[64]; | |
129 | + int fd = TEMP_FAILURE_RETRY(open(SYS_POWER_STATE, O_RDONLY)); | |
130 | + if (fd < 0) { | |
131 | + ALOGE("Error reading power state: %s", SYS_POWER_STATE); | |
132 | + return false; | |
133 | + } | |
134 | + TEMP_FAILURE_RETRY(read(fd, buf, 64)); | |
135 | + close(fd); | |
136 | + return !!strstr(buf, state); | |
137 | +} | |
138 | + | |
139 | +const char *get_sleep_state() | |
140 | +{ | |
141 | + static char sleep_state[PROPERTY_VALUE_MAX] = ""; | |
142 | + | |
143 | + if (!sleep_state[0]) { | |
144 | + if (property_get("sleep.state", sleep_state, NULL) > 0) { | |
145 | + ALOGD("autosuspend using sleep.state property (%s)", sleep_state); | |
146 | + } else if (sleep_state_available(default_sleep_state)) { | |
147 | + ALOGD("autosuspend using default sleep_state (%s)", default_sleep_state); | |
148 | + strncpy(sleep_state, default_sleep_state, PROPERTY_VALUE_MAX); | |
149 | + } else { | |
150 | + ALOGW("autosuspend \"%s\" unavailable, using fallback sleep.state (%s)", default_sleep_state, fallback_sleep_state); | |
151 | + strncpy(sleep_state, fallback_sleep_state, PROPERTY_VALUE_MAX); | |
152 | + } | |
153 | + } | |
154 | + return sleep_state; | |
155 | +} |
@@ -29,12 +29,10 @@ | ||
29 | 29 | |
30 | 30 | #include "autosuspend_ops.h" |
31 | 31 | |
32 | -#define EARLYSUSPEND_SYS_POWER_STATE "/sys/power/state" | |
33 | 32 | #define EARLYSUSPEND_WAIT_FOR_FB_SLEEP "/sys/power/wait_for_fb_sleep" |
34 | 33 | #define EARLYSUSPEND_WAIT_FOR_FB_WAKE "/sys/power/wait_for_fb_wake" |
35 | 34 | |
36 | 35 | static int sPowerStatefd; |
37 | -static const char *pwr_state_mem = "mem"; | |
38 | 36 | static const char *pwr_state_on = "on"; |
39 | 37 | static pthread_t earlysuspend_thread; |
40 | 38 | static pthread_mutex_t earlysuspend_mutex = PTHREAD_MUTEX_INITIALIZER; |
@@ -45,37 +43,58 @@ static enum { | ||
45 | 43 | EARLYSUSPEND_MEM, |
46 | 44 | } earlysuspend_state = EARLYSUSPEND_ON; |
47 | 45 | |
48 | -int wait_for_fb_wake(void) | |
46 | +static void log_err(const char *fmt, ...) | |
49 | 47 | { |
50 | - int err = 0; | |
51 | - char buf; | |
52 | - int fd = TEMP_FAILURE_RETRY(open(EARLYSUSPEND_WAIT_FOR_FB_WAKE, O_RDONLY, 0)); | |
48 | + char err[80]; | |
49 | + char buf[512]; | |
50 | + | |
51 | + strerror_r(errno, err, sizeof(err)); | |
52 | + | |
53 | + va_list ap; | |
54 | + va_start(ap, fmt); | |
55 | + vsnprintf(buf, sizeof(buf), fmt, ap); | |
56 | + va_end(ap); | |
57 | + ALOGE("Error %s: %s", buf, err); | |
58 | +} | |
59 | + | |
60 | +static int open_file(const char *file, char *buf, size_t sz, int *fd) | |
61 | +{ | |
62 | + int err; | |
63 | + int f = TEMP_FAILURE_RETRY(open(file, fd ? O_RDWR : O_RDONLY, 0)); | |
53 | 64 | // if the file doesn't exist, the error will be caught in read() below |
54 | - err = TEMP_FAILURE_RETRY(read(fd, &buf, 1)); | |
55 | - ALOGE_IF(err < 0, | |
56 | - "*** ANDROID_WAIT_FOR_FB_WAKE failed (%s)", strerror(errno)); | |
57 | - close(fd); | |
58 | - return err < 0 ? err : 0; | |
65 | + err = TEMP_FAILURE_RETRY(read(f, buf, sz)); | |
66 | + | |
67 | + if (err < 0) { | |
68 | + log_err("opening %s", file); | |
69 | + } else { | |
70 | + err = 0; | |
71 | + } | |
72 | + | |
73 | + if (fd == NULL) { | |
74 | + close(f); | |
75 | + } else { | |
76 | + *fd = f; | |
77 | + } | |
78 | + return err; | |
79 | +} | |
80 | + | |
81 | +static int wait_for_fb_wake(void) | |
82 | +{ | |
83 | + char buf; | |
84 | + return open_file(EARLYSUSPEND_WAIT_FOR_FB_WAKE, &buf, 1, NULL); | |
59 | 85 | } |
60 | 86 | |
61 | 87 | static int wait_for_fb_sleep(void) |
62 | 88 | { |
63 | - int err = 0; | |
64 | 89 | char buf; |
65 | - int fd = TEMP_FAILURE_RETRY(open(EARLYSUSPEND_WAIT_FOR_FB_SLEEP, O_RDONLY, 0)); | |
66 | - // if the file doesn't exist, the error will be caught in read() below | |
67 | - err = TEMP_FAILURE_RETRY(read(fd, &buf, 1)); | |
68 | - ALOGE_IF(err < 0, | |
69 | - "*** ANDROID_WAIT_FOR_FB_SLEEP failed (%s)", strerror(errno)); | |
70 | - close(fd); | |
71 | - return err < 0 ? err : 0; | |
90 | + return open_file(EARLYSUSPEND_WAIT_FOR_FB_SLEEP, &buf, 1, NULL); | |
72 | 91 | } |
73 | 92 | |
74 | 93 | static void *earlysuspend_thread_func(void __unused *arg) |
75 | 94 | { |
76 | 95 | while (1) { |
77 | 96 | if (wait_for_fb_sleep()) { |
78 | - ALOGE("Failed reading wait_for_fb_sleep, exiting earlysuspend thread\n"); | |
97 | + ALOGE("Failed reading wait_for_fb_sleep, exiting earlysuspend thread"); | |
79 | 98 | return NULL; |
80 | 99 | } |
81 | 100 | pthread_mutex_lock(&earlysuspend_mutex); |
@@ -84,7 +103,7 @@ static void *earlysuspend_thread_func(void __unused *arg) | ||
84 | 103 | pthread_mutex_unlock(&earlysuspend_mutex); |
85 | 104 | |
86 | 105 | if (wait_for_fb_wake()) { |
87 | - ALOGE("Failed reading wait_for_fb_wake, exiting earlysuspend thread\n"); | |
106 | + ALOGE("Failed reading wait_for_fb_wake, exiting earlysuspend thread"); | |
88 | 107 | return NULL; |
89 | 108 | } |
90 | 109 | pthread_mutex_lock(&earlysuspend_mutex); |
@@ -95,16 +114,15 @@ static void *earlysuspend_thread_func(void __unused *arg) | ||
95 | 114 | } |
96 | 115 | static int autosuspend_earlysuspend_enable(void) |
97 | 116 | { |
98 | - char buf[80]; | |
99 | 117 | int ret; |
118 | + const char *sleep_state = get_sleep_state(); | |
100 | 119 | |
101 | - ALOGV("autosuspend_earlysuspend_enable\n"); | |
120 | + ALOGI("autosuspend_earlysuspend_enable"); | |
102 | 121 | |
103 | - ret = write(sPowerStatefd, pwr_state_mem, strlen(pwr_state_mem)); | |
122 | + ret = TEMP_FAILURE_RETRY(write(sPowerStatefd, sleep_state, strlen(sleep_state))); | |
104 | 123 | if (ret < 0) { |
105 | - strerror_r(errno, buf, sizeof(buf)); | |
106 | - ALOGE("Error writing to %s: %s\n", EARLYSUSPEND_SYS_POWER_STATE, buf); | |
107 | - goto err; | |
124 | + log_err("writing %s to %s", sleep_state, SYS_POWER_STATE); | |
125 | + return ret; | |
108 | 126 | } |
109 | 127 | |
110 | 128 | if (wait_for_earlysuspend) { |
@@ -115,26 +133,22 @@ static int autosuspend_earlysuspend_enable(void) | ||
115 | 133 | pthread_mutex_unlock(&earlysuspend_mutex); |
116 | 134 | } |
117 | 135 | |
118 | - ALOGV("autosuspend_earlysuspend_enable done\n"); | |
136 | + ALOGD("autosuspend_earlysuspend_enable done"); | |
119 | 137 | |
120 | 138 | return 0; |
121 | - | |
122 | -err: | |
123 | - return ret; | |
124 | 139 | } |
125 | 140 | |
126 | 141 | static int autosuspend_earlysuspend_disable(void) |
127 | 142 | { |
128 | - char buf[80]; | |
129 | 143 | int ret; |
130 | 144 | |
131 | - ALOGV("autosuspend_earlysuspend_disable\n"); | |
145 | + ALOGI("autosuspend_earlysuspend_disable"); | |
132 | 146 | |
133 | 147 | ret = TEMP_FAILURE_RETRY(write(sPowerStatefd, pwr_state_on, strlen(pwr_state_on))); |
134 | 148 | if (ret < 0) { |
135 | - strerror_r(errno, buf, sizeof(buf)); | |
136 | - ALOGE("Error writing to %s: %s\n", EARLYSUSPEND_SYS_POWER_STATE, buf); | |
137 | - goto err; | |
149 | +#if DEBUG | |
150 | + log_err("writing %s to %s", pwr_state_on, SYS_POWER_STATE); | |
151 | +#endif | |
138 | 152 | } |
139 | 153 | |
140 | 154 | if (wait_for_earlysuspend) { |
@@ -145,12 +159,9 @@ static int autosuspend_earlysuspend_disable(void) | ||
145 | 159 | pthread_mutex_unlock(&earlysuspend_mutex); |
146 | 160 | } |
147 | 161 | |
148 | - ALOGV("autosuspend_earlysuspend_disable done\n"); | |
162 | + ALOGD("autosuspend_earlysuspend_disable done"); | |
149 | 163 | |
150 | 164 | return 0; |
151 | - | |
152 | -err: | |
153 | - return ret; | |
154 | 165 | } |
155 | 166 | |
156 | 167 | struct autosuspend_ops autosuspend_earlysuspend_ops = { |
@@ -160,26 +171,26 @@ struct autosuspend_ops autosuspend_earlysuspend_ops = { | ||
160 | 171 | |
161 | 172 | void start_earlysuspend_thread(void) |
162 | 173 | { |
163 | - char buf[80]; | |
164 | 174 | int ret; |
165 | 175 | |
166 | 176 | ret = access(EARLYSUSPEND_WAIT_FOR_FB_SLEEP, F_OK); |
167 | 177 | if (ret < 0) { |
178 | + log_err("accessing %s", EARLYSUSPEND_WAIT_FOR_FB_SLEEP); | |
168 | 179 | return; |
169 | 180 | } |
170 | 181 | |
171 | 182 | ret = access(EARLYSUSPEND_WAIT_FOR_FB_WAKE, F_OK); |
172 | 183 | if (ret < 0) { |
184 | + log_err("accessing %s", EARLYSUSPEND_WAIT_FOR_FB_WAKE); | |
173 | 185 | return; |
174 | 186 | } |
175 | 187 | |
176 | 188 | wait_for_fb_wake(); |
177 | 189 | |
178 | - ALOGI("Starting early suspend unblocker thread\n"); | |
190 | + ALOGI("Starting early suspend unblocker thread"); | |
179 | 191 | ret = pthread_create(&earlysuspend_thread, NULL, earlysuspend_thread_func, NULL); |
180 | 192 | if (ret) { |
181 | - strerror_r(errno, buf, sizeof(buf)); | |
182 | - ALOGE("Error creating thread: %s\n", buf); | |
193 | + log_err("creating thread"); | |
183 | 194 | return; |
184 | 195 | } |
185 | 196 |
@@ -188,31 +199,18 @@ void start_earlysuspend_thread(void) | ||
188 | 199 | |
189 | 200 | struct autosuspend_ops *autosuspend_earlysuspend_init(void) |
190 | 201 | { |
191 | - char buf[80]; | |
192 | 202 | int ret; |
203 | + char pwr_st[128]; | |
193 | 204 | |
194 | - sPowerStatefd = TEMP_FAILURE_RETRY(open(EARLYSUSPEND_SYS_POWER_STATE, O_RDWR)); | |
195 | - | |
196 | - if (sPowerStatefd < 0) { | |
197 | - strerror_r(errno, buf, sizeof(buf)); | |
198 | - ALOGW("Error opening %s: %s\n", EARLYSUSPEND_SYS_POWER_STATE, buf); | |
199 | - return NULL; | |
200 | - } | |
201 | - | |
202 | - ret = TEMP_FAILURE_RETRY(write(sPowerStatefd, "on", 2)); | |
205 | + ret = open_file(SYS_POWER_STATE, pwr_st, sizeof(pwr_st), &sPowerStatefd); | |
203 | 206 | if (ret < 0) { |
204 | - strerror_r(errno, buf, sizeof(buf)); | |
205 | - ALOGW("Error writing 'on' to %s: %s\n", EARLYSUSPEND_SYS_POWER_STATE, buf); | |
206 | - goto err_write; | |
207 | + close(sPowerStatefd); | |
208 | + return NULL; | |
207 | 209 | } |
208 | 210 | |
209 | - ALOGI("Selected early suspend\n"); | |
211 | + ALOGI("Selected early suspend"); | |
210 | 212 | |
211 | 213 | start_earlysuspend_thread(); |
212 | 214 | |
213 | 215 | return &autosuspend_earlysuspend_ops; |
214 | - | |
215 | -err_write: | |
216 | - close(sPowerStatefd); | |
217 | - return NULL; | |
218 | 216 | } |
@@ -17,6 +17,8 @@ | ||
17 | 17 | #ifndef _LIBSUSPEND_AUTOSUSPEND_OPS_H_ |
18 | 18 | #define _LIBSUSPEND_AUTOSUSPEND_OPS_H_ |
19 | 19 | |
20 | +#define SYS_POWER_STATE "/sys/power/state" | |
21 | + | |
20 | 22 | struct autosuspend_ops { |
21 | 23 | int (*enable)(void); |
22 | 24 | int (*disable)(void); |
@@ -26,4 +28,6 @@ struct autosuspend_ops *autosuspend_autosleep_init(void); | ||
26 | 28 | struct autosuspend_ops *autosuspend_earlysuspend_init(void); |
27 | 29 | struct autosuspend_ops *autosuspend_wakeup_count_init(void); |
28 | 30 | |
31 | +const char *get_sleep_state(); | |
32 | + | |
29 | 33 | #endif |
@@ -29,18 +29,165 @@ | ||
29 | 29 | //#define LOG_NDEBUG 0 |
30 | 30 | #include <cutils/log.h> |
31 | 31 | |
32 | +#include <cutils/properties.h> | |
33 | +#include <linux/uinput.h> | |
34 | +#include <dirent.h> | |
35 | +#include <poll.h> | |
36 | + | |
32 | 37 | #include "autosuspend_ops.h" |
33 | 38 | |
34 | -#define SYS_POWER_STATE "/sys/power/state" | |
35 | 39 | #define SYS_POWER_WAKEUP_COUNT "/sys/power/wakeup_count" |
40 | +#define MAX_POWERBTNS 3 | |
36 | 41 | |
42 | +static int uinput_fd = -1; | |
37 | 43 | static int state_fd; |
38 | 44 | static int wakeup_count_fd; |
39 | 45 | static pthread_t suspend_thread; |
40 | 46 | static sem_t suspend_lockout; |
41 | -static const char *sleep_state = "mem"; | |
42 | 47 | static void (*wakeup_func)(bool success) = NULL; |
43 | 48 | |
49 | +static void emit_key(int ufd, int key_code, int val) | |
50 | +{ | |
51 | + struct input_event iev; | |
52 | + iev.type = EV_KEY; | |
53 | + iev.code = key_code; | |
54 | + iev.value = val; | |
55 | + iev.time.tv_sec = 0; | |
56 | + iev.time.tv_usec = 0; | |
57 | + write(ufd, &iev, sizeof(iev)); | |
58 | + iev.type = EV_SYN; | |
59 | + iev.code = SYN_REPORT; | |
60 | + iev.value = 0; | |
61 | + write(ufd, &iev, sizeof(iev)); | |
62 | + ALOGD("send key %d (%d) on fd %d", key_code, val, ufd); | |
63 | +} | |
64 | + | |
65 | +static void send_key_wakeup(int ufd) | |
66 | +{ | |
67 | + emit_key(ufd, KEY_WAKEUP, 1); | |
68 | + emit_key(ufd, KEY_WAKEUP, 0); | |
69 | +} | |
70 | + | |
71 | +static void send_key_power(int ufd, bool longpress) | |
72 | +{ | |
73 | + emit_key(ufd, KEY_POWER, 1); | |
74 | + if (longpress) sleep(2); | |
75 | + emit_key(ufd, KEY_POWER, 0); | |
76 | +} | |
77 | + | |
78 | +static int openfds(struct pollfd pfds[]) | |
79 | +{ | |
80 | + int cnt = 0; | |
81 | + const char *dirname = "/dev/input"; | |
82 | + struct dirent *de; | |
83 | + DIR *dir; | |
84 | + | |
85 | + if ((dir = opendir(dirname))) { | |
86 | + while ((cnt < MAX_POWERBTNS) && (de = readdir(dir))) { | |
87 | + int fd; | |
88 | + char name[PATH_MAX]; | |
89 | + if (de->d_name[0] != 'e') /* eventX */ | |
90 | + continue; | |
91 | + snprintf(name, PATH_MAX, "%s/%s", dirname, de->d_name); | |
92 | + fd = open(name, O_RDWR | O_NONBLOCK); | |
93 | + if (fd < 0) { | |
94 | + ALOGE("could not open %s, %s", name, strerror(errno)); | |
95 | + continue; | |
96 | + } | |
97 | + name[sizeof(name) - 1] = '\0'; | |
98 | + if (ioctl(fd, EVIOCGNAME(sizeof(name) - 1), &name) < 1) { | |
99 | + ALOGE("could not get device name for %s, %s", name, strerror(errno)); | |
100 | + name[0] = '\0'; | |
101 | + } | |
102 | + // TODO: parse /etc/excluded-input-devices.xml | |
103 | + if (strcmp(name, "Power Button")) { | |
104 | + close(fd); | |
105 | + continue; | |
106 | + } | |
107 | + | |
108 | + ALOGI("open %s(%s) ok fd=%d", de->d_name, name, fd); | |
109 | + pfds[cnt].events = POLLIN; | |
110 | + pfds[cnt++].fd = fd; | |
111 | + } | |
112 | + closedir(dir); | |
113 | + } | |
114 | + | |
115 | + return cnt; | |
116 | +} | |
117 | + | |
118 | +static void *powerbtnd_thread_func(void *arg __attribute__((unused))) | |
119 | +{ | |
120 | + int cnt, timeout, pollres; | |
121 | + bool longpress = true; | |
122 | + bool doubleclick = property_get_bool("poweroff.doubleclick", 0); | |
123 | + struct pollfd pfds[MAX_POWERBTNS]; | |
124 | + | |
125 | + timeout = -1; | |
126 | + cnt = openfds(pfds); | |
127 | + | |
128 | + while (cnt > 0 && (pollres = poll(pfds, cnt, timeout)) >= 0) { | |
129 | + ALOGV("pollres=%d %d\n", pollres, timeout); | |
130 | + if (pollres == 0) { | |
131 | + ALOGI("timeout, send one power key"); | |
132 | + send_key_power(uinput_fd, 0); | |
133 | + timeout = -1; | |
134 | + longpress = true; | |
135 | + continue; | |
136 | + } | |
137 | + for (int i = 0; i < cnt; ++i) { | |
138 | + if (pfds[i].revents & POLLIN) { | |
139 | + struct input_event iev; | |
140 | + size_t res = read(pfds[i].fd, &iev, sizeof(iev)); | |
141 | + if (res < sizeof(iev)) { | |
142 | + ALOGW("insufficient input data(%zd)? fd=%d", res, pfds[i].fd); | |
143 | + continue; | |
144 | + } | |
145 | + ALOGD("type=%d code=%d value=%d from fd=%d", iev.type, iev.code, iev.value, pfds[i].fd); | |
146 | + if (iev.type == EV_KEY && iev.code == KEY_POWER && !iev.value) { | |
147 | + if (!doubleclick || timeout > 0) { | |
148 | + send_key_power(uinput_fd, longpress); | |
149 | + timeout = -1; | |
150 | + } else { | |
151 | + timeout = 1000; // one second | |
152 | + } | |
153 | + } else if (iev.type == EV_SYN && iev.code == SYN_REPORT && iev.value) { | |
154 | + ALOGI("got a resuming event"); | |
155 | + longpress = false; | |
156 | + timeout = 1000; // one second | |
157 | + } | |
158 | + } | |
159 | + } | |
160 | + } | |
161 | + | |
162 | + ALOGE_IF(cnt, "poll error: %s", strerror(errno)); | |
163 | + return NULL; | |
164 | +} | |
165 | + | |
166 | +static void init_android_power_button() | |
167 | +{ | |
168 | + static pthread_t powerbtnd_thread; | |
169 | + struct uinput_user_dev ud; | |
170 | + | |
171 | + if (uinput_fd >= 0) return; | |
172 | + | |
173 | + uinput_fd = open("/dev/uinput", O_WRONLY | O_NDELAY); | |
174 | + if (uinput_fd < 0) { | |
175 | + ALOGE("could not open uinput device: %s", strerror(errno)); | |
176 | + return; | |
177 | + } | |
178 | + | |
179 | + memset(&ud, 0, sizeof(ud)); | |
180 | + strcpy(ud.name, "Android Power Button"); | |
181 | + write(uinput_fd, &ud, sizeof(ud)); | |
182 | + ioctl(uinput_fd, UI_SET_EVBIT, EV_KEY); | |
183 | + ioctl(uinput_fd, UI_SET_KEYBIT, KEY_POWER); | |
184 | + ioctl(uinput_fd, UI_SET_KEYBIT, KEY_WAKEUP); | |
185 | + ioctl(uinput_fd, UI_DEV_CREATE, 0); | |
186 | + | |
187 | + pthread_create(&powerbtnd_thread, NULL, powerbtnd_thread_func, NULL); | |
188 | + pthread_setname_np(powerbtnd_thread, "powerbtnd"); | |
189 | +} | |
190 | + | |
44 | 191 | static void *suspend_thread_func(void *arg __attribute__((unused))) |
45 | 192 | { |
46 | 193 | char buf[80]; |
@@ -81,10 +228,13 @@ static void *suspend_thread_func(void *arg __attribute__((unused))) | ||
81 | 228 | strerror_r(errno, buf, sizeof(buf)); |
82 | 229 | ALOGE("Error writing to %s: %s\n", SYS_POWER_WAKEUP_COUNT, buf); |
83 | 230 | } else { |
231 | + const char *sleep_state = get_sleep_state(); | |
84 | 232 | ALOGV("%s: write %s to %s\n", __func__, sleep_state, SYS_POWER_STATE); |
85 | 233 | ret = TEMP_FAILURE_RETRY(write(state_fd, sleep_state, strlen(sleep_state))); |
86 | 234 | if (ret < 0) { |
87 | 235 | success = false; |
236 | + } else { | |
237 | + send_key_wakeup(uinput_fd); | |
88 | 238 | } |
89 | 239 | void (*func)(bool success) = wakeup_func; |
90 | 240 | if (func != NULL) { |
@@ -159,6 +309,8 @@ struct autosuspend_ops *autosuspend_wakeup_count_init(void) | ||
159 | 309 | int ret; |
160 | 310 | char buf[80]; |
161 | 311 | |
312 | + init_android_power_button(); | |
313 | + | |
162 | 314 | state_fd = TEMP_FAILURE_RETRY(open(SYS_POWER_STATE, O_RDWR)); |
163 | 315 | if (state_fd < 0) { |
164 | 316 | strerror_r(errno, buf, sizeof(buf)); |
@@ -4,17 +4,27 @@ include $(CLEAR_VARS) | ||
4 | 4 | LOCAL_SRC_FILES := sync.c |
5 | 5 | LOCAL_MODULE := libsync |
6 | 6 | LOCAL_MODULE_TAGS := optional |
7 | -LOCAL_SHARED_LIBRARIES := liblog | |
8 | 7 | LOCAL_C_INCLUDES := $(LOCAL_PATH)/include |
9 | 8 | LOCAL_EXPORT_C_INCLUDE_DIRS := $(LOCAL_PATH)/include |
10 | 9 | LOCAL_CFLAGS := -Werror |
11 | 10 | include $(BUILD_SHARED_LIBRARY) |
12 | 11 | |
12 | +# libsync_recovery is only intended for the recovery binary. | |
13 | +# Future versions of the kernel WILL require an updated libsync, and will break | |
14 | +# anything statically linked against the current libsync. | |
15 | +include $(CLEAR_VARS) | |
16 | +LOCAL_SRC_FILES := sync.c | |
17 | +LOCAL_MODULE := libsync_recovery | |
18 | +LOCAL_MODULE_TAGS := optional | |
19 | +LOCAL_C_INCLUDES := $(LOCAL_PATH)/include | |
20 | +LOCAL_EXPORT_C_INCLUDE_DIRS := $(LOCAL_PATH)/include | |
21 | +LOCAL_CFLAGS := -Werror | |
22 | +include $(BUILD_STATIC_LIBRARY) | |
23 | + | |
13 | 24 | include $(CLEAR_VARS) |
14 | 25 | LOCAL_SRC_FILES := sync.c sync_test.c |
15 | 26 | LOCAL_MODULE := sync_test |
16 | 27 | LOCAL_MODULE_TAGS := optional tests |
17 | -LOCAL_SHARED_LIBRARIES := liblog | |
18 | 28 | LOCAL_C_INCLUDES := $(LOCAL_PATH)/include |
19 | 29 | LOCAL_CFLAGS := -Werror |
20 | 30 | include $(BUILD_EXECUTABLE) |
@@ -22,9 +22,16 @@ | ||
22 | 22 | #include <sys/cdefs.h> |
23 | 23 | #include <stdint.h> |
24 | 24 | |
25 | +#include <linux/types.h> | |
26 | + | |
25 | 27 | __BEGIN_DECLS |
26 | 28 | |
27 | -// XXX: These structs are copied from the header "linux/sync.h". | |
29 | +struct sync_legacy_merge_data { | |
30 | + int32_t fd2; | |
31 | + char name[32]; | |
32 | + int32_t fence; | |
33 | +}; | |
34 | + | |
28 | 35 | struct sync_fence_info_data { |
29 | 36 | uint32_t len; |
30 | 37 | char name[32]; |
@@ -41,6 +48,108 @@ struct sync_pt_info { | ||
41 | 48 | uint8_t driver_data[0]; |
42 | 49 | }; |
43 | 50 | |
51 | +#define SYNC_IOC_MAGIC '>' | |
52 | + | |
53 | +/** | |
54 | + * DOC: SYNC_IOC_LEGACY_WAIT - wait for a fence to signal | |
55 | + * | |
56 | + * pass timeout in milliseconds. Waits indefinitely timeout < 0. | |
57 | + * | |
58 | + * This is the legacy version of the Sync API before the de-stage that happened | |
59 | + * on Linux kernel 4.7. | |
60 | + */ | |
61 | +#define SYNC_IOC_LEGACY_WAIT _IOW(SYNC_IOC_MAGIC, 0, __s32) | |
62 | + | |
63 | +/** | |
64 | + * DOC: SYNC_IOC_MERGE - merge two fences | |
65 | + * | |
66 | + * Takes a struct sync_merge_data. Creates a new fence containing copies of | |
67 | + * the sync_pts in both the calling fd and sync_merge_data.fd2. Returns the | |
68 | + * new fence's fd in sync_merge_data.fence | |
69 | + * | |
70 | + * This is the legacy version of the Sync API before the de-stage that happened | |
71 | + * on Linux kernel 4.7. | |
72 | + */ | |
73 | +#define SYNC_IOC_LEGACY_MERGE _IOWR(SYNC_IOC_MAGIC, 1, \ | |
74 | + struct sync_legacy_merge_data) | |
75 | + | |
76 | +/** | |
77 | + * DOC: SYNC_IOC_LEGACY_FENCE_INFO - get detailed information on a fence | |
78 | + * | |
79 | + * Takes a struct sync_fence_info_data with extra space allocated for pt_info. | |
80 | + * Caller should write the size of the buffer into len. On return, len is | |
81 | + * updated to reflect the total size of the sync_fence_info_data including | |
82 | + * pt_info. | |
83 | + * | |
84 | + * pt_info is a buffer containing sync_pt_infos for every sync_pt in the fence. | |
85 | + * To iterate over the sync_pt_infos, use the sync_pt_info.len field. | |
86 | + * | |
87 | + * This is the legacy version of the Sync API before the de-stage that happened | |
88 | + * on Linux kernel 4.7. | |
89 | + */ | |
90 | +#define SYNC_IOC_LEGACY_FENCE_INFO _IOWR(SYNC_IOC_MAGIC, 2,\ | |
91 | + struct sync_fence_info_data) | |
92 | + | |
93 | +struct sync_merge_data { | |
94 | + char name[32]; | |
95 | + int32_t fd2; | |
96 | + int32_t fence; | |
97 | + uint32_t flags; | |
98 | + uint32_t pad; | |
99 | +}; | |
100 | + | |
101 | +struct sync_file_info { | |
102 | + char name[32]; | |
103 | + int32_t status; | |
104 | + uint32_t flags; | |
105 | + uint32_t num_fences; | |
106 | + uint32_t pad; | |
107 | + | |
108 | + uint64_t sync_fence_info; | |
109 | +}; | |
110 | + | |
111 | +struct sync_fence_info { | |
112 | + char obj_name[32]; | |
113 | + char driver_name[32]; | |
114 | + int32_t status; | |
115 | + uint32_t flags; | |
116 | + uint64_t timestamp_ns; | |
117 | +}; | |
118 | + | |
119 | +/** | |
120 | + * Mainline API: | |
121 | + * | |
122 | + * Opcodes 0, 1 and 2 were burned during a API change to avoid users of the | |
123 | + * old API to get weird errors when trying to handling sync_files. The API | |
124 | + * change happened during the de-stage of the Sync Framework when there was | |
125 | + * no upstream users available. | |
126 | + */ | |
127 | + | |
128 | +/** | |
129 | + * DOC: SYNC_IOC_MERGE - merge two fences | |
130 | + * | |
131 | + * Takes a struct sync_merge_data. Creates a new fence containing copies of | |
132 | + * the sync_pts in both the calling fd and sync_merge_data.fd2. Returns the | |
133 | + * new fence's fd in sync_merge_data.fence | |
134 | + * | |
135 | + * This is the new version of the Sync API after the de-stage that happened | |
136 | + * on Linux kernel 4.7. | |
137 | + */ | |
138 | +#define SYNC_IOC_MERGE _IOWR(SYNC_IOC_MAGIC, 3, struct sync_merge_data) | |
139 | + | |
140 | +/** | |
141 | + * DOC: SYNC_IOC_FILE_INFO - get detailed information on a sync_file | |
142 | + * | |
143 | + * Takes a struct sync_file_info. If num_fences is 0, the field is updated | |
144 | + * with the actual number of fences. If num_fences is > 0, the system will | |
145 | + * use the pointer provided on sync_fence_info to return up to num_fences of | |
146 | + * struct sync_fence_info, with detailed fence information. | |
147 | + * | |
148 | + * This is the new version of the Sync API after the de-stage that happened | |
149 | + * on Linux kernel 4.7. | |
150 | + */ | |
151 | +#define SYNC_IOC_FILE_INFO _IOWR(SYNC_IOC_MAGIC, 4, struct sync_file_info) | |
152 | + | |
44 | 153 | /* timeout in msecs */ |
45 | 154 | int sync_wait(int fd, int timeout); |
46 | 155 | int sync_merge(const char *name, int fd1, int fd2); |
@@ -20,53 +20,155 @@ | ||
20 | 20 | #include <malloc.h> |
21 | 21 | #include <stdint.h> |
22 | 22 | #include <string.h> |
23 | - | |
24 | -#include <linux/sync.h> | |
25 | -#include <linux/sw_sync.h> | |
23 | +#include <errno.h> | |
24 | +#include <poll.h> | |
26 | 25 | |
27 | 26 | #include <sys/ioctl.h> |
28 | 27 | #include <sys/stat.h> |
29 | 28 | #include <sys/types.h> |
30 | 29 | |
30 | +#include <sync/sync.h> | |
31 | + | |
32 | + | |
33 | +struct sw_sync_create_fence_data { | |
34 | + __u32 value; | |
35 | + char name[32]; | |
36 | + __s32 fence; | |
37 | +}; | |
38 | + | |
39 | +#define SW_SYNC_IOC_MAGIC 'W' | |
40 | +#define SW_SYNC_IOC_CREATE_FENCE _IOWR(SW_SYNC_IOC_MAGIC, 0, struct sw_sync_create_fence_data) | |
41 | +#define SW_SYNC_IOC_INC _IOW(SW_SYNC_IOC_MAGIC, 1, __u32) | |
42 | + | |
31 | 43 | int sync_wait(int fd, int timeout) |
32 | 44 | { |
33 | - __s32 to = timeout; | |
45 | + struct pollfd fds; | |
46 | + int ret; | |
47 | + | |
48 | + if (fd < 0) { | |
49 | + errno = EINVAL; | |
50 | + return -1; | |
51 | + } | |
34 | 52 | |
35 | - return ioctl(fd, SYNC_IOC_WAIT, &to); | |
53 | + fds.fd = fd; | |
54 | + fds.events = POLLIN; | |
55 | + | |
56 | + do { | |
57 | + ret = poll(&fds, 1, timeout); | |
58 | + if (ret > 0) { | |
59 | + if (fds.revents & (POLLERR | POLLNVAL)) { | |
60 | + errno = EINVAL; | |
61 | + return -1; | |
62 | + } | |
63 | + return 0; | |
64 | + } else if (ret == 0) { | |
65 | + errno = ETIME; | |
66 | + return -1; | |
67 | + } | |
68 | + } while (ret == -1 && (errno == EINTR || errno == EAGAIN)); | |
69 | + | |
70 | + return ret; | |
36 | 71 | } |
37 | 72 | |
38 | 73 | int sync_merge(const char *name, int fd1, int fd2) |
39 | 74 | { |
75 | + struct sync_legacy_merge_data legacy_data; | |
40 | 76 | struct sync_merge_data data; |
41 | - int err; | |
77 | + int ret; | |
42 | 78 | |
43 | 79 | data.fd2 = fd2; |
44 | 80 | strlcpy(data.name, name, sizeof(data.name)); |
81 | + data.flags = 0; | |
82 | + data.pad = 0; | |
45 | 83 | |
46 | - err = ioctl(fd1, SYNC_IOC_MERGE, &data); | |
47 | - if (err < 0) | |
48 | - return err; | |
84 | + ret = ioctl(fd1, SYNC_IOC_MERGE, &data); | |
85 | + if (ret < 0 && errno == ENOTTY) { | |
86 | + legacy_data.fd2 = fd2; | |
87 | + strlcpy(legacy_data.name, name, sizeof(legacy_data.name)); | |
88 | + | |
89 | + ret = ioctl(fd1, SYNC_IOC_LEGACY_MERGE, &legacy_data); | |
90 | + if (ret < 0) | |
91 | + return ret; | |
92 | + | |
93 | + return legacy_data.fence; | |
94 | + } else if (ret < 0) { | |
95 | + return ret; | |
96 | + } | |
49 | 97 | |
50 | 98 | return data.fence; |
51 | 99 | } |
52 | 100 | |
53 | 101 | struct sync_fence_info_data *sync_fence_info(int fd) |
54 | 102 | { |
55 | - struct sync_fence_info_data *info; | |
56 | - int err; | |
57 | - | |
58 | - info = malloc(4096); | |
59 | - if (info == NULL) | |
103 | + struct sync_fence_info_data *legacy_info; | |
104 | + struct sync_pt_info *legacy_pt_info; | |
105 | + struct sync_file_info *info; | |
106 | + struct sync_fence_info *fence_info; | |
107 | + int err, num_fences, i; | |
108 | + | |
109 | + legacy_info = malloc(4096); | |
110 | + if (legacy_info == NULL) | |
60 | 111 | return NULL; |
61 | 112 | |
62 | - info->len = 4096; | |
63 | - err = ioctl(fd, SYNC_IOC_FENCE_INFO, info); | |
64 | - if (err < 0) { | |
65 | - free(info); | |
113 | + legacy_info->len = 4096; | |
114 | + err = ioctl(fd, SYNC_IOC_LEGACY_FENCE_INFO, legacy_info); | |
115 | + if (err < 0 && errno != ENOTTY) { | |
116 | + free(legacy_info); | |
66 | 117 | return NULL; |
118 | + } else if (err == 0) { | |
119 | + return legacy_info; | |
120 | + } | |
121 | + | |
122 | + info = calloc(1, sizeof(*info)); | |
123 | + if (info == NULL) | |
124 | + goto free; | |
125 | + | |
126 | + err = ioctl(fd, SYNC_IOC_FILE_INFO, info); | |
127 | + if (err < 0) | |
128 | + goto free; | |
129 | + | |
130 | + num_fences = info->num_fences; | |
131 | + | |
132 | + if (num_fences) { | |
133 | + info->flags = 0; | |
134 | + info->num_fences = num_fences; | |
135 | + info->sync_fence_info = (uint64_t) calloc(num_fences, | |
136 | + sizeof(struct sync_fence_info)); | |
137 | + if ((void *)info->sync_fence_info == NULL) | |
138 | + goto free; | |
139 | + | |
140 | + err = ioctl(fd, SYNC_IOC_FILE_INFO, info); | |
141 | + if (err < 0) { | |
142 | + free((void *)info->sync_fence_info); | |
143 | + goto free; | |
144 | + } | |
67 | 145 | } |
68 | 146 | |
69 | - return info; | |
147 | + legacy_info->len = sizeof(*legacy_info) + | |
148 | + num_fences * sizeof(struct sync_fence_info); | |
149 | + strlcpy(legacy_info->name, info->name, sizeof(legacy_info->name)); | |
150 | + legacy_info->status = info->status; | |
151 | + | |
152 | + legacy_pt_info = (struct sync_pt_info *)legacy_info->pt_info; | |
153 | + fence_info = (struct sync_fence_info *)info->sync_fence_info; | |
154 | + for (i = 0 ; i < num_fences ; i++) { | |
155 | + legacy_pt_info[i].len = sizeof(*legacy_pt_info); | |
156 | + strlcpy(legacy_pt_info[i].obj_name, fence_info[i].obj_name, | |
157 | + sizeof(legacy_pt_info->obj_name)); | |
158 | + strlcpy(legacy_pt_info[i].driver_name, fence_info[i].driver_name, | |
159 | + sizeof(legacy_pt_info->driver_name)); | |
160 | + legacy_pt_info[i].status = fence_info[i].status; | |
161 | + legacy_pt_info[i].timestamp_ns = fence_info[i].timestamp_ns; | |
162 | + } | |
163 | + | |
164 | + free((void *)info->sync_fence_info); | |
165 | + free(info); | |
166 | + return legacy_info; | |
167 | + | |
168 | +free: | |
169 | + free(legacy_info); | |
170 | + free(info); | |
171 | + return NULL; | |
70 | 172 | } |
71 | 173 | |
72 | 174 | struct sync_pt_info *sync_pt_info(struct sync_fence_info_data *info, |
@@ -91,7 +193,13 @@ void sync_fence_info_free(struct sync_fence_info_data *info) | ||
91 | 193 | |
92 | 194 | int sw_sync_timeline_create(void) |
93 | 195 | { |
94 | - return open("/dev/sw_sync", O_RDWR); | |
196 | + int ret; | |
197 | + | |
198 | + ret = open("/sys/kernel/debug/sync/sw_sync", O_RDWR); | |
199 | + if (ret < 0) | |
200 | + ret = open("/dev/sw_sync", O_RDWR); | |
201 | + | |
202 | + return ret; | |
95 | 203 | } |
96 | 204 | |
97 | 205 | int sw_sync_timeline_inc(int fd, unsigned count) |
@@ -92,7 +92,7 @@ int main(int argc __attribute__((unused)), char *argv[] __attribute__((unused))) | ||
92 | 92 | |
93 | 93 | for (j = 0; j < 2; j++) { |
94 | 94 | unsigned val = i + j * 3 + 1; |
95 | - sprintf(str, "test_fence%d-%d", i, j); | |
95 | + snprintf(str, sizeof(str), "test_fence%d-%d", i, j); | |
96 | 96 | int fd = sw_sync_fence_create(sync_timeline_fd, str, val); |
97 | 97 | if (fd < 0) { |
98 | 98 | printf("can't create sync pt %d: %s", val, strerror(errno)); |
@@ -106,7 +106,7 @@ int main(int argc __attribute__((unused)), char *argv[] __attribute__((unused))) | ||
106 | 106 | |
107 | 107 | sync_data[3].thread_no = 3; |
108 | 108 | for (j = 0; j < 2; j++) { |
109 | - sprintf(str, "merged_fence%d", j); | |
109 | + snprintf(str, sizeof(str), "merged_fence%d", j); | |
110 | 110 | sync_data[3].fd[j] = sync_merge(str, sync_data[0].fd[j], sync_data[1].fd[j]); |
111 | 111 | if (sync_data[3].fd[j] < 0) { |
112 | 112 | printf("can't merge sync pts %d and %d: %s\n", |
@@ -251,17 +251,22 @@ public: | ||
251 | 251 | { |
252 | 252 | Mutex::Autolock _l(mMutex); |
253 | 253 | char buf[128]; |
254 | - sprintf(buf, "Strong references on RefBase %p (weakref_type %p):\n", mBase, this); | |
254 | + snprintf(buf, sizeof(buf), | |
255 | + "Strong references on RefBase %p (weakref_type %p):\n", | |
256 | + mBase, this); | |
255 | 257 | text.append(buf); |
256 | 258 | printRefsLocked(&text, mStrongRefs); |
257 | - sprintf(buf, "Weak references on RefBase %p (weakref_type %p):\n", mBase, this); | |
259 | + snprintf(buf, sizeof(buf), | |
260 | + "Weak references on RefBase %p (weakref_type %p):\n", | |
261 | + mBase, this); | |
258 | 262 | text.append(buf); |
259 | 263 | printRefsLocked(&text, mWeakRefs); |
260 | 264 | } |
261 | 265 | |
262 | 266 | { |
263 | 267 | char name[100]; |
264 | - snprintf(name, 100, DEBUG_REFS_CALLSTACK_PATH "/%p.stack", this); | |
268 | + snprintf(name, sizeof(name), DEBUG_REFS_CALLSTACK_PATH "/%p.stack", | |
269 | + this); | |
265 | 270 | int rc = open(name, O_RDWR | O_CREAT | O_APPEND, 644); |
266 | 271 | if (rc >= 0) { |
267 | 272 | write(rc, text.string(), text.length()); |
@@ -354,8 +359,8 @@ private: | ||
354 | 359 | char buf[128]; |
355 | 360 | while (refs) { |
356 | 361 | char inc = refs->ref >= 0 ? '+' : '-'; |
357 | - sprintf(buf, "\t%c ID %p (ref %d):\n", | |
358 | - inc, refs->id, refs->ref); | |
362 | + snprintf(buf, sizeof(buf), "\t%c ID %p (ref %d):\n", | |
363 | + inc, refs->id, refs->ref); | |
359 | 364 | out->append(buf); |
360 | 365 | #if DEBUG_REFS_CALLSTACK_ENABLED |
361 | 366 | out->append(refs->stack.toString("\t\t")); |
@@ -129,7 +129,7 @@ size_t strnlen32(const char32_t *s, size_t maxlen) | ||
129 | 129 | |
130 | 130 | static inline int32_t utf32_at_internal(const char* cur, size_t *num_read) |
131 | 131 | { |
132 | - const char first_char = *cur; | |
132 | + const unsigned char first_char = *cur; | |
133 | 133 | if ((first_char & 0x80) == 0) { // ASCII |
134 | 134 | *num_read = 1; |
135 | 135 | return *cur; |
@@ -391,7 +391,7 @@ ssize_t utf8_length(const char *src) | ||
391 | 391 | const char *cur = src; |
392 | 392 | size_t ret = 0; |
393 | 393 | while (*cur != '\0') { |
394 | - const char first_char = *cur++; | |
394 | + const unsigned char first_char = *cur++; | |
395 | 395 | if ((first_char & 0x80) == 0) { // ASCII |
396 | 396 | ret += 1; |
397 | 397 | continue; |
@@ -482,7 +482,7 @@ size_t utf8_to_utf32_length(const char *src, size_t src_len) | ||
482 | 482 | for (cur = src, end = src + src_len, num_to_skip = 1; |
483 | 483 | cur < end; |
484 | 484 | cur += num_to_skip, ret++) { |
485 | - const char first_char = *cur; | |
485 | + const unsigned char first_char = *cur; | |
486 | 486 | num_to_skip = 1; |
487 | 487 | if ((first_char & 0x80) == 0) { // ASCII |
488 | 488 | continue; |
@@ -30,6 +30,11 @@ on early-init | ||
30 | 30 | # Set the security context of /postinstall if present. |
31 | 31 | restorecon /postinstall |
32 | 32 | |
33 | + mount debugfs /sys/kernel/debug /sys/kernel/debug mode=755 | |
34 | + | |
35 | + # for /lib/firmware | |
36 | + symlink system/lib /lib | |
37 | + | |
33 | 38 | start ueventd |
34 | 39 | |
35 | 40 | on init |
@@ -148,6 +153,7 @@ on init | ||
148 | 153 | mkdir /dev/cpuctl |
149 | 154 | mount cgroup none /dev/cpuctl cpu |
150 | 155 | chown system system /dev/cpuctl |
156 | + chmod 0660 /dev/cpuctl | |
151 | 157 | chown system system /dev/cpuctl/tasks |
152 | 158 | chmod 0666 /dev/cpuctl/tasks |
153 | 159 | write /dev/cpuctl/cpu.rt_period_us 1000000 |
@@ -662,7 +668,7 @@ service console /system/bin/sh | ||
662 | 668 | class core |
663 | 669 | console |
664 | 670 | disabled |
665 | - user shell | |
671 | +# user shell | |
666 | 672 | group shell log readproc |
667 | 673 | seclabel u:r:shell:s0 |
668 | 674 |
@@ -78,9 +78,6 @@ subsystem adf | ||
78 | 78 | /dev/htc-acoustic 0660 system audio |
79 | 79 | /dev/vdec 0660 system audio |
80 | 80 | /dev/q6venc 0660 system audio |
81 | -/dev/snd/dsp 0660 system audio | |
82 | -/dev/snd/dsp1 0660 system audio | |
83 | -/dev/snd/mixer 0660 system audio | |
84 | 81 | /dev/smd0 0640 radio radio |
85 | 82 | /dev/qmi 0640 radio radio |
86 | 83 | /dev/qmi0 0640 radio radio |
@@ -2071,7 +2071,7 @@ static bool should_use_sdcardfs(void) { | ||
2071 | 2071 | } |
2072 | 2072 | |
2073 | 2073 | // Fall back to device opinion about state |
2074 | - if (property_get_bool(PROP_SDCARDFS_DEVICE, false)) { | |
2074 | + if (property_get_bool(PROP_SDCARDFS_DEVICE, true)) { | |
2075 | 2075 | ALOGW("Device explicitly enabled sdcardfs"); |
2076 | 2076 | return supports_sdcardfs(); |
2077 | 2077 | } else { |
@@ -249,7 +249,7 @@ int newfs_msdos_main(int argc, char *argv[]) | ||
249 | 249 | char buf[MAXPATHLEN]; |
250 | 250 | struct stat sb; |
251 | 251 | struct timeval tv; |
252 | - struct bpb bpb; | |
252 | + struct bpb bpb, tempbpb; | |
253 | 253 | struct tm *tm; |
254 | 254 | struct bs *bs; |
255 | 255 | struct bsbpb *bsbpb; |
@@ -553,6 +553,7 @@ int newfs_msdos_main(int argc, char *argv[]) | ||
553 | 553 | set_spf = !bpb.bspf; |
554 | 554 | set_spc = !bpb.spc; |
555 | 555 | tempx = x; |
556 | + memset(&tempbpb, 0, sizeof(bpb)); | |
556 | 557 | /* |
557 | 558 | * Attempt to align if opt_A is set. This is done by increasing the number |
558 | 559 | * of reserved blocks. This can cause other factors to change, which can in |
@@ -600,10 +601,14 @@ int newfs_msdos_main(int argc, char *argv[]) | ||
600 | 601 | alignment = (bpb.res + bpb.bspf * bpb.nft) % bpb.spc; |
601 | 602 | extra_res += bpb.spc - alignment; |
602 | 603 | } |
603 | - attempts++; | |
604 | + if (++attempts == 1) | |
605 | + memcpy(&tempbpb, &bpb, sizeof(bpb)); | |
604 | 606 | } while(opt_A && alignment != 0 && attempts < 2); |
605 | - if (alignment != 0) | |
607 | + if (alignment != 0) { | |
606 | 608 | warnx("warning: Alignment failed."); |
609 | + /* return to data from first iteration */ | |
610 | + memcpy(&bpb, &tempbpb, sizeof(bpb)); | |
611 | + } | |
607 | 612 | |
608 | 613 | cls = (bpb.bsec - x1) / bpb.spc; |
609 | 614 | x = (u_int64_t)bpb.bspf * bpb.bps * NPB / (fat / BPN) - RESFTE; |
@@ -695,7 +700,7 @@ int newfs_msdos_main(int argc, char *argv[]) | ||
695 | 700 | (u_int)tm->tm_min)); |
696 | 701 | mk4(bsx->volid, x); |
697 | 702 | mklabel(bsx->label, opt_L ? opt_L : "NO NAME"); |
698 | - sprintf(buf, "FAT%u", fat); | |
703 | + snprintf(buf, sizeof(buf), "FAT%u", fat); | |
699 | 704 | setstr(bsx->type, buf, sizeof(bsx->type)); |
700 | 705 | if (!opt_B) { |
701 | 706 | x1 += sizeof(struct bsx); |
@@ -57,16 +57,16 @@ static int ps_line(int pid, int tid) | ||
57 | 57 | int prio, nice, rtprio, sched, psr; |
58 | 58 | struct passwd *pw; |
59 | 59 | |
60 | - sprintf(statline, "/proc/%d", tid ? tid : pid); | |
60 | + snprintf(statline, sizeof(statline), "/proc/%d", tid ? tid : pid); | |
61 | 61 | stat(statline, &stats); |
62 | 62 | |
63 | 63 | if(tid) { |
64 | - sprintf(statline, "/proc/%d/task/%d/stat", pid, tid); | |
64 | + snprintf(statline, sizeof(statline), "/proc/%d/task/%d/stat", pid, tid); | |
65 | 65 | cmdline[0] = 0; |
66 | 66 | snprintf(macline, sizeof(macline), "/proc/%d/task/%d/attr/current", pid, tid); |
67 | 67 | } else { |
68 | - sprintf(statline, "/proc/%d/stat", pid); | |
69 | - sprintf(cmdline, "/proc/%d/cmdline", pid); | |
68 | + snprintf(statline, sizeof(statline), "/proc/%d/stat", pid); | |
69 | + snprintf(cmdline, sizeof(cmdline), "/proc/%d/cmdline", pid); | |
70 | 70 | snprintf(macline, sizeof(macline), "/proc/%d/attr/current", pid); |
71 | 71 | int fd = open(cmdline, O_RDONLY); |
72 | 72 | if(fd == 0) { |
@@ -149,7 +149,7 @@ static int ps_line(int pid, int tid) | ||
149 | 149 | |
150 | 150 | pw = getpwuid(stats.st_uid); |
151 | 151 | if(pw == 0 || (display_flags & SHOW_NUMERIC_UID)) { |
152 | - sprintf(user,"%d",(int)stats.st_uid); | |
152 | + snprintf(user,sizeof(user),"%d",(int)stats.st_uid); | |
153 | 153 | } else { |
154 | 154 | strcpy(user,pw->pw_name); |
155 | 155 | } |
@@ -208,7 +208,7 @@ static void print_exe_abi(int pid) | ||
208 | 208 | int fd, r; |
209 | 209 | char exeline[1024]; |
210 | 210 | |
211 | - sprintf(exeline, "/proc/%d/exe", pid); | |
211 | + snprintf(exeline, sizeof(exeline), "/proc/%d/exe", pid); | |
212 | 212 | fd = open(exeline, O_RDONLY); |
213 | 213 | if(fd == 0) { |
214 | 214 | printf(" "); |
@@ -243,7 +243,7 @@ void ps_threads(int pid) | ||
243 | 243 | DIR *d; |
244 | 244 | struct dirent *de; |
245 | 245 | |
246 | - sprintf(tmp,"/proc/%d/task",pid); | |
246 | + snprintf(tmp,sizeof(tmp),"/proc/%d/task",pid); | |
247 | 247 | d = opendir(tmp); |
248 | 248 | if(d == 0) return; |
249 | 249 |
@@ -265,29 +265,29 @@ static void read_procs(void) { | ||
265 | 265 | |
266 | 266 | proc->pid = proc->tid = pid; |
267 | 267 | |
268 | - sprintf(filename, "/proc/%d/stat", pid); | |
268 | + snprintf(filename, sizeof(filename), "/proc/%d/stat", pid); | |
269 | 269 | read_stat(filename, proc); |
270 | 270 | |
271 | - sprintf(filename, "/proc/%d/cmdline", pid); | |
271 | + snprintf(filename, sizeof(filename), "/proc/%d/cmdline", pid); | |
272 | 272 | read_cmdline(filename, proc); |
273 | 273 | |
274 | - sprintf(filename, "/proc/%d/status", pid); | |
274 | + snprintf(filename, sizeof(filename), "/proc/%d/status", pid); | |
275 | 275 | read_status(filename, proc); |
276 | 276 | |
277 | 277 | read_policy(pid, proc); |
278 | 278 | |
279 | 279 | proc->num_threads = 0; |
280 | 280 | } else { |
281 | - sprintf(filename, "/proc/%d/cmdline", pid); | |
281 | + snprintf(filename, sizeof(filename), "/proc/%d/cmdline", pid); | |
282 | 282 | read_cmdline(filename, &cur_proc); |
283 | 283 | |
284 | - sprintf(filename, "/proc/%d/status", pid); | |
284 | + snprintf(filename, sizeof(filename), "/proc/%d/status", pid); | |
285 | 285 | read_status(filename, &cur_proc); |
286 | 286 | |
287 | 287 | proc = NULL; |
288 | 288 | } |
289 | 289 | |
290 | - sprintf(filename, "/proc/%d/task", pid); | |
290 | + snprintf(filename, sizeof(filename), "/proc/%d/task", pid); | |
291 | 291 | task_dir = opendir(filename); |
292 | 292 | if (!task_dir) continue; |
293 | 293 |
@@ -302,7 +302,7 @@ static void read_procs(void) { | ||
302 | 302 | |
303 | 303 | proc->pid = pid; proc->tid = tid; |
304 | 304 | |
305 | - sprintf(filename, "/proc/%d/task/%d/stat", pid, tid); | |
305 | + snprintf(filename, sizeof(filename), "/proc/%d/task/%d/stat", pid, tid); | |
306 | 306 | read_stat(filename, proc); |
307 | 307 | |
308 | 308 | read_policy(tid, proc); |
@@ -491,7 +491,7 @@ static void print_procs(void) { | ||
491 | 491 | if (user && user->pw_name) { |
492 | 492 | user_str = user->pw_name; |
493 | 493 | } else { |
494 | - snprintf(user_buf, 20, "%d", proc->uid); | |
494 | + snprintf(user_buf, sizeof(user_buf), "%d", proc->uid); | |
495 | 495 | user_str = user_buf; |
496 | 496 | } |
497 | 497 | if (!threads) { |