1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
|
/*
* Copyright (C) 2011 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#ifndef RECOVERY_UI_H
#define RECOVERY_UI_H
#include <linux/input.h>
#include <pthread.h>
#include <time.h>
#include "messagesocket.h"
#include "voldclient.h"
#define MAX_NR_INPUT_DEVICES 8
#define MAX_NR_VKEYS 8
/*
* Simple representation of a (x,y) coordinate with convenience operators
*/
struct point {
point() : x(0), y(0) {}
point operator+(const point& rhs) const {
point tmp;
tmp.x = x + rhs.x;
tmp.y = y + rhs.y;
return tmp;
}
point operator-(const point& rhs) const {
point tmp;
tmp.x = x - rhs.x;
tmp.y = y - rhs.y;
return tmp;
}
int x;
int y;
};
/*
* Virtual key representation. Valid when keycode != -1.
*/
struct vkey {
vkey() : keycode(-1) {}
int keycode;
point min;
point max;
};
/*
* Input device representation. Valid when fd != -1.
* This holds all information and state related to a given input device.
*/
struct input_device {
input_device() : fd(-1) {}
int fd;
vkey virtual_keys[MAX_NR_VKEYS];
point touch_min;
point touch_max;
int rel_sum; // Accumulated relative movement
bool saw_pos_x; // Did sequence have ABS_MT_POSITION_X?
bool saw_pos_y; // Did sequence have ABS_MT_POSITION_Y?
bool saw_mt_report; // Did sequence have SYN_MT_REPORT?
bool saw_tracking_id; // Did sequence have SYN_TRACKING_ID?
bool in_touch; // Are we in a touch event?
bool in_swipe; // Are we in a swipe event?
point touch_pos; // Current touch coordinates
point touch_start; // Coordinates of touch start
point touch_track; // Last tracked coordinates
int slot_nr_active;
int slot_first;
int slot_current;
int tracking_id;
};
// Abstract class for controlling the user interface during recovery.
class RecoveryUI {
public:
RecoveryUI();
virtual ~RecoveryUI() { }
// Initialize the object; called before anything else.
virtual void Init();
// Show a stage indicator. Call immediately after Init().
virtual void SetStage(int current, int max) = 0;
// After calling Init(), you can tell the UI what locale it is operating in.
virtual void SetLocale(const char* locale) = 0;
// Set the overall recovery state ("background image").
enum Icon { NONE, INSTALLING_UPDATE, VIEWING_LOG, ERASING, NO_COMMAND, D_INFO, D_ERROR, HEADLESS, NR_ICONS };
virtual void SetBackground(Icon icon) = 0;
// --- progress indicator ---
enum ProgressType { EMPTY, INDETERMINATE, DETERMINATE };
virtual void SetProgressType(ProgressType determinate) = 0;
// Show a progress bar and define the scope of the next operation:
// portion - fraction of the progress bar the next operation will use
// seconds - expected time interval (progress bar moves at this minimum rate)
virtual void ShowProgress(float portion, float seconds) = 0;
// Set progress bar position (0.0 - 1.0 within the scope defined
// by the last call to ShowProgress).
virtual void SetProgress(float fraction) = 0;
// --- text log ---
virtual void ShowText(bool visible) = 0;
virtual bool IsTextVisible() = 0;
virtual bool WasTextEverVisible() = 0;
// Write a message to the on-screen log (shown if the user has
// toggled on the text display). Print() will also dump the message
// to stdout / log file, while PrintOnScreenOnly() not.
virtual void Print(const char* fmt, ...) __printflike(2, 3) = 0;
virtual void PrintOnScreenOnly(const char* fmt, ...) __printflike(2, 3) = 0;
virtual void ShowFile(const char* filename) = 0;
virtual void ClearText() = 0;
virtual void DialogShowInfo(const char* text) = 0;
virtual void DialogShowError(const char* text) = 0;
virtual void DialogShowErrorLog(const char* text) = 0;
virtual int DialogShowing() const = 0;
virtual bool DialogDismissable() const = 0;
virtual void DialogDismiss() = 0;
virtual void SetHeadlessMode() = 0;
// --- key handling ---
// Wait for a key and return it. May return -1 after timeout.
virtual int WaitKey();
// Cancel a WaitKey()
virtual void CancelWaitKey();
virtual bool IsKeyPressed(int key);
virtual bool IsLongPress();
// Returns true if you have the volume up/down and power trio typical
// of phones and tablets, false otherwise.
virtual bool HasThreeButtons();
// Erase any queued-up keys.
virtual void FlushKeys();
// Called on each key press, even while operations are in progress.
// Return value indicates whether an immediate operation should be
// triggered (toggling the display, rebooting the device), or if
// the key should be enqueued for use by the main thread.
enum KeyAction { ENQUEUE, TOGGLE, REBOOT, IGNORE };
virtual KeyAction CheckKey(int key, bool is_long_press);
// Called when a key is held down long enough to have been a
// long-press (but before the key is released). This means that
// if the key is eventually registered (released without any other
// keys being pressed in the meantime), CheckKey will be called with
// 'is_long_press' true.
virtual void KeyLongPress(int key);
// Normally in recovery there's a key sequence that triggers
// immediate reboot of the device, regardless of what recovery is
// doing (with the default CheckKey implementation, it's pressing
// the power button 7 times in row). Call this to enable or
// disable that feature. It is enabled by default.
virtual void SetEnableReboot(bool enabled);
// --- menu display ---
virtual int MenuItemStart() const = 0;
virtual int MenuItemHeight() const = 0;
// Display some header text followed by a menu of items, which appears
// at the top of the screen (in place of any scrolling ui_print()
// output, if necessary).
virtual void StartMenu(const char* const * headers, const char* const * items,
int initial_selection) = 0;
// Set the menu highlight to the given index, wrapping if necessary.
// Returns the actual item selected.
virtual int SelectMenu(int sel, bool abs = false) = 0;
// End menu mode, resetting the text overlay so that ui_print()
// statements will be displayed.
virtual void EndMenu() = 0;
// Notify of volume state change
void onVolumeChanged() { v_changed = 1; }
protected:
void EnqueueKey(int key_code);
private:
// Key event input queue
pthread_mutex_t key_queue_mutex;
pthread_cond_t key_queue_cond;
int key_queue[256], key_queue_len;
char key_pressed[KEY_MAX + 1]; // under key_queue_mutex
int key_last_down; // under key_queue_mutex
bool key_long_press; // under key_queue_mutex
int key_down_count; // under key_queue_mutex
bool enable_reboot; // under key_queue_mutex
int rel_sum;
int v_changed;
int consecutive_power_keys;
int last_key;
bool has_power_key;
bool has_up_key;
bool has_down_key;
input_device input_devices[MAX_NR_INPUT_DEVICES];
point fb_dimensions;
point min_swipe_px;
struct key_timer_t {
RecoveryUI* ui;
int key_code;
int count;
};
pthread_t input_thread_;
MessageSocket message_socket;
void OnKeyDetected(int key_code);
static int InputCallback(int fd, uint32_t epevents, void* data);
int OnInputEvent(int fd, uint32_t epevents);
void ProcessKey(input_device* dev, int key_code, int updown);
void ProcessSyn(input_device* dev, int code, int value);
void ProcessAbs(input_device* dev, int code, int value);
void ProcessRel(input_device* dev, int code, int value);
bool IsUsbConnected();
bool VolumesChanged();
static void* time_key_helper(void* cookie);
void time_key(int key_code, int count);
void process_touch(int fd, struct input_event *ev);
void calibrate_touch(input_device* dev);
void setup_vkeys(input_device* dev);
void calibrate_swipe();
void handle_press(input_device* dev);
void handle_release(input_device* dev);
void handle_gestures(input_device* dev);
};
#endif // RECOVERY_UI_H
|