Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Unverified Commit a6aa3504 authored by Chippa-a's avatar Chippa-a
Browse files

recovery_ui: Add support for battery capacity status



This is a reworked version from the older GUI
implementation (I89c963e75bbc40f4bb7204211773fbfb28a5206b).

- Update for the current recovery/fastbootd UI
- Use loop to update battery capacity in background
- Reflect charging status by appending "+"

Change-Id: If7a6c080da273dfedddffcbea5e0ce12e677bf2f
Signed-off-by: default avatarChippa-a <bagirovvusal99@gmail.com>
parent e5c3f128
Loading
Loading
Loading
Loading
+6 −0
Original line number Diff line number Diff line
@@ -43,13 +43,19 @@ cc_library {
    export_include_dirs: ["include"],

    static_libs: [
        "libbatterymonitor",
        "libhealthloop",
        "libminui",
        "libotautil",
    ],

    shared_libs: [
        "android.hardware.health-V1-ndk",
        "libbase",
        "libcutils",
        "libhidlbase",
        "libpng",
        "libutils",
        "libz",
        "libvolume_manager",
    ],
+8 −0
Original line number Diff line number Diff line
@@ -32,6 +32,7 @@
class GRSurface;

enum class UIElement {
  BATTERY_LOW,
  HEADER,
  MENU,
  MENU_SEL_BG,
@@ -392,6 +393,7 @@ class ScreenRecoveryUI : public RecoveryUI, public DrawInterface {
  virtual std::vector<std::string> GetMenuHelpMessage() const;

  virtual void draw_background_locked();
  virtual void draw_battery_capacity_locked();
  virtual void draw_foreground_locked();
  virtual void draw_screen_locked();
  virtual void draw_menu_and_text_buffer_locked(const std::vector<std::string>& help_message);
@@ -401,6 +403,7 @@ class ScreenRecoveryUI : public RecoveryUI, public DrawInterface {
  const GRSurface* GetCurrentFrame() const;
  const GRSurface* GetCurrentText() const;

  void BattMonitorThreadLoop();
  void ProgressThreadLoop();

  virtual void ShowFile(FILE*);
@@ -523,6 +526,11 @@ class ScreenRecoveryUI : public RecoveryUI, public DrawInterface {

  std::mutex updateMutex;

  std::thread batt_monitor_thread_;
  std::atomic<bool> batt_monitor_thread_stopped_{ false };
  int32_t batt_capacity_;
  bool charging_;

  // Switch the display to active one after graphics is ready
  bool is_graphics_available;

+122 −0
Original line number Diff line number Diff line
@@ -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 = 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,52 @@ 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) {
        LOG(WARNING) << "Using fake battery capacity 100.";
        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 +1189,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);