• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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.
SetEnableFastbootdLogo(bool enable)179   void SetEnableFastbootdLogo(bool enable) {
180     fastbootd_logo_enabled_ = enable;
181   }
182 
183   // Resets the key interrupt status.
ResetKeyInterruptStatus()184   void ResetKeyInterruptStatus() {
185     key_interrupted_ = false;
186   }
187 
188   // Returns the key interrupt status.
IsKeyInterrupted()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