aboutsummaryrefslogtreecommitdiff
path: root/recovery_ui/screen_ui.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'recovery_ui/screen_ui.cpp')
-rw-r--r--recovery_ui/screen_ui.cpp149
1 files changed, 148 insertions, 1 deletions
diff --git a/recovery_ui/screen_ui.cpp b/recovery_ui/screen_ui.cpp
index f7a6ee1f..5d713d6f 100644
--- a/recovery_ui/screen_ui.cpp
+++ b/recovery_ui/screen_ui.cpp
@@ -37,12 +37,17 @@
#include <unordered_map>
#include <vector>
+#include <aidl/android/hardware/health/BatteryStatus.h>
+
#include <android-base/chrono_utils.h>
#include <android-base/logging.h>
#include <android-base/properties.h>
#include <android-base/stringprintf.h>
#include <android-base/strings.h>
+#include <health/utils.h>
+#include <healthd/BatteryMonitor.h>
+
#include "minui/minui.h"
#include "otautil/paths.h"
#include "recovery_ui/device.h"
@@ -406,9 +411,16 @@ ScreenRecoveryUI::ScreenRecoveryUI()
max_stage(-1),
locale_(""),
rtl_locale_(false),
+ batt_capacity_(0),
+ charging_(false),
is_graphics_available(false) {}
ScreenRecoveryUI::~ScreenRecoveryUI() {
+ batt_monitor_thread_stopped_ = true;
+ if (batt_monitor_thread_.joinable()) {
+ batt_monitor_thread_.join();
+ }
+
progress_thread_stopped_ = true;
if (progress_thread_.joinable()) {
progress_thread_.join();
@@ -570,6 +582,12 @@ void ScreenRecoveryUI::draw_foreground_locked() {
fastboot light: #FDD835 */
void ScreenRecoveryUI::SetColor(UIElement e) const {
switch (e) {
+ case UIElement::BATTERY_LOW:
+ if (fastbootd_logo_enabled_)
+ gr_color(0xfd, 0x35, 0x35, 255);
+ else
+ gr_color(0xc7, 0x15, 0x85, 255);
+ break;
case UIElement::INFO:
if (fastbootd_logo_enabled_)
gr_color(0xfd, 0xd8, 0x35, 255);
@@ -807,6 +825,7 @@ void ScreenRecoveryUI::draw_screen_locked() {
gr_clear();
draw_menu_and_text_buffer_locked(GetMenuHelpMessage());
+ draw_battery_capacity_locked();
}
// Draws the menu and text buffer on the screen. Should only be called with updateMutex locked.
@@ -860,6 +879,60 @@ void ScreenRecoveryUI::draw_menu_and_text_buffer_locked(
}
}
+// Draws the battery capacity on the screen. Should only be called with updateMutex locked.
+void ScreenRecoveryUI::draw_battery_capacity_locked() {
+ int x;
+ int y = margin_height_ + gr_get_height(lineage_logo_.get());
+ int icon_x, icon_y, icon_h, icon_w;
+
+ // Battery status
+ std::string batt_capacity = std::to_string(batt_capacity_) + '%';
+
+ if (charging_)
+ batt_capacity.push_back('+');
+ else if (batt_capacity.back() == '+')
+ batt_capacity.pop_back();
+
+ if (menu_) {
+ // Battery icon
+ x = (ScreenWidth() - margin_width_ * 2 - kMenuIndent) - char_width_;
+
+ SetColor(UIElement::INFO);
+
+ // Top
+ icon_x = x + char_width_ / 3;
+ icon_y = y;
+ icon_w = char_width_ / 3;
+ icon_h = char_height_ / 12;
+ gr_fill(icon_x, icon_y, icon_x + icon_w, icon_y + icon_h);
+
+ // Main rect
+ icon_x = x;
+ icon_y = y + icon_h;
+ icon_w = char_width_;
+ icon_h = char_height_ - (char_height_ / 12);
+ gr_fill(icon_x, icon_y, icon_x + icon_w, icon_y + icon_h);
+
+ // Capacity
+ if (batt_capacity_ <= 15) SetColor(UIElement::BATTERY_LOW);
+ icon_x = x + char_width_ / 6;
+ icon_y = y + char_height_ / 12;
+ icon_w = char_width_ - (2 * char_width_ / 6);
+ icon_h = char_height_ - (3 * char_height_ / 12);
+ int cap_h = icon_h * batt_capacity_ / 100;
+ gr_fill(icon_x, icon_y + icon_h - cap_h, icon_x + icon_w, icon_y + icon_h);
+ gr_color(0, 0, 0, 255);
+ gr_fill(icon_x, icon_y, icon_x + icon_w, icon_y + icon_h - cap_h);
+
+ x -= char_width_; // Separator
+
+ // Battery text
+ SetColor(UIElement::INFO);
+ x -= batt_capacity.size() * char_width_;
+ DrawTextLine(x, icon_y, batt_capacity.c_str(), false);
+ }
+}
+
// Redraw everything on the screen and flip the screen (make it visible).
// Should only be called with updateMutex locked.
void ScreenRecoveryUI::update_screen_locked() {
@@ -879,6 +952,51 @@ void ScreenRecoveryUI::update_progress_locked() {
gr_flip();
}
+void ScreenRecoveryUI::BattMonitorThreadLoop() {
+ using aidl::android::hardware::health::BatteryStatus;
+ using android::hardware::health::InitHealthdConfig;
+
+ auto config = std::make_unique<healthd_config>();
+ InitHealthdConfig(config.get());
+
+ auto batt_monitor = std::make_unique<android::BatteryMonitor>();
+ batt_monitor->init(config.get());
+
+ while (!batt_monitor_thread_stopped_) {
+ bool redraw = false;
+ {
+ std::lock_guard<std::mutex> lg(updateMutex);
+
+ auto charge_status = static_cast<BatteryStatus>(batt_monitor->getChargeStatus());
+ // Treat unknown status as on charger.
+ bool charging = (charge_status != BatteryStatus::DISCHARGING &&
+ charge_status != BatteryStatus::NOT_CHARGING &&
+ charge_status != BatteryStatus::FULL);
+ if (charging_ != charging) {
+ charging_ = charging;
+ redraw = true;
+ }
+
+ android::BatteryProperty prop;
+ android::status_t status = batt_monitor->getProperty(android::BATTERY_PROP_CAPACITY, &prop);
+ // If we can't read battery percentage, it may be a device without battery. In this
+ // situation, use 100 as a fake battery percentage.
+ if (status != android::OK) {
+ prop.valueInt64 = 100;
+ }
+
+ int32_t batt_capacity = static_cast<int32_t>(prop.valueInt64);
+ if (batt_capacity_ != batt_capacity) {
+ batt_capacity_ = batt_capacity;
+ redraw = true;
+ }
+
+ if (redraw) update_screen_locked();
+ }
+ std::this_thread::sleep_for(5s);
+ }
+}
+
void ScreenRecoveryUI::ProgressThreadLoop() {
double interval = 1.0 / animation_fps_;
while (!progress_thread_stopped_) {
@@ -1070,6 +1188,9 @@ bool ScreenRecoveryUI::Init(const std::string& locale) {
LoadAnimation();
+ // Keep the battery capacity updated.
+ batt_monitor_thread_ = std::thread(&ScreenRecoveryUI::BattMonitorThreadLoop, this);
+
// Keep the progress bar updated, even when the process is otherwise busy.
progress_thread_ = std::thread(&ScreenRecoveryUI::ProgressThreadLoop, this);
@@ -1353,8 +1474,34 @@ int ScreenRecoveryUI::SelectMenu(int sel) {
}
int ScreenRecoveryUI::SelectMenu(const Point& p) {
+ Point point;
+
+ const auto scaleX = static_cast<double>(p.x()) / ScreenWidth();
+ const auto scaleY = static_cast<double>(p.y()) / ScreenHeight();
+
+ // Correct position for touch rotation
+ switch (gr_touch_rotation()) {
+ case GRRotation::NONE:
+ point.x(ScreenWidth() * scaleX);
+ point.y(ScreenHeight() * scaleY);
+ break;
+ case GRRotation::RIGHT:
+ point.x(ScreenWidth() * scaleY);
+ point.y(ScreenHeight() - (ScreenHeight() * scaleX));
+ break;
+ case GRRotation::DOWN:
+ point.x(ScreenWidth() - (ScreenWidth() * scaleX));
+ point.y(ScreenHeight() - (ScreenHeight() * scaleY));
+ break;
+ case GRRotation::LEFT:
+ point.x(ScreenWidth() - (ScreenWidth() * scaleY));
+ point.y(ScreenHeight() * scaleX);
+ break;
+ }
+
// Correct position for overscan
- const Point point(p.x() - gr_overscan_offset_x(), p.y() - gr_overscan_offset_y());
+ point.x(point.x() - gr_overscan_offset_x());
+ point.y(point.y() - gr_overscan_offset_y());
int new_sel = Device::kNoAction;
std::lock_guard<std::mutex> lg(updateMutex);