e5d1b62300
Log an error if minui init fails, and avoid subsequent calls to minui
in this case (which are likely to crash).
Warn if no system text font available. This is now expected on most
devices, and the fallback text is not expected to be needed, but just
in case.
Avoid the attempt to print text if no system font available, log
warnings instead.
Bug: 80249440
Test: manual: charger mode with no system font
Change-Id: Ib0c761d37e41a893b2a192438eebcf48c4827049
Merged-In: Ib0c761d37e41a893b2a192438eebcf48c4827049
(cherry picked from commit 8211515fbe
)
217 lines
6.5 KiB
C++
217 lines
6.5 KiB
C++
/*
|
|
* 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 LOGW(x...) KLOG_WARNING("charger", x);
|
|
#define LOGV(x...) KLOG_DEBUG("charger", x);
|
|
|
|
HealthdDraw::HealthdDraw(animation* anim)
|
|
: kSplitScreen(HEALTHD_DRAW_SPLIT_SCREEN),
|
|
kSplitOffset(HEALTHD_DRAW_SPLIT_OFFSET) {
|
|
int ret = gr_init();
|
|
|
|
if (ret < 0) {
|
|
LOGE("gr_init failed\n");
|
|
graphics_available = false;
|
|
return;
|
|
}
|
|
|
|
graphics_available = true;
|
|
sys_font = gr_sys_font();
|
|
if (sys_font == nullptr) {
|
|
LOGW("No system font, screen fallback text not available\n");
|
|
} else {
|
|
gr_font_size(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) {
|
|
if (!graphics_available) return;
|
|
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) {
|
|
if (!graphics_available) return;
|
|
gr_fb_blank(blank);
|
|
}
|
|
|
|
void HealthdDraw::clear_screen(void) {
|
|
if (!graphics_available) return;
|
|
gr_color(0, 0, 0, 255);
|
|
gr_clear();
|
|
}
|
|
|
|
int HealthdDraw::draw_surface_centered(GRSurface* surface) {
|
|
if (!graphics_available) return 0;
|
|
|
|
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) {
|
|
if (!graphics_available) return 0;
|
|
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 (!graphics_available || 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) {
|
|
if (!graphics_available) return;
|
|
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) {
|
|
if (!graphics_available) return;
|
|
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 if (sys_font) {
|
|
gr_color(0xa4, 0xc6, 0x39, 255);
|
|
y = draw_text(sys_font, -1, -1, "Charging!");
|
|
draw_text(sys_font, -1, y + 25, "?\?/100");
|
|
} else {
|
|
LOGW("Charging, level unknown\n");
|
|
}
|
|
}
|