Home | History | Annotate | Download | only in recovery_ui
      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 
    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