diff options
Diffstat (limited to 'recovery_ui')
-rw-r--r-- | recovery_ui/Android.bp | 1 | ||||
-rw-r--r-- | recovery_ui/device.cpp | 13 | ||||
-rw-r--r-- | recovery_ui/include/recovery_ui/device.h | 12 | ||||
-rw-r--r-- | recovery_ui/include/recovery_ui/screen_ui.h | 3 | ||||
-rw-r--r-- | recovery_ui/include/recovery_ui/stub_ui.h | 6 | ||||
-rw-r--r-- | recovery_ui/include/recovery_ui/ui.h | 21 | ||||
-rw-r--r-- | recovery_ui/screen_ui.cpp | 46 | ||||
-rw-r--r-- | recovery_ui/stub_ui.cpp | 36 | ||||
-rw-r--r-- | recovery_ui/ui.cpp | 24 |
9 files changed, 121 insertions, 41 deletions
diff --git a/recovery_ui/Android.bp b/recovery_ui/Android.bp index ee3149d5e..149ef8acc 100644 --- a/recovery_ui/Android.bp +++ b/recovery_ui/Android.bp @@ -23,6 +23,7 @@ cc_library { srcs: [ "device.cpp", "screen_ui.cpp", + "stub_ui.cpp", "ui.cpp", "vr_ui.cpp", "wear_ui.cpp", diff --git a/recovery_ui/device.cpp b/recovery_ui/device.cpp index e7ae1a3e1..d46df92d3 100644 --- a/recovery_ui/device.cpp +++ b/recovery_ui/device.cpp @@ -23,6 +23,7 @@ #include <android-base/logging.h> +#include "otautil/boot_state.h" #include "recovery_ui/ui.h" static std::vector<std::pair<std::string, Device::BuiltinAction>> g_menu_actions{ @@ -95,3 +96,15 @@ int Device::HandleMenuKey(int key, bool visible) { return ui_->HasThreeButtons() ? kNoAction : kHighlightDown; } } + +void Device::SetBootState(const BootState* state) { + boot_state_ = state; +} + +std::optional<std::string> Device::GetReason() const { + return boot_state_ ? std::make_optional(boot_state_->reason()) : std::nullopt; +} + +std::optional<std::string> Device::GetStage() const { + return boot_state_ ? std::make_optional(boot_state_->stage()) : std::nullopt; +} diff --git a/recovery_ui/include/recovery_ui/device.h b/recovery_ui/include/recovery_ui/device.h index 7c76cdb0a..f4f993638 100644 --- a/recovery_ui/include/recovery_ui/device.h +++ b/recovery_ui/include/recovery_ui/device.h @@ -20,12 +20,15 @@ #include <stddef.h> #include <memory> +#include <optional> #include <string> #include <vector> // Forward declaration to avoid including "ui.h". class RecoveryUI; +class BootState; + class Device { public: static constexpr const int kNoAction = -1; @@ -58,6 +61,8 @@ class Device { REBOOT_FASTBOOT = 17, REBOOT_RECOVERY = 18, REBOOT_RESCUE = 19, + REBOOT_FROM_FASTBOOT = 20, + SHUTDOWN_FROM_FASTBOOT = 21, }; explicit Device(RecoveryUI* ui); @@ -124,9 +129,16 @@ class Device { return true; } + void SetBootState(const BootState* state); + // The getters for reason and stage may return std::nullopt until StartRecovery() is called. It's + // the caller's responsibility to perform the check and handle the exception. + std::optional<std::string> GetReason() const; + std::optional<std::string> GetStage() const; + private: // The RecoveryUI object that should be used to display the user interface for this device. std::unique_ptr<RecoveryUI> ui_; + const BootState* boot_state_{ nullptr }; }; // Disable name mangling, as this function will be loaded via dlsym(3). diff --git a/recovery_ui/include/recovery_ui/screen_ui.h b/recovery_ui/include/recovery_ui/screen_ui.h index 5cda2a2e5..92b3c2546 100644 --- a/recovery_ui/include/recovery_ui/screen_ui.h +++ b/recovery_ui/include/recovery_ui/screen_ui.h @@ -286,6 +286,9 @@ class ScreenRecoveryUI : public RecoveryUI, public DrawInterface { // selected. virtual int SelectMenu(int sel); + // Returns the help message displayed on top of the menu. + virtual std::vector<std::string> GetMenuHelpMessage() const; + virtual void draw_background_locked(); virtual void draw_foreground_locked(); virtual void draw_screen_locked(); diff --git a/recovery_ui/include/recovery_ui/stub_ui.h b/recovery_ui/include/recovery_ui/stub_ui.h index fb1d8c7a6..511b1314a 100644 --- a/recovery_ui/include/recovery_ui/stub_ui.h +++ b/recovery_ui/include/recovery_ui/stub_ui.h @@ -62,11 +62,9 @@ class StubRecoveryUI : public RecoveryUI { // menu display size_t ShowMenu(const std::vector<std::string>& /* headers */, - const std::vector<std::string>& /* items */, size_t initial_selection, + const std::vector<std::string>& /* items */, size_t /* initial_selection */, bool /* menu_only */, - const std::function<int(int, bool)>& /* key_handler */) override { - return initial_selection; - } + const std::function<int(int, bool)>& /* key_handler */) override; size_t ShowPromptWipeDataMenu(const std::vector<std::string>& /* backup_headers */, const std::vector<std::string>& /* backup_items */, diff --git a/recovery_ui/include/recovery_ui/ui.h b/recovery_ui/include/recovery_ui/ui.h index d55322cf0..08ec1d76a 100644 --- a/recovery_ui/include/recovery_ui/ui.h +++ b/recovery_ui/include/recovery_ui/ui.h @@ -27,6 +27,8 @@ #include <thread> #include <vector> +static constexpr const char* DEFAULT_LOCALE = "en-US"; + // Abstract class for controlling the user interface during recovery. class RecoveryUI { public: @@ -116,7 +118,7 @@ class RecoveryUI { // Returns true if you have the volume up/down and power trio typical of phones and tablets, false // otherwise. - virtual bool HasThreeButtons(); + virtual bool HasThreeButtons() const; // Returns true if it has a power key. virtual bool HasPowerKey() const; @@ -228,20 +230,23 @@ class RecoveryUI { bool InitScreensaver(); void SetScreensaverState(ScreensaverState state); + // Key event input queue std::mutex key_queue_mutex; std::condition_variable key_queue_cond; bool key_interrupted_; 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 - bool key_long_press; // under key_queue_mutex - int key_down_count; // under key_queue_mutex - bool enable_reboot; // under key_queue_mutex - int rel_sum; + // key press events + std::mutex key_press_mutex; + char key_pressed[KEY_MAX + 1]; + int key_last_down; + bool key_long_press; + int key_down_count; + bool enable_reboot; + + int rel_sum; int consecutive_power_keys; - int last_key; bool has_power_key; bool has_up_key; diff --git a/recovery_ui/screen_ui.cpp b/recovery_ui/screen_ui.cpp index 870db621c..087fc0e84 100644 --- a/recovery_ui/screen_ui.cpp +++ b/recovery_ui/screen_ui.cpp @@ -673,6 +673,19 @@ void ScreenRecoveryUI::SetTitle(const std::vector<std::string>& lines) { title_lines_ = lines; } +std::vector<std::string> ScreenRecoveryUI::GetMenuHelpMessage() const { + // clang-format off + static std::vector<std::string> REGULAR_HELP{ + "Use volume up/down and power.", + }; + static std::vector<std::string> LONG_PRESS_HELP{ + "Any button cycles highlight.", + "Long-press activates.", + }; + // clang-format on + return HasThreeButtons() ? REGULAR_HELP : LONG_PRESS_HELP; +} + // Redraws everything on the screen. Does not flip pages. Should only be called with updateMutex // locked. void ScreenRecoveryUI::draw_screen_locked() { @@ -685,16 +698,7 @@ void ScreenRecoveryUI::draw_screen_locked() { gr_color(0, 0, 0, 255); gr_clear(); - // clang-format off - static std::vector<std::string> REGULAR_HELP{ - "Use volume up/down and power.", - }; - static std::vector<std::string> LONG_PRESS_HELP{ - "Any button cycles highlight.", - "Long-press activates.", - }; - // clang-format on - draw_menu_and_text_buffer_locked(HasThreeButtons() ? REGULAR_HELP : LONG_PRESS_HELP); + draw_menu_and_text_buffer_locked(GetMenuHelpMessage()); } // Draws the menu and text buffer on the screen. Should only be called with updateMutex locked. @@ -817,12 +821,22 @@ std::unique_ptr<GRSurface> ScreenRecoveryUI::LoadBitmap(const std::string& filen std::unique_ptr<GRSurface> ScreenRecoveryUI::LoadLocalizedBitmap(const std::string& filename) { GRSurface* surface; - if (auto result = res_create_localized_alpha_surface(filename.c_str(), locale_.c_str(), &surface); - result < 0) { - LOG(ERROR) << "Failed to load bitmap " << filename << " (error " << result << ")"; - return nullptr; + auto result = res_create_localized_alpha_surface(filename.c_str(), locale_.c_str(), &surface); + if (result == 0) { + return std::unique_ptr<GRSurface>(surface); } - return std::unique_ptr<GRSurface>(surface); + // TODO(xunchang) create a error code enum to refine the retry condition. + LOG(WARNING) << "Failed to load bitmap " << filename << " for locale " << locale_ << " (error " + << result << "). Falling back to use default locale."; + + result = res_create_localized_alpha_surface(filename.c_str(), DEFAULT_LOCALE, &surface); + if (result == 0) { + return std::unique_ptr<GRSurface>(surface); + } + + LOG(ERROR) << "Failed to load bitmap " << filename << " for locale " << DEFAULT_LOCALE + << " (error " << result << ")"; + return nullptr; } static char** Alloc2d(size_t rows, size_t cols) { @@ -1253,7 +1267,7 @@ size_t ScreenRecoveryUI::ShowMenu(const std::vector<std::string>& headers, return initial_selection; } - return ShowMenu(CreateMenu(headers, items, initial_selection), menu_only, key_handler); + return ShowMenu(std::move(menu), menu_only, key_handler); } size_t ScreenRecoveryUI::ShowPromptWipeDataMenu(const std::vector<std::string>& backup_headers, diff --git a/recovery_ui/stub_ui.cpp b/recovery_ui/stub_ui.cpp new file mode 100644 index 000000000..a56b3f725 --- /dev/null +++ b/recovery_ui/stub_ui.cpp @@ -0,0 +1,36 @@ +/* + * Copyright (C) 2019 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "recovery_ui/stub_ui.h" + +#include <android-base/logging.h> + +#include "recovery_ui/device.h" + +size_t StubRecoveryUI::ShowMenu(const std::vector<std::string>& /* headers */, + const std::vector<std::string>& /* items */, + size_t /* initial_selection */, bool /* menu_only */, + const std::function<int(int, bool)>& /*key_handler*/) { + while (true) { + int key = WaitKey(); + // Exit the loop in the case of interruption or time out. + if (key == static_cast<int>(KeyError::INTERRUPTED) || + key == static_cast<int>(KeyError::TIMED_OUT)) { + return static_cast<size_t>(key); + } + } + LOG(FATAL) << "Unreachable key selected in ShowMenu of stub UI"; +} diff --git a/recovery_ui/ui.cpp b/recovery_ui/ui.cpp index b7107ff21..6f5cbbca6 100644 --- a/recovery_ui/ui.cpp +++ b/recovery_ui/ui.cpp @@ -70,7 +70,6 @@ RecoveryUI::RecoveryUI() key_down_count(0), enable_reboot(true), consecutive_power_keys(0), - last_key(-1), has_power_key(false), has_up_key(false), has_down_key(false), @@ -346,7 +345,7 @@ void RecoveryUI::ProcessKey(int key_code, int updown) { bool long_press = false; { - std::lock_guard<std::mutex> lg(key_queue_mutex); + std::lock_guard<std::mutex> lg(key_press_mutex); key_pressed[key_code] = updown; if (updown) { ++key_down_count; @@ -375,7 +374,7 @@ void RecoveryUI::ProcessKey(int key_code, int updown) { case RecoveryUI::REBOOT: if (reboot_enabled) { - reboot("reboot,"); + Reboot("userrequested,recovery,ui"); while (true) { pause(); } @@ -393,7 +392,7 @@ void RecoveryUI::TimeKey(int key_code, int count) { std::this_thread::sleep_for(750ms); // 750 ms == "long" bool long_press = false; { - std::lock_guard<std::mutex> lg(key_queue_mutex); + std::lock_guard<std::mutex> lg(key_press_mutex); if (key_last_down == key_code && key_down_count == count) { long_press = key_long_press = true; } @@ -419,7 +418,7 @@ void RecoveryUI::SetScreensaverState(ScreensaverState state) { LOG(INFO) << "Brightness: " << brightness_normal_value_ << " (" << brightness_normal_ << "%)"; } else { - LOG(ERROR) << "Unable to set brightness to normal"; + LOG(WARNING) << "Unable to set brightness to normal"; } break; case ScreensaverState::DIMMED: @@ -429,7 +428,7 @@ void RecoveryUI::SetScreensaverState(ScreensaverState state) { << "%)"; screensaver_state_ = ScreensaverState::DIMMED; } else { - LOG(ERROR) << "Unable to set brightness to dim"; + LOG(WARNING) << "Unable to set brightness to dim"; } break; case ScreensaverState::OFF: @@ -437,7 +436,7 @@ void RecoveryUI::SetScreensaverState(ScreensaverState state) { LOG(INFO) << "Brightness: 0 (off)"; screensaver_state_ = ScreensaverState::OFF; } else { - LOG(ERROR) << "Unable to set brightness to off"; + LOG(WARNING) << "Unable to set brightness to off"; } break; default: @@ -518,18 +517,18 @@ bool RecoveryUI::IsUsbConnected() { } bool RecoveryUI::IsKeyPressed(int key) { - std::lock_guard<std::mutex> lg(key_queue_mutex); + std::lock_guard<std::mutex> lg(key_press_mutex); int pressed = key_pressed[key]; return pressed; } bool RecoveryUI::IsLongPress() { - std::lock_guard<std::mutex> lg(key_queue_mutex); + std::lock_guard<std::mutex> lg(key_press_mutex); bool result = key_long_press; return result; } -bool RecoveryUI::HasThreeButtons() { +bool RecoveryUI::HasThreeButtons() const { return has_power_key && has_up_key && has_down_key; } @@ -548,7 +547,7 @@ void RecoveryUI::FlushKeys() { RecoveryUI::KeyAction RecoveryUI::CheckKey(int key, bool is_long_press) { { - std::lock_guard<std::mutex> lg(key_queue_mutex); + std::lock_guard<std::mutex> lg(key_press_mutex); key_long_press = false; } @@ -585,13 +584,12 @@ RecoveryUI::KeyAction RecoveryUI::CheckKey(int key, bool is_long_press) { consecutive_power_keys = 0; } - last_key = key; return (IsTextVisible() || screensaver_state_ == ScreensaverState::OFF) ? ENQUEUE : IGNORE; } void RecoveryUI::KeyLongPress(int) {} void RecoveryUI::SetEnableReboot(bool enabled) { - std::lock_guard<std::mutex> lg(key_queue_mutex); + std::lock_guard<std::mutex> lg(key_press_mutex); enable_reboot = enabled; } |