From c0441d171914e59941ec4f815ae0aabf56d6504f Mon Sep 17 00:00:00 2001 From: Doug Zongker Date: Wed, 31 Jul 2013 11:28:24 -0700 Subject: notify about pending long press Recovery changes: - add a method to the UI class that is called when a key is held down long enough to be a "long press" (but before it is released). Device-specific subclasses can override this to indicate a long press. - do color selection for ScreenRecoveryUI's menu-and-log drawing function. Subclasses can override this to customize the colors they use for various elements. - Include the value of ro.build.display.id in the menu headers, so you can see on the screen what version of recovery you are running. Change-Id: I426a6daf892b9011638e2035aebfa2831d4f596d --- recovery.cpp | 14 ++++++-------- screen_ui.cpp | 48 ++++++++++++++++++++++++++++++++++++++---------- screen_ui.h | 5 +++++ ui.cpp | 41 +++++++++++++++++++++++++++++++++-------- ui.h | 21 ++++++++++++++++++++- 5 files changed, 102 insertions(+), 27 deletions(-) diff --git a/recovery.cpp b/recovery.cpp index c5a589cc6..38366b65a 100644 --- a/recovery.cpp +++ b/recovery.cpp @@ -75,6 +75,7 @@ static const char *SIDELOAD_TEMP_DIR = "/tmp/sideload"; RecoveryUI* ui = NULL; char* locale = NULL; +char recovery_version[PROPERTY_VALUE_MAX+1]; /* * The recovery tool communicates with the main system through /cache files. @@ -526,21 +527,17 @@ copy_sideloaded_package(const char* original_path) { static const char** prepend_title(const char* const* headers) { - const char* title[] = { "Android system recovery <" - EXPAND(RECOVERY_API_VERSION) "e>", - "", - NULL }; - // count the number of lines in our title, plus the // caller-provided headers. - int count = 0; + int count = 3; // our title has 3 lines const char* const* p; - for (p = title; *p; ++p, ++count); for (p = headers; *p; ++p, ++count); const char** new_headers = (const char**)malloc((count+1) * sizeof(char*)); const char** h = new_headers; - for (p = title; *p; ++p, ++h) *h = *p; + *(h++) = "Android system recovery <" EXPAND(RECOVERY_API_VERSION) "e>"; + *(h++) = recovery_version; + *(h++) = ""; for (p = headers; *p; ++p, ++h) *h = *p; *h = NULL; @@ -1022,6 +1019,7 @@ main(int argc, char **argv) { printf("\n"); property_list(print_property, NULL); + property_get("ro.build.display.id", recovery_version, ""); printf("\n"); int status = INSTALL_SUCCESS; diff --git a/screen_ui.cpp b/screen_ui.cpp index 93e260936..6a638582e 100644 --- a/screen_ui.cpp +++ b/screen_ui.cpp @@ -196,9 +196,29 @@ void ScreenRecoveryUI::draw_progress_locked() } } -#define C_HEADER 247,0,6 -#define C_MENU 0,106,157 -#define C_LOG 249,194,0 +void ScreenRecoveryUI::SetColor(UIElement e) { + switch (e) { + case HEADER: + gr_color(247, 0, 6, 255); + break; + case MENU: + case MENU_SEL_BG: + gr_color(0, 106, 157, 255); + break; + case MENU_SEL_FG: + gr_color(255, 255, 255, 255); + break; + case LOG: + gr_color(249, 194, 0, 255); + break; + case TEXT_FILL: + gr_color(0, 0, 0, 160); + break; + default: + gr_color(255, 255, 255, 255); + break; + } +} // Redraw everything on the screen. Does not flip pages. // Should only be called with updateMutex locked. @@ -208,37 +228,38 @@ void ScreenRecoveryUI::draw_screen_locked() draw_progress_locked(); if (show_text) { - gr_color(0, 0, 0, 160); + SetColor(TEXT_FILL); gr_fill(0, 0, gr_fb_width(), gr_fb_height()); int y = 0; int i = 0; if (show_menu) { - gr_color(C_HEADER, 255); + SetColor(HEADER); for (; i < menu_top + menu_items; ++i) { - if (i == menu_top) gr_color(C_MENU, 255); + if (i == menu_top) SetColor(MENU); if (i == menu_top + menu_sel) { // draw the highlight bar + SetColor(MENU_SEL_BG); gr_fill(0, y-2, gr_fb_width(), y+char_height+2); // white text of selected item - gr_color(255, 255, 255, 255); + SetColor(MENU_SEL_FG); if (menu[i][0]) gr_text(4, y, menu[i], 1); - gr_color(C_MENU, 255); + SetColor(MENU); } else { if (menu[i][0]) gr_text(4, y, menu[i], i < menu_top); } y += char_height+4; } - gr_color(C_MENU, 255); + SetColor(MENU); y += 4; gr_fill(0, y, gr_fb_width(), y+2); y += 4; ++i; } - gr_color(C_LOG, 255); + SetColor(LOG); // display from the bottom up, until we hit the top of the // screen, the bottom of the menu, or we've displayed the @@ -585,3 +606,10 @@ void ScreenRecoveryUI::ShowText(bool visible) update_screen_locked(); pthread_mutex_unlock(&updateMutex); } + +void ScreenRecoveryUI::Redraw() +{ + pthread_mutex_lock(&updateMutex); + update_screen_locked(); + pthread_mutex_unlock(&updateMutex); +} diff --git a/screen_ui.h b/screen_ui.h index fe0de46e8..0bd220f74 100644 --- a/screen_ui.h +++ b/screen_ui.h @@ -53,6 +53,11 @@ class ScreenRecoveryUI : public RecoveryUI { int SelectMenu(int sel); void EndMenu(); + void Redraw(); + + enum UIElement { HEADER, MENU, MENU_SEL_BG, MENU_SEL_FG, LOG, TEXT_FILL }; + virtual void SetColor(UIElement e); + private: Icon currentIcon; int installingFrame; diff --git a/ui.cpp b/ui.cpp index 65f402821..cece02d31 100644 --- a/ui.cpp +++ b/ui.cpp @@ -46,7 +46,8 @@ static RecoveryUI* self = NULL; RecoveryUI::RecoveryUI() : key_queue_len(0), key_last_down(-1), - key_down_time(0) { + key_long_press(false), + key_down_count(0) { pthread_mutex_init(&key_queue_mutex, NULL); pthread_cond_init(&key_queue_cond, NULL); self = this; @@ -112,19 +113,22 @@ void RecoveryUI::process_key(int key_code, int updown) { bool register_key = false; bool long_press = false; - const long long_threshold = CLOCKS_PER_SEC * 750 / 1000; - pthread_mutex_lock(&key_queue_mutex); key_pressed[key_code] = updown; if (updown) { + ++key_down_count; key_last_down = key_code; - key_down_time = clock(); + 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); } else { if (key_last_down == key_code) { - long duration = clock() - key_down_time; - if (duration > long_threshold) { - long_press = true; - } + long_press = key_long_press; register_key = true; } key_last_down = -1; @@ -152,6 +156,24 @@ void RecoveryUI::process_key(int key_code, int updown) { } } +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; +} + +void RecoveryUI::time_key(int key_code, int count) { + usleep(750000); // 750 ms == "long" + bool long_press = false; + pthread_mutex_lock(&key_queue_mutex); + if (key_last_down == key_code && key_down_count == count) { + long_press = key_long_press = true; + } + pthread_mutex_unlock(&key_queue_mutex); + if (long_press) KeyLongPress(key_code); +} + void RecoveryUI::EnqueueKey(int key_code) { pthread_mutex_lock(&key_queue_mutex); const int queue_max = sizeof(key_queue) / sizeof(key_queue[0]); @@ -242,3 +264,6 @@ RecoveryUI::KeyAction RecoveryUI::CheckKey(int key) { void RecoveryUI::NextCheckKeyIsLong(bool is_long_press) { } + +void RecoveryUI::KeyLongPress(int key) { +} diff --git a/ui.h b/ui.h index aca7b7b87..6c8987a33 100644 --- a/ui.h +++ b/ui.h @@ -80,8 +80,17 @@ class RecoveryUI { enum KeyAction { ENQUEUE, TOGGLE, REBOOT, IGNORE }; virtual KeyAction CheckKey(int key); + // Called immediately before each call to CheckKey(), tell you if + // the key was long-pressed. virtual void NextCheckKeyIsLong(bool is_long_press); + // Called when a key is held down long enough to have been a + // long-press (but before the key is released). This means that + // if the key is eventually registered (released without any other + // keys being pressed in the meantime), NextCheckKeyIsLong() will + // be called with "true". + virtual void KeyLongPress(int key); + // --- menu display --- // Display some header text followed by a menu of items, which appears @@ -108,15 +117,25 @@ private: int key_queue[256], key_queue_len; char key_pressed[KEY_MAX + 1]; // under key_queue_mutex int key_last_down; // under key_queue_mutex - clock_t key_down_time; // under key_queue_mutex + bool key_long_press; // under key_queue_mutex + int key_down_count; // under key_queue_mutex int rel_sum; + typedef struct { + RecoveryUI* ui; + int key_code; + int count; + } key_timer_t; + pthread_t input_t; static void* input_thread(void* cookie); static int input_callback(int fd, short revents, void* data); void process_key(int key_code, int updown); bool usb_connected(); + + static void* time_key_helper(void* cookie); + void time_key(int key_code, int count); }; #endif // RECOVERY_UI_H -- cgit v1.2.3