Loading healthd/Android.mk +26 −0 Original line number Diff line number Diff line Loading @@ -33,6 +33,30 @@ include $(BUILD_STATIC_LIBRARY) include $(CLEAR_VARS) LOCAL_MODULE := libhealthd_draw LOCAL_EXPORT_C_INCLUDE_DIRS := $(LOCAL_PATH) LOCAL_STATIC_LIBRARIES := \ libminui \ libbase LOCAL_SRC_FILES := healthd_draw.cpp ifneq ($(TARGET_HEALTHD_DRAW_SPLIT_SCREEN),) LOCAL_CFLAGS += -DHEALTHD_DRAW_SPLIT_SCREEN=$(TARGET_HEALTHD_DRAW_SPLIT_SCREEN) else LOCAL_CFLAGS += -DHEALTHD_DRAW_SPLIT_SCREEN=0 endif ifneq ($(TARGET_HEALTHD_DRAW_SPLIT_OFFSET),) LOCAL_CFLAGS += -DHEALTHD_DRAW_SPLIT_OFFSET=$(TARGET_HEALTHD_DRAW_SPLIT_OFFSET) else LOCAL_CFLAGS += -DHEALTHD_DRAW_SPLIT_OFFSET=0 endif include $(BUILD_STATIC_LIBRARY) include $(CLEAR_VARS) LOCAL_CFLAGS := -Werror ifeq ($(strip $(BOARD_CHARGER_DISABLE_INIT_BLANK)),true) LOCAL_CFLAGS += -DCHARGER_DISABLE_INIT_BLANK Loading @@ -58,6 +82,7 @@ LOCAL_STATIC_LIBRARIES := \ libutils \ libbase \ libcutils \ libhealthd_draw \ liblog \ libm \ libc \ Loading Loading @@ -101,6 +126,7 @@ endif LOCAL_STATIC_LIBRARIES := \ libhealthd_charger \ libhealthd_draw \ libbatterymonitor \ libbase \ libutils \ Loading healthd/healthd_draw.cpp 0 → 100644 +195 −0 Original line number Diff line number Diff line /* * Copyright (C) 2017 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 <android-base/stringprintf.h> #include <batteryservice/BatteryService.h> #include <cutils/klog.h> #include "healthd_draw.h" #define LOGE(x...) KLOG_ERROR("charger", x); #define LOGV(x...) KLOG_DEBUG("charger", x); HealthdDraw::HealthdDraw(animation* anim) : kSplitScreen(HEALTHD_DRAW_SPLIT_SCREEN), kSplitOffset(HEALTHD_DRAW_SPLIT_OFFSET) { gr_init(); gr_font_size(gr_sys_font(), &char_width_, &char_height_); screen_width_ = gr_fb_width() / (kSplitScreen ? 2 : 1); screen_height_ = gr_fb_height(); int res; if (!anim->text_clock.font_file.empty() && (res = gr_init_font(anim->text_clock.font_file.c_str(), &anim->text_clock.font)) < 0) { LOGE("Could not load time font (%d)\n", res); } if (!anim->text_percent.font_file.empty() && (res = gr_init_font(anim->text_percent.font_file.c_str(), &anim->text_percent.font)) < 0) { LOGE("Could not load percent font (%d)\n", res); } } HealthdDraw::~HealthdDraw() {} void HealthdDraw::redraw_screen(const animation* batt_anim, GRSurface* surf_unknown) { clear_screen(); /* try to display *something* */ if (batt_anim->cur_level < 0 || batt_anim->num_frames == 0) draw_unknown(surf_unknown); else draw_battery(batt_anim); gr_flip(); } void HealthdDraw::blank_screen(bool blank) { gr_fb_blank(blank); } void HealthdDraw::clear_screen(void) { gr_color(0, 0, 0, 255); gr_clear(); } int HealthdDraw::draw_surface_centered(GRSurface* surface) { int w = gr_get_width(surface); int h = gr_get_height(surface); int x = (screen_width_ - w) / 2 + kSplitOffset; int y = (screen_height_ - h) / 2; LOGV("drawing surface %dx%d+%d+%d\n", w, h, x, y); gr_blit(surface, 0, 0, w, h, x, y); if (kSplitScreen) { x += screen_width_ - 2 * kSplitOffset; LOGV("drawing surface %dx%d+%d+%d\n", w, h, x, y); gr_blit(surface, 0, 0, w, h, x, y); } return y + h; } int HealthdDraw::draw_text(const GRFont* font, int x, int y, const char* str) { int str_len_px = gr_measure(font, str); if (x < 0) x = (screen_width_ - str_len_px) / 2; if (y < 0) y = (screen_height_ - char_height_) / 2; gr_text(font, x + kSplitOffset, y, str, false /* bold */); if (kSplitScreen) gr_text(font, x - kSplitOffset + screen_width_, y, str, false /* bold */); return y + char_height_; } void HealthdDraw::determine_xy(const animation::text_field& field, const int length, int* x, int* y) { *x = field.pos_x; int str_len_px = length * field.font->char_width; if (field.pos_x == CENTER_VAL) { *x = (screen_width_ - str_len_px) / 2; } else if (field.pos_x >= 0) { *x = field.pos_x; } else { // position from max edge *x = screen_width_ + field.pos_x - str_len_px - kSplitOffset; } *y = field.pos_y; if (field.pos_y == CENTER_VAL) { *y = (screen_height_ - field.font->char_height) / 2; } else if (field.pos_y >= 0) { *y = field.pos_y; } else { // position from max edge *y = screen_height_ + field.pos_y - field.font->char_height; } } void HealthdDraw::draw_clock(const animation* anim) { static constexpr char CLOCK_FORMAT[] = "%H:%M"; static constexpr int CLOCK_LENGTH = 6; const animation::text_field& field = anim->text_clock; if (field.font == nullptr || field.font->char_width == 0 || field.font->char_height == 0) return; time_t rawtime; time(&rawtime); tm* time_info = localtime(&rawtime); char clock_str[CLOCK_LENGTH]; size_t length = strftime(clock_str, CLOCK_LENGTH, CLOCK_FORMAT, time_info); if (length != CLOCK_LENGTH - 1) { LOGE("Could not format time\n"); return; } int x, y; determine_xy(field, length, &x, &y); LOGV("drawing clock %s %d %d\n", clock_str, x, y); gr_color(field.color_r, field.color_g, field.color_b, field.color_a); draw_text(field.font, x, y, clock_str); } void HealthdDraw::draw_percent(const animation* anim) { int cur_level = anim->cur_level; if (anim->cur_status == BATTERY_STATUS_FULL) { cur_level = 100; } if (cur_level <= 0) return; const animation::text_field& field = anim->text_percent; if (field.font == nullptr || field.font->char_width == 0 || field.font->char_height == 0) { return; } std::string str = base::StringPrintf("%d%%", cur_level); int x, y; determine_xy(field, str.size(), &x, &y); LOGV("drawing percent %s %d %d\n", str.c_str(), x, y); gr_color(field.color_r, field.color_g, field.color_b, field.color_a); draw_text(field.font, x, y, str.c_str()); } void HealthdDraw::draw_battery(const animation* anim) { const animation::frame& frame = anim->frames[anim->cur_frame]; if (anim->num_frames != 0) { draw_surface_centered(frame.surface); LOGV("drawing frame #%d min_cap=%d time=%d\n", anim->cur_frame, frame.min_level, frame.disp_time); } draw_clock(anim); draw_percent(anim); } void HealthdDraw::draw_unknown(GRSurface* surf_unknown) { int y; if (surf_unknown) { draw_surface_centered(surf_unknown); } else { gr_color(0xa4, 0xc6, 0x39, 255); y = draw_text(gr_sys_font(), -1, -1, "Charging!"); draw_text(gr_sys_font(), -1, y + 25, "?\?/100"); } } healthd/healthd_draw.h 0 → 100644 +75 −0 Original line number Diff line number Diff line /* * Copyright (C) 2017 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 HEALTHD_DRAW_H #define HEALTHD_DRAW_H #include <linux/input.h> #include <minui/minui.h> #include "animation.h" using namespace android; class HealthdDraw { public: // Configures font using given animation. HealthdDraw(animation* anim); virtual ~HealthdDraw(); // Redraws screen. void redraw_screen(const animation* batt_anim, GRSurface* surf_unknown); // Blanks screen if true, unblanks if false. virtual void blank_screen(bool blank); protected: virtual void clear_screen(); // returns the last y-offset of where the surface ends. virtual int draw_surface_centered(GRSurface* surface); // Negative x or y coordinates center text. virtual int draw_text(const GRFont* font, int x, int y, const char* str); // Negative x or y coordinates position the text away from the opposite edge // that positive ones do. virtual void determine_xy(const animation::text_field& field, const int length, int* x, int* y); // Draws battery animation, if it exists. virtual void draw_battery(const animation* anim); // Draws clock text, if animation contains text_field data. virtual void draw_clock(const animation* anim); // Draws battery percentage text if animation contains text_field data. virtual void draw_percent(const animation* anim); // Draws charger->surf_unknown or basic text. virtual void draw_unknown(GRSurface* surf_unknown); // Pixel sizes of characters for default font. int char_width_; int char_height_; // Width and height of screen in pixels. int screen_width_; int screen_height_; // Device screen is split vertically. const bool kSplitScreen; // Pixels to offset graphics towards center split. const int kSplitOffset; }; #endif // HEALTHD_DRAW_H Loading
healthd/Android.mk +26 −0 Original line number Diff line number Diff line Loading @@ -33,6 +33,30 @@ include $(BUILD_STATIC_LIBRARY) include $(CLEAR_VARS) LOCAL_MODULE := libhealthd_draw LOCAL_EXPORT_C_INCLUDE_DIRS := $(LOCAL_PATH) LOCAL_STATIC_LIBRARIES := \ libminui \ libbase LOCAL_SRC_FILES := healthd_draw.cpp ifneq ($(TARGET_HEALTHD_DRAW_SPLIT_SCREEN),) LOCAL_CFLAGS += -DHEALTHD_DRAW_SPLIT_SCREEN=$(TARGET_HEALTHD_DRAW_SPLIT_SCREEN) else LOCAL_CFLAGS += -DHEALTHD_DRAW_SPLIT_SCREEN=0 endif ifneq ($(TARGET_HEALTHD_DRAW_SPLIT_OFFSET),) LOCAL_CFLAGS += -DHEALTHD_DRAW_SPLIT_OFFSET=$(TARGET_HEALTHD_DRAW_SPLIT_OFFSET) else LOCAL_CFLAGS += -DHEALTHD_DRAW_SPLIT_OFFSET=0 endif include $(BUILD_STATIC_LIBRARY) include $(CLEAR_VARS) LOCAL_CFLAGS := -Werror ifeq ($(strip $(BOARD_CHARGER_DISABLE_INIT_BLANK)),true) LOCAL_CFLAGS += -DCHARGER_DISABLE_INIT_BLANK Loading @@ -58,6 +82,7 @@ LOCAL_STATIC_LIBRARIES := \ libutils \ libbase \ libcutils \ libhealthd_draw \ liblog \ libm \ libc \ Loading Loading @@ -101,6 +126,7 @@ endif LOCAL_STATIC_LIBRARIES := \ libhealthd_charger \ libhealthd_draw \ libbatterymonitor \ libbase \ libutils \ Loading
healthd/healthd_draw.cpp 0 → 100644 +195 −0 Original line number Diff line number Diff line /* * Copyright (C) 2017 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 <android-base/stringprintf.h> #include <batteryservice/BatteryService.h> #include <cutils/klog.h> #include "healthd_draw.h" #define LOGE(x...) KLOG_ERROR("charger", x); #define LOGV(x...) KLOG_DEBUG("charger", x); HealthdDraw::HealthdDraw(animation* anim) : kSplitScreen(HEALTHD_DRAW_SPLIT_SCREEN), kSplitOffset(HEALTHD_DRAW_SPLIT_OFFSET) { gr_init(); gr_font_size(gr_sys_font(), &char_width_, &char_height_); screen_width_ = gr_fb_width() / (kSplitScreen ? 2 : 1); screen_height_ = gr_fb_height(); int res; if (!anim->text_clock.font_file.empty() && (res = gr_init_font(anim->text_clock.font_file.c_str(), &anim->text_clock.font)) < 0) { LOGE("Could not load time font (%d)\n", res); } if (!anim->text_percent.font_file.empty() && (res = gr_init_font(anim->text_percent.font_file.c_str(), &anim->text_percent.font)) < 0) { LOGE("Could not load percent font (%d)\n", res); } } HealthdDraw::~HealthdDraw() {} void HealthdDraw::redraw_screen(const animation* batt_anim, GRSurface* surf_unknown) { clear_screen(); /* try to display *something* */ if (batt_anim->cur_level < 0 || batt_anim->num_frames == 0) draw_unknown(surf_unknown); else draw_battery(batt_anim); gr_flip(); } void HealthdDraw::blank_screen(bool blank) { gr_fb_blank(blank); } void HealthdDraw::clear_screen(void) { gr_color(0, 0, 0, 255); gr_clear(); } int HealthdDraw::draw_surface_centered(GRSurface* surface) { int w = gr_get_width(surface); int h = gr_get_height(surface); int x = (screen_width_ - w) / 2 + kSplitOffset; int y = (screen_height_ - h) / 2; LOGV("drawing surface %dx%d+%d+%d\n", w, h, x, y); gr_blit(surface, 0, 0, w, h, x, y); if (kSplitScreen) { x += screen_width_ - 2 * kSplitOffset; LOGV("drawing surface %dx%d+%d+%d\n", w, h, x, y); gr_blit(surface, 0, 0, w, h, x, y); } return y + h; } int HealthdDraw::draw_text(const GRFont* font, int x, int y, const char* str) { int str_len_px = gr_measure(font, str); if (x < 0) x = (screen_width_ - str_len_px) / 2; if (y < 0) y = (screen_height_ - char_height_) / 2; gr_text(font, x + kSplitOffset, y, str, false /* bold */); if (kSplitScreen) gr_text(font, x - kSplitOffset + screen_width_, y, str, false /* bold */); return y + char_height_; } void HealthdDraw::determine_xy(const animation::text_field& field, const int length, int* x, int* y) { *x = field.pos_x; int str_len_px = length * field.font->char_width; if (field.pos_x == CENTER_VAL) { *x = (screen_width_ - str_len_px) / 2; } else if (field.pos_x >= 0) { *x = field.pos_x; } else { // position from max edge *x = screen_width_ + field.pos_x - str_len_px - kSplitOffset; } *y = field.pos_y; if (field.pos_y == CENTER_VAL) { *y = (screen_height_ - field.font->char_height) / 2; } else if (field.pos_y >= 0) { *y = field.pos_y; } else { // position from max edge *y = screen_height_ + field.pos_y - field.font->char_height; } } void HealthdDraw::draw_clock(const animation* anim) { static constexpr char CLOCK_FORMAT[] = "%H:%M"; static constexpr int CLOCK_LENGTH = 6; const animation::text_field& field = anim->text_clock; if (field.font == nullptr || field.font->char_width == 0 || field.font->char_height == 0) return; time_t rawtime; time(&rawtime); tm* time_info = localtime(&rawtime); char clock_str[CLOCK_LENGTH]; size_t length = strftime(clock_str, CLOCK_LENGTH, CLOCK_FORMAT, time_info); if (length != CLOCK_LENGTH - 1) { LOGE("Could not format time\n"); return; } int x, y; determine_xy(field, length, &x, &y); LOGV("drawing clock %s %d %d\n", clock_str, x, y); gr_color(field.color_r, field.color_g, field.color_b, field.color_a); draw_text(field.font, x, y, clock_str); } void HealthdDraw::draw_percent(const animation* anim) { int cur_level = anim->cur_level; if (anim->cur_status == BATTERY_STATUS_FULL) { cur_level = 100; } if (cur_level <= 0) return; const animation::text_field& field = anim->text_percent; if (field.font == nullptr || field.font->char_width == 0 || field.font->char_height == 0) { return; } std::string str = base::StringPrintf("%d%%", cur_level); int x, y; determine_xy(field, str.size(), &x, &y); LOGV("drawing percent %s %d %d\n", str.c_str(), x, y); gr_color(field.color_r, field.color_g, field.color_b, field.color_a); draw_text(field.font, x, y, str.c_str()); } void HealthdDraw::draw_battery(const animation* anim) { const animation::frame& frame = anim->frames[anim->cur_frame]; if (anim->num_frames != 0) { draw_surface_centered(frame.surface); LOGV("drawing frame #%d min_cap=%d time=%d\n", anim->cur_frame, frame.min_level, frame.disp_time); } draw_clock(anim); draw_percent(anim); } void HealthdDraw::draw_unknown(GRSurface* surf_unknown) { int y; if (surf_unknown) { draw_surface_centered(surf_unknown); } else { gr_color(0xa4, 0xc6, 0x39, 255); y = draw_text(gr_sys_font(), -1, -1, "Charging!"); draw_text(gr_sys_font(), -1, y + 25, "?\?/100"); } }
healthd/healthd_draw.h 0 → 100644 +75 −0 Original line number Diff line number Diff line /* * Copyright (C) 2017 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 HEALTHD_DRAW_H #define HEALTHD_DRAW_H #include <linux/input.h> #include <minui/minui.h> #include "animation.h" using namespace android; class HealthdDraw { public: // Configures font using given animation. HealthdDraw(animation* anim); virtual ~HealthdDraw(); // Redraws screen. void redraw_screen(const animation* batt_anim, GRSurface* surf_unknown); // Blanks screen if true, unblanks if false. virtual void blank_screen(bool blank); protected: virtual void clear_screen(); // returns the last y-offset of where the surface ends. virtual int draw_surface_centered(GRSurface* surface); // Negative x or y coordinates center text. virtual int draw_text(const GRFont* font, int x, int y, const char* str); // Negative x or y coordinates position the text away from the opposite edge // that positive ones do. virtual void determine_xy(const animation::text_field& field, const int length, int* x, int* y); // Draws battery animation, if it exists. virtual void draw_battery(const animation* anim); // Draws clock text, if animation contains text_field data. virtual void draw_clock(const animation* anim); // Draws battery percentage text if animation contains text_field data. virtual void draw_percent(const animation* anim); // Draws charger->surf_unknown or basic text. virtual void draw_unknown(GRSurface* surf_unknown); // Pixel sizes of characters for default font. int char_width_; int char_height_; // Width and height of screen in pixels. int screen_width_; int screen_height_; // Device screen is split vertically. const bool kSplitScreen; // Pixels to offset graphics towards center split. const int kSplitOffset; }; #endif // HEALTHD_DRAW_H