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_UI_H
     18 #define RECOVERY_UI_H
     19 
     20 #include <linux/input.h>  // KEY_MAX
     21 
     22 #include <atomic>
     23 #include <condition_variable>
     24 #include <functional>
     25 #include <mutex>
     26 #include <string>
     27 #include <thread>
     28 #include <vector>
     29 
     30 // Abstract class for controlling the user interface during recovery.
     31 class RecoveryUI {
     32  public:
     33   enum Icon {
     34     NONE,
     35     INSTALLING_UPDATE,
     36     ERASING,
     37     NO_COMMAND,
     38     ERROR,
     39   };
     40 
     41   enum ProgressType {
     42     EMPTY,
     43     INDETERMINATE,
     44     DETERMINATE,
     45   };
     46 
     47   enum KeyAction {
     48     ENQUEUE,
     49     TOGGLE,
     50     REBOOT,
     51     IGNORE,
     52   };
     53 
     54   enum class KeyError : int {
     55     TIMED_OUT = -1,
     56     INTERRUPTED = -2,
     57   };
     58 
     59   RecoveryUI();
     60 
     61   virtual ~RecoveryUI();
     62 
     63   // Initializes the object; called before anything else. UI texts will be initialized according
     64   // to the given locale. Returns true on success.
     65   virtual bool Init(const std::string& locale);
     66 
     67   virtual std::string GetLocale() const = 0;
     68 
     69   // Shows a stage indicator. Called immediately after Init().
     70   virtual void SetStage(int current, int max) = 0;
     71 
     72   // Sets the overall recovery state ("background image").
     73   virtual void SetBackground(Icon icon) = 0;
     74   virtual void SetSystemUpdateText(bool security_update) = 0;
     75 
     76   // --- progress indicator ---
     77   virtual void SetProgressType(ProgressType determinate) = 0;
     78 
     79   // Shows a progress bar and define the scope of the next operation:
     80   //   portion - fraction of the progress bar the next operation will use
     81   //   seconds - expected time interval (progress bar moves at this minimum rate)
     82   virtual void ShowProgress(float portion, float seconds) = 0;
     83 
     84   // Sets progress bar position (0.0 - 1.0 within the scope defined by the last call to
     85   // ShowProgress).
     86   virtual void SetProgress(float fraction) = 0;
     87 
     88   // --- text log ---
     89 
     90   virtual void ShowText(bool visible) = 0;
     91 
     92   virtual bool IsTextVisible() = 0;
     93 
     94   virtual bool WasTextEverVisible() = 0;
     95 
     96   // Writes a message to the on-screen log (shown if the user has toggled on the text display).
     97   // Print() will also dump the message to stdout / log file, while PrintOnScreenOnly() not.
     98   virtual void Print(const char* fmt, ...) __printflike(2, 3) = 0;
     99   virtual void PrintOnScreenOnly(const char* fmt, ...) __printflike(2, 3) = 0;
    100 
    101   // Shows the contents of the given file. Caller ensures the patition that contains the file has
    102   // been mounted.
    103   virtual void ShowFile(const std::string& filename) = 0;
    104 
    105   // --- key handling ---
    106 
    107   // Waits for a key and return it. May return TIMED_OUT after timeout and
    108   // KeyError::INTERRUPTED on a key interrupt.
    109   virtual int WaitKey();
    110 
    111   // Wakes up the UI if it is waiting on key input, causing WaitKey to return KeyError::INTERRUPTED.
    112   virtual void InterruptKey();
    113 
    114   virtual bool IsKeyPressed(int key);
    115   virtual bool IsLongPress();
    116 
    117   // Returns true if you have the volume up/down and power trio typical of phones and tablets, false
    118   // otherwise.
    119   virtual bool HasThreeButtons();
    120 
    121   // Returns true if it has a power key.
    122   virtual bool HasPowerKey() const;
    123 
    124   // Returns true if it supports touch inputs.
    125   virtual bool HasTouchScreen() const;
    126 
    127   // Erases any queued-up keys.
    128   virtual void FlushKeys();
    129 
    130   // Called on each key press, even while operations are in progress. Return value indicates whether
    131   // an immediate operation should be triggered (toggling the display, rebooting the device), or if
    132   // the key should be enqueued for use by the main thread.
    133   virtual KeyAction CheckKey(int key, bool is_long_press);
    134 
    135   // Called when a key is held down long enough to have been a long-press (but before the key is
    136   // released). This means that if the key is eventually registered (released without any other keys
    137   // being pressed in the meantime), CheckKey will be called with 'is_long_press' true.
    138   virtual void KeyLongPress(int key);
    139 
    140   // Normally in recovery there's a key sequence that triggers immediate reboot of the device,
    141   // regardless of what recovery is doing (with the default CheckKey implementation, it's pressing
    142   // the power button 7 times in row). Call this to enable or disable that feature. It is enabled by
    143   // default.
    144   virtual void SetEnableReboot(bool enabled);
    145 
    146   // --- menu display ---
    147 
    148   virtual void SetTitle(const std::vector<std::string>& lines) = 0;
    149 
    150   // Displays a menu with the given 'headers' and 'items'. The supplied 'key_handler' callback,
    151   // which is typically bound to Device::HandleMenuKey(), should return the expected action for the
    152   // given key code and menu visibility (e.g. to move the cursor or to select an item). Caller sets
    153   // 'menu_only' to true to ensure only a menu item gets selected and returned. Otherwise if
    154   // 'menu_only' is false, ShowMenu() will forward any non-negative value returned from the
    155   // key_handler, which may be beyond the range of menu items. This could be used to trigger a
    156   // device-specific action, even without that being listed in the menu. Caller needs to handle
    157   // such a case accordingly (e.g. by calling Device::InvokeMenuItem() to process the action).
    158   // Returns a non-negative value (the chosen item number or device-specific action code), or
    159   // static_cast<size_t>(TIMED_OUT) if timed out waiting for input or
    160   // static_cast<size_t>(ERR_KEY_INTERTUPT) if interrupted, such as by InterruptKey().
    161   virtual size_t ShowMenu(const std::vector<std::string>& headers,
    162                           const std::vector<std::string>& items, size_t initial_selection,
    163                           bool menu_only, const std::function<int(int, bool)>& key_handler) = 0;
    164 
    165   // Displays the localized wipe data menu with pre-generated graphs. If there's an issue
    166   // with the graphs, falls back to use the backup string headers and items instead. The initial
    167   // selection is the 0th item in the menu, which is expected to reboot the device without a wipe.
    168   virtual size_t ShowPromptWipeDataMenu(const std::vector<std::string>& backup_headers,
    169                                         const std::vector<std::string>& backup_items,
    170                                         const std::function<int(int, bool)>& key_handler) = 0;
    171   // Displays the localized wipe data confirmation menu with pre-generated images. Falls back to
    172   // the text strings upon failures. The initial selection is the 0th item, which returns to the
    173   // upper level menu.
    174   virtual size_t ShowPromptWipeDataConfirmationMenu(
    175       const std::vector<std::string>& backup_headers, const std::vector<std::string>& backup_items,
    176       const std::function<int(int, bool)>& key_handler) = 0;
    177 
    178   // Set whether or not the fastbootd logo is displayed.
    179   void SetEnableFastbootdLogo(bool enable) {
    180     fastbootd_logo_enabled_ = enable;
    181   }
    182 
    183   // Resets the key interrupt status.
    184   void ResetKeyInterruptStatus() {
    185     key_interrupted_ = false;
    186   }
    187 
    188   // Returns the key interrupt status.
    189   bool IsKeyInterrupted() const {
    190     return key_interrupted_;
    191   }
    192 
    193  protected:
    194   void EnqueueKey(int key_code);
    195 
    196   // The normal and dimmed brightness percentages (default: 50 and 25, which means 50% and 25% of
    197   // the max_brightness). Because the absolute values may vary across devices. These two values can
    198   // be configured via subclassing. Setting brightness_normal_ to 0 to disable screensaver.
    199   unsigned int brightness_normal_;
    200   unsigned int brightness_dimmed_;
    201   std::string brightness_file_;
    202   std::string max_brightness_file_;
    203 
    204   // Whether we should listen for touch inputs (default: false).
    205   bool touch_screen_allowed_;
    206 
    207   bool fastbootd_logo_enabled_;
    208 
    209  private:
    210   enum class ScreensaverState {
    211     DISABLED,
    212     NORMAL,
    213     DIMMED,
    214     OFF,
    215   };
    216 
    217   // The sensitivity when detecting a swipe.
    218   const int touch_low_threshold_;
    219   const int touch_high_threshold_;
    220 
    221   void OnKeyDetected(int key_code);
    222   void OnTouchDetected(int dx, int dy);
    223   int OnInputEvent(int fd, uint32_t epevents);
    224   void ProcessKey(int key_code, int updown);
    225   void TimeKey(int key_code, int count);
    226 
    227   bool IsUsbConnected();
    228 
    229   bool InitScreensaver();
    230   void SetScreensaverState(ScreensaverState state);
    231   // Key event input queue
    232   std::mutex key_queue_mutex;
    233   std::condition_variable key_queue_cond;
    234   bool key_interrupted_;
    235   int key_queue[256], key_queue_len;
    236   char key_pressed[KEY_MAX + 1];  // under key_queue_mutex
    237   int key_last_down;              // under key_queue_mutex
    238   bool key_long_press;            // under key_queue_mutex
    239   int key_down_count;             // under key_queue_mutex
    240   bool enable_reboot;             // under key_queue_mutex
    241   int rel_sum;
    242 
    243   int consecutive_power_keys;
    244   int last_key;
    245 
    246   bool has_power_key;
    247   bool has_up_key;
    248   bool has_down_key;
    249   bool has_touch_screen;
    250 
    251   // Touch event related variables. See the comments in RecoveryUI::OnInputEvent().
    252   int touch_slot_;
    253   int touch_X_;
    254   int touch_Y_;
    255   int touch_start_X_;
    256   int touch_start_Y_;
    257   bool touch_finger_down_;
    258   bool touch_swiping_;
    259   bool is_bootreason_recovery_ui_;
    260 
    261   std::thread input_thread_;
    262   std::atomic<bool> input_thread_stopped_{ false };
    263 
    264   ScreensaverState screensaver_state_;
    265 
    266   // The following two contain the absolute values computed from brightness_normal_ and
    267   // brightness_dimmed_ respectively.
    268   unsigned int brightness_normal_value_;
    269   unsigned int brightness_dimmed_value_;
    270 };
    271 
    272 #endif  // RECOVERY_UI_H
    273