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_DEVICE_H
18 #define _RECOVERY_DEVICE_H
19 
20 #include <stddef.h>
21 
22 #include <memory>
23 #include <optional>
24 #include <string>
25 #include <vector>
26 
27 // Forward declaration to avoid including "ui.h".
28 class RecoveryUI;
29 
30 class BootState;
31 
32 class Device {
33  public:
34   static constexpr const int kNoAction = -1;
35   static constexpr const int kHighlightUp = -2;
36   static constexpr const int kHighlightDown = -3;
37   static constexpr const int kInvokeItem = -4;
38 
39   // ENTER vs REBOOT: The latter will trigger a reboot that goes through bootloader, which allows
40   // using a new bootloader / recovery image if applicable. For example, REBOOT_RESCUE goes from
41   // rescue -> bootloader -> rescue, whereas ENTER_RESCUE switches from recovery -> rescue
42   // directly.
43   enum BuiltinAction {
44     NO_ACTION = 0,
45     REBOOT = 1,
46     APPLY_SDCARD = 2,
47     // APPLY_CACHE was 3.
48     APPLY_ADB_SIDELOAD = 4,
49     WIPE_DATA = 5,
50     WIPE_CACHE = 6,
51     REBOOT_BOOTLOADER = 7,
52     SHUTDOWN = 8,
53     VIEW_RECOVERY_LOGS = 9,
54     MOUNT_SYSTEM = 10,
55     RUN_GRAPHICS_TEST = 11,
56     RUN_LOCALE_TEST = 12,
57     KEY_INTERRUPTED = 13,
58     ENTER_FASTBOOT = 14,
59     ENTER_RECOVERY = 15,
60     ENTER_RESCUE = 16,
61     REBOOT_FASTBOOT = 17,
62     REBOOT_RECOVERY = 18,
63     REBOOT_RESCUE = 19,
64     REBOOT_FROM_FASTBOOT = 20,
65     SHUTDOWN_FROM_FASTBOOT = 21,
66   };
67 
68   explicit Device(RecoveryUI* ui);
~Device()69   virtual ~Device() {}
70 
71   // Returns a raw pointer to the RecoveryUI object.
GetUI()72   virtual RecoveryUI* GetUI() {
73     return ui_.get();
74   }
75 
76   // Resets the UI object to the given UI. Used to override the default UI in case initialization
77   // failed, or we want a different UI for some reason. The device object will take the ownership.
ResetUI(RecoveryUI * ui)78   virtual void ResetUI(RecoveryUI* ui) {
79     ui_.reset(ui);
80   }
81 
82   // Called before recovery mode started up, to perform whatever device-specific recovery mode
83   // preparation as needed.
PreRecovery()84   virtual void PreRecovery() {}
85 
86   // Called when recovery starts up (after the UI has been obtained and initialized and after the
87   // arguments have been parsed, but before anything else).
StartRecovery()88   virtual void StartRecovery() {}
89 
90   // Called before fastboot mode is started up, to perform whatever device-specific fastboot mode
91   // preparation as needed.
PreFastboot()92   virtual void PreFastboot() {}
93 
94   // Called when fastboot starts up (after the UI has been obtained and initialized and after the
95   // arguments have been parsed, but before anything else).
StartFastboot()96   virtual void StartFastboot() {}
97 
98   // Called from the main thread when recovery is at the main menu and waiting for input, and a key
99   // is pressed. (Note that "at" the main menu does not necessarily mean the menu is visible;
100   // recovery will be at the main menu with it invisible after an unsuccessful operation, such as
101   // failed to install an OTA package, or if recovery is started with no command.)
102   //
103   // 'key' is the code of the key just pressed. (You can call IsKeyPressed() on the RecoveryUI
104   // object you returned from GetUI() if you want to find out if other keys are held down.)
105   //
106   // 'visible' is true if the menu is visible.
107   //
108   // Returns one of the defined constants below in order to:
109   //   - move the menu highlight (kHighlight{Up,Down}: negative value)
110   //   - invoke the highlighted item (kInvokeItem: negative value)
111   //   - do nothing (kNoAction: negative value)
112   //   - invoke a specific action (a menu position: non-negative value)
113   virtual int HandleMenuKey(int key, bool visible);
114 
115   // Returns the list of menu items (a vector of strings). The menu_position passed to
116   // InvokeMenuItem() will correspond to the indexes into this array.
117   virtual const std::vector<std::string>& GetMenuItems();
118 
119   // Performs a recovery action selected from the menu. 'menu_position' will be the index of the
120   // selected menu item, or a non-negative value returned from HandleMenuKey(). The menu will be
121   // hidden when this is called; implementations can call GetUI()->Print() to print information to
122   // the screen. If the menu position is one of the builtin actions, you can just return the
123   // corresponding enum value. If it is an action specific to your device, you actually perform it
124   // here and return NO_ACTION.
125   virtual BuiltinAction InvokeMenuItem(size_t menu_position);
126 
127   // Removes the menu item for the given action. This allows tailoring the menu based on the
128   // runtime info, such as the availability of /cache or /sdcard.
129   virtual void RemoveMenuItemForAction(Device::BuiltinAction action);
130 
131   // Called before and after we do a wipe data/factory reset operation, either via a reboot from the
132   // main system with the --wipe_data flag, or when the user boots into recovery image manually and
133   // selects the option from the menu, to perform whatever device-specific wiping actions as needed.
134   // Returns true on success; returning false from PreWipeData will prevent the regular wipe, and
135   // returning false from PostWipeData will cause the wipe to be considered a failure.
PreWipeData()136   virtual bool PreWipeData() {
137     return true;
138   }
139 
PostWipeData()140   virtual bool PostWipeData() {
141     return true;
142   }
143 
144   void SetBootState(const BootState* state);
145   // The getters for reason and stage may return std::nullopt until StartRecovery() is called. It's
146   // the caller's responsibility to perform the check and handle the exception.
147   std::optional<std::string> GetReason() const;
148   std::optional<std::string> GetStage() const;
149 
150  private:
151   // The RecoveryUI object that should be used to display the user interface for this device.
152   std::unique_ptr<RecoveryUI> ui_;
153   const BootState* boot_state_{ nullptr };
154 };
155 
156 // Disable name mangling, as this function will be loaded via dlsym(3).
157 extern "C" {
158 
159 // The device-specific library must define this function (or the default one will be used, if there
160 // is no device-specific library). It returns the Device object that recovery should use.
161 Device* make_device();
162 }
163 
164 #endif  // _DEVICE_H
165