1 /* 2 * Copyright (C) 2011 The Android Open Source Project 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 */ 16 17 #ifndef RECOVERY_SCREEN_UI_H 18 #define RECOVERY_SCREEN_UI_H 19 20 #include <stdio.h> 21 22 #include <atomic> 23 #include <functional> 24 #include <memory> 25 #include <string> 26 #include <thread> 27 #include <vector> 28 29 #include "ui.h" 30 31 // From minui/minui.h. 32 class GRSurface; 33 34 enum class UIElement { 35 HEADER, 36 MENU, 37 MENU_SEL_BG, 38 MENU_SEL_BG_ACTIVE, 39 MENU_SEL_FG, 40 LOG, 41 TEXT_FILL, 42 INFO 43 }; 44 45 // Interface to draw the UI elements on the screen. 46 class DrawInterface { 47 public: 48 virtual ~DrawInterface() = default; 49 50 // Sets the color to the predefined value for |element|. 51 virtual void SetColor(UIElement element) const = 0; 52 53 // Draws a highlight bar at (x, y) - (x + width, y + height). 54 virtual void DrawHighlightBar(int x, int y, int width, int height) const = 0; 55 56 // Draws a horizontal rule at Y. Returns the offset it should be moving along Y-axis. 57 virtual int DrawHorizontalRule(int y) const = 0; 58 59 // Draws a line of text. Returns the offset it should be moving along Y-axis. 60 virtual int DrawTextLine(int x, int y, const std::string& line, bool bold) const = 0; 61 62 // Draws surface portion (sx, sy, w, h) at screen location (dx, dy). 63 virtual void DrawSurface(const GRSurface* surface, int sx, int sy, int w, int h, int dx, 64 int dy) const = 0; 65 66 // Draws rectangle at (x, y) - (x + w, y + h). 67 virtual void DrawFill(int x, int y, int w, int h) const = 0; 68 69 // Draws given surface (surface->pixel_bytes = 1) as text at (x, y). 70 virtual void DrawTextIcon(int x, int y, const GRSurface* surface) const = 0; 71 72 // Draws multiple text lines. Returns the offset it should be moving along Y-axis. 73 virtual int DrawTextLines(int x, int y, const std::vector<std::string>& lines) const = 0; 74 75 // Similar to DrawTextLines() to draw multiple text lines, but additionally wraps long lines. It 76 // keeps symmetrical margins of 'x' at each end of a line. Returns the offset it should be moving 77 // along Y-axis. 78 virtual int DrawWrappedTextLines(int x, int y, const std::vector<std::string>& lines) const = 0; 79 }; 80 81 // Interface for classes that maintain the menu selection and display. 82 class Menu { 83 public: 84 virtual ~Menu() = default; 85 // Returns the current menu selection. 86 size_t selection() const; 87 // Sets the current selection to |sel|. Handle the overflow cases depending on if the menu is 88 // scrollable. 89 virtual int Select(int sel) = 0; 90 // Displays the menu headers on the screen at offset x, y 91 virtual int DrawHeader(int x, int y) const = 0; 92 // Iterates over the menu items and displays each of them at offset x, y. 93 virtual int DrawItems(int x, int y, int screen_width, bool long_press) const = 0; 94 95 protected: 96 Menu(size_t initial_selection, const DrawInterface& draw_func); 97 // Current menu selection. 98 size_t selection_; 99 // Reference to the class that implements all the draw functions. 100 const DrawInterface& draw_funcs_; 101 }; 102 103 // This class uses strings as the menu header and items. 104 class TextMenu : public Menu { 105 public: 106 // Constructs a Menu instance with the given |headers|, |items| and properties. Sets the initial 107 // selection to |initial_selection|. 108 TextMenu(bool scrollable, size_t max_items, size_t max_length, 109 const std::vector<std::string>& headers, const std::vector<std::string>& items, 110 size_t initial_selection, int char_height, const DrawInterface& draw_funcs); 111 112 int Select(int sel) override; 113 int DrawHeader(int x, int y) const override; 114 int DrawItems(int x, int y, int screen_width, bool long_press) const override; 115 scrollable()116 bool scrollable() const { 117 return scrollable_; 118 } 119 120 // Returns count of menu items. 121 size_t ItemsCount() const; 122 123 // Returns the index of the first menu item. 124 size_t MenuStart() const; 125 126 // Returns the index of the last menu item + 1. 127 size_t MenuEnd() const; 128 129 // Menu example: 130 // info: Android Recovery 131 // .... 132 // help messages: Swipe up/down to move 133 // Swipe left/right to select 134 // empty line (horizontal rule): 135 // menu headers: Select file to view 136 // menu items: /cache/recovery/last_log 137 // /cache/recovery/last_log.1 138 // /cache/recovery/last_log.2 139 // ... 140 const std::vector<std::string>& text_headers() const; 141 std::string TextItem(size_t index) const; 142 143 // Checks if the menu items fit vertically on the screen. Returns true and set the 144 // |cur_selection_str| if the items exceed the screen limit. 145 bool ItemsOverflow(std::string* cur_selection_str) const; 146 147 private: 148 // The menu is scrollable to display more items. Used on wear devices who have smaller screens. 149 const bool scrollable_; 150 // The max number of menu items to fit vertically on a screen. 151 const size_t max_display_items_; 152 // The length of each item to fit horizontally on a screen. 153 const size_t max_item_length_; 154 // The menu headers. 155 std::vector<std::string> text_headers_; 156 // The actual menu items trimmed to fit the given properties. 157 std::vector<std::string> text_items_; 158 // The first item to display on the screen. 159 size_t menu_start_; 160 161 // Height in pixels of each character. 162 int char_height_; 163 }; 164 165 // This class uses GRSurface's as the menu header and items. 166 class GraphicMenu : public Menu { 167 public: 168 // Constructs a Menu instance with the given |headers|, |items| and properties. Sets the initial 169 // selection to |initial_selection|. |headers| and |items| will be made local copies. 170 GraphicMenu(const GRSurface* graphic_headers, const std::vector<const GRSurface*>& graphic_items, 171 size_t initial_selection, const DrawInterface& draw_funcs); 172 173 int Select(int sel) override; 174 int DrawHeader(int x, int y) const override; 175 int DrawItems(int x, int y, int screen_width, bool long_press) const override; 176 177 // Checks if all the header and items are valid GRSurface's; and that they can fit in the area 178 // defined by |max_width| and |max_height|. 179 static bool Validate(size_t max_width, size_t max_height, const GRSurface* graphic_headers, 180 const std::vector<const GRSurface*>& graphic_items); 181 182 // Returns true if |surface| fits on the screen with a vertical offset |y|. 183 static bool ValidateGraphicSurface(size_t max_width, size_t max_height, int y, 184 const GRSurface* surface); 185 186 private: 187 // Menu headers and items in graphic icons. These are the copies owned by the class instance. 188 std::unique_ptr<GRSurface> graphic_headers_; 189 std::vector<std::unique_ptr<GRSurface>> graphic_items_; 190 }; 191 192 // Implementation of RecoveryUI appropriate for devices with a screen 193 // (shows an icon + a progress bar, text logging, menu, etc.) 194 class ScreenRecoveryUI : public RecoveryUI, public DrawInterface { 195 public: 196 ScreenRecoveryUI(); 197 explicit ScreenRecoveryUI(bool scrollable_menu); 198 ~ScreenRecoveryUI() override; 199 200 bool Init(const std::string& locale) override; 201 std::string GetLocale() const override; 202 203 // overall recovery state ("background image") 204 void SetBackground(Icon icon) override; 205 void SetSystemUpdateText(bool security_update) override; 206 207 // progress indicator 208 void SetProgressType(ProgressType type) override; 209 void ShowProgress(float portion, float seconds) override; 210 void SetProgress(float fraction) override; 211 212 void SetStage(int current, int max) override; 213 214 // text log 215 void ShowText(bool visible) override; 216 bool IsTextVisible() override; 217 bool WasTextEverVisible() override; 218 219 // printing messages 220 void Print(const char* fmt, ...) override __printflike(2, 3); 221 void PrintOnScreenOnly(const char* fmt, ...) override __printflike(2, 3); 222 void ShowFile(const std::string& filename) override; 223 224 // menu display 225 size_t ShowMenu(const std::vector<std::string>& headers, const std::vector<std::string>& items, 226 size_t initial_selection, bool menu_only, 227 const std::function<int(int, bool)>& key_handler) override; 228 void SetTitle(const std::vector<std::string>& lines) override; 229 230 void KeyLongPress(int) override; 231 232 void Redraw(); 233 234 // Checks the background text image, for debugging purpose. It iterates the locales embedded in 235 // the on-device resource files and shows the localized text, for manual inspection. 236 void CheckBackgroundTextImages(); 237 238 // Displays the localized wipe data menu. 239 size_t ShowPromptWipeDataMenu(const std::vector<std::string>& backup_headers, 240 const std::vector<std::string>& backup_items, 241 const std::function<int(int, bool)>& key_handler) override; 242 243 // Displays the localized wipe data confirmation menu. 244 size_t ShowPromptWipeDataConfirmationMenu( 245 const std::vector<std::string>& backup_headers, const std::vector<std::string>& backup_items, 246 const std::function<int(int, bool)>& key_handler) override; 247 248 protected: 249 static constexpr int kMenuIndent = 4; 250 251 // The margin that we don't want to use for showing texts (e.g. round screen, or screen with 252 // rounded corners). 253 const int margin_width_; 254 const int margin_height_; 255 256 // Number of frames per sec (default: 30) for both parts of the animation. 257 const int animation_fps_; 258 259 // The scale factor from dp to pixels. 1.0 for mdpi, 4.0 for xxxhdpi. 260 const float density_; 261 262 virtual bool InitTextParams(); 263 264 virtual bool LoadWipeDataMenuText(); 265 266 // Creates a GraphicMenu with |graphic_header| and |graphic_items|. If the GraphicMenu isn't 267 // valid or it doesn't fit on the screen; falls back to create a TextMenu instead. If succeeds, 268 // returns a unique pointer to the created menu; otherwise returns nullptr. 269 virtual std::unique_ptr<Menu> CreateMenu(const GRSurface* graphic_header, 270 const std::vector<const GRSurface*>& graphic_items, 271 const std::vector<std::string>& text_headers, 272 const std::vector<std::string>& text_items, 273 size_t initial_selection) const; 274 275 // Creates a TextMenu with |text_headers| and |text_items|; and sets the menu selection to 276 // |initial_selection|. 277 virtual std::unique_ptr<Menu> CreateMenu(const std::vector<std::string>& text_headers, 278 const std::vector<std::string>& text_items, 279 size_t initial_selection) const; 280 281 // Takes the ownership of |menu| and displays it. 282 virtual size_t ShowMenu(std::unique_ptr<Menu>&& menu, bool menu_only, 283 const std::function<int(int, bool)>& key_handler); 284 285 // Sets the menu highlight to the given index, wrapping if necessary. Returns the actual item 286 // selected. 287 virtual int SelectMenu(int sel); 288 289 virtual void draw_background_locked(); 290 virtual void draw_foreground_locked(); 291 virtual void draw_screen_locked(); 292 virtual void draw_menu_and_text_buffer_locked(const std::vector<std::string>& help_message); 293 virtual void update_screen_locked(); 294 virtual void update_progress_locked(); 295 296 const GRSurface* GetCurrentFrame() const; 297 const GRSurface* GetCurrentText() const; 298 299 void ProgressThreadLoop(); 300 301 virtual void ShowFile(FILE*); 302 virtual void PrintV(const char*, bool, va_list); 303 void PutChar(char); 304 void ClearText(); 305 306 void LoadAnimation(); 307 std::unique_ptr<GRSurface> LoadBitmap(const std::string& filename); 308 std::unique_ptr<GRSurface> LoadLocalizedBitmap(const std::string& filename); 309 310 int PixelsFromDp(int dp) const; 311 virtual int GetAnimationBaseline() const; 312 virtual int GetProgressBaseline() const; 313 virtual int GetTextBaseline() const; 314 315 // Returns pixel width of draw buffer. 316 virtual int ScreenWidth() const; 317 // Returns pixel height of draw buffer. 318 virtual int ScreenHeight() const; 319 320 // Implementation of the draw functions in DrawInterface. 321 void SetColor(UIElement e) const override; 322 void DrawHighlightBar(int x, int y, int width, int height) const override; 323 int DrawHorizontalRule(int y) const override; 324 void DrawSurface(const GRSurface* surface, int sx, int sy, int w, int h, int dx, 325 int dy) const override; 326 void DrawFill(int x, int y, int w, int h) const override; 327 void DrawTextIcon(int x, int y, const GRSurface* surface) const override; 328 int DrawTextLine(int x, int y, const std::string& line, bool bold) const override; 329 int DrawTextLines(int x, int y, const std::vector<std::string>& lines) const override; 330 int DrawWrappedTextLines(int x, int y, const std::vector<std::string>& lines) const override; 331 332 // The layout to use. 333 int layout_; 334 335 // The images that contain localized texts. 336 std::unique_ptr<GRSurface> erasing_text_; 337 std::unique_ptr<GRSurface> error_text_; 338 std::unique_ptr<GRSurface> installing_text_; 339 std::unique_ptr<GRSurface> no_command_text_; 340 341 // Localized text images for the wipe data menu. 342 std::unique_ptr<GRSurface> cancel_wipe_data_text_; 343 std::unique_ptr<GRSurface> factory_data_reset_text_; 344 std::unique_ptr<GRSurface> try_again_text_; 345 std::unique_ptr<GRSurface> wipe_data_confirmation_text_; 346 std::unique_ptr<GRSurface> wipe_data_menu_header_text_; 347 348 std::unique_ptr<GRSurface> fastbootd_logo_; 349 350 // current_icon_ points to one of the frames in intro_frames_ or loop_frames_, indexed by 351 // current_frame_, or error_icon_. 352 Icon current_icon_; 353 std::unique_ptr<GRSurface> error_icon_; 354 std::vector<std::unique_ptr<GRSurface>> intro_frames_; 355 std::vector<std::unique_ptr<GRSurface>> loop_frames_; 356 size_t current_frame_; 357 bool intro_done_; 358 359 // progress_bar and stage_marker images. 360 std::unique_ptr<GRSurface> progress_bar_empty_; 361 std::unique_ptr<GRSurface> progress_bar_fill_; 362 std::unique_ptr<GRSurface> stage_marker_empty_; 363 std::unique_ptr<GRSurface> stage_marker_fill_; 364 365 ProgressType progressBarType; 366 367 float progressScopeStart, progressScopeSize, progress; 368 double progressScopeTime, progressScopeDuration; 369 370 // true when both graphics pages are the same (except for the progress bar). 371 bool pagesIdentical; 372 373 size_t text_cols_, text_rows_; 374 375 // Log text overlay, displayed when a magic key is pressed. 376 char** text_; 377 size_t text_col_, text_row_; 378 379 bool show_text; 380 bool show_text_ever; // has show_text ever been true? 381 382 std::vector<std::string> title_lines_; 383 384 bool scrollable_menu_; 385 std::unique_ptr<Menu> menu_; 386 387 // An alternate text screen, swapped with 'text_' when we're viewing a log file. 388 char** file_viewer_text_; 389 390 std::thread progress_thread_; 391 std::atomic<bool> progress_thread_stopped_{ false }; 392 393 int stage, max_stage; 394 395 int char_width_; 396 int char_height_; 397 398 // The locale that's used to show the rendered texts. 399 std::string locale_; 400 bool rtl_locale_; 401 402 std::mutex updateMutex; 403 404 private: 405 void SetLocale(const std::string&); 406 407 // Display the background texts for "erasing", "error", "no_command" and "installing" for the 408 // selected locale. 409 void SelectAndShowBackgroundText(const std::vector<std::string>& locales_entries, size_t sel); 410 }; 411 412 #endif // RECOVERY_UI_H 413