From ec28340cf3af1029a00db1c83d78d14e8798e245 Mon Sep 17 00:00:00 2001 From: Elliott Hughes Date: Fri, 10 Apr 2015 10:01:53 -0700 Subject: Move "Mount /system" to the main menu. Everyone's adding secret key combinations for this anyway, and it's very useful when debugging. Change-Id: Iad549452b872a7af963dd649f283ebcd3ea24234 --- ui.cpp | 56 ++++++++++++++++---------------------------------------- 1 file changed, 16 insertions(+), 40 deletions(-) (limited to 'ui.cpp') diff --git a/ui.cpp b/ui.cpp index c8f08cdd1..871624520 100644 --- a/ui.cpp +++ b/ui.cpp @@ -44,15 +44,14 @@ // so use a global variable. static RecoveryUI* self = NULL; -RecoveryUI::RecoveryUI() : - key_queue_len(0), - key_last_down(-1), - key_long_press(false), - key_down_count(0), - enable_reboot(true), - consecutive_power_keys(0), - consecutive_alternate_keys(0), - last_key(-1) { +RecoveryUI::RecoveryUI() + : key_queue_len(0), + key_last_down(-1), + key_long_press(false), + key_down_count(0), + enable_reboot(true), + consecutive_power_keys(0), + last_key(-1) { pthread_mutex_init(&key_queue_mutex, NULL); pthread_cond_init(&key_queue_cond, NULL); self = this; @@ -65,8 +64,7 @@ void RecoveryUI::Init() { } -int RecoveryUI::input_callback(int fd, uint32_t epevents, void* data) -{ +int RecoveryUI::input_callback(int fd, uint32_t epevents, void* data) { struct input_event ev; int ret; @@ -162,13 +160,6 @@ void RecoveryUI::process_key(int key_code, int updown) { case RecoveryUI::ENQUEUE: EnqueueKey(key_code); break; - - case RecoveryUI::MOUNT_SYSTEM: -#ifndef NO_RECOVERY_MOUNT - ensure_path_mounted("/system"); - Print("Mounted /system."); -#endif - break; } } } @@ -203,17 +194,16 @@ void RecoveryUI::EnqueueKey(int key_code) { // Reads input events, handles special hot keys, and adds to the key queue. -void* RecoveryUI::input_thread(void *cookie) -{ - for (;;) { - if (!ev_wait(-1)) +void* RecoveryUI::input_thread(void* cookie) { + while (true) { + if (!ev_wait(-1)) { ev_dispatch(); + } } return NULL; } -int RecoveryUI::WaitKey() -{ +int RecoveryUI::WaitKey() { pthread_mutex_lock(&key_queue_mutex); // Time out after UI_WAIT_KEY_TIMEOUT_SEC, unless a USB cable is @@ -228,8 +218,7 @@ int RecoveryUI::WaitKey() int rc = 0; while (key_queue_len == 0 && rc != ETIMEDOUT) { - rc = pthread_cond_timedwait(&key_queue_cond, &key_queue_mutex, - &timeout); + rc = pthread_cond_timedwait(&key_queue_cond, &key_queue_mutex, &timeout); } } while (usb_connected() && key_queue_len == 0); @@ -261,8 +250,7 @@ bool RecoveryUI::usb_connected() { return connected; } -bool RecoveryUI::IsKeyPressed(int key) -{ +bool RecoveryUI::IsKeyPressed(int key) { pthread_mutex_lock(&key_queue_mutex); int pressed = key_pressed[key]; pthread_mutex_unlock(&key_queue_mutex); @@ -301,18 +289,6 @@ RecoveryUI::KeyAction RecoveryUI::CheckKey(int key) { consecutive_power_keys = 0; } - if ((key == KEY_VOLUMEUP && - (last_key == KEY_VOLUMEDOWN || last_key == -1)) || - (key == KEY_VOLUMEDOWN && - (last_key == KEY_VOLUMEUP || last_key == -1))) { - ++consecutive_alternate_keys; - if (consecutive_alternate_keys >= 7) { - consecutive_alternate_keys = 0; - return MOUNT_SYSTEM; - } - } else { - consecutive_alternate_keys = 0; - } last_key = key; return ENQUEUE; -- cgit v1.2.3 From 642aaa7a3e11b2de719fc9decc45174bcc235c0c Mon Sep 17 00:00:00 2001 From: Elliott Hughes Date: Fri, 10 Apr 2015 12:47:46 -0700 Subject: Fix ScreenRecoveryUI to handle devices without power/up/down. Currently fugu has a custom subclass to handle this. The default code supports devices with trackballs but not all shipping Nexus devices? That's just silly. Change-Id: Id2779c91284899a26b4bb1af41e7033aa889df10 --- ui.cpp | 79 ++++++++++++++++++++++++++++++++++++++++++++++-------------------- 1 file changed, 55 insertions(+), 24 deletions(-) (limited to 'ui.cpp') diff --git a/ui.cpp b/ui.cpp index 871624520..064890ea4 100644 --- a/ui.cpp +++ b/ui.cpp @@ -51,26 +51,40 @@ RecoveryUI::RecoveryUI() key_down_count(0), enable_reboot(true), consecutive_power_keys(0), - last_key(-1) { + last_key(-1), + has_power_key(false), + has_up_key(false), + has_down_key(false) { pthread_mutex_init(&key_queue_mutex, NULL); pthread_cond_init(&key_queue_cond, NULL); self = this; memset(key_pressed, 0, sizeof(key_pressed)); } +void RecoveryUI::OnKeyDetected(int key_code) { + if (key_code == KEY_POWER) { + has_power_key = true; + } else if (key_code == KEY_DOWN || key_code == KEY_VOLUMEDOWN) { + has_down_key = true; + } else if (key_code == KEY_UP || key_code == KEY_VOLUMEUP) { + has_up_key = true; + } +} + void RecoveryUI::Init() { ev_init(input_callback, NULL); + + using namespace std::placeholders; + ev_iterate_available_keys(std::bind(&RecoveryUI::OnKeyDetected, this, _1)); + pthread_create(&input_t, NULL, input_thread, NULL); } - int RecoveryUI::input_callback(int fd, uint32_t epevents, void* data) { struct input_event ev; - int ret; - - ret = ev_get_input(fd, epevents, &ev); - if (ret) + if (ev_get_input(fd, epevents, &ev) == -1) { return -1; + } if (ev.type == EV_SYN) { return 0; @@ -95,8 +109,9 @@ int RecoveryUI::input_callback(int fd, uint32_t epevents, void* data) { self->rel_sum = 0; } - if (ev.type == EV_KEY && ev.code <= KEY_MAX) + if (ev.type == EV_KEY && ev.code <= KEY_MAX) { self->process_key(ev.code, ev.value); + } return 0; } @@ -142,8 +157,7 @@ void RecoveryUI::process_key(int key_code, int updown) { pthread_mutex_unlock(&key_queue_mutex); if (register_key) { - NextCheckKeyIsLong(long_press); - switch (CheckKey(key_code)) { + switch (CheckKey(key_code, long_press)) { case RecoveryUI::IGNORE: break; @@ -257,23 +271,44 @@ bool RecoveryUI::IsKeyPressed(int key) { return pressed; } +bool RecoveryUI::IsLongPress() { + pthread_mutex_lock(&key_queue_mutex); + bool result = key_long_press; + pthread_mutex_unlock(&key_queue_mutex); + return result; +} + void RecoveryUI::FlushKeys() { pthread_mutex_lock(&key_queue_mutex); key_queue_len = 0; pthread_mutex_unlock(&key_queue_mutex); } -// The default CheckKey implementation assumes the device has power, -// volume up, and volume down keys. -// -// - Hold power and press vol-up to toggle display. -// - Press power seven times in a row to reboot. -// - Alternate vol-up and vol-down seven times to mount /system. -RecoveryUI::KeyAction RecoveryUI::CheckKey(int key) { - if ((IsKeyPressed(KEY_POWER) && key == KEY_VOLUMEUP) || key == KEY_HOME) { - return TOGGLE; +RecoveryUI::KeyAction RecoveryUI::CheckKey(int key, bool is_long_press) { + pthread_mutex_lock(&key_queue_mutex); + key_long_press = false; + pthread_mutex_unlock(&key_queue_mutex); + + // If we have power and volume up keys, that chord is the signal to toggle the text display. + if (has_power_key && has_up_key) { + if (key == KEY_VOLUMEUP && IsKeyPressed(KEY_POWER)) { + return TOGGLE; + } + } else { + // Otherwise long press of any button toggles to the text display, + // and there's no way to toggle back (but that's pretty useless anyway). + if (is_long_press && !IsTextVisible()) { + return TOGGLE; + } + + // Also, for button-limited devices, a long press is translated to KEY_ENTER. + if (is_long_press && IsTextVisible()) { + EnqueueKey(KEY_ENTER); + return IGNORE; + } } + // Press power seven times in a row to reboot. if (key == KEY_POWER) { pthread_mutex_lock(&key_queue_mutex); bool reboot_enabled = enable_reboot; @@ -290,14 +325,10 @@ RecoveryUI::KeyAction RecoveryUI::CheckKey(int key) { } last_key = key; - - return ENQUEUE; -} - -void RecoveryUI::NextCheckKeyIsLong(bool is_long_press) { + return IsTextVisible() ? ENQUEUE : IGNORE; } -void RecoveryUI::KeyLongPress(int key) { +void RecoveryUI::KeyLongPress(int) { } void RecoveryUI::SetEnableReboot(bool enabled) { -- cgit v1.2.3 From 4af215b2c35b41e983753256ad6dbebbf879c982 Mon Sep 17 00:00:00 2001 From: Elliott Hughes Date: Fri, 10 Apr 2015 15:00:34 -0700 Subject: Auto-detect whether to use the long-press UI. Change-Id: Ie77a5584e301467c6a5e164d2c62d6f036b2c0c0 --- ui.cpp | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) (limited to 'ui.cpp') diff --git a/ui.cpp b/ui.cpp index 064890ea4..dbe5c5164 100644 --- a/ui.cpp +++ b/ui.cpp @@ -278,6 +278,10 @@ bool RecoveryUI::IsLongPress() { return result; } +bool RecoveryUI::HasThreeButtons() { + return has_power_key && has_up_key && has_down_key; +} + void RecoveryUI::FlushKeys() { pthread_mutex_lock(&key_queue_mutex); key_queue_len = 0; @@ -290,7 +294,7 @@ RecoveryUI::KeyAction RecoveryUI::CheckKey(int key, bool is_long_press) { pthread_mutex_unlock(&key_queue_mutex); // If we have power and volume up keys, that chord is the signal to toggle the text display. - if (has_power_key && has_up_key) { + if (HasThreeButtons()) { if (key == KEY_VOLUMEUP && IsKeyPressed(KEY_POWER)) { return TOGGLE; } -- cgit v1.2.3 From 985022a6231814de2bfaf621fd0725c48bb98411 Mon Sep 17 00:00:00 2001 From: Elliott Hughes Date: Mon, 13 Apr 2015 13:04:32 -0700 Subject: Remove unnecessary globals. Change-Id: I76a042432aede08ceaf250319cf5eeb25d601150 --- ui.cpp | 85 +++++++++++++++++++++++++++++++----------------------------------- 1 file changed, 40 insertions(+), 45 deletions(-) (limited to 'ui.cpp') diff --git a/ui.cpp b/ui.cpp index dbe5c5164..dca325fea 100644 --- a/ui.cpp +++ b/ui.cpp @@ -39,11 +39,6 @@ #define UI_WAIT_KEY_TIMEOUT_SEC 120 -// There's only (at most) one of these objects, and global callbacks -// (for pthread_create, and the input event system) need to find it, -// so use a global variable. -static RecoveryUI* self = NULL; - RecoveryUI::RecoveryUI() : key_queue_len(0), key_last_down(-1), @@ -55,9 +50,8 @@ RecoveryUI::RecoveryUI() has_power_key(false), has_up_key(false), has_down_key(false) { - pthread_mutex_init(&key_queue_mutex, NULL); - pthread_cond_init(&key_queue_cond, NULL); - self = this; + pthread_mutex_init(&key_queue_mutex, nullptr); + pthread_cond_init(&key_queue_cond, nullptr); memset(key_pressed, 0, sizeof(key_pressed)); } @@ -71,16 +65,29 @@ void RecoveryUI::OnKeyDetected(int key_code) { } } +int RecoveryUI::InputCallback(int fd, uint32_t epevents, void* data) { + return reinterpret_cast(data)->OnInputEvent(fd, epevents); +} + +// Reads input events, handles special hot keys, and adds to the key queue. +static void* InputThreadLoop(void*) { + while (true) { + if (!ev_wait(-1)) { + ev_dispatch(); + } + } + return nullptr; +} + void RecoveryUI::Init() { - ev_init(input_callback, NULL); + ev_init(InputCallback, this); - using namespace std::placeholders; - ev_iterate_available_keys(std::bind(&RecoveryUI::OnKeyDetected, this, _1)); + ev_iterate_available_keys(std::bind(&RecoveryUI::OnKeyDetected, this, std::placeholders::_1)); - pthread_create(&input_t, NULL, input_thread, NULL); + pthread_create(&input_thread_, nullptr, InputThreadLoop, nullptr); } -int RecoveryUI::input_callback(int fd, uint32_t epevents, void* data) { +int RecoveryUI::OnInputEvent(int fd, uint32_t epevents) { struct input_event ev; if (ev_get_input(fd, epevents, &ev) == -1) { return -1; @@ -94,23 +101,23 @@ int RecoveryUI::input_callback(int fd, uint32_t epevents, void* data) { // the trackball. When it exceeds a threshold // (positive or negative), fake an up/down // key event. - self->rel_sum += ev.value; - if (self->rel_sum > 3) { - self->process_key(KEY_DOWN, 1); // press down key - self->process_key(KEY_DOWN, 0); // and release it - self->rel_sum = 0; - } else if (self->rel_sum < -3) { - self->process_key(KEY_UP, 1); // press up key - self->process_key(KEY_UP, 0); // and release it - self->rel_sum = 0; + rel_sum += ev.value; + if (rel_sum > 3) { + ProcessKey(KEY_DOWN, 1); // press down key + ProcessKey(KEY_DOWN, 0); // and release it + rel_sum = 0; + } else if (rel_sum < -3) { + ProcessKey(KEY_UP, 1); // press up key + ProcessKey(KEY_UP, 0); // and release it + rel_sum = 0; } } } else { - self->rel_sum = 0; + rel_sum = 0; } if (ev.type == EV_KEY && ev.code <= KEY_MAX) { - self->process_key(ev.code, ev.value); + ProcessKey(ev.code, ev.value); } return 0; @@ -128,7 +135,7 @@ int RecoveryUI::input_callback(int fd, uint32_t epevents, void* data) { // a key is registered. // // updown == 1 for key down events; 0 for key up events -void RecoveryUI::process_key(int key_code, int updown) { +void RecoveryUI::ProcessKey(int key_code, int updown) { bool register_key = false; bool long_press = false; bool reboot_enabled; @@ -139,13 +146,13 @@ void RecoveryUI::process_key(int key_code, int updown) { ++key_down_count; key_last_down = key_code; key_long_press = false; - pthread_t th; key_timer_t* info = new key_timer_t; info->ui = this; info->key_code = key_code; info->count = key_down_count; - pthread_create(&th, NULL, &RecoveryUI::time_key_helper, info); - pthread_detach(th); + pthread_t thread; + pthread_create(&thread, nullptr, &RecoveryUI::time_key_helper, info); + pthread_detach(thread); } else { if (key_last_down == key_code) { long_press = key_long_press; @@ -182,7 +189,7 @@ void* RecoveryUI::time_key_helper(void* cookie) { key_timer_t* info = (key_timer_t*) cookie; info->ui->time_key(info->key_code, info->count); delete info; - return NULL; + return nullptr; } void RecoveryUI::time_key(int key_code, int count) { @@ -206,17 +213,6 @@ void RecoveryUI::EnqueueKey(int key_code) { pthread_mutex_unlock(&key_queue_mutex); } - -// Reads input events, handles special hot keys, and adds to the key queue. -void* RecoveryUI::input_thread(void* cookie) { - while (true) { - if (!ev_wait(-1)) { - ev_dispatch(); - } - } - return NULL; -} - int RecoveryUI::WaitKey() { pthread_mutex_lock(&key_queue_mutex); @@ -225,7 +221,7 @@ int RecoveryUI::WaitKey() { do { struct timeval now; struct timespec timeout; - gettimeofday(&now, NULL); + gettimeofday(&now, nullptr); timeout.tv_sec = now.tv_sec; timeout.tv_nsec = now.tv_usec * 1000; timeout.tv_sec += UI_WAIT_KEY_TIMEOUT_SEC; @@ -234,7 +230,7 @@ int RecoveryUI::WaitKey() { while (key_queue_len == 0 && rc != ETIMEDOUT) { rc = pthread_cond_timedwait(&key_queue_cond, &key_queue_mutex, &timeout); } - } while (usb_connected() && key_queue_len == 0); + } while (IsUsbConnected() && key_queue_len == 0); int key = -1; if (key_queue_len > 0) { @@ -245,8 +241,7 @@ int RecoveryUI::WaitKey() { return key; } -// Return true if USB is connected. -bool RecoveryUI::usb_connected() { +bool RecoveryUI::IsUsbConnected() { int fd = open("/sys/class/android_usb/android0/state", O_RDONLY); if (fd < 0) { printf("failed to open /sys/class/android_usb/android0/state: %s\n", @@ -255,7 +250,7 @@ bool RecoveryUI::usb_connected() { } char buf; - /* USB is connected if android_usb state is CONNECTED or CONFIGURED */ + // USB is connected if android_usb state is CONNECTED or CONFIGURED. int connected = (read(fd, &buf, 1) == 1) && (buf == 'C'); if (close(fd) < 0) { printf("failed to close /sys/class/android_usb/android0/state: %s\n", -- cgit v1.2.3 From 2f5feedf1d705b53e5bf90c8b5207dd91f4522f1 Mon Sep 17 00:00:00 2001 From: Elliott Hughes Date: Tue, 28 Apr 2015 17:24:24 -0700 Subject: Check all lseek calls succeed. Also add missing TEMP_FAILURE_RETRYs on read, write, and lseek. Bug: http://b/20625546 Change-Id: I03b198e11c1921b35518ee2dd005a7cfcf4fd94b (cherry picked from commit 7bad7c4646ee8fd8d6e6ed0ffd3ddbb0c1b41a2f) --- ui.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'ui.cpp') diff --git a/ui.cpp b/ui.cpp index dca325fea..1a0b079cc 100644 --- a/ui.cpp +++ b/ui.cpp @@ -251,7 +251,7 @@ bool RecoveryUI::IsUsbConnected() { char buf; // USB is connected if android_usb state is CONNECTED or CONFIGURED. - int connected = (read(fd, &buf, 1) == 1) && (buf == 'C'); + int connected = (TEMP_FAILURE_RETRY(read(fd, &buf, 1)) == 1) && (buf == 'C'); if (close(fd) < 0) { printf("failed to close /sys/class/android_usb/android0/state: %s\n", strerror(errno)); -- cgit v1.2.3