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>
21 #include <pthread.h>
22 #include <time.h>
23 
24 #include <string>
25 
26 // Abstract class for controlling the user interface during recovery.
27 class RecoveryUI {
28  public:
29   enum Icon {
30     NONE,
31     INSTALLING_UPDATE,
32     ERASING,
33     NO_COMMAND,
34     ERROR
35   };
36 
37   enum ProgressType {
38     EMPTY,
39     INDETERMINATE,
40     DETERMINATE
41   };
42 
43   enum KeyAction {
44     ENQUEUE,
45     TOGGLE,
46     REBOOT,
47     IGNORE
48   };
49 
50   RecoveryUI();
51 
~RecoveryUI()52   virtual ~RecoveryUI() {}
53 
54   // Initializes the object; called before anything else. UI texts will be initialized according to
55   // the given locale. Returns true on success.
56   virtual bool Init(const std::string& locale);
57 
58   // Shows a stage indicator. Called immediately after Init().
59   virtual void SetStage(int current, int max) = 0;
60 
61   // Sets the overall recovery state ("background image").
62   virtual void SetBackground(Icon icon) = 0;
63   virtual void SetSystemUpdateText(bool security_update) = 0;
64 
65   // --- progress indicator ---
66   virtual void SetProgressType(ProgressType determinate) = 0;
67 
68   // Shows a progress bar and define the scope of the next operation:
69   //   portion - fraction of the progress bar the next operation will use
70   //   seconds - expected time interval (progress bar moves at this minimum rate)
71   virtual void ShowProgress(float portion, float seconds) = 0;
72 
73   // Sets progress bar position (0.0 - 1.0 within the scope defined by the last call to
74   // ShowProgress).
75   virtual void SetProgress(float fraction) = 0;
76 
77   // --- text log ---
78 
79   virtual void ShowText(bool visible) = 0;
80 
81   virtual bool IsTextVisible() = 0;
82 
83   virtual bool WasTextEverVisible() = 0;
84 
85   // Writes a message to the on-screen log (shown if the user has toggled on the text display).
86   // Print() will also dump the message to stdout / log file, while PrintOnScreenOnly() not.
87   virtual void Print(const char* fmt, ...) __printflike(2, 3) = 0;
88   virtual void PrintOnScreenOnly(const char* fmt, ...) __printflike(2, 3) = 0;
89 
90   virtual void ShowFile(const char* filename) = 0;
91 
92   // --- key handling ---
93 
94   // Waits for a key and return it. May return -1 after timeout.
95   virtual int WaitKey();
96 
97   virtual bool IsKeyPressed(int key);
98   virtual bool IsLongPress();
99 
100   // Returns true if you have the volume up/down and power trio typical of phones and tablets, false
101   // otherwise.
102   virtual bool HasThreeButtons();
103 
104   // Returns true if it has a power key.
105   virtual bool HasPowerKey() const;
106 
107   // Returns true if it supports touch inputs.
108   virtual bool HasTouchScreen() const;
109 
110   // Erases any queued-up keys.
111   virtual void FlushKeys();
112 
113   // Called on each key press, even while operations are in progress. Return value indicates whether
114   // an immediate operation should be triggered (toggling the display, rebooting the device), or if
115   // the key should be enqueued for use by the main thread.
116   virtual KeyAction CheckKey(int key, bool is_long_press);
117 
118   // Called when a key is held down long enough to have been a long-press (but before the key is
119   // released). This means that if the key is eventually registered (released without any other keys
120   // being pressed in the meantime), CheckKey will be called with 'is_long_press' true.
121   virtual void KeyLongPress(int key);
122 
123   // Normally in recovery there's a key sequence that triggers immediate reboot of the device,
124   // regardless of what recovery is doing (with the default CheckKey implementation, it's pressing
125   // the power button 7 times in row). Call this to enable or disable that feature. It is enabled by
126   // default.
127   virtual void SetEnableReboot(bool enabled);
128 
129   // --- menu display ---
130 
131   // Display some header text followed by a menu of items, which appears at the top of the screen
132   // (in place of any scrolling ui_print() output, if necessary).
133   virtual void StartMenu(const char* const* headers, const char* const* items,
134                          int initial_selection) = 0;
135 
136   // Sets the menu highlight to the given index, wrapping if necessary. Returns the actual item
137   // selected.
138   virtual int SelectMenu(int sel) = 0;
139 
140   // Ends menu mode, resetting the text overlay so that ui_print() statements will be displayed.
141   virtual void EndMenu() = 0;
142 
143  protected:
144   void EnqueueKey(int key_code);
145 
146   // The normal and dimmed brightness percentages (default: 50 and 25, which means 50% and 25% of
147   // the max_brightness). Because the absolute values may vary across devices. These two values can
148   // be configured via subclassing. Setting brightness_normal_ to 0 to disable screensaver.
149   unsigned int brightness_normal_;
150   unsigned int brightness_dimmed_;
151   std::string brightness_file_;
152   std::string max_brightness_file_;
153 
154   // Whether we should listen for touch inputs (default: false).
155   bool touch_screen_allowed_;
156 
157  private:
158   enum class ScreensaverState {
159     DISABLED,
160     NORMAL,
161     DIMMED,
162     OFF
163   };
164 
165   struct key_timer_t {
166     RecoveryUI* ui;
167     int key_code;
168     int count;
169   };
170 
171   // The sensitivity when detecting a swipe.
172   const int kTouchLowThreshold;
173   const int kTouchHighThreshold;
174 
175   void OnKeyDetected(int key_code);
176   void OnTouchDetected(int dx, int dy);
177   int OnInputEvent(int fd, uint32_t epevents);
178   void ProcessKey(int key_code, int updown);
179 
180   bool IsUsbConnected();
181 
182   static void* time_key_helper(void* cookie);
183   void time_key(int key_code, int count);
184 
185   bool InitScreensaver();
186 
187   // Key event input queue
188   pthread_mutex_t key_queue_mutex;
189   pthread_cond_t key_queue_cond;
190   int key_queue[256], key_queue_len;
191   char key_pressed[KEY_MAX + 1];  // under key_queue_mutex
192   int key_last_down;              // under key_queue_mutex
193   bool key_long_press;            // under key_queue_mutex
194   int key_down_count;             // under key_queue_mutex
195   bool enable_reboot;             // under key_queue_mutex
196   int rel_sum;
197 
198   int consecutive_power_keys;
199   int last_key;
200 
201   bool has_power_key;
202   bool has_up_key;
203   bool has_down_key;
204   bool has_touch_screen;
205 
206   // Touch event related variables. See the comments in RecoveryUI::OnInputEvent().
207   int touch_slot_;
208   int touch_X_;
209   int touch_Y_;
210   int touch_start_X_;
211   int touch_start_Y_;
212   bool touch_finger_down_;
213   bool touch_swiping_;
214   bool is_bootreason_recovery_ui_;
215 
216   pthread_t input_thread_;
217 
218   ScreensaverState screensaver_state_;
219 
220   // The following two contain the absolute values computed from brightness_normal_ and
221   // brightness_dimmed_ respectively.
222   unsigned int brightness_normal_value_;
223   unsigned int brightness_dimmed_value_;
224 };
225 
226 #endif  // RECOVERY_UI_H
227