Merge "Add wall-clock timing for each fastboot Action."
diff --git a/CleanSpec.mk b/CleanSpec.mk
new file mode 100644
index 0000000..b84e1b65
--- /dev/null
+++ b/CleanSpec.mk
@@ -0,0 +1,49 @@
+# Copyright (C) 2007 The Android Open Source Project
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+#
+
+# If you don't need to do a full clean build but would like to touch
+# a file or delete some intermediate files, add a clean step to the end
+# of the list. These steps will only be run once, if they haven't been
+# run before.
+#
+# E.g.:
+# $(call add-clean-step, touch -c external/sqlite/sqlite3.h)
+# $(call add-clean-step, rm -rf $(PRODUCT_OUT)/obj/STATIC_LIBRARIES/libz_intermediates)
+#
+# Always use "touch -c" and "rm -f" or "rm -rf" to gracefully deal with
+# files that are missing or have been moved.
+#
+# Use $(PRODUCT_OUT) to get to the "out/target/product/blah/" directory.
+# Use $(OUT_DIR) to refer to the "out" directory.
+#
+# If you need to re-do something that's already mentioned, just copy
+# the command and add it to the bottom of the list. E.g., if a change
+# that you made last week required touching a file and a change you
+# made today requires touching the same file, just copy the old
+# touch step and add it to the end of the list.
+#
+# ************************************************
+# NEWER CLEAN STEPS MUST BE AT THE END OF THE LIST
+# ************************************************
+
+# For example:
+#$(call add-clean-step, rm -rf $(OUT_DIR)/target/common/obj/APPS/AndroidTests_intermediates)
+#$(call add-clean-step, rm -rf $(OUT_DIR)/target/common/obj/JAVA_LIBRARIES/core_intermediates)
+#$(call add-clean-step, find $(OUT_DIR) -type f -name "IGTalkSession*" -print0 | xargs -0 rm -f)
+#$(call add-clean-step, rm -rf $(PRODUCT_OUT)/data/*)
+
+# ************************************************
+# NEWER CLEAN STEPS MUST BE AT THE END OF THE LIST
+# ************************************************
diff --git a/adb/adb.h b/adb/adb.h
index a148019..aaf8a28 100644
--- a/adb/adb.h
+++ b/adb/adb.h
@@ -33,7 +33,7 @@
#define ADB_VERSION_MAJOR 1 // Used for help/version information
#define ADB_VERSION_MINOR 0 // Used for help/version information
-#define ADB_SERVER_VERSION 25 // Increment this when we want to force users to start a new adb server
+#define ADB_SERVER_VERSION 26 // Increment this when we want to force users to start a new adb server
typedef struct amessage amessage;
typedef struct apacket apacket;
diff --git a/adb/commandline.c b/adb/commandline.c
index 0352cf2..857cee3 100644
--- a/adb/commandline.c
+++ b/adb/commandline.c
@@ -105,8 +105,8 @@
" environment variable is used, which must\n"
" be an absolute path.\n"
" devices - list all connected devices\n"
- " connect <host>:<port> - connect to a device via TCP/IP"
- " disconnect <host>:<port> - disconnect from a TCP/IP device"
+ " connect <host>:<port> - connect to a device via TCP/IP\n"
+ " disconnect <host>:<port> - disconnect from a TCP/IP device\n"
"\n"
"device commands:\n"
" adb push <local> <remote> - copy file/dir to device\n"
@@ -221,8 +221,8 @@
if(errno == EINTR) continue;
break;
}
- /* we want to output to stdout, so no adb_write here !! */
- unix_write(1, buf, len);
+ fwrite(buf, 1, len, stdout);
+ fflush(stdout);
}
}
diff --git a/adb/usb_linux.c b/adb/usb_linux.c
index 66ee317..bb86813 100644
--- a/adb/usb_linux.c
+++ b/adb/usb_linux.c
@@ -21,6 +21,7 @@
#include <sys/ioctl.h>
#include <sys/types.h>
+#include <sys/time.h>
#include <dirent.h>
#include <fcntl.h>
#include <errno.h>
@@ -287,6 +288,8 @@
{
struct usbdevfs_urb *urb = &h->urb_out;
int res;
+ struct timeval tv;
+ struct timespec ts;
memset(urb, 0, sizeof(*urb));
urb->type = USBDEVFS_URB_TYPE_BULK;
@@ -313,8 +316,12 @@
res = -1;
h->urb_out_busy = 1;
for(;;) {
- adb_cond_wait(&h->notify, &h->lock);
- if(h->dead) {
+ /* time out after five seconds */
+ gettimeofday(&tv, NULL);
+ ts.tv_sec = tv.tv_sec + 5;
+ ts.tv_nsec = tv.tv_usec * 1000L;
+ res = pthread_cond_timedwait(&h->notify, &h->lock, &ts);
+ if(res < 0 || h->dead) {
break;
}
if(h->urb_out_busy == 0) {
diff --git a/adb/usb_vendors.c b/adb/usb_vendors.c
index 866e3af..fd34052 100644
--- a/adb/usb_vendors.c
+++ b/adb/usb_vendors.c
@@ -61,6 +61,8 @@
#define VENDOR_ID_GARMIN_ASUS 0x091E
// Sharp's USB Vendor ID
#define VENDOR_ID_SHARP 0x04dd
+// ZTE's USB Vendor ID
+#define VENDOR_ID_ZTE 0x19D2
/** built-in vendor list */
int builtInVendorIds[] = {
@@ -77,6 +79,7 @@
VENDOR_ID_NVIDIA,
VENDOR_ID_GARMIN_ASUS,
VENDOR_ID_SHARP,
+ VENDOR_ID_ZTE,
};
#define BUILT_IN_VENDOR_COUNT (sizeof(builtInVendorIds)/sizeof(builtInVendorIds[0]))
diff --git a/debuggerd/Android.mk b/debuggerd/Android.mk
index b86f2a5..3c1cf02 100644
--- a/debuggerd/Android.mk
+++ b/debuggerd/Android.mk
@@ -9,6 +9,13 @@
LOCAL_CFLAGS := -Wall
LOCAL_MODULE := debuggerd
+ifeq ($(ARCH_ARM_HAVE_VFP),true)
+LOCAL_CFLAGS += -DWITH_VFP
+endif # ARCH_ARM_HAVE_VFP
+ifeq ($(ARCH_ARM_HAVE_VFP_D32),true)
+LOCAL_CFLAGS += -DWITH_VFP_D32
+endif # ARCH_ARM_HAVE_VFP_D32
+
LOCAL_STATIC_LIBRARIES := libcutils libc
include $(BUILD_EXECUTABLE)
@@ -23,14 +30,20 @@
LOCAL_SHARED_LIBRARIES := libcutils libc
include $(BUILD_EXECUTABLE)
-ifeq ($(TARGET_ARCH_VARIANT),armv7-a)
+ifeq ($(ARCH_ARM_HAVE_VFP),true)
include $(CLEAR_VARS)
+
+LOCAL_CFLAGS += -DWITH_VFP
+ifeq ($(ARCH_ARM_HAVE_VFP_D32),true)
+LOCAL_CFLAGS += -DWITH_VFP_D32
+endif # ARCH_ARM_HAVE_VFP_D32
+
LOCAL_SRC_FILES := vfp-crasher.c vfp.S
LOCAL_MODULE := vfp-crasher
LOCAL_MODULE_PATH := $(TARGET_OUT_OPTIONAL_EXECUTABLES)
LOCAL_MODULE_TAGS := eng
LOCAL_SHARED_LIBRARIES := libcutils libc
include $(BUILD_EXECUTABLE)
-endif # TARGET_ARCH_VARIANT == armv7-a
+endif # ARCH_ARM_HAVE_VFP == true
endif # TARGET_ARCH == arm
diff --git a/debuggerd/debuggerd.c b/debuggerd/debuggerd.c
index 7b987cf..e850a2e 100644
--- a/debuggerd/debuggerd.c
+++ b/debuggerd/debuggerd.c
@@ -42,6 +42,14 @@
#include "utility.h"
+#ifdef WITH_VFP
+#ifdef WITH_VFP_D32
+#define NUM_VFP_REGS 32
+#else
+#define NUM_VFP_REGS 16
+#endif
+#endif
+
/* Main entry point to get the backtrace from the crashing process */
extern int unwind_backtrace_with_ptrace(int tfd, pid_t pid, mapinfo *map,
unsigned int sp_list[],
@@ -278,7 +286,7 @@
" ip %08x sp %08x lr %08x pc %08x cpsr %08x\n",
r.ARM_ip, r.ARM_sp, r.ARM_lr, r.ARM_pc, r.ARM_cpsr);
-#if __ARM_NEON__
+#ifdef WITH_VFP
struct user_vfp vfp_regs;
int i;
@@ -288,7 +296,7 @@
return;
}
- for (i = 0; i < 32; i += 2) {
+ for (i = 0; i < NUM_VFP_REGS; i += 2) {
_LOG(tfd, only_in_tombstone,
" d%-2d %016llx d%-2d %016llx\n",
i, vfp_regs.fpregs[i], i+1, vfp_regs.fpregs[i+1]);
diff --git a/debuggerd/vfp.S b/debuggerd/vfp.S
index 2192415..9744f6f 100644
--- a/debuggerd/vfp.S
+++ b/debuggerd/vfp.S
@@ -19,6 +19,7 @@
fconstd d13, #13
fconstd d14, #14
fconstd d15, #15
+#ifdef WITH_VFP_D32
fconstd d16, #16
fconstd d17, #17
fconstd d18, #18
@@ -35,6 +36,7 @@
fconstd d29, #29
fconstd d30, #30
fconstd d31, #31
+#endif
mov r0, #0
str r0, [r0]
bx lr
diff --git a/include/cutils/iosched_policy.h b/include/cutils/iosched_policy.h
new file mode 100644
index 0000000..07c5d1f
--- /dev/null
+++ b/include/cutils/iosched_policy.h
@@ -0,0 +1,38 @@
+/*
+ * Copyright (C) 2007 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef __CUTILS_IOSCHED_POLICY_H
+#define __CUTILS_IOSCHED_POLICY_H
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+typedef enum {
+ IoSchedClass_NONE,
+ IoSchedClass_RT,
+ IoSchedClass_BE,
+ IoSchedClass_IDLE,
+} IoSchedClass;
+
+extern int android_set_ioprio(int pid, IoSchedClass clazz, int ioprio);
+extern int android_get_ioprio(int pid, IoSchedClass *clazz, int *ioprio);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* __CUTILS_IOSCHED_POLICY_H */
diff --git a/include/cutils/log.h b/include/cutils/log.h
index ec3cac8..dd47c35 100644
--- a/include/cutils/log.h
+++ b/include/cutils/log.h
@@ -196,6 +196,91 @@
#define IF_LOGE() IF_LOG(LOG_ERROR, LOG_TAG)
#endif
+
+// ---------------------------------------------------------------------
+
+/*
+ * Simplified macro to send a verbose system log message using the current LOG_TAG.
+ */
+#ifndef SLOGV
+#if LOG_NDEBUG
+#define SLOGV(...) ((void)0)
+#else
+#define SLOGV(...) ((void)__android_log_buf_print(LOG_ID_SYSTEM, ANDROID_LOG_VERBOSE, LOG_TAG, __VA_ARGS__))
+#endif
+#endif
+
+#define CONDITION(cond) (__builtin_expect((cond)!=0, 0))
+
+#ifndef SLOGV_IF
+#if LOG_NDEBUG
+#define SLOGV_IF(cond, ...) ((void)0)
+#else
+#define SLOGV_IF(cond, ...) \
+ ( (CONDITION(cond)) \
+ ? ((void)__android_log_buf_print(LOG_ID_SYSTEM, ANDROID_LOG_VERBOSE, LOG_TAG, __VA_ARGS__)) \
+ : (void)0 )
+#endif
+#endif
+
+/*
+ * Simplified macro to send a debug system log message using the current LOG_TAG.
+ */
+#ifndef SLOGD
+#define SLOGD(...) ((void)__android_log_buf_print(LOG_ID_SYSTEM, ANDROID_LOG_DEBUG, LOG_TAG, __VA_ARGS__))
+#endif
+
+#ifndef SLOGD_IF
+#define SLOGD_IF(cond, ...) \
+ ( (CONDITION(cond)) \
+ ? ((void)__android_log_buf_print(LOG_ID_SYSTEM, ANDROID_LOG_DEBUG, LOG_TAG, __VA_ARGS__)) \
+ : (void)0 )
+#endif
+
+/*
+ * Simplified macro to send an info system log message using the current LOG_TAG.
+ */
+#ifndef SLOGI
+#define SLOGI(...) ((void)__android_log_buf_print(LOG_ID_SYSTEM, ANDROID_LOG_INFO, LOG_TAG, __VA_ARGS__))
+#endif
+
+#ifndef SLOGI_IF
+#define SLOGI_IF(cond, ...) \
+ ( (CONDITION(cond)) \
+ ? ((void)__android_log_buf_print(LOG_ID_SYSTEM, ANDROID_LOG_INFO, LOG_TAG, __VA_ARGS__)) \
+ : (void)0 )
+#endif
+
+/*
+ * Simplified macro to send a warning system log message using the current LOG_TAG.
+ */
+#ifndef SLOGW
+#define SLOGW(...) ((void)__android_log_buf_print(LOG_ID_SYSTEM, ANDROID_LOG_WARN, LOG_TAG, __VA_ARGS__))
+#endif
+
+#ifndef SLOGW_IF
+#define SLOGW_IF(cond, ...) \
+ ( (CONDITION(cond)) \
+ ? ((void)__android_log_buf_print(LOG_ID_SYSTEM, ANDROID_LOG_WARN, LOG_TAG, __VA_ARGS__)) \
+ : (void)0 )
+#endif
+
+/*
+ * Simplified macro to send an error system log message using the current LOG_TAG.
+ */
+#ifndef SLOGE
+#define SLOGE(...) ((void)__android_log_buf_print(LOG_ID_SYSTEM, ANDROID_LOG_ERROR, LOG_TAG, __VA_ARGS__))
+#endif
+
+#ifndef SLOGE_IF
+#define SLOGE_IF(cond, ...) \
+ ( (CONDITION(cond)) \
+ ? ((void)__android_log_buf_print(LOG_ID_SYSTEM, ANDROID_LOG_ERROR, LOG_TAG, __VA_ARGS__)) \
+ : (void)0 )
+#endif
+
+
+
// ---------------------------------------------------------------------
/*
@@ -338,6 +423,21 @@
#define android_logToFile(tag, file) (0)
#define android_logToFd(tag, fd) (0)
+typedef enum {
+ LOG_ID_MAIN = 0,
+ LOG_ID_RADIO = 1,
+ LOG_ID_EVENTS = 2,
+ LOG_ID_SYSTEM = 3,
+
+ LOG_ID_MAX
+} log_id_t;
+
+/*
+ * Send a simple string to the log.
+ */
+int __android_log_buf_write(int bufID, int prio, const char *tag, const char *text);
+int __android_log_buf_print(int bufID, int prio, const char *tag, const char *fmt, ...);
+
#ifdef __cplusplus
}
diff --git a/include/cutils/logger.h b/include/cutils/logger.h
index 3a08019..b60f7ad 100644
--- a/include/cutils/logger.h
+++ b/include/cutils/logger.h
@@ -25,6 +25,7 @@
#define LOGGER_LOG_MAIN "log/main"
#define LOGGER_LOG_RADIO "log/radio"
#define LOGGER_LOG_EVENTS "log/events"
+#define LOGGER_LOG_SYSTEM "log/system"
#define LOGGER_ENTRY_MAX_LEN (4*1024)
#define LOGGER_ENTRY_MAX_PAYLOAD \
diff --git a/include/cutils/logprint.h b/include/cutils/logprint.h
index d6ec480..769c8a7 100644
--- a/include/cutils/logprint.h
+++ b/include/cutils/logprint.h
@@ -142,7 +142,7 @@
* Assumes single threaded execution
*
*/
-int android_log_filterAndPrintLogLine(
+int android_log_printLogLine(
AndroidLogFormat *p_format,
int fd,
const AndroidLogEntry *entry);
diff --git a/include/private/android_filesystem_config.h b/include/private/android_filesystem_config.h
index 24b7c81..49fa912 100644
--- a/include/private/android_filesystem_config.h
+++ b/include/private/android_filesystem_config.h
@@ -156,9 +156,10 @@
{ 00550, AID_ROOT, AID_SHELL, "system/etc/init.testmenu" },
{ 00550, AID_DHCP, AID_SHELL, "system/etc/dhcpcd/dhcpcd-run-hooks" },
{ 00440, AID_BLUETOOTH, AID_BLUETOOTH, "system/etc/dbus.conf" },
- { 00440, AID_BLUETOOTH, AID_BLUETOOTH, "system/etc/bluez/main.conf" },
- { 00440, AID_BLUETOOTH, AID_BLUETOOTH, "system/etc/bluez/input.conf" },
- { 00440, AID_BLUETOOTH, AID_BLUETOOTH, "system/etc/bluez/audio.conf" },
+ { 00440, AID_BLUETOOTH, AID_BLUETOOTH, "system/etc/bluetooth/main.conf" },
+ { 00440, AID_BLUETOOTH, AID_BLUETOOTH, "system/etc/bluetooth/input.conf" },
+ { 00440, AID_BLUETOOTH, AID_BLUETOOTH, "system/etc/bluetooth/audio.conf" },
+ { 00640, AID_SYSTEM, AID_SYSTEM, "system/etc/bluetooth/auto_pairing.conf" },
{ 00444, AID_RADIO, AID_AUDIO, "system/etc/AudioPara4.csv" },
{ 00555, AID_ROOT, AID_ROOT, "system/etc/ppp/*" },
{ 00644, AID_SYSTEM, AID_SYSTEM, "data/app/*" },
@@ -167,7 +168,7 @@
/* the following two files are INTENTIONALLY set-gid and not set-uid.
* Do not change. */
{ 02755, AID_ROOT, AID_NET_RAW, "system/bin/ping" },
- { 02755, AID_ROOT, AID_INET, "system/bin/netcfg" },
+ { 02750, AID_ROOT, AID_INET, "system/bin/netcfg" },
/* the following four files are INTENTIONALLY set-uid, but they
* are NOT included on user builds. */
{ 06755, AID_ROOT, AID_ROOT, "system/xbin/su" },
diff --git a/include/sysutils/FrameworkListener.h b/include/sysutils/FrameworkListener.h
index 4e3d396..142f50c 100644
--- a/include/sysutils/FrameworkListener.h
+++ b/include/sysutils/FrameworkListener.h
@@ -23,7 +23,7 @@
class FrameworkListener : public SocketListener {
public:
- static const int CMD_ARGS_MAX = 8;
+ static const int CMD_ARGS_MAX = 16;
private:
FrameworkCommandCollection *mCommands;
diff --git a/init/init.c b/init/init.c
index 16a3530..4d98cc2 100755
--- a/init/init.c
+++ b/init/init.c
@@ -35,6 +35,7 @@
#include <sys/reboot.h>
#include <cutils/sockets.h>
+#include <cutils/iosched_policy.h>
#include <termios.h>
#include <linux/kd.h>
#include <linux/keychord.h>
@@ -224,6 +225,13 @@
}
}
+ if (svc->ioprio_class != IoSchedClass_NONE) {
+ if (android_set_ioprio(getpid(), svc->ioprio_class, svc->ioprio_pri)) {
+ ERROR("Failed to set pid %d ioprio = %d,%d: %s\n",
+ getpid(), svc->ioprio_class, svc->ioprio_pri, strerror(errno));
+ }
+ }
+
if (needs_console) {
setsid();
open_console();
diff --git a/init/init.h b/init/init.h
index 60c3055..8c0571c 100644
--- a/init/init.h
+++ b/init/init.h
@@ -146,6 +146,9 @@
int nkeycodes;
int keychord_id;
+ int ioprio_class;
+ int ioprio_pri;
+
int nargs;
/* "MUST BE AT THE END OF THE STRUCT" */
char *args[1];
diff --git a/init/keywords.h b/init/keywords.h
index 308118e..254c785 100644
--- a/init/keywords.h
+++ b/init/keywords.h
@@ -75,6 +75,7 @@
KEYWORD(chmod, COMMAND, 2, do_chmod)
KEYWORD(loglevel, COMMAND, 1, do_loglevel)
KEYWORD(device, COMMAND, 4, do_device)
+ KEYWORD(ioprio, OPTION, 0, 0)
#ifdef __MAKE_KEYWORD_ENUM__
KEYWORD_COUNT,
};
diff --git a/init/parser.c b/init/parser.c
index 54622cc..7da0d19 100644
--- a/init/parser.c
+++ b/init/parser.c
@@ -10,6 +10,8 @@
#include "init.h"
#include "property_service.h"
+#include <cutils/iosched_policy.h>
+
#define _REALLY_INCLUDE_SYS__SYSTEM_PROPERTIES_H_
#include <sys/_system_properties.h>
@@ -155,6 +157,7 @@
if (!strcmp(s, "ostname")) return K_hostname;
break;
case 'i':
+ if (!strcmp(s, "oprio")) return K_ioprio;
if (!strcmp(s, "fup")) return K_ifup;
if (!strcmp(s, "nsmod")) return K_insmod;
if (!strcmp(s, "mport")) return K_import;
@@ -619,6 +622,8 @@
return;
}
+ svc->ioprio_class = IoSchedClass_NONE;
+
kw = lookup_keyword(args[0]);
switch (kw) {
case K_capability:
@@ -636,6 +641,28 @@
case K_disabled:
svc->flags |= SVC_DISABLED;
break;
+ case K_ioprio:
+ if (nargs != 3) {
+ parse_error(state, "ioprio optin usage: ioprio <rt|be|idle> <ioprio 0-7>\n");
+ } else {
+ svc->ioprio_pri = strtoul(args[2], 0, 8);
+
+ if (svc->ioprio_pri < 0 || svc->ioprio_pri > 7) {
+ parse_error(state, "priority value must be range 0 - 7\n");
+ break;
+ }
+
+ if (!strcmp(args[1], "rt")) {
+ svc->ioprio_class = IoSchedClass_RT;
+ } else if (!strcmp(args[1], "be")) {
+ svc->ioprio_class = IoSchedClass_BE;
+ } else if (!strcmp(args[1], "idle")) {
+ svc->ioprio_class = IoSchedClass_IDLE;
+ } else {
+ parse_error(state, "ioprio option usage: ioprio <rt|be|idle> <0-7>\n");
+ }
+ }
+ break;
case K_group:
if (nargs < 2) {
parse_error(state, "group option requires a group id\n");
diff --git a/libcutils/Android.mk b/libcutils/Android.mk
index 93933e2..4c45cc9 100644
--- a/libcutils/Android.mk
+++ b/libcutils/Android.mk
@@ -38,7 +38,8 @@
process_name.c \
properties.c \
threads.c \
- sched_policy.c
+ sched_policy.c \
+ iosched_policy.c
commonHostSources := \
ashmem-host.c
diff --git a/libcutils/iosched_policy.c b/libcutils/iosched_policy.c
new file mode 100644
index 0000000..f350f58
--- /dev/null
+++ b/libcutils/iosched_policy.c
@@ -0,0 +1,67 @@
+
+/* libs/cutils/iosched_policy.c
+**
+** Copyright 2007, The Android Open Source Project
+**
+** Licensed under the Apache License, Version 2.0 (the "License");
+** you may not use this file except in compliance with the License.
+** You may obtain a copy of the License at
+**
+** http://www.apache.org/licenses/LICENSE-2.0
+**
+** Unless required by applicable law or agreed to in writing, software
+** distributed under the License is distributed on an "AS IS" BASIS,
+** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+** See the License for the specific language governing permissions and
+** limitations under the License.
+*/
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <unistd.h>
+#include <string.h>
+#include <errno.h>
+#include <fcntl.h>
+
+#ifdef HAVE_SCHED_H
+
+#include <cutils/iosched_policy.h>
+
+extern int ioprio_set(int which, int who, int ioprio);
+
+enum {
+ WHO_PROCESS = 1,
+ WHO_PGRP,
+ WHO_USER,
+};
+
+#define CLASS_SHIFT 13
+#define IOPRIO_NORM 4
+
+int android_set_ioprio(int pid, IoSchedClass clazz, int ioprio) {
+#ifdef HAVE_ANDROID_OS
+ if (ioprio_set(WHO_PROCESS, pid, ioprio | (clazz << CLASS_SHIFT))) {
+ return -1;
+ }
+#endif
+ return 0;
+}
+
+int android_get_ioprio(int pid, IoSchedClass *clazz, int *ioprio) {
+#ifdef HAVE_ANDROID_OS
+ int rc;
+
+ if ((rc = ioprio_get(WHO_PROCESS, pid)) < 0) {
+ return -1;
+ }
+
+ *clazz = (rc >> CLASS_SHIFT);
+ *ioprio = (rc & 0xff);
+#else
+ *clazz = IoSchedClass_NONE;
+ *ioprio = 0;
+#endif
+ return 0;
+}
+
+#endif /* HAVE_SCHED_H */
diff --git a/libcutils/sched_policy.c b/libcutils/sched_policy.c
index 8134aa1..2333762 100644
--- a/libcutils/sched_policy.c
+++ b/libcutils/sched_policy.c
@@ -90,8 +90,9 @@
/*
* Try to get the scheduler group.
*
- * The data from /proc/<pid>/cgroup looks like:
+ * The data from /proc/<pid>/cgroup looks (something) like:
* 2:cpu:/bg_non_interactive
+ * 1:cpuacct:/
*
* We return the part after the "/", which will be an empty string for
* the default cgroup. If the string is longer than "bufLen", the string
@@ -101,34 +102,57 @@
{
#ifdef HAVE_ANDROID_OS
char pathBuf[32];
- char readBuf[256];
- ssize_t count;
- int fd;
+ char lineBuf[256];
+ FILE *fp;
snprintf(pathBuf, sizeof(pathBuf), "/proc/%d/cgroup", tid);
- if ((fd = open(pathBuf, O_RDONLY)) < 0) {
+ if (!(fp = fopen(pathBuf, "r"))) {
return -1;
}
- count = read(fd, readBuf, sizeof(readBuf));
- if (count <= 0) {
- close(fd);
- errno = ENODATA;
- return -1;
- }
- close(fd);
+ while(fgets(lineBuf, sizeof(lineBuf) -1, fp)) {
+ char *next = lineBuf;
+ char *subsys;
+ char *grp;
+ size_t len;
- readBuf[--count] = '\0'; /* remove the '\n', now count==strlen */
+ /* Junk the first field */
+ if (!strsep(&next, ":")) {
+ goto out_bad_data;
+ }
- char* cp = strchr(readBuf, '/');
- if (cp == NULL) {
- readBuf[sizeof(readBuf)-1] = '\0';
- errno = ENODATA;
- return -1;
+ if (!(subsys = strsep(&next, ":"))) {
+ goto out_bad_data;
+ }
+
+ if (strcmp(subsys, "cpu")) {
+ /* Not the subsys we're looking for */
+ continue;
+ }
+
+ if (!(grp = strsep(&next, ":"))) {
+ goto out_bad_data;
+ }
+ grp++; /* Drop the leading '/' */
+ len = strlen(grp);
+ grp[len-1] = '\0'; /* Drop the trailing '\n' */
+
+ if (bufLen <= len) {
+ len = bufLen - 1;
+ }
+ strncpy(buf, grp, len);
+ buf[len] = '\0';
+ fclose(fp);
+ return 0;
}
- memcpy(buf, cp+1, count); /* count-1 for cp+1, count+1 for NUL */
- return 0;
+ LOGE("Failed to find cpu subsys");
+ fclose(fp);
+ return -1;
+ out_bad_data:
+ LOGE("Bad cgroup data {%s}", lineBuf);
+ fclose(fp);
+ return -1;
#else
errno = ENOSYS;
return -1;
diff --git a/liblog/logd_write.c b/liblog/logd_write.c
index 241dbf0..9923bba 100644
--- a/liblog/logd_write.c
+++ b/liblog/logd_write.c
@@ -27,6 +27,7 @@
#include <cutils/logger.h>
#include <cutils/logd.h>
+#include <cutils/log.h>
#define LOG_BUF_SIZE 1024
@@ -41,21 +42,13 @@
#define log_close(filedes) close(filedes)
#endif
-typedef enum {
- LOG_ID_MAIN = 0,
- LOG_ID_RADIO,
- LOG_ID_EVENTS,
- LOG_ID_MAX
-} log_id_t;
-
static int __write_to_log_init(log_id_t, struct iovec *vec, size_t nr);
-static int (*write_to_log)(log_id_t, struct iovec *vec, size_t nr) =
- __write_to_log_init;
+static int (*write_to_log)(log_id_t, struct iovec *vec, size_t nr) = __write_to_log_init;
#ifdef HAVE_PTHREADS
static pthread_mutex_t log_init_lock = PTHREAD_MUTEX_INITIALIZER;
#endif
-static int log_fds[(int)LOG_ID_MAX] = { -1, -1, -1 };
+static int log_fds[(int)LOG_ID_MAX] = { -1, -1, -1, -1 };
/*
* This is used by the C++ code to decide if it should write logs through
@@ -110,6 +103,7 @@
log_fds[LOG_ID_MAIN] = log_open("/dev/"LOGGER_LOG_MAIN, O_WRONLY);
log_fds[LOG_ID_RADIO] = log_open("/dev/"LOGGER_LOG_RADIO, O_WRONLY);
log_fds[LOG_ID_EVENTS] = log_open("/dev/"LOGGER_LOG_EVENTS, O_WRONLY);
+ log_fds[LOG_ID_SYSTEM] = log_open("/dev/"LOGGER_LOG_SYSTEM, O_WRONLY);
write_to_log = __write_to_log_kernel;
@@ -123,6 +117,10 @@
log_fds[LOG_ID_EVENTS] = -1;
write_to_log = __write_to_log_null;
}
+
+ if (log_fds[LOG_ID_SYSTEM] < 0) {
+ log_fds[LOG_ID_SYSTEM] = log_fds[LOG_ID_MAIN];
+ }
}
#ifdef HAVE_PTHREADS
@@ -161,6 +159,34 @@
return write_to_log(log_id, vec, 3);
}
+int __android_log_buf_write(int bufID, int prio, const char *tag, const char *msg)
+{
+ struct iovec vec[3];
+
+ if (!tag)
+ tag = "";
+
+ /* XXX: This needs to go! */
+ if (!strcmp(tag, "HTC_RIL") ||
+ !strncmp(tag, "RIL", 3) || /* Any log tag with "RIL" as the prefix */
+ !strcmp(tag, "AT") ||
+ !strcmp(tag, "GSM") ||
+ !strcmp(tag, "STK") ||
+ !strcmp(tag, "CDMA") ||
+ !strcmp(tag, "PHONE") ||
+ !strcmp(tag, "SMS"))
+ bufID = LOG_ID_RADIO;
+
+ vec[0].iov_base = (unsigned char *) &prio;
+ vec[0].iov_len = 1;
+ vec[1].iov_base = (void *) tag;
+ vec[1].iov_len = strlen(tag) + 1;
+ vec[2].iov_base = (void *) msg;
+ vec[2].iov_len = strlen(msg) + 1;
+
+ return write_to_log(bufID, vec, 3);
+}
+
int __android_log_vprint(int prio, const char *tag, const char *fmt, va_list ap)
{
char buf[LOG_BUF_SIZE];
@@ -173,7 +199,7 @@
int __android_log_print(int prio, const char *tag, const char *fmt, ...)
{
va_list ap;
- char buf[LOG_BUF_SIZE];
+ char buf[LOG_BUF_SIZE];
va_start(ap, fmt);
vsnprintf(buf, LOG_BUF_SIZE, fmt, ap);
@@ -182,6 +208,18 @@
return __android_log_write(prio, tag, buf);
}
+int __android_log_buf_print(int bufID, int prio, const char *tag, const char *fmt, ...)
+{
+ va_list ap;
+ char buf[LOG_BUF_SIZE];
+
+ va_start(ap, fmt);
+ vsnprintf(buf, LOG_BUF_SIZE, fmt, ap);
+ va_end(ap);
+
+ return __android_log_buf_write(bufID, prio, tag, buf);
+}
+
void __android_log_assert(const char *cond, const char *tag,
const char *fmt, ...)
{
diff --git a/liblog/logprint.c b/liblog/logprint.c
index 080f9e3..4c5b3e5 100644
--- a/liblog/logprint.c
+++ b/liblog/logprint.c
@@ -753,6 +753,16 @@
suffixLen = 1;
break;
}
+ /* snprintf has a weird return value. It returns what would have been
+ * written given a large enough buffer. In the case that the prefix is
+ * longer then our buffer(128), it messes up the calculations below
+ * possibly causing heap corruption. To avoid this we double check and
+ * set the length at the maximum (size minus null byte)
+ */
+ if(prefixLen >= sizeof(prefixBuf))
+ prefixLen = sizeof(prefixBuf) - 1;
+ if(suffixLen >= sizeof(suffixBuf))
+ suffixLen = sizeof(suffixBuf) - 1;
/* the following code is tragically unreadable */
@@ -840,7 +850,7 @@
* Returns count bytes written
*/
-int android_log_filterAndPrintLogLine(
+int android_log_printLogLine(
AndroidLogFormat *p_format,
int fd,
const AndroidLogEntry *entry)
@@ -850,11 +860,6 @@
char *outBuffer = NULL;
size_t totalLen;
- if (0 == android_log_shouldPrintLine(p_format, entry->tag,
- entry->priority)) {
- return 0;
- }
-
outBuffer = android_log_formatLogLine(p_format, defaultBuffer,
sizeof(defaultBuffer), entry, &totalLen);
diff --git a/logcat/event.logtags b/logcat/event.logtags
index 1b38f4c..5e6c256 100644
--- a/logcat/event.logtags
+++ b/logcat/event.logtags
@@ -111,8 +111,6 @@
75003 sqlite_mem_released (Memory released|1|2)
75004 sqlite_db_corrupt (Database file corrupt|3)
-40000 checkin (Check in time|2|3)
-
50000 menu_item_selected (Menu type where 0 is options and 1 is context|1|5),(Menu item title|3)
50001 menu_opened (Menu type where 0 is options and 1 is context|1|5)
diff --git a/logcat/logcat.cpp b/logcat/logcat.cpp
index 3130a1c..670408c 100644
--- a/logcat/logcat.cpp
+++ b/logcat/logcat.cpp
@@ -24,12 +24,64 @@
#define DEFAULT_MAX_ROTATED_LOGS 4
static AndroidLogFormat * g_logformat;
+static bool g_nonblock = false;
/* logd prefixes records with a length field */
#define RECORD_LENGTH_FIELD_SIZE_BYTES sizeof(uint32_t)
#define LOG_FILE_DIR "/dev/log/"
+struct queued_entry_t {
+ union {
+ unsigned char buf[LOGGER_ENTRY_MAX_LEN + 1] __attribute__((aligned(4)));
+ struct logger_entry entry __attribute__((aligned(4)));
+ };
+ queued_entry_t* next;
+
+ queued_entry_t() {
+ next = NULL;
+ }
+};
+
+static int cmp(queued_entry_t* a, queued_entry_t* b) {
+ int n = a->entry.sec - b->entry.sec;
+ if (n != 0) {
+ return n;
+ }
+ return a->entry.nsec - b->entry.nsec;
+}
+
+struct log_device_t {
+ char* device;
+ bool binary;
+ int fd;
+ bool printed;
+ char label;
+
+ queued_entry_t* queue;
+ log_device_t* next;
+
+ log_device_t(char* d, bool b, char l) {
+ device = d;
+ binary = b;
+ label = l;
+ next = NULL;
+ printed = false;
+ }
+
+ void enqueue(queued_entry_t* entry) {
+ if (this->queue == NULL) {
+ this->queue = entry;
+ } else {
+ queued_entry_t** e = &this->queue;
+ while (*e && cmp(entry, *e) >= 0) {
+ e = &((*e)->next);
+ }
+ entry->next = *e;
+ *e = entry;
+ }
+ }
+};
namespace android {
@@ -40,8 +92,8 @@
static int g_maxRotatedLogs = DEFAULT_MAX_ROTATED_LOGS; // 0 means "unbounded"
static int g_outFD = -1;
static off_t g_outByteCount = 0;
-static int g_isBinary = 0;
static int g_printBinary = 0;
+static int g_devCount = 0;
static EventTagMap* g_eventTagMap = NULL;
@@ -103,14 +155,27 @@
} while (ret < 0 && errno == EINTR);
}
-static void processBuffer(struct logger_entry *buf)
+static void processBuffer(log_device_t* dev, struct logger_entry *buf)
{
int bytesWritten;
int err;
AndroidLogEntry entry;
char binaryMsgBuf[1024];
- if (g_isBinary) {
+ if (!dev->printed) {
+ dev->printed = true;
+ if (g_devCount > 1) {
+ snprintf(binaryMsgBuf, sizeof(binaryMsgBuf), "--------- beginning of %s\n",
+ dev->device);
+ bytesWritten = write(g_outFD, binaryMsgBuf, strlen(binaryMsgBuf));
+ if (bytesWritten < 0) {
+ perror("output error");
+ exit(-1);
+ }
+ }
+ }
+
+ if (dev->binary) {
err = android_log_processBinaryLogBuffer(buf, &entry, g_eventTagMap,
binaryMsgBuf, sizeof(binaryMsgBuf));
//printf(">>> pri=%d len=%d msg='%s'\n",
@@ -118,15 +183,27 @@
} else {
err = android_log_processLogBuffer(buf, &entry);
}
- if (err < 0)
+ if (err < 0) {
goto error;
+ }
- bytesWritten = android_log_filterAndPrintLogLine(
- g_logformat, g_outFD, &entry);
+ if (android_log_shouldPrintLine(g_logformat, entry.tag, entry.priority)) {
+ if (false && g_devCount > 1) {
+ binaryMsgBuf[0] = dev->label;
+ binaryMsgBuf[1] = ' ';
+ bytesWritten = write(g_outFD, binaryMsgBuf, 2);
+ if (bytesWritten < 0) {
+ perror("output error");
+ exit(-1);
+ }
+ }
- if (bytesWritten < 0) {
- perror("output error");
- exit(-1);
+ bytesWritten = android_log_printLogLine(g_logformat, g_outFD, &entry);
+
+ if (bytesWritten < 0) {
+ perror("output error");
+ exit(-1);
+ }
}
g_outByteCount += bytesWritten;
@@ -142,36 +219,129 @@
return;
}
-static void readLogLines(int logfd)
+static void chooseFirst(log_device_t* dev, log_device_t** firstdev, queued_entry_t** firstentry) {
+ *firstdev = NULL;
+ *firstentry = NULL;
+ int i=0;
+ for (; dev; dev=dev->next) {
+ i++;
+ if (dev->queue) {
+ if ((*firstentry) == NULL || cmp(dev->queue, *firstentry) < 0) {
+ (*firstentry) = dev->queue;
+ *firstdev = dev;
+ }
+ }
+ }
+}
+
+static void printEntry(log_device_t* dev, queued_entry_t* entry) {
+ if (g_printBinary) {
+ printBinary(&entry->entry);
+ } else {
+ processBuffer(dev, &entry->entry);
+ }
+}
+
+static void eatEntry(log_device_t* dev, queued_entry_t* entry) {
+ if (dev->queue != entry) {
+ perror("assertion failed: entry isn't first in queue");
+ exit(1);
+ }
+ printEntry(dev, entry);
+ dev->queue = entry->next;
+ delete entry;
+}
+
+static void readLogLines(log_device_t* devices)
{
+ log_device_t* dev;
+ int max = 0;
+ queued_entry_t* entry;
+ queued_entry_t* old;
+ int ret;
+ bool somethingForEveryone;
+ bool sleep = true;
+
+ int result;
+ fd_set readset;
+
+ for (dev=devices; dev; dev = dev->next) {
+ if (dev->fd > max) {
+ max = dev->fd;
+ }
+ }
+
while (1) {
- unsigned char buf[LOGGER_ENTRY_MAX_LEN + 1] __attribute__((aligned(4)));
- struct logger_entry *entry = (struct logger_entry *) buf;
- int ret;
+ do {
+ timeval timeout = { 0, 5000 /* 5ms */ }; // If we oversleep it's ok, i.e. ignore EINTR.
+ FD_ZERO(&readset);
+ for (dev=devices; dev; dev = dev->next) {
+ FD_SET(dev->fd, &readset);
+ }
+ result = select(max + 1, &readset, NULL, NULL, sleep ? NULL : &timeout);
+ } while (result == -1 && errno == EINTR);
- ret = read(logfd, entry, LOGGER_ENTRY_MAX_LEN);
- if (ret < 0) {
- if (errno == EINTR)
- continue;
- if (errno == EAGAIN)
- break;
- perror("logcat read");
- exit(EXIT_FAILURE);
+ if (result >= 0) {
+ for (dev=devices; dev; dev = dev->next) {
+ if (FD_ISSET(dev->fd, &readset)) {
+ entry = new queued_entry_t;
+ /* NOTE: driver guarantees we read exactly one full entry */
+ ret = read(dev->fd, entry->buf, LOGGER_ENTRY_MAX_LEN);
+ if (ret < 0) {
+ if (errno == EINTR) {
+ delete entry;
+ goto next;
+ }
+ if (errno == EAGAIN) {
+ delete entry;
+ break;
+ }
+ perror("logcat read");
+ exit(EXIT_FAILURE);
+ }
+ else if (!ret) {
+ fprintf(stderr, "read: Unexpected EOF!\n");
+ exit(EXIT_FAILURE);
+ }
+
+ entry->entry.msg[entry->entry.len] = '\0';
+
+ dev->enqueue(entry);
+ }
+ }
+
+ if (result == 0) {
+ // we did our short timeout trick and there's nothing new
+ // print all that aren't the last in their list
+ sleep = true;
+ while (true) {
+ chooseFirst(devices, &dev, &entry);
+ if (!entry) {
+ break;
+ }
+ eatEntry(dev, entry);
+ }
+ // They requested to just dump the log
+ if (g_nonblock) {
+ exit(0);
+ }
+ } else {
+ // print all that aren't the last in their list
+ while (true) {
+ chooseFirst(devices, &dev, &entry);
+ if (!entry) {
+ sleep = false;
+ break;
+ } else if (entry->next == NULL) {
+ sleep = false;
+ break;
+ }
+ eatEntry(dev, entry);
+ }
+ }
}
- else if (!ret) {
- fprintf(stderr, "read: Unexpected EOF!\n");
- exit(EXIT_FAILURE);
- }
-
- /* NOTE: driver guarantees we read exactly one full entry */
-
- entry->msg[entry->len] = '\0';
-
- if (g_printBinary) {
- printBinary(entry);
- } else {
- (void) processBuffer(entry);
- }
+next:
+ ;
}
}
@@ -275,16 +445,17 @@
extern "C" void logprint_run_tests(void);
-int main (int argc, char **argv)
+int main(int argc, char **argv)
{
- int logfd;
int err;
int hasSetLogFormat = 0;
int clearLog = 0;
int getLogSize = 0;
int mode = O_RDONLY;
- char *log_device = strdup("/dev/"LOGGER_LOG_MAIN);
const char *forceFilters = NULL;
+ log_device_t* devices = NULL;
+ log_device_t* dev;
+ bool needBinary = false;
g_logformat = android_log_format_new();
@@ -319,21 +490,34 @@
break;
case 'd':
- mode |= O_NONBLOCK;
+ g_nonblock = true;
break;
case 'g':
getLogSize = 1;
break;
- case 'b':
- free(log_device);
- log_device =
- (char*) malloc(strlen(LOG_FILE_DIR) + strlen(optarg) + 1);
- strcpy(log_device, LOG_FILE_DIR);
- strcat(log_device, optarg);
+ case 'b': {
+ char* buf = (char*) malloc(strlen(LOG_FILE_DIR) + strlen(optarg) + 1);
+ strcpy(buf, LOG_FILE_DIR);
+ strcat(buf, optarg);
- android::g_isBinary = (strcmp(optarg, "events") == 0);
+ bool binary = strcmp(optarg, "events") == 0;
+ if (binary) {
+ needBinary = true;
+ }
+
+ if (devices) {
+ dev = devices;
+ while (dev->next) {
+ dev = dev->next;
+ }
+ dev->next = new log_device_t(buf, binary, optarg[0]);
+ } else {
+ devices = new log_device_t(buf, binary, optarg[0]);
+ }
+ android::g_devCount++;
+ }
break;
case 'B':
@@ -460,6 +644,19 @@
}
}
+ if (!devices) {
+ devices = new log_device_t(strdup("/dev/"LOGGER_LOG_MAIN), false, 'm');
+ android::g_devCount = 1;
+ int accessmode =
+ (mode & O_RDONLY) ? R_OK : 0
+ | (mode & O_WRONLY) ? W_OK : 0;
+ // only add this if it's available
+ if (0 == access("/dev/"LOGGER_LOG_SYSTEM, accessmode)) {
+ devices->next = new log_device_t(strdup("/dev/"LOGGER_LOG_SYSTEM), false, 's');
+ android::g_devCount++;
+ }
+ }
+
if (android::g_logRotateSizeKBytes != 0
&& android::g_outputFileName == NULL
) {
@@ -516,42 +713,52 @@
}
}
- logfd = open(log_device, mode);
- if (logfd < 0) {
- fprintf(stderr, "Unable to open log device '%s': %s\n",
- log_device, strerror(errno));
- exit(EXIT_FAILURE);
- }
-
- if (clearLog) {
- int ret;
- ret = android::clearLog(logfd);
- if (ret) {
- perror("ioctl");
+ dev = devices;
+ while (dev) {
+ dev->fd = open(dev->device, mode);
+ if (dev->fd < 0) {
+ fprintf(stderr, "Unable to open log device '%s': %s\n",
+ dev->device, strerror(errno));
exit(EXIT_FAILURE);
}
- return 0;
+
+ if (clearLog) {
+ int ret;
+ ret = android::clearLog(dev->fd);
+ if (ret) {
+ perror("ioctl");
+ exit(EXIT_FAILURE);
+ }
+ }
+
+ if (getLogSize) {
+ int size, readable;
+
+ size = android::getLogSize(dev->fd);
+ if (size < 0) {
+ perror("ioctl");
+ exit(EXIT_FAILURE);
+ }
+
+ readable = android::getLogReadableSize(dev->fd);
+ if (readable < 0) {
+ perror("ioctl");
+ exit(EXIT_FAILURE);
+ }
+
+ printf("%s: ring buffer is %dKb (%dKb consumed), "
+ "max entry is %db, max payload is %db\n", dev->device,
+ size / 1024, readable / 1024,
+ (int) LOGGER_ENTRY_MAX_LEN, (int) LOGGER_ENTRY_MAX_PAYLOAD);
+ }
+
+ dev = dev->next;
}
if (getLogSize) {
- int size, readable;
-
- size = android::getLogSize(logfd);
- if (size < 0) {
- perror("ioctl");
- exit(EXIT_FAILURE);
- }
-
- readable = android::getLogReadableSize(logfd);
- if (readable < 0) {
- perror("ioctl");
- exit(EXIT_FAILURE);
- }
-
- printf("ring buffer is %dKb (%dKb consumed), "
- "max entry is %db, max payload is %db\n",
- size / 1024, readable / 1024,
- (int) LOGGER_ENTRY_MAX_LEN, (int) LOGGER_ENTRY_MAX_PAYLOAD);
+ return 0;
+ }
+ if (clearLog) {
return 0;
}
@@ -559,10 +766,10 @@
//LOG_EVENT_LONG(11, 0x1122334455667788LL);
//LOG_EVENT_STRING(0, "whassup, doc?");
- if (android::g_isBinary)
+ if (needBinary)
android::g_eventTagMap = android_openEventTagMap(EVENT_TAG_MAP_FILE);
- android::readLogLines(logfd);
+ android::readLogLines(devices);
return 0;
}
diff --git a/rootdir/init.rc b/rootdir/init.rc
index 0e52e54..4a67011 100644
--- a/rootdir/init.rc
+++ b/rootdir/init.rc
@@ -24,6 +24,11 @@
mkdir /mnt 0775 root system
mkdir /mnt/sdcard 0000 system system
+# Create cgroup mount point for cpu accounting
+ mkdir /acct
+ mount cgroup none /acct cpuacct
+ mkdir /acct/uid
+
# Backwards Compat - XXX: Going away in G*
symlink /mnt/sdcard /sdcard
@@ -120,6 +125,7 @@
# create basic filesystem structure
mkdir /data/misc 01771 system misc
mkdir /data/misc/bluetoothd 0770 bluetooth bluetooth
+ mkdir /data/misc/bluetooth 0770 system system
mkdir /data/misc/keystore 0700 keystore keystore
mkdir /data/misc/vpn 0770 system system
mkdir /data/misc/systemkeys 0700 system system
@@ -280,6 +286,7 @@
service vold /system/bin/vold
socket vold stream 0660 root mount
+ ioprio be 2
service netd /system/bin/netd
socket netd stream 0660 root system
@@ -301,6 +308,7 @@
service media /system/bin/mediaserver
user media
group system audio camera graphics inet net_bt net_bt_admin
+ ioprio rt 4
service bootanim /system/bin/bootanimation
user graphics
diff --git a/toolbox/Android.mk b/toolbox/Android.mk
index 122a544..a6114ac 100644
--- a/toolbox/Android.mk
+++ b/toolbox/Android.mk
@@ -51,7 +51,8 @@
iftop \
id \
vmstat \
- nandread
+ nandread \
+ ionice
LOCAL_SRC_FILES:= \
toolbox.c \
diff --git a/toolbox/ionice.c b/toolbox/ionice.c
new file mode 100644
index 0000000..4a182f2
--- /dev/null
+++ b/toolbox/ionice.c
@@ -0,0 +1,57 @@
+#include <stdio.h>
+#include <stdlib.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/nandread.c b/toolbox/nandread.c
index aacccdb..9644973 100644
--- a/toolbox/nandread.c
+++ b/toolbox/nandread.c
@@ -8,7 +8,7 @@
#include <mtd/mtd-user.h>
#include <sys/ioctl.h>
-int test_empty(const char *buf, size_t size)
+static int test_empty(const char *buf, size_t size)
{
while(size--) {
if (*buf++ != 0xff)
@@ -29,12 +29,14 @@
int ret;
int verbose = 0;
void *buffer;
- loff_t pos, opos;
+ loff_t pos, opos, end, bpos;
+ loff_t start = 0, len = 0;
int c;
int i;
int empty_pages = 0;
int page_count = 0;
int bad_block;
+ int rawmode = 0;
uint32_t *oob_data;
uint8_t *oob_fixed;
size_t spare_size = 64;
@@ -44,7 +46,7 @@
struct nand_ecclayout ecclayout;
do {
- c = getopt(argc, argv, "d:f:s:hv");
+ c = getopt(argc, argv, "d:f:s:S:L:Rhv");
if (c == EOF)
break;
switch (c) {
@@ -57,6 +59,15 @@
case 's':
spare_size = atoi(optarg);
break;
+ case 'S':
+ start = strtoll(optarg, NULL, 0);
+ break;
+ case 'L':
+ len = strtoll(optarg, NULL, 0);
+ break;
+ case 'R':
+ rawmode = 1;
+ break;
case 'v':
verbose++;
break;
@@ -65,6 +76,9 @@
" -d <dev> Read from <dev>\n"
" -f <file> Write to <file>\n"
" -s <size> Number of spare bytes in file (default 64)\n"
+ " -R Raw mode\n"
+ " -S <start> Start offset (default 0)\n"
+ " -L <len> Length (default 0)\n"
" -v Print info\n"
" -h Print help\n", argv[0]);
return -1;
@@ -129,7 +143,7 @@
oobbuf.length = mtdinfo.oobsize;
oob_data = (uint32_t *)((uint8_t *)buffer + mtdinfo.writesize);
- memset(oob_data, 0xff, spare_size);
+ memset(oob_data, 0xff, mtdinfo.oobsize + spare_size);
oobbuf.ptr = (uint8_t *)oob_data + spare_size;
ret = ioctl(fd, ECCGETLAYOUT, &ecclayout);
@@ -160,21 +174,34 @@
printf("initial ecc bbtblocks: %u\n", initial_ecc.bbtblocks);
}
- for (pos = 0, opos = 0; pos < mtdinfo.size; pos += mtdinfo.writesize) {
+ if (rawmode) {
+ rawmode = mtdinfo.oobsize;
+ ret = ioctl(fd, MTDFILEMODE, MTD_MODE_RAW);
+ if (ret) {
+ fprintf(stderr, "failed set raw mode for %s, %s\n",
+ devname, strerror(errno));
+ return 1;
+ }
+ }
+
+ end = len ? (start + len) : mtdinfo.size;
+ for (pos = start, opos = 0; pos < end; pos += mtdinfo.writesize) {
bad_block = 0;
if (verbose > 3)
printf("reading at %llx\n", pos);
lseek64(fd, pos, SEEK_SET);
- ret = read(fd, buffer, mtdinfo.writesize);
+ ret = read(fd, buffer, mtdinfo.writesize + rawmode);
if (ret < (int)mtdinfo.writesize) {
fprintf(stderr, "short read at %llx, %d\n", pos, ret);
bad_block = 2;
}
- oobbuf.start = pos;
- ret = ioctl(fd, MEMREADOOB, &oobbuf);
- if (ret) {
- fprintf(stderr, "failed to read oob data at %llx, %d\n", pos, ret);
- bad_block = 2;
+ if (!rawmode) {
+ oobbuf.start = pos;
+ ret = ioctl(fd, MEMREADOOB, &oobbuf);
+ if (ret) {
+ fprintf(stderr, "failed to read oob data at %llx, %d\n", pos, ret);
+ bad_block = 2;
+ }
}
ret = ioctl(fd, ECCGETSTATS, &ecc);
if (ret) {
@@ -182,7 +209,8 @@
devname, strerror(errno));
return 1;
}
- ret = ioctl(fd, MEMGETBADBLOCK, &pos);
+ bpos = pos / mtdinfo.erasesize * mtdinfo.erasesize;
+ ret = ioctl(fd, MEMGETBADBLOCK, &bpos);
if (ret && errno != EOPNOTSUPP) {
printf("badblock at %llx\n", pos);
bad_block = 1;
@@ -196,14 +224,16 @@
if (ecc.bbtblocks != last_ecc.bbtblocks)
printf("ecc bbtblocks, %u, at %llx\n", ecc.bbtblocks - last_ecc.bbtblocks, pos);
- oob_fixed = (uint8_t *)oob_data;
- for (i = 0; i < MTD_MAX_OOBFREE_ENTRIES; i++) {
- int len = ecclayout.oobfree[i].length;
- if (oob_fixed + len > oobbuf.ptr)
- len = oobbuf.ptr - oob_fixed;
- if (len) {
- memcpy(oob_fixed, oobbuf.ptr + ecclayout.oobfree[i].offset, len);
- oob_fixed += len;
+ if (!rawmode) {
+ oob_fixed = (uint8_t *)oob_data;
+ for (i = 0; i < MTD_MAX_OOBFREE_ENTRIES; i++) {
+ int len = ecclayout.oobfree[i].length;
+ if (oob_fixed + len > oobbuf.ptr)
+ len = oobbuf.ptr - oob_fixed;
+ if (len) {
+ memcpy(oob_fixed, oobbuf.ptr + ecclayout.oobfree[i].offset, len);
+ oob_fixed += len;
+ }
}
}
diff --git a/toolbox/newfs_msdos.c b/toolbox/newfs_msdos.c
index 8e611c6..ff9e844 100644
--- a/toolbox/newfs_msdos.c
+++ b/toolbox/newfs_msdos.c
@@ -414,11 +414,14 @@
if (!(opt_f || (opt_h && opt_u && opt_S && opt_s && oflag))) {
off_t delta;
getdiskinfo(fd, fname, dtype, oflag, &bpb);
+ if (opt_s) {
+ bpb.bsec = opt_s;
+ }
bpb.bsec -= (opt_ofs / bpb.bps);
delta = bpb.bsec % bpb.spt;
if (delta != 0) {
- warnx("trim %d sectors to adjust to a multiple of %d",
- (int)delta, bpb.spt);
+ warnx("trim %d sectors from %d to adjust to a multiple of %d",
+ (int)delta, bpb.bsec, bpb.spt);
bpb.bsec -= delta;
}
if (bpb.spc == 0) { /* set defaults */