aboutsummaryrefslogtreecommitdiffstats
path: root/ui.cpp
diff options
context:
space:
mode:
authorTao Bao2017-01-16 19:38:18 -0600
committerTao Bao2017-01-30 18:12:30 -0600
commit6278bdf3490a2f6682f5a9c47350b3d9f92a9165 (patch)
treed6ea708f810fc06bc0c33d8386b3d01f035c25a5 /ui.cpp
parent56ff8061b1bc58cf646a14054485b617e916f423 (diff)
downloadplatform-bootable-recovery-6278bdf3490a2f6682f5a9c47350b3d9f92a9165.tar.gz
platform-bootable-recovery-6278bdf3490a2f6682f5a9c47350b3d9f92a9165.tar.xz
platform-bootable-recovery-6278bdf3490a2f6682f5a9c47350b3d9f92a9165.zip
recovery: Add screensaver mode.
While it's waiting for user input, dim or turn off the backlight to avoid OLED burn-in. The backlight brightness will be reduced after the first timeout (default 120s), and then turned off after the second. Pressing any key will take it back to the normal brightness. While the display is off, the first key input will only turn on the backlight. The most common case that triggers the screensaver is under text mode, such as waiting for menu selection or viewing recovery logs. This CL doesn't change the brightness while it's installing updates or performing wipes under UI mode. When it encounters any install error under UI mode (user builds): - If it's NOT USB connected, it will reboot automatically after the first timeout (same as before); - If it's USB connected, it will dim and turn off the display per the change in this CL. Bug: 34077703 Test: Boot a device with the new recovery image. Wait for timeout. Change-Id: I0c14907e60340a7f037adb6e464942d099ada08b
Diffstat (limited to 'ui.cpp')
-rw-r--r--ui.cpp129
1 files changed, 105 insertions, 24 deletions
diff --git a/ui.cpp b/ui.cpp
index a0f741e5..5efdc5a4 100644
--- a/ui.cpp
+++ b/ui.cpp
@@ -32,7 +32,11 @@
32 32
33#include <string> 33#include <string>
34 34
35#include <android-base/file.h>
36#include <android-base/logging.h>
37#include <android-base/parseint.h>
35#include <android-base/properties.h> 38#include <android-base/properties.h>
39#include <android-base/strings.h>
36#include <cutils/android_reboot.h> 40#include <cutils/android_reboot.h>
37#include <minui/minui.h> 41#include <minui/minui.h>
38 42
@@ -40,11 +44,15 @@
40#include "roots.h" 44#include "roots.h"
41#include "device.h" 45#include "device.h"
42 46
43#define UI_WAIT_KEY_TIMEOUT_SEC 120 47static constexpr int UI_WAIT_KEY_TIMEOUT_SEC = 120;
48static constexpr const char* BRIGHTNESS_FILE = "/sys/class/leds/lcd-backlight/brightness";
49static constexpr const char* MAX_BRIGHTNESS_FILE = "/sys/class/leds/lcd-backlight/max_brightness";
44 50
45RecoveryUI::RecoveryUI() 51RecoveryUI::RecoveryUI()
46 : locale_(""), 52 : locale_(""),
47 rtl_locale_(false), 53 rtl_locale_(false),
54 brightness_normal_(50),
55 brightness_dimmed_(25),
48 key_queue_len(0), 56 key_queue_len(0),
49 key_last_down(-1), 57 key_last_down(-1),
50 key_long_press(false), 58 key_long_press(false),
@@ -54,7 +62,8 @@ RecoveryUI::RecoveryUI()
54 last_key(-1), 62 last_key(-1),
55 has_power_key(false), 63 has_power_key(false),
56 has_up_key(false), 64 has_up_key(false),
57 has_down_key(false) { 65 has_down_key(false),
66 screensaver_state_(ScreensaverState::DISABLED) {
58 pthread_mutex_init(&key_queue_mutex, nullptr); 67 pthread_mutex_init(&key_queue_mutex, nullptr);
59 pthread_cond_init(&key_queue_cond, nullptr); 68 pthread_cond_init(&key_queue_cond, nullptr);
60 memset(key_pressed, 0, sizeof(key_pressed)); 69 memset(key_pressed, 0, sizeof(key_pressed));
@@ -80,6 +89,40 @@ static void* InputThreadLoop(void*) {
80 return nullptr; 89 return nullptr;
81} 90}
82 91
92bool RecoveryUI::InitScreensaver() {
93 // Disabled.
94 if (brightness_normal_ == 0 || brightness_dimmed_ > brightness_normal_) {
95 return false;
96 }
97
98 // Set the initial brightness level based on the max brightness. Note that reading the initial
99 // value from BRIGHTNESS_FILE doesn't give the actual brightness value (bullhead, sailfish), so
100 // we don't have a good way to query the default value.
101 std::string content;
102 if (!android::base::ReadFileToString(MAX_BRIGHTNESS_FILE, &content)) {
103 LOG(WARNING) << "Failed to read max brightness: " << content;
104 return false;
105 }
106
107 unsigned int max_value;
108 if (!android::base::ParseUint(android::base::Trim(content), &max_value)) {
109 LOG(WARNING) << "Failed to parse max brightness: " << content;
110 return false;
111 }
112
113 brightness_normal_value_ = max_value * brightness_normal_ / 100.0;
114 brightness_dimmed_value_ = max_value * brightness_dimmed_ / 100.0;
115 if (!android::base::WriteStringToFile(std::to_string(brightness_normal_value_),
116 BRIGHTNESS_FILE)) {
117 PLOG(WARNING) << "Failed to set brightness";
118 return false;
119 }
120
121 LOG(INFO) << "Brightness: " << brightness_normal_value_ << " (" << brightness_normal_ << "%)";
122 screensaver_state_ = ScreensaverState::NORMAL;
123 return true;
124}
125
83bool RecoveryUI::Init(const std::string& locale) { 126bool RecoveryUI::Init(const std::string& locale) {
84 // Set up the locale info. 127 // Set up the locale info.
85 SetLocale(locale); 128 SetLocale(locale);
@@ -88,6 +131,10 @@ bool RecoveryUI::Init(const std::string& locale) {
88 131
89 ev_iterate_available_keys(std::bind(&RecoveryUI::OnKeyDetected, this, std::placeholders::_1)); 132 ev_iterate_available_keys(std::bind(&RecoveryUI::OnKeyDetected, this, std::placeholders::_1));
90 133
134 if (!InitScreensaver()) {
135 LOG(INFO) << "Screensaver disabled";
136 }
137
91 pthread_create(&input_thread_, nullptr, InputThreadLoop, nullptr); 138 pthread_create(&input_thread_, nullptr, InputThreadLoop, nullptr);
92 return true; 139 return true;
93} 140}
@@ -220,31 +267,65 @@ void RecoveryUI::EnqueueKey(int key_code) {
220} 267}
221 268
222int RecoveryUI::WaitKey() { 269int RecoveryUI::WaitKey() {
223 pthread_mutex_lock(&key_queue_mutex); 270 pthread_mutex_lock(&key_queue_mutex);
271
272 // Time out after UI_WAIT_KEY_TIMEOUT_SEC, unless a USB cable is
273 // plugged in.
274 do {
275 struct timeval now;
276 struct timespec timeout;
277 gettimeofday(&now, nullptr);
278 timeout.tv_sec = now.tv_sec;
279 timeout.tv_nsec = now.tv_usec * 1000;
280 timeout.tv_sec += UI_WAIT_KEY_TIMEOUT_SEC;
281
282 int rc = 0;
283 while (key_queue_len == 0 && rc != ETIMEDOUT) {
284 rc = pthread_cond_timedwait(&key_queue_cond, &key_queue_mutex, &timeout);
285 }
224 286
225 // Time out after UI_WAIT_KEY_TIMEOUT_SEC, unless a USB cable is 287 if (screensaver_state_ != ScreensaverState::DISABLED) {
226 // plugged in. 288 if (rc == ETIMEDOUT) {
227 do { 289 // Lower the brightness level: NORMAL -> DIMMED; DIMMED -> OFF.
228 struct timeval now; 290 if (screensaver_state_ == ScreensaverState::NORMAL) {
229 struct timespec timeout; 291 if (android::base::WriteStringToFile(std::to_string(brightness_dimmed_value_),
230 gettimeofday(&now, nullptr); 292 BRIGHTNESS_FILE)) {
231 timeout.tv_sec = now.tv_sec; 293 LOG(INFO) << "Brightness: " << brightness_dimmed_value_ << " (" << brightness_dimmed_
232 timeout.tv_nsec = now.tv_usec * 1000; 294 << "%)";
233 timeout.tv_sec += UI_WAIT_KEY_TIMEOUT_SEC; 295 screensaver_state_ = ScreensaverState::DIMMED;
234 296 }
235 int rc = 0; 297 } else if (screensaver_state_ == ScreensaverState::DIMMED) {
236 while (key_queue_len == 0 && rc != ETIMEDOUT) { 298 if (android::base::WriteStringToFile("0", BRIGHTNESS_FILE)) {
237 rc = pthread_cond_timedwait(&key_queue_cond, &key_queue_mutex, &timeout); 299 LOG(INFO) << "Brightness: 0 (off)";
300 screensaver_state_ = ScreensaverState::OFF;
301 }
302 }
303 } else if (screensaver_state_ != ScreensaverState::NORMAL) {
304 // Drop the first key if it's changing from OFF to NORMAL.
305 if (screensaver_state_ == ScreensaverState::OFF) {
306 if (key_queue_len > 0) {
307 memcpy(&key_queue[0], &key_queue[1], sizeof(int) * --key_queue_len);
308 }
238 } 309 }
239 } while (IsUsbConnected() && key_queue_len == 0);
240 310
241 int key = -1; 311 // Reset the brightness to normal.
242 if (key_queue_len > 0) { 312 if (android::base::WriteStringToFile(std::to_string(brightness_normal_value_),
243 key = key_queue[0]; 313 BRIGHTNESS_FILE)) {
244 memcpy(&key_queue[0], &key_queue[1], sizeof(int) * --key_queue_len); 314 screensaver_state_ = ScreensaverState::NORMAL;
315 LOG(INFO) << "Brightness: " << brightness_normal_value_ << " (" << brightness_normal_
316 << "%)";
317 }
318 }
245 } 319 }
246 pthread_mutex_unlock(&key_queue_mutex); 320 } while (IsUsbConnected() && key_queue_len == 0);
247 return key; 321
322 int key = -1;
323 if (key_queue_len > 0) {
324 key = key_queue[0];
325 memcpy(&key_queue[0], &key_queue[1], sizeof(int) * --key_queue_len);
326 }
327 pthread_mutex_unlock(&key_queue_mutex);
328 return key;
248} 329}
249 330
250bool RecoveryUI::IsUsbConnected() { 331bool RecoveryUI::IsUsbConnected() {
@@ -330,7 +411,7 @@ RecoveryUI::KeyAction RecoveryUI::CheckKey(int key, bool is_long_press) {
330 } 411 }
331 412
332 last_key = key; 413 last_key = key;
333 return IsTextVisible() ? ENQUEUE : IGNORE; 414 return (IsTextVisible() || screensaver_state_ == ScreensaverState::OFF) ? ENQUEUE : IGNORE;
334} 415}
335 416
336void RecoveryUI::KeyLongPress(int) { 417void RecoveryUI::KeyLongPress(int) {