Merge "recovery: Add screensaver mode."
diff --git a/ui.cpp b/ui.cpp
index a0f741e..5efdc5a 100644
--- a/ui.cpp
+++ b/ui.cpp
@@ -32,7 +32,11 @@
#include <string>
+#include <android-base/file.h>
+#include <android-base/logging.h>
+#include <android-base/parseint.h>
#include <android-base/properties.h>
+#include <android-base/strings.h>
#include <cutils/android_reboot.h>
#include <minui/minui.h>
@@ -40,11 +44,15 @@
#include "roots.h"
#include "device.h"
-#define UI_WAIT_KEY_TIMEOUT_SEC 120
+static constexpr int UI_WAIT_KEY_TIMEOUT_SEC = 120;
+static constexpr const char* BRIGHTNESS_FILE = "/sys/class/leds/lcd-backlight/brightness";
+static constexpr const char* MAX_BRIGHTNESS_FILE = "/sys/class/leds/lcd-backlight/max_brightness";
RecoveryUI::RecoveryUI()
: locale_(""),
rtl_locale_(false),
+ brightness_normal_(50),
+ brightness_dimmed_(25),
key_queue_len(0),
key_last_down(-1),
key_long_press(false),
@@ -54,7 +62,8 @@
last_key(-1),
has_power_key(false),
has_up_key(false),
- has_down_key(false) {
+ has_down_key(false),
+ screensaver_state_(ScreensaverState::DISABLED) {
pthread_mutex_init(&key_queue_mutex, nullptr);
pthread_cond_init(&key_queue_cond, nullptr);
memset(key_pressed, 0, sizeof(key_pressed));
@@ -80,6 +89,40 @@
return nullptr;
}
+bool RecoveryUI::InitScreensaver() {
+ // Disabled.
+ if (brightness_normal_ == 0 || brightness_dimmed_ > brightness_normal_) {
+ return false;
+ }
+
+ // Set the initial brightness level based on the max brightness. Note that reading the initial
+ // value from BRIGHTNESS_FILE doesn't give the actual brightness value (bullhead, sailfish), so
+ // we don't have a good way to query the default value.
+ std::string content;
+ if (!android::base::ReadFileToString(MAX_BRIGHTNESS_FILE, &content)) {
+ LOG(WARNING) << "Failed to read max brightness: " << content;
+ return false;
+ }
+
+ unsigned int max_value;
+ if (!android::base::ParseUint(android::base::Trim(content), &max_value)) {
+ LOG(WARNING) << "Failed to parse max brightness: " << content;
+ return false;
+ }
+
+ brightness_normal_value_ = max_value * brightness_normal_ / 100.0;
+ brightness_dimmed_value_ = max_value * brightness_dimmed_ / 100.0;
+ if (!android::base::WriteStringToFile(std::to_string(brightness_normal_value_),
+ BRIGHTNESS_FILE)) {
+ PLOG(WARNING) << "Failed to set brightness";
+ return false;
+ }
+
+ LOG(INFO) << "Brightness: " << brightness_normal_value_ << " (" << brightness_normal_ << "%)";
+ screensaver_state_ = ScreensaverState::NORMAL;
+ return true;
+}
+
bool RecoveryUI::Init(const std::string& locale) {
// Set up the locale info.
SetLocale(locale);
@@ -88,6 +131,10 @@
ev_iterate_available_keys(std::bind(&RecoveryUI::OnKeyDetected, this, std::placeholders::_1));
+ if (!InitScreensaver()) {
+ LOG(INFO) << "Screensaver disabled";
+ }
+
pthread_create(&input_thread_, nullptr, InputThreadLoop, nullptr);
return true;
}
@@ -220,31 +267,65 @@
}
int RecoveryUI::WaitKey() {
- pthread_mutex_lock(&key_queue_mutex);
+ pthread_mutex_lock(&key_queue_mutex);
- // Time out after UI_WAIT_KEY_TIMEOUT_SEC, unless a USB cable is
- // plugged in.
- do {
- struct timeval now;
- struct timespec timeout;
- gettimeofday(&now, nullptr);
- timeout.tv_sec = now.tv_sec;
- timeout.tv_nsec = now.tv_usec * 1000;
- timeout.tv_sec += UI_WAIT_KEY_TIMEOUT_SEC;
+ // Time out after UI_WAIT_KEY_TIMEOUT_SEC, unless a USB cable is
+ // plugged in.
+ do {
+ struct timeval now;
+ struct timespec timeout;
+ gettimeofday(&now, nullptr);
+ timeout.tv_sec = now.tv_sec;
+ timeout.tv_nsec = now.tv_usec * 1000;
+ timeout.tv_sec += UI_WAIT_KEY_TIMEOUT_SEC;
- int rc = 0;
- while (key_queue_len == 0 && rc != ETIMEDOUT) {
- rc = pthread_cond_timedwait(&key_queue_cond, &key_queue_mutex, &timeout);
- }
- } while (IsUsbConnected() && key_queue_len == 0);
-
- int key = -1;
- if (key_queue_len > 0) {
- key = key_queue[0];
- memcpy(&key_queue[0], &key_queue[1], sizeof(int) * --key_queue_len);
+ int rc = 0;
+ while (key_queue_len == 0 && rc != ETIMEDOUT) {
+ rc = pthread_cond_timedwait(&key_queue_cond, &key_queue_mutex, &timeout);
}
- pthread_mutex_unlock(&key_queue_mutex);
- return key;
+
+ if (screensaver_state_ != ScreensaverState::DISABLED) {
+ if (rc == ETIMEDOUT) {
+ // Lower the brightness level: NORMAL -> DIMMED; DIMMED -> OFF.
+ if (screensaver_state_ == ScreensaverState::NORMAL) {
+ if (android::base::WriteStringToFile(std::to_string(brightness_dimmed_value_),
+ BRIGHTNESS_FILE)) {
+ LOG(INFO) << "Brightness: " << brightness_dimmed_value_ << " (" << brightness_dimmed_
+ << "%)";
+ screensaver_state_ = ScreensaverState::DIMMED;
+ }
+ } else if (screensaver_state_ == ScreensaverState::DIMMED) {
+ if (android::base::WriteStringToFile("0", BRIGHTNESS_FILE)) {
+ LOG(INFO) << "Brightness: 0 (off)";
+ screensaver_state_ = ScreensaverState::OFF;
+ }
+ }
+ } else if (screensaver_state_ != ScreensaverState::NORMAL) {
+ // Drop the first key if it's changing from OFF to NORMAL.
+ if (screensaver_state_ == ScreensaverState::OFF) {
+ if (key_queue_len > 0) {
+ memcpy(&key_queue[0], &key_queue[1], sizeof(int) * --key_queue_len);
+ }
+ }
+
+ // Reset the brightness to normal.
+ if (android::base::WriteStringToFile(std::to_string(brightness_normal_value_),
+ BRIGHTNESS_FILE)) {
+ screensaver_state_ = ScreensaverState::NORMAL;
+ LOG(INFO) << "Brightness: " << brightness_normal_value_ << " (" << brightness_normal_
+ << "%)";
+ }
+ }
+ }
+ } while (IsUsbConnected() && key_queue_len == 0);
+
+ int key = -1;
+ if (key_queue_len > 0) {
+ key = key_queue[0];
+ memcpy(&key_queue[0], &key_queue[1], sizeof(int) * --key_queue_len);
+ }
+ pthread_mutex_unlock(&key_queue_mutex);
+ return key;
}
bool RecoveryUI::IsUsbConnected() {
@@ -330,7 +411,7 @@
}
last_key = key;
- return IsTextVisible() ? ENQUEUE : IGNORE;
+ return (IsTextVisible() || screensaver_state_ == ScreensaverState::OFF) ? ENQUEUE : IGNORE;
}
void RecoveryUI::KeyLongPress(int) {
diff --git a/ui.h b/ui.h
index 53ce060..823eb65 100644
--- a/ui.h
+++ b/ui.h
@@ -130,6 +130,13 @@
std::string locale_;
bool rtl_locale_;
+ // The normal and dimmed brightness percentages (default: 50 and 25, which means 50% and 25%
+ // of the max_brightness). Because the absolute values may vary across devices. These two
+ // values can be configured via subclassing. Setting brightness_normal_ to 0 to disable
+ // screensaver.
+ unsigned int brightness_normal_;
+ unsigned int brightness_dimmed_;
+
private:
// Key event input queue
pthread_mutex_t key_queue_mutex;
@@ -167,6 +174,14 @@
void time_key(int key_code, int count);
void SetLocale(const std::string&);
+
+ enum class ScreensaverState { DISABLED, NORMAL, DIMMED, OFF };
+ ScreensaverState screensaver_state_;
+ // The following two contain the absolute values computed from brightness_normal_ and
+ // brightness_dimmed_ respectively.
+ unsigned int brightness_normal_value_;
+ unsigned int brightness_dimmed_value_;
+ bool InitScreensaver();
};
#endif // RECOVERY_UI_H