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