Merge "Add drmrpc group to mediaserver and drmserver so they can make the drm rpc calls"
diff --git a/adb/commandline.c b/adb/commandline.c
index 75f337b..4c15232 100644
--- a/adb/commandline.c
+++ b/adb/commandline.c
@@ -129,18 +129,22 @@
" adb bugreport - return all information from the device\n"
" that should be included in a bug report.\n"
"\n"
- " adb backup [-f <file>] [-apk|-noapk] [-shared|-noshared] [-all] [<packages...>]\n"
- " - Write an archive of the device's data to <file>.\n"
- " If a -f option is not supplied then the data is\n"
- " written to \"backup.ab\" in the current directory.\n"
+ " adb backup [-f <file>] [-apk|-noapk] [-shared|-noshared] [-all] [-system|-nosystem] [<packages...>]\n"
+ " - write an archive of the device's data to <file>.\n"
+ " If no -f option is supplied then the data is written\n"
+ " to \"backup.ab\" in the current directory.\n"
" (-apk|-noapk enable/disable backup of the .apks themselves\n"
" in the archive; the default is noapk.)\n"
" (-shared|-noshared enable/disable backup of the device's\n"
" shared storage / SD card contents; the default is noshared.)\n"
" (-all means to back up all installed applications)\n"
+ " (-system|-nosystem toggles whether -all automatically includes\n"
+ " system applications; the default is to include system apps)\n"
" (<packages...> is the list of applications to be backed up. If\n"
" the -all or -shared flags are passed, then the package\n"
- " list is optional.)\n"
+ " list is optional. Applications explicitly given on the\n"
+ " command line will be included even if -nosystem would\n"
+ " ordinarily cause them to be omitted.)\n"
"\n"
" adb restore <file> - restore device contents from the <file> backup archive\n"
"\n"
@@ -1419,16 +1423,19 @@
if (*argv[i] != '-') {
file_arg = i;
break;
+ } else if (!strcmp(argv[i], "-i")) {
+ // Skip the installer package name.
+ i++;
} else if (!strcmp(argv[i], "-s")) {
where = SD_DEST;
}
}
if (file_arg < 0) {
- fprintf(stderr, "can't find filename in arguments");
+ fprintf(stderr, "can't find filename in arguments\n");
return 1;
} else if (file_arg + 2 < argc) {
- fprintf(stderr, "too many files specified; only takes APK file and verifier file");
+ fprintf(stderr, "too many files specified; only takes APK file and verifier file\n");
return 1;
}
diff --git a/charger/Android.mk b/charger/Android.mk
index 75e78d5..5367a98 100644
--- a/charger/Android.mk
+++ b/charger/Android.mk
@@ -1,5 +1,7 @@
# Copyright 2011 The Android Open Source Project
+ifneq ($(BUILD_TINY_ANDROID),true)
+
LOCAL_PATH := $(call my-dir)
include $(CLEAR_VARS)
@@ -18,3 +20,31 @@
LOCAL_STATIC_LIBRARIES += libz libstdc++ libcutils libc
include $(BUILD_EXECUTABLE)
+
+define _add-charger-image
+include $$(CLEAR_VARS)
+LOCAL_MODULE := system_core_charger_$(notdir $(1))
+LOCAL_MODULE_STEM := $(notdir $(1))
+_img_modules += $$(LOCAL_MODULE)
+LOCAL_SRC_FILES := $1
+LOCAL_MODULE_TAGS := optional
+LOCAL_MODULE_CLASS := ETC
+LOCAL_MODULE_PATH := $$(TARGET_ROOT_OUT)/res/images/charger
+include $$(BUILD_PREBUILT)
+endef
+
+_img_modules :=
+_images :=
+$(foreach _img, $(call find-subdir-subdir-files, "images", "*.png"), \
+ $(eval $(call _add-charger-image,$(_img))))
+
+include $(CLEAR_VARS)
+LOCAL_MODULE := charger_res_images
+LOCAL_MODULE_TAGS := optional
+LOCAL_REQUIRED_MODULES := $(_img_modules)
+include $(BUILD_PHONY_PACKAGE)
+
+_add-charger-image :=
+_img_modules :=
+
+endif
diff --git a/charger/charger.c b/charger/charger.c
index 9320e8a..d3b414d 100644
--- a/charger/charger.c
+++ b/charger/charger.c
@@ -37,6 +37,7 @@
#include <cutils/android_reboot.h>
#include <cutils/klog.h>
#include <cutils/list.h>
+#include <cutils/misc.h>
#include <cutils/uevent.h>
#include "minui/minui.h"
@@ -49,13 +50,20 @@
#define min(a,b) ((a) < (b) ? (a) : (b))
#endif
+#define ARRAY_SIZE(x) (sizeof(x)/sizeof(x[0]))
+
#define MSEC_PER_SEC (1000LL)
#define NSEC_PER_MSEC (1000000LL)
-#define SCREEN_ON_TIME (5 * MSEC_PER_SEC)
+#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 BATTERY_FULL_THRESH 95
+
+#define LAST_KMSG_PATH "/proc/last_kmsg"
+#define LAST_KMSG_MAX_SZ (32 * 1024)
+
#define LOGE(x...) do { KLOG_ERROR("charger", x); } while (0)
#define LOGI(x...) do { KLOG_INFO("charger", x); } while (0)
#define LOGV(x...) do { KLOG_DEBUG("charger", x); } while (0)
@@ -72,22 +80,46 @@
char type[32];
bool online;
bool valid;
+ char cap_path[PATH_MAX];
+};
+
+struct frame {
+ const char *name;
+ int disp_time;
+ int min_capacity;
+
+ gr_surface surface;
+};
+
+struct animation {
+ bool run;
+
+ struct frame *frames;
+ int cur_frame;
+ int num_frames;
+
+ int cur_cycle;
+ int num_cycles;
+
+ /* current capacity being animated */
+ int capacity;
};
struct charger {
int64_t next_screen_transition;
int64_t next_key_check;
int64_t next_pwr_check;
- bool screen_on;
struct key_state keys[KEY_MAX + 1];
- gr_surface surf_charging;
int uevent_fd;
struct listnode supplies;
int num_supplies;
int num_supplies_online;
+ struct animation *batt_anim;
+ gr_surface surf_unknown;
+
struct power_supply *battery;
};
@@ -100,11 +132,52 @@
const char *ps_online;
};
+static struct frame batt_anim_frames[] = {
+ {
+ .name = "charger/battery_0",
+ .disp_time = 750,
+ .min_capacity = 0,
+ },
+ {
+ .name = "charger/battery_1",
+ .disp_time = 750,
+ .min_capacity = 20,
+ },
+ {
+ .name = "charger/battery_2",
+ .disp_time = 750,
+ .min_capacity = 40,
+ },
+ {
+ .name = "charger/battery_3",
+ .disp_time = 750,
+ .min_capacity = 60,
+ },
+ {
+ .name = "charger/battery_4",
+ .disp_time = 750,
+ .min_capacity = 80,
+ },
+ {
+ .name = "charger/battery_5",
+ .disp_time = 750,
+ .min_capacity = BATTERY_FULL_THRESH,
+ },
+};
+
+static struct animation battery_animation = {
+ .frames = batt_anim_frames,
+ .num_frames = ARRAY_SIZE(batt_anim_frames),
+ .num_cycles = 3,
+};
+
+static struct charger charger_state = {
+ .batt_anim = &battery_animation,
+};
+
static int char_width;
static int char_height;
-struct charger charger_state;
-
/* current time in milliseconds */
static int64_t curr_time_ms(void)
{
@@ -119,6 +192,53 @@
gr_fill(0, 0, gr_fb_width(), gr_fb_height());
};
+#define MAX_KLOG_WRITE_BUF_SZ 256
+
+static void dump_last_kmsg(void)
+{
+ char *buf;
+ char *ptr;
+ unsigned sz = 0;
+ int len;
+
+ LOGI("\n");
+ LOGI("*************** LAST KMSG ***************\n");
+ LOGI("\n");
+ buf = load_file(LAST_KMSG_PATH, &sz);
+ if (!buf || !sz) {
+ LOGI("last_kmsg not found. Cold reset?\n");
+ goto out;
+ }
+
+ len = min(sz, LAST_KMSG_MAX_SZ);
+ ptr = buf + (sz - len);
+
+ while (len > 0) {
+ int cnt = min(len, MAX_KLOG_WRITE_BUF_SZ);
+ char yoink;
+ char *nl;
+
+ nl = memrchr(ptr, '\n', cnt - 1);
+ if (nl)
+ cnt = nl - ptr + 1;
+
+ yoink = ptr[cnt];
+ ptr[cnt] = '\0';
+ KLOG_INFO("", "%s", ptr);
+ ptr[cnt] = yoink;
+
+ len -= cnt;
+ ptr += cnt;
+ }
+
+ free(buf);
+
+out:
+ LOGI("\n");
+ LOGI("************* END LAST KMSG *************\n");
+ LOGI("\n");
+}
+
static int read_file(const char *path, char *buf, size_t sz)
{
int fd;
@@ -169,6 +289,22 @@
return -1;
}
+static int get_battery_capacity(struct charger *charger)
+{
+ int ret;
+ int batt_cap = -1;
+
+ if (!charger->battery)
+ return -1;
+
+ ret = read_file_int(charger->battery->cap_path, &batt_cap);
+ if (ret < 0 || batt_cap > 100) {
+ batt_cap = -1;
+ }
+
+ return batt_cap;
+}
+
static struct power_supply *find_supply(struct charger *charger,
const char *name)
{
@@ -185,7 +321,7 @@
static struct power_supply *add_supply(struct charger *charger,
const char *name, const char *type,
- bool online)
+ const char *path, bool online)
{
struct power_supply *supply;
@@ -195,6 +331,8 @@
strlcpy(supply->name, name, sizeof(supply->name));
strlcpy(supply->type, type, sizeof(supply->type));
+ snprintf(supply->cap_path, sizeof(supply->cap_path),
+ "/sys/%s/capacity", path);
supply->online = online;
list_add_tail(&charger->supplies, &supply->list);
charger->num_supplies++;
@@ -293,7 +431,8 @@
if (!strcmp(uevent->action, "add")) {
if (!supply) {
- supply = add_supply(charger, uevent->ps_name, ps_type, online);
+ supply = add_supply(charger, uevent->ps_name, ps_type, uevent->path,
+ online);
if (!supply) {
LOGE("cannot add supply '%s' (%s %d)\n", uevent->ps_name,
uevent->ps_type, online);
@@ -459,74 +598,151 @@
gr_color(0xa4, 0xc6, 0x39, 255);
}
-static void redraw_screen(struct charger *charger)
+/* returns the last y-offset of where the surface ends */
+static int draw_surface_centered(struct charger *charger, gr_surface surface)
{
- int surf_height;
- int surf_width;
+ int w;
+ int h;
int x;
- int y = 0;
- int batt_cap;
- int ret;
- char cap_string[128];
- char cap_path[256];
+ int y;
- clear_screen();
+ w = gr_get_width(surface);
+ h = gr_get_height(surface);
+ x = (gr_fb_width() - w) / 2 ;
+ y = (gr_fb_height() - h) / 2 ;
- if (charger->surf_charging) {
- surf_width = gr_get_width(charger->surf_charging);
- surf_height = gr_get_height(charger->surf_charging);
- x = (gr_fb_width() - surf_width) / 2 ;
- y = (gr_fb_height() - surf_height) / 2 ;
+ LOGV("drawing surface %dx%d+%d+%d\n", w, h, x, y);
+ gr_blit(surface, 0, 0, w, h, x, y);
+ return y + h;
+}
- gr_blit(charger->surf_charging, 0, 0,
- surf_width, surf_height,
- x, y);
- y += surf_height;
+static void draw_unknown(struct charger *charger)
+{
+ int y;
+ if (charger->surf_unknown) {
+ draw_surface_centered(charger, charger->surf_unknown);
} else {
android_green();
y = draw_text("Charging!", -1, -1);
+ draw_text("?\?/100", -1, y + 25);
}
+}
- cap_string[0] = '\0';
- if (charger->battery) {
- ret = snprintf(cap_path, sizeof(cap_path),
- "/sys/class/power_supply/%s/capacity",
- charger->battery->name);
- if (ret <= 0)
- goto done;
- ret = read_file_int(cap_path, &batt_cap);
- if (ret >= 0)
- snprintf(cap_string, sizeof(cap_string), "%d/100", batt_cap);
+static void draw_battery(struct charger *charger)
+{
+ struct animation *batt_anim = charger->batt_anim;
+ struct frame *frame = &batt_anim->frames[batt_anim->cur_frame];
+
+ if (batt_anim->num_frames != 0) {
+ draw_surface_centered(charger, frame->surface);
+ LOGV("drawing frame #%d name=%s min_cap=%d time=%d\n",
+ batt_anim->cur_frame, frame->name, frame->min_capacity,
+ frame->disp_time);
}
+}
- if (cap_string[0] == '\0')
- snprintf(cap_string, sizeof(cap_string), "?\?/100");
+static void redraw_screen(struct charger *charger)
+{
+ struct animation *batt_anim = charger->batt_anim;
- y += 25;
- android_green();
- draw_text(cap_string, -1, y);
+ clear_screen();
-done:
+ /* try to display *something* */
+ if (batt_anim->capacity < 0 || batt_anim->num_frames == 0)
+ draw_unknown(charger);
+ else
+ draw_battery(charger);
gr_flip();
}
-static void update_screen_state(struct charger *charger, int64_t now,
- bool force)
+static void kick_animation(struct animation *anim)
{
- if (!force && ((now < charger->next_screen_transition) ||
- (charger->next_screen_transition == -1)))
+ anim->run = true;
+}
+
+static void reset_animation(struct animation *anim)
+{
+ anim->cur_cycle = 0;
+ anim->cur_frame = 0;
+ anim->run = false;
+}
+
+static void update_screen_state(struct charger *charger, int64_t now)
+{
+ struct animation *batt_anim = charger->batt_anim;
+ int cur_frame;
+ int disp_time;
+
+ if (!batt_anim->run || now < charger->next_screen_transition)
return;
- if (!charger->screen_on)
- charger->next_screen_transition = now + SCREEN_ON_TIME;
- else
+ /* animation is over, blank screen and leave */
+ if (batt_anim->cur_cycle == batt_anim->num_cycles) {
+ reset_animation(batt_anim);
charger->next_screen_transition = -1;
- charger->screen_on = !charger->screen_on;
+ gr_fb_blank(true);
+ LOGV("[%lld] animation done\n", now);
+ return;
+ }
- gr_fb_blank(!charger->screen_on);
- if (charger->screen_on)
- redraw_screen(charger);
- LOGV("[%lld] screen %s\n", now, charger->screen_on ? "on" : "off");
+ disp_time = batt_anim->frames[batt_anim->cur_frame].disp_time;
+
+ /* animation starting, set up the animation */
+ if (batt_anim->cur_frame == 0) {
+ int batt_cap;
+ int ret;
+
+ LOGV("[%lld] animation starting\n", now);
+ batt_cap = get_battery_capacity(charger);
+ if (batt_cap >= 0 && batt_anim->num_frames != 0) {
+ int i;
+
+ /* find first frame given current capacity */
+ for (i = 1; i < batt_anim->num_frames; i++) {
+ if (batt_cap < batt_anim->frames[i].min_capacity)
+ break;
+ }
+ batt_anim->cur_frame = i - 1;
+
+ /* show the first frame for twice as long */
+ disp_time = batt_anim->frames[batt_anim->cur_frame].disp_time * 2;
+ }
+
+ batt_anim->capacity = batt_cap;
+ }
+
+ /* unblank the screen on first cycle */
+ if (batt_anim->cur_cycle == 0)
+ gr_fb_blank(false);
+
+ /* draw the new frame (@ cur_frame) */
+ redraw_screen(charger);
+
+ /* if we don't have anim frames, we only have one image, so just bump
+ * the cycle counter and exit
+ */
+ if (batt_anim->num_frames == 0 || batt_anim->capacity < 0) {
+ LOGV("[%lld] animation missing or unknown battery status\n", now);
+ charger->next_screen_transition = now + BATTERY_UNKNOWN_TIME;
+ batt_anim->cur_cycle++;
+ return;
+ }
+
+ /* schedule next screen transition */
+ charger->next_screen_transition = now + disp_time;
+
+ /* advance frame cntr to the next valid frame
+ * if necessary, advance cycle cntr, and reset frame cntr
+ */
+ batt_anim->cur_frame++;
+ if (batt_anim->cur_frame == batt_anim->num_frames) {
+ batt_anim->cur_cycle++;
+ batt_anim->cur_frame = 0;
+
+ /* don't reset the cycle counter, since we use that as a signal
+ * in a test above to check if animation is over
+ */
+ }
}
static void update_input_state(struct charger *charger,
@@ -585,7 +801,7 @@
} else {
/* if the power key got released, force screen state cycle */
if (key->pending)
- update_screen_state(charger, now, true);
+ kick_animation(charger->batt_anim);
}
}
@@ -617,7 +833,7 @@
/* online supply present, reset shutdown timer if set */
if (charger->next_pwr_check != -1) {
LOGI("[%lld] device plugged in: shutdown cancelled\n", now);
- update_screen_state(charger, now, true);
+ kick_animation(charger->batt_anim);
}
charger->next_pwr_check = -1;
}
@@ -634,8 +850,6 @@
charger->next_screen_transition, charger->next_key_check,
charger->next_pwr_check);
- /* TODO: right now it's just screen on/off and keys, but later I'm sure
- * there will be animations */
if (charger->next_screen_transition != -1)
next_event = charger->next_screen_transition;
if (charger->next_key_check != -1 && charger->next_key_check < next_event)
@@ -675,9 +889,13 @@
LOGV("[%lld] event_loop()\n", now);
handle_input_state(charger, now);
- update_screen_state(charger, now, false);
handle_power_supply_state(charger, now);
+ /* do screen update last in case any of the above want to start
+ * screen transitions (animations, etc)
+ */
+ update_screen_state(charger, now);
+
wait_next_event(charger, now);
}
}
@@ -688,12 +906,17 @@
struct charger *charger = &charger_state;
int64_t now = curr_time_ms() - 1;
int fd;
+ int i;
list_init(&charger->supplies);
klog_init();
klog_set_level(CHARGER_KLOG_LEVEL);
+ dump_last_kmsg();
+
+ LOGI("--------------- STARTING CHARGER MODE ---------------\n");
+
gr_init();
gr_font_size(&char_width, &char_height);
@@ -707,10 +930,23 @@
charger->uevent_fd = fd;
coldboot(charger, "/sys/class/power_supply", "add");
- ret = res_create_surface("charging", &charger->surf_charging);
+ ret = res_create_surface("charger/battery_fail", &charger->surf_unknown);
if (ret < 0) {
LOGE("Cannot load image\n");
- charger->surf_charging = NULL;
+ charger->surf_unknown = NULL;
+ }
+
+ for (i = 0; i < charger->batt_anim->num_frames; i++) {
+ struct frame *frame = &charger->batt_anim->frames[i];
+
+ ret = res_create_surface(frame->name, &frame->surface);
+ if (ret < 0) {
+ LOGE("Cannot load image %s\n", frame->name);
+ /* TODO: free the already allocated surfaces... */
+ charger->batt_anim->num_frames = 0;
+ charger->batt_anim->num_cycles = 1;
+ break;
+ }
}
gr_fb_blank(true);
@@ -718,7 +954,8 @@
charger->next_screen_transition = now - 1;
charger->next_key_check = -1;
charger->next_pwr_check = -1;
- charger->screen_on = false;
+ reset_animation(charger->batt_anim);
+ kick_animation(charger->batt_anim);
event_loop(charger);
diff --git a/charger/images/battery_0.png b/charger/images/battery_0.png
new file mode 100644
index 0000000..2347074
--- /dev/null
+++ b/charger/images/battery_0.png
Binary files differ
diff --git a/charger/images/battery_1.png b/charger/images/battery_1.png
new file mode 100644
index 0000000..cd34620
--- /dev/null
+++ b/charger/images/battery_1.png
Binary files differ
diff --git a/charger/images/battery_2.png b/charger/images/battery_2.png
new file mode 100644
index 0000000..3e4095e
--- /dev/null
+++ b/charger/images/battery_2.png
Binary files differ
diff --git a/charger/images/battery_3.png b/charger/images/battery_3.png
new file mode 100644
index 0000000..08c1551
--- /dev/null
+++ b/charger/images/battery_3.png
Binary files differ
diff --git a/charger/images/battery_4.png b/charger/images/battery_4.png
new file mode 100644
index 0000000..3a678da
--- /dev/null
+++ b/charger/images/battery_4.png
Binary files differ
diff --git a/charger/images/battery_5.png b/charger/images/battery_5.png
new file mode 100644
index 0000000..d8dc40e
--- /dev/null
+++ b/charger/images/battery_5.png
Binary files differ
diff --git a/charger/images/battery_charge.png b/charger/images/battery_charge.png
new file mode 100644
index 0000000..b501933
--- /dev/null
+++ b/charger/images/battery_charge.png
Binary files differ
diff --git a/charger/images/battery_fail.png b/charger/images/battery_fail.png
new file mode 100644
index 0000000..36fc254
--- /dev/null
+++ b/charger/images/battery_fail.png
Binary files differ
diff --git a/charger/images/charging.png b/charger/images/charging.png
deleted file mode 100644
index 94ce4b1..0000000
--- a/charger/images/charging.png
+++ /dev/null
Binary files differ
diff --git a/include/arch/linux-arm/AndroidConfig.h b/include/arch/linux-arm/AndroidConfig.h
index 83891cd..cae112b 100644
--- a/include/arch/linux-arm/AndroidConfig.h
+++ b/include/arch/linux-arm/AndroidConfig.h
@@ -190,7 +190,7 @@
* with a memory address. If not defined, stack crawls will not have symbolic
* information.
*/
-#define HAVE_DLADDR 0
+#define HAVE_DLADDR 1
/*
* Defined if we have the cxxabi.h header for demangling C++ symbols. If
diff --git a/include/netutils/ifc.h b/include/netutils/ifc.h
index 575e72e..67a4a45 100644
--- a/include/netutils/ifc.h
+++ b/include/netutils/ifc.h
@@ -38,9 +38,13 @@
extern int ifc_get_addr(const char *name, in_addr_t *addr);
extern int ifc_set_addr(const char *name, in_addr_t addr);
-extern int ifc_get_prefixLength(const char *name, uint32_t *prefixLength);
-extern int ifc_set_prefixLength(const char *name, uint32_t prefixLength);
+extern int ifc_add_address(const char *name, const char *address,
+ int prefixlen);
+extern int ifc_del_address(const char *name, const char *address,
+ int prefixlen);
+extern int ifc_set_prefixLength(const char *name, int prefixLength);
extern int ifc_set_hwaddr(const char *name, const void *ptr);
+extern int ifc_clear_addresses(const char *name);
/* This function is deprecated. Use ifc_add_route instead. */
extern int ifc_add_host_route(const char *name, in_addr_t addr);
@@ -53,9 +57,10 @@
extern int ifc_remove_default_route(const char *ifname);
extern int ifc_add_route(const char *name, const char *addr, int prefix_length,
const char *gw);
-
-extern int ifc_get_info(const char *name, in_addr_t *addr, in_addr_t *mask,
- in_addr_t *flags);
+extern int ifc_remove_route(const char *ifname, const char *dst,
+ int prefix_length, const char *gw);
+extern int ifc_get_info(const char *name, in_addr_t *addr, int *prefixLength,
+ unsigned *flags);
extern int ifc_configure(const char *ifname, in_addr_t address,
uint32_t prefixLength, in_addr_t gateway,
diff --git a/include/system/camera.h b/include/system/camera.h
index 81ce4cb..86b62b7 100644
--- a/include/system/camera.h
+++ b/include/system/camera.h
@@ -105,8 +105,8 @@
* This does not affect the order of byte array of
* CAMERA_MSG_PREVIEW_FRAME, CAMERA_MSG_VIDEO_FRAME,
* CAMERA_MSG_POSTVIEW_FRAME, CAMERA_MSG_RAW_IMAGE, or
- * CAMERA_MSG_COMPRESSED_IMAGE. This is not allowed to be set during
- * preview
+ * CAMERA_MSG_COMPRESSED_IMAGE. This is allowed to be set during preview
+ * since API level 14.
*/
CAMERA_CMD_SET_DISPLAY_ORIENTATION = 3,
diff --git a/include/sysutils/SocketClient.h b/include/sysutils/SocketClient.h
index d6bb7d5..7d2b1d6 100644
--- a/include/sysutils/SocketClient.h
+++ b/include/sysutils/SocketClient.h
@@ -8,6 +8,7 @@
class SocketClient {
int mSocket;
+ bool mSocketOwned;
pthread_mutex_t mWriteMutex;
/* Peer process ID */
@@ -24,8 +25,8 @@
int mRefCount;
public:
- SocketClient(int sock);
- virtual ~SocketClient() {}
+ SocketClient(int sock, bool owned);
+ virtual ~SocketClient();
int getSocket() { return mSocket; }
pid_t getPid() const { return mPid; }
diff --git a/init/init.c b/init/init.c
index af88f30..7b4a963 100755
--- a/init/init.c
+++ b/init/init.c
@@ -92,7 +92,7 @@
int add_environment(const char *key, const char *val)
{
int n;
-
+
for (n = 0; n < 31; n++) {
if (!ENV[n]) {
size_t len = strlen(key) + strlen(val) + 2;
@@ -156,7 +156,7 @@
*/
svc->flags &= (~(SVC_DISABLED|SVC_RESTARTING|SVC_RESET));
svc->time_started = 0;
-
+
/* running processes require no additional work -- if
* they're in the process of exiting, we've ensured
* that they will immediately restart on exit, unless
@@ -381,7 +381,7 @@
svc = service_find_by_name(tmp);
}
-
+
if (svc) {
service_start(svc, args);
} else {
@@ -455,38 +455,6 @@
}
}
-static void import_kernel_cmdline(int in_qemu)
-{
- char cmdline[1024];
- char *ptr;
- int fd;
-
- fd = open("/proc/cmdline", O_RDONLY);
- if (fd >= 0) {
- int n = read(fd, cmdline, 1023);
- 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;
- import_kernel_nv(ptr, in_qemu);
- ptr = x;
- }
-
- /* don't expose the raw commandline to nonpriv processes */
- chmod("/proc/cmdline", 0440);
-}
-
static struct command *get_first_command(struct action *act)
{
struct listnode *node;
@@ -609,7 +577,7 @@
char tmp[PROP_VALUE_MAX];
if (qemu[0])
- import_kernel_cmdline(1);
+ import_kernel_cmdline(1, import_kernel_nv);
if (!strcmp(bootmode,"factory"))
property_set("ro.factorytest", "1");
@@ -729,13 +697,14 @@
*/
open_devnull_stdio();
klog_init();
-
+
INFO("reading config file\n");
init_parse_config_file("/init.rc");
/* pull the kernel commandline and ramdisk properties file in */
- import_kernel_cmdline(0);
-
+ import_kernel_cmdline(0, import_kernel_nv);
+ /* don't expose the raw commandline to nonpriv processes */
+ chmod("/proc/cmdline", 0440);
get_hardware_name(hardware, &revision);
snprintf(tmp, sizeof(tmp), "/init.%s.rc", hardware);
init_parse_config_file(tmp);
diff --git a/init/ueventd.c b/init/ueventd.c
index ddf42be..ecf3b9b 100644
--- a/init/ueventd.c
+++ b/init/ueventd.c
@@ -33,6 +33,20 @@
static char hardware[32];
static unsigned revision = 0;
+static void import_kernel_nv(char *name, int in_qemu)
+{
+ if (*name != '\0') {
+ char *value = strchr(name, '=');
+ if (value != NULL) {
+ *value++ = 0;
+ if (!strcmp(name,"androidboot.hardware"))
+ {
+ strlcpy(hardware, value, sizeof(hardware));
+ }
+ }
+ }
+}
+
int ueventd_main(int argc, char **argv)
{
struct pollfd ufd;
@@ -51,6 +65,11 @@
INFO("starting ueventd\n");
+ /* Respect hardware passed in through the kernel cmd line. Here we will look
+ * for androidboot.hardware param in kernel cmdline, and save its value in
+ * hardware[]. */
+ import_kernel_cmdline(0, import_kernel_nv);
+
get_hardware_name(hardware, &revision);
ueventd_parse_config_file("/ueventd.rc");
diff --git a/init/util.c b/init/util.c
index fd4bee2..13c9ca2 100755
--- a/init/util.c
+++ b/init/util.c
@@ -399,3 +399,33 @@
}
}
}
+
+void import_kernel_cmdline(int in_qemu,
+ void (*import_kernel_nv)(char *name, int in_qemu))
+{
+ char cmdline[1024];
+ char *ptr;
+ int fd;
+
+ fd = open("/proc/cmdline", O_RDONLY);
+ if (fd >= 0) {
+ int n = read(fd, cmdline, 1023);
+ 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;
+ import_kernel_nv(ptr, in_qemu);
+ ptr = x;
+ }
+}
diff --git a/init/util.h b/init/util.h
index 2e47369..9247739 100644
--- a/init/util.h
+++ b/init/util.h
@@ -38,4 +38,5 @@
int wait_for_file(const char *filename, int timeout);
void open_devnull_stdio(void);
void get_hardware_name(char *hardware, unsigned int *revision);
+void import_kernel_cmdline(int in_qemu, void (*import_kernel_nv)(char *name, int in_qemu));
#endif
diff --git a/libcutils/qtaguid.c b/libcutils/qtaguid.c
index 7e1c42b..994ad32 100644
--- a/libcutils/qtaguid.c
+++ b/libcutils/qtaguid.c
@@ -15,6 +15,8 @@
** limitations under the License.
*/
+// #define LOG_NDEBUG 0
+
#define LOG_TAG "qtaguid"
#include <cutils/qtaguid.h>
@@ -58,7 +60,7 @@
static int write_ctrl(const char *cmd) {
int fd, res, savedErrno;
- LOGI("write_ctrl(%s)", cmd);
+ LOGV("write_ctrl(%s)", cmd);
fd = TEMP_FAILURE_RETRY(open(CTRL_PROCPATH, O_WRONLY));
if (fd < 0) {
@@ -105,7 +107,7 @@
snprintf(lineBuf, sizeof(lineBuf), "t %d %llu %d", sockfd, kTag, uid);
- LOGI("Tagging socket %d with tag %llx{%u,0} for uid %d", sockfd, kTag, tag, uid);
+ LOGV("Tagging socket %d with tag %llx{%u,0} for uid %d", sockfd, kTag, tag, uid);
res = write_ctrl(lineBuf);
if (res < 0) {
@@ -120,7 +122,7 @@
char lineBuf[CTRL_MAX_INPUT_LEN];
int res;
- LOGI("Untagging socket %d", sockfd);
+ LOGV("Untagging socket %d", sockfd);
snprintf(lineBuf, sizeof(lineBuf), "u %d", sockfd);
res = write_ctrl(lineBuf);
@@ -135,7 +137,7 @@
char lineBuf[CTRL_MAX_INPUT_LEN];
int res;
- LOGI("Setting counters to set %d for uid %d", counterSetNum, uid);
+ LOGV("Setting counters to set %d for uid %d", counterSetNum, uid);
snprintf(lineBuf, sizeof(lineBuf), "s %d %d", counterSetNum, uid);
res = write_ctrl(lineBuf);
@@ -147,7 +149,7 @@
int fd, cnt = 0, res = 0;
uint64_t kTag = (uint64_t)tag << 32;
- LOGI("Deleting tag data with tag %llx{%d,0} for uid %d", kTag, tag, uid);
+ LOGV("Deleting tag data with tag %llx{%d,0} for uid %d", kTag, tag, uid);
pthread_once(&resTrackInitDone, qtaguid_resTrack);
diff --git a/liblog/logprint.c b/liblog/logprint.c
index 4c5b3e5..59fed9b 100644
--- a/liblog/logprint.c
+++ b/liblog/logprint.c
@@ -350,16 +350,28 @@
int android_log_processLogBuffer(struct logger_entry *buf,
AndroidLogEntry *entry)
{
- size_t tag_len;
-
entry->tv_sec = buf->sec;
entry->tv_nsec = buf->nsec;
entry->priority = buf->msg[0];
entry->pid = buf->pid;
entry->tid = buf->tid;
+
+ /*
+ * format: <priority:1><tag:N>\0<message:N>\0
+ *
+ * tag str
+ * starts at msg+1
+ * msg
+ * starts at msg+1+len(tag)+1
+ */
entry->tag = buf->msg + 1;
- tag_len = strlen(entry->tag);
- entry->messageLen = buf->len - tag_len - 3;
+ const size_t tag_len = strlen(entry->tag);
+ const size_t preambleAndNullLen = tag_len + 3;
+ if (buf->len <= preambleAndNullLen) {
+ fprintf(stderr, "+++ LOG: entry corrupt or truncated\n");
+ return -1;
+ }
+ entry->messageLen = buf->len - preambleAndNullLen;
entry->message = entry->tag + tag_len + 1;
return 0;
diff --git a/libnetutils/Android.mk b/libnetutils/Android.mk
index 1ef7da9..5f5849f 100644
--- a/libnetutils/Android.mk
+++ b/libnetutils/Android.mk
@@ -6,10 +6,10 @@
dhcpmsg.c \
dhcp_utils.c \
ifc_utils.c \
- packet.c
+ packet.c
LOCAL_SHARED_LIBRARIES := \
- libcutils
+ libcutils
LOCAL_MODULE:= libnetutils
diff --git a/libnetutils/ifc_utils.c b/libnetutils/ifc_utils.c
index 04b0dfa..0a2f760 100644
--- a/libnetutils/ifc_utils.c
+++ b/libnetutils/ifc_utils.c
@@ -26,15 +26,18 @@
#include <netinet/in.h>
#include <arpa/inet.h>
#include <net/if.h>
+#include <netdb.h>
#include <linux/if.h>
#include <linux/if_ether.h>
#include <linux/if_arp.h>
-#include <linux/sockios.h>
+#include <linux/netlink.h>
#include <linux/route.h>
#include <linux/ipv6_route.h>
-#include <netdb.h>
-#include <linux/wireless.h>
+#include <linux/rtnetlink.h>
+#include <linux/sockios.h>
+
+#include "netutils/ifc.h"
#ifdef ANDROID
#define LOG_TAG "NetUtils"
@@ -52,6 +55,8 @@
void printerr(char *fmt, ...);
#define DBG 0
+#define INET_ADDRLEN 4
+#define INET6_ADDRLEN 16
in_addr_t prefixLengthToIpv4Netmask(int prefix_length)
{
@@ -88,6 +93,28 @@
return inet_ntoa(in_addr);
}
+int string_to_ip(const char *string, struct sockaddr_storage *ss) {
+ struct addrinfo hints, *ai;
+ int ret;
+
+ if (ss == NULL) {
+ return -EFAULT;
+ }
+
+ memset(&hints, 0, sizeof(hints));
+ hints.ai_family = AF_UNSPEC;
+ hints.ai_flags = AI_NUMERICHOST;
+ hints.ai_socktype = SOCK_DGRAM;
+
+ ret = getaddrinfo(string, NULL, &hints, &ai);
+ if (ret == 0) {
+ memcpy(ss, ai->ai_addr, ai->ai_addrlen);
+ freeaddrinfo(ai);
+ }
+
+ return ret;
+}
+
int ifc_init(void)
{
int ret;
@@ -209,6 +236,185 @@
return ret;
}
+/*
+ * Adds or deletes an IP address on an interface.
+ *
+ * Action is one of:
+ * - RTM_NEWADDR (to add a new address)
+ * - RTM_DELADDR (to delete an existing address)
+ *
+ * Returns zero on success and negative errno on failure.
+ */
+int ifc_act_on_address(int action, const char *name, const char *address,
+ int prefixlen) {
+ int ifindex, s, len, ret;
+ struct sockaddr_storage ss;
+ void *addr;
+ size_t addrlen;
+ struct {
+ struct nlmsghdr n;
+ struct ifaddrmsg r;
+ // Allow for IPv6 address, headers, and padding.
+ char attrbuf[NLMSG_ALIGN(sizeof(struct nlmsghdr)) +
+ NLMSG_ALIGN(sizeof(struct rtattr)) +
+ NLMSG_ALIGN(INET6_ADDRLEN)];
+ } req;
+ struct rtattr *rta;
+ struct nlmsghdr *nh;
+ struct nlmsgerr *err;
+ char buf[NLMSG_ALIGN(sizeof(struct nlmsghdr)) +
+ NLMSG_ALIGN(sizeof(struct nlmsgerr)) +
+ NLMSG_ALIGN(sizeof(struct nlmsghdr))];
+
+ // Get interface ID.
+ ifindex = if_nametoindex(name);
+ if (ifindex == 0) {
+ return -errno;
+ }
+
+ // Convert string representation to sockaddr_storage.
+ ret = string_to_ip(address, &ss);
+ if (ret) {
+ return ret;
+ }
+
+ // Determine address type and length.
+ if (ss.ss_family == AF_INET) {
+ struct sockaddr_in *sin = (struct sockaddr_in *) &ss;
+ addr = &sin->sin_addr;
+ addrlen = INET_ADDRLEN;
+ } else if (ss.ss_family == AF_INET6) {
+ struct sockaddr_in6 *sin6 = (struct sockaddr_in6 *) &ss;
+ addr = &sin6->sin6_addr;
+ addrlen = INET6_ADDRLEN;
+ } else {
+ return -EAFNOSUPPORT;
+ }
+
+ // Fill in netlink structures.
+ memset(&req, 0, sizeof(req));
+
+ // Netlink message header.
+ req.n.nlmsg_len = NLMSG_LENGTH(sizeof(req.r));
+ req.n.nlmsg_type = action;
+ req.n.nlmsg_flags = NLM_F_REQUEST | NLM_F_ACK;
+ req.n.nlmsg_pid = getpid();
+
+ // Interface address message header.
+ req.r.ifa_family = ss.ss_family;
+ req.r.ifa_prefixlen = prefixlen;
+ req.r.ifa_index = ifindex;
+
+ // Routing attribute. Contains the actual IP address.
+ rta = (struct rtattr *) (((char *) &req) + NLMSG_ALIGN(req.n.nlmsg_len));
+ rta->rta_type = IFA_LOCAL;
+ rta->rta_len = RTA_LENGTH(addrlen);
+ req.n.nlmsg_len = NLMSG_ALIGN(req.n.nlmsg_len) + RTA_LENGTH(addrlen);
+ memcpy(RTA_DATA(rta), addr, addrlen);
+
+ s = socket(PF_NETLINK, SOCK_RAW, NETLINK_ROUTE);
+ if (send(s, &req, req.n.nlmsg_len, 0) < 0) {
+ close(s);
+ return -errno;
+ }
+
+ len = recv(s, buf, sizeof(buf), 0);
+ close(s);
+ if (len < 0) {
+ return -errno;
+ }
+
+ // Parse the acknowledgement to find the return code.
+ nh = (struct nlmsghdr *) buf;
+ if (!NLMSG_OK(nh, (unsigned) len) || nh->nlmsg_type != NLMSG_ERROR) {
+ return -EINVAL;
+ }
+ err = NLMSG_DATA(nh);
+
+ // Return code is negative errno.
+ return err->error;
+}
+
+int ifc_add_address(const char *name, const char *address, int prefixlen) {
+ return ifc_act_on_address(RTM_NEWADDR, name, address, prefixlen);
+}
+
+int ifc_del_address(const char *name, const char * address, int prefixlen) {
+ return ifc_act_on_address(RTM_DELADDR, name, address, prefixlen);
+}
+
+/*
+ * Clears IPv6 addresses on the specified interface.
+ */
+int ifc_clear_ipv6_addresses(const char *name) {
+ char rawaddrstr[INET6_ADDRSTRLEN], addrstr[INET6_ADDRSTRLEN];
+ unsigned int prefixlen;
+ int lasterror = 0, i, j, ret;
+ char ifname[64]; // Currently, IFNAMSIZ = 16.
+ FILE *f = fopen("/proc/net/if_inet6", "r");
+ if (!f) {
+ return -errno;
+ }
+
+ // Format:
+ // 20010db8000a0001fc446aa4b5b347ed 03 40 00 01 wlan0
+ while (fscanf(f, "%32s %*02x %02x %*02x %*02x %63s\n",
+ rawaddrstr, &prefixlen, ifname) == 3) {
+ // Is this the interface we're looking for?
+ if (strcmp(name, ifname)) {
+ continue;
+ }
+
+ // Put the colons back into the address.
+ for (i = 0, j = 0; i < 32; i++, j++) {
+ addrstr[j] = rawaddrstr[i];
+ if (i % 4 == 3) {
+ addrstr[++j] = ':';
+ }
+ }
+ addrstr[j - 1] = '\0';
+
+ // Don't delete the link-local address as well, or it will disable IPv6
+ // on the interface.
+ if (strncmp(addrstr, "fe80:", 5) == 0) {
+ continue;
+ }
+
+ ret = ifc_del_address(ifname, addrstr, prefixlen);
+ if (ret) {
+ LOGE("Deleting address %s/%d on %s: %s", addrstr, prefixlen, ifname,
+ strerror(-ret));
+ lasterror = ret;
+ }
+ }
+
+ fclose(f);
+ return lasterror;
+}
+
+/*
+ * Clears IPv4 addresses on the specified interface.
+ */
+void ifc_clear_ipv4_addresses(const char *name) {
+ unsigned count, addr;
+ ifc_init();
+ for (count=0, addr=1;((addr != 0) && (count < 255)); count++) {
+ if (ifc_get_addr(name, &addr) < 0)
+ break;
+ if (addr)
+ ifc_set_addr(name, 0);
+ }
+ ifc_close();
+}
+
+/*
+ * Clears all IP addresses on the specified interface.
+ */
+int ifc_clear_addresses(const char *name) {
+ ifc_clear_ipv4_addresses(name);
+ return ifc_clear_ipv6_addresses(name);
+}
+
int ifc_set_hwaddr(const char *name, const void *ptr)
{
int r;
@@ -739,7 +945,7 @@
struct in_addr gw)
{
int i =ifc_act_on_ipv4_route(SIOCADDRT, ifname, dst, prefix_length, gw);
- printerr("ifc_add_ipv4_route(%s, xx, %d, xx) = %d", ifname, prefix_length, i);
+ if (DBG) printerr("ifc_add_ipv4_route(%s, xx, %d, xx) = %d", ifname, prefix_length, i);
return i;
}
@@ -755,7 +961,7 @@
int ifc_add_route(const char *ifname, const char *dst, int prefix_length, const char *gw)
{
int i = ifc_act_on_route(SIOCADDRT, ifname, dst, prefix_length, gw);
- printerr("ifc_add_route(%s, %s, %d, %s) = %d", ifname, dst, prefix_length, gw, i);
+ if (DBG) printerr("ifc_add_route(%s, %s, %d, %s) = %d", ifname, dst, prefix_length, gw, i);
return i;
}
diff --git a/libnl_2/genl/genl.c b/libnl_2/genl/genl.c
index dd20717..2442993 100644
--- a/libnl_2/genl/genl.c
+++ b/libnl_2/genl/genl.c
@@ -112,6 +112,7 @@
nlmhdr.nlmsg_pid = sock->s_local.nl_pid;
/* Generic netlink header */
+ memset(&gmhhdr, 0, sizeof(gmhhdr));
gmhhdr.cmd = CTRL_CMD_GETFAMILY;
gmhhdr.version = CTRL_ATTR_FAMILY_ID;
@@ -221,9 +222,11 @@
/* Save the family id */
else if (nl80211_flag &&
- nla->nla_type == CTRL_ATTR_FAMILY_ID)
- nl80211_genl_id = \
+ nla->nla_type == CTRL_ATTR_FAMILY_ID) {
+ nl80211_genl_id =
*((int *)nla_data(nla));
+ nl80211_flag = 0;
+ }
}
diff --git a/libsysutils/src/SocketClient.cpp b/libsysutils/src/SocketClient.cpp
index 90ca52e..722dcb2 100644
--- a/libsysutils/src/SocketClient.cpp
+++ b/libsysutils/src/SocketClient.cpp
@@ -10,8 +10,9 @@
#include <sysutils/SocketClient.h>
-SocketClient::SocketClient(int socket)
+SocketClient::SocketClient(int socket, bool owned)
: mSocket(socket)
+ , mSocketOwned(owned)
, mPid(-1)
, mUid(-1)
, mGid(-1)
@@ -32,6 +33,13 @@
}
}
+SocketClient::~SocketClient()
+{
+ if (mSocketOwned) {
+ close(mSocket);
+ }
+}
+
int SocketClient::sendMsg(int code, const char *msg, bool addErrno) {
char *buf;
const char* arg;
diff --git a/libsysutils/src/SocketListener.cpp b/libsysutils/src/SocketListener.cpp
index fcad624..3f871ea 100644
--- a/libsysutils/src/SocketListener.cpp
+++ b/libsysutils/src/SocketListener.cpp
@@ -79,7 +79,7 @@
SLOGE("Unable to listen on socket (%s)", strerror(errno));
return -1;
} else if (!mListen)
- mClients->push_back(new SocketClient(mSock));
+ mClients->push_back(new SocketClient(mSock, false));
if (pipe(mCtrlPipe)) {
SLOGE("pipe failed (%s)", strerror(errno));
@@ -191,7 +191,7 @@
continue;
}
pthread_mutex_lock(&mClientsLock);
- mClients->push_back(new SocketClient(c));
+ mClients->push_back(new SocketClient(c, true));
pthread_mutex_unlock(&mClientsLock);
}
@@ -225,12 +225,8 @@
}
}
pthread_mutex_unlock(&mClientsLock);
- /* Destroy the client */
- int socket = c->getSocket();
- if (c->decRef()) {
- // Note: 'c' is deleted memory at this point.
- close(socket);
- }
+ /* Remove our reference to the client */
+ c->decRef();
}
}
}
diff --git a/logcat/logcat.cpp b/logcat/logcat.cpp
index 96b68ef..4cd2151 100644
--- a/logcat/logcat.cpp
+++ b/logcat/logcat.cpp
@@ -323,7 +323,7 @@
// the caller requested to just dump the log and exit
if (g_nonblock) {
- exit(0);
+ return;
}
} else {
// print all that aren't the last in their list
@@ -765,10 +765,10 @@
}
if (getLogSize) {
- return 0;
+ exit(0);
}
if (clearLog) {
- return 0;
+ exit(0);
}
//LOG_EVENT_INT(10, 12345);
diff --git a/netcfg/netcfg.c b/netcfg/netcfg.c
index c520075..3738f24 100644
--- a/netcfg/netcfg.c
+++ b/netcfg/netcfg.c
@@ -50,8 +50,9 @@
int dump_interface(const char *name)
{
- unsigned addr, prefixLength, flags;
+ unsigned addr, flags;
unsigned char hwbuf[ETH_ALEN];
+ int prefixLength;
if(ifc_get_info(name, &addr, &prefixLength, &flags)) {
return 0;
diff --git a/rootdir/etc/init.goldfish.rc b/rootdir/etc/init.goldfish.rc
index 1ac09ca..83b7f8a 100644
--- a/rootdir/etc/init.goldfish.rc
+++ b/rootdir/etc/init.goldfish.rc
@@ -52,6 +52,18 @@
group root
oneshot
+# The qemu-props program is used to set various system
+# properties on boot. It must be run early during the boot
+# process to avoid race conditions with other daemons that
+# might read them (e.g. surface flinger), so define it in
+# class 'core'
+#
+service qemu-props /system/bin/qemu-props
+ class core
+ user root
+ group root
+ oneshot
+
service qemud /system/bin/qemud
socket qemud stream 666
oneshot
diff --git a/rootdir/etc/init.goldfish.sh b/rootdir/etc/init.goldfish.sh
index 1156dd7..ece75b4 100755
--- a/rootdir/etc/init.goldfish.sh
+++ b/rootdir/etc/init.goldfish.sh
@@ -57,10 +57,6 @@
;;
esac
-# call 'qemu-props' to set system properties from the emulator.
-#
-/system/bin/qemu-props
-
# set up the second interface (for inter-emulator connections)
# if required
my_ip=`getprop net.shared_net_ip`