summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--charger/Android.mk26
-rw-r--r--charger/charger.c283
-rw-r--r--charger/images/battery_0.pngbin0 -> 1292 bytes
-rw-r--r--charger/images/battery_1.pngbin0 -> 1290 bytes
-rw-r--r--charger/images/battery_2.pngbin0 -> 1289 bytes
-rw-r--r--charger/images/battery_3.pngbin0 -> 1291 bytes
-rw-r--r--charger/images/battery_4.pngbin0 -> 1269 bytes
-rw-r--r--charger/images/battery_charge.pngbin0 -> 2516 bytes
-rw-r--r--charger/images/battery_fail.pngbin0 -> 1805 bytes
-rw-r--r--charger/images/charging.pngbin9895 -> 0 bytes
10 files changed, 248 insertions, 61 deletions
diff --git a/charger/Android.mk b/charger/Android.mk
index 75e78d546..ba21a9b2b 100644
--- a/charger/Android.mk
+++ b/charger/Android.mk
@@ -18,3 +18,29 @@ LOCAL_STATIC_LIBRARIES := libminui libpixelflinger_static libpng
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 :=
diff --git a/charger/charger.c b/charger/charger.c
index 9320e8a55..a6f8509da 100644
--- a/charger/charger.c
+++ b/charger/charger.c
@@ -49,10 +49,12 @@
#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)
@@ -72,22 +74,46 @@ struct power_supply {
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 +126,47 @@ struct uevent {
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,
+ },
+};
+
+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)
{
@@ -185,7 +247,7 @@ static struct power_supply *find_supply(struct charger *charger,
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 +257,8 @@ static struct power_supply *add_supply(struct charger *charger,
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 +357,8 @@ static void process_ps_uevent(struct charger *charger, struct uevent *uevent)
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 +524,153 @@ static void android_green(void)
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)
+{
+ 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)
{
- if (!force && ((now < charger->next_screen_transition) ||
- (charger->next_screen_transition == -1)))
+ 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;
+ }
+
+ 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);
+ ret = read_file_int(charger->battery->cap_path, &batt_cap);
+ if (ret < 0 || batt_cap > 100) {
+ batt_cap = -1;
+ } else if (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;
- gr_fb_blank(!charger->screen_on);
- if (charger->screen_on)
- redraw_screen(charger);
- LOGV("[%lld] screen %s\n", now, charger->screen_on ? "on" : "off");
+ /* 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 +729,7 @@ static void process_key(struct charger *charger, int code, int64_t now)
} else {
/* if the power key got released, force screen state cycle */
if (key->pending)
- update_screen_state(charger, now, true);
+ kick_animation(charger->batt_anim);
}
}
@@ -617,7 +761,7 @@ static void handle_power_supply_state(struct charger *charger, int64_t now)
/* 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 +778,6 @@ static void wait_next_event(struct charger *charger, int64_t now)
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 +817,13 @@ static void event_loop(struct charger *charger)
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,6 +834,7 @@ int main(int argc, char **argv)
struct charger *charger = &charger_state;
int64_t now = curr_time_ms() - 1;
int fd;
+ int i;
list_init(&charger->supplies);
@@ -707,10 +854,23 @@ int main(int argc, char **argv)
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 +878,8 @@ int main(int argc, char **argv)
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 000000000..8128acd43
--- /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 000000000..d9098155f
--- /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 000000000..c710ca9eb
--- /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 000000000..f7a926bb3
--- /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 000000000..51c4d248a
--- /dev/null
+++ b/charger/images/battery_4.png
Binary files differ
diff --git a/charger/images/battery_charge.png b/charger/images/battery_charge.png
new file mode 100644
index 000000000..f7678fae7
--- /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 000000000..25c7e9717
--- /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 94ce4b16b..000000000
--- a/charger/images/charging.png
+++ /dev/null
Binary files differ