Skip to content

Commit a4bf0a0

Browse files
authored
[SPLIT] OrangeFox support (#218)
Some modifications to the code, so OrangeFox recovery can be supported (especially useful for Xiaomi devices) Work started in #188 It works, but I don't like the fix line 267 of `tooling.py`
2 parents a603e05 + 8971253 commit a4bf0a0

File tree

9 files changed

+168
-48
lines changed

9 files changed

+168
-48
lines changed

README.md

Lines changed: 7 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -42,14 +42,18 @@ Linux is currently the best supported platform (tested with Ubuntu 20.04/22.04 L
4242
1. Download the [.exe or appropriate executable file for your OS](https://github.com/openandroidinstaller-dev/openandroidinstaller/releases) from the releases or get the [official flatpak from flathub](https://flathub.org/apps/org.openandroidinstaller.OpenAndroidInstaller). You might need to change permissions to run the executable.
4343
- On Windows also [install the Universal USB Drivers](https://adb.clockworkmod.com/) and other potentially drivers needed for your device.
4444
2. Download the custom ROM image and the TWRP recovery image for your device and optionally some addons. A source for files can be found on the following websites:
45-
- some custom ROMs:
45+
- Some custom ROMs:
4646
- [LineageOS](https://wiki.lineageos.org/devices)
4747
- [/e/OS](https://doc.e.foundation/devices)
4848
- [LineageOS for microg](https://download.lineage.microg.org)
4949
- [BlissRoms](https://blissroms.org)
5050
- [PixelExperience](https://download.pixelexperience.org)
51-
- TWRP Recovery:
51+
- [crDroid](https://crdroid.net/)
52+
- [ArrowOS](https://arrowos.net/)
53+
- [DivestOS](https://divestos.org/)
54+
- Recoveries:
5255
- [TWRP recovery](https://twrp.me/Devices)
56+
- [OrangeFox](https://wiki.orangefox.tech)
5357
- Optional Addons:
5458
- There are different packages of *Google Apps* available.
5559
- [MindTheGapps](https://wiki.lineageos.org/gapps#downloads)
@@ -214,6 +218,7 @@ Every config file should have `metadata` with the following fields:
214218
- `is_ab_device`: bool; A boolean to determine if the device is a/b-partitioned or not.
215219
- `device_code`: str; The official device code.
216220
- `supported_device_codes`: List[str]; A list of supported device codes for the config. The config will be loaded based on this field.
221+
- `supported_recovery`: [OPTIONAL] List[str]; A list of supported recoveries. For the moment, can be twrp and/or orangefox (twrp by default)
217222
- `twrp-link`: [OPTIONAL] str; name of the corresponding twrp page.
218223

219224
In addition to these metadata, every config can have optional `requirements`. If these are set, the user is asked to check if they are meet.
80.4 KB
Loading

openandroidinstaller/installer_config.py

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -64,6 +64,7 @@ def __init__(
6464
self.is_ab = metadata.get("is_ab_device", False)
6565
self.supported_device_codes = metadata.get("supported_device_codes")
6666
self.twrp_link = metadata.get("twrp-link")
67+
self.supported_recovery = metadata.get("supported_recovery")
6768

6869
@classmethod
6970
def from_file(cls, path):
@@ -124,6 +125,8 @@ def _load_config(device_code: str, config_path: Path) -> Optional[InstallerConfi
124125
if custom_path:
125126
config = InstallerConfig.from_file(custom_path)
126127
logger.info(f"Loaded custom device config from {custom_path}.")
128+
if "supported_recovery" not in config.metadata:
129+
config.metadata.update({"supported_recovery": "['twrp']"})
127130
logger.info(f"Config metadata: {config.metadata}.")
128131
return config
129132
else:
@@ -134,6 +137,8 @@ def _load_config(device_code: str, config_path: Path) -> Optional[InstallerConfi
134137
config = InstallerConfig.from_file(path)
135138
logger.info(f"Loaded device config from {path}.")
136139
if config:
140+
if "supported_recovery" not in config.metadata:
141+
config.metadata.update({"supported_recovery": "['twrp']"})
137142
logger.info(f"Config metadata: {config.metadata}.")
138143
return config
139144
else:
@@ -150,7 +155,7 @@ def validate_config(config: str) -> bool:
150155
),
151156
"content": str,
152157
schema.Optional("command"): Regex(
153-
r"adb_reboot|adb_reboot_bootloader|adb_reboot_download|adb_sideload|adb_twrp_wipe_and_install|adb_twrp_copy_partitions|fastboot_boot_recovery|fastboot_flash_boot|fastboot_unlock_with_code|fastboot_get_unlock_data|fastboot_unlock|fastboot_oem_unlock|fastboot_reboot|heimdall_flash_recovery"
158+
r"adb_reboot|adb_reboot_bootloader|adb_reboot_download|adb_sideload|adb_twrp_wipe_and_install|adb_twrp_copy_partitions|fastboot_boot_recovery|fastboot_flash_recovery|fastboot_reboot_recovery|fastboot_flash_boot|fastboot_unlock_with_code|fastboot_get_unlock_data|fastboot_unlock|fastboot_oem_unlock|fastboot_reboot|heimdall_flash_recovery"
154159
),
155160
schema.Optional("allow_skip"): bool,
156161
schema.Optional("img"): str,
@@ -166,6 +171,7 @@ def validate_config(config: str) -> bool:
166171
"device_code": str,
167172
"supported_device_codes": [str],
168173
schema.Optional("twrp-link"): str,
174+
schema.Optional("supported_recovery"): [str],
169175
},
170176
schema.Optional("requirements"): {
171177
schema.Optional("android"): schema.Or(str, int),

openandroidinstaller/tooling.py

Lines changed: 75 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -140,6 +140,15 @@ def activate_sideload(bin_path: Path) -> TerminalResponse:
140140
yield line
141141

142142

143+
@add_logging("Activate sideloading in OranfeFox.", return_if_fail=True)
144+
def activate_sideload_ofox(bin_path: Path) -> TerminalResponse:
145+
"""Activate sideload with adb shell in OrangeFox."""
146+
for line in run_command(
147+
"adb shell twrp sideload help", bin_path
148+
): # Why help ? Don't know, but it works
149+
yield line
150+
151+
143152
@add_logging("Wait for device")
144153
def adb_wait_for_device(bin_path: Path) -> TerminalResponse:
145154
"""Use adb to wait for the device to become available."""
@@ -216,12 +225,13 @@ def adb_twrp_wipe_and_install(
216225
target: str,
217226
config_path: Path,
218227
is_ab: bool,
228+
chosen_recovery: str,
219229
install_addons=True,
220230
recovery: Optional[str] = None,
221231
) -> TerminalResponse:
222-
"""Wipe and format data with twrp, then flash os image with adb.
232+
"""Wipe and format data with recovery, then flash os image with adb.
223233
224-
Only works for twrp recovery.
234+
Only works for twrp and OrangeFox recovery.
225235
"""
226236
logger.info("Wipe and format data with twrp, then install os image.")
227237
for line in adb_wait_for_recovery(bin_path):
@@ -233,38 +243,46 @@ def adb_twrp_wipe_and_install(
233243

234244
sleep(1)
235245
# wipe some partitions
236-
for partition in ["cache", "system"]:
246+
for partition in ["cache", "dalvik", "system"]:
237247
for line in adb_twrp_wipe_partition(bin_path=bin_path, partition=partition):
238248
yield line
239249
sleep(1)
240250

241251
# activate sideload
242-
logger.info("Wiping is done, now activate sideload.")
243-
for line in activate_sideload(bin_path=bin_path):
244-
yield line
252+
if chosen_recovery == "twrp":
253+
logger.info("Wiping is done, now activate sideload.")
254+
for line in activate_sideload(bin_path=bin_path):
255+
yield line
256+
else:
257+
logger.info("Wiping is done, now activate sideload (ofox)")
258+
for line in activate_sideload_ofox(bin_path=bin_path):
259+
yield line
260+
sleep(5)
245261
# now flash os image
246262
logger.info("Sideload and install os image.")
247263
for line in adb_sideload(bin_path=bin_path, target=target):
248264
yield line
249-
# wipe some cache partitions
250265
sleep(7)
251-
for partition in ["dalvik", "cache"]:
252-
for line in run_command(f"adb shell twrp wipe {partition}", bin_path):
253-
yield line
254-
sleep(3)
255-
if (type(line) == bool) and not line:
256-
logger.error(f"Wiping {partition} failed.")
257-
# TODO: if this fails, a fix can be to just sideload something and then adb reboot
258-
for line in adb_sideload(
259-
target=f"{config_path.parent.joinpath(Path('helper.txt'))}",
260-
bin_path=bin_path,
261-
):
266+
# wipe some cache partitions
267+
if chosen_recovery == "twrp": # OrangeFox go in buggy sideload mode when wiping dalvik here (and already been wiped before)
268+
logger.info("Wiping cache and dalvik...")
269+
for partition in ["dalvik", "cache"]:
270+
for line in run_command(f"adb shell twrp wipe {partition}", bin_path):
262271
yield line
263-
sleep(1)
272+
sleep(3)
264273
if (type(line) == bool) and not line:
265-
yield False
266-
break
267-
sleep(2)
274+
logger.error(f"Wiping {partition} failed.")
275+
# TODO: if this fails, a fix can be to just sideload something and then adb reboot
276+
for line in adb_sideload(
277+
target=f"{config_path.parent.joinpath(Path('helper.txt'))}",
278+
bin_path=bin_path,
279+
):
280+
yield line
281+
sleep(1)
282+
if (type(line) == bool) and not line:
283+
yield False
284+
break
285+
sleep(2)
268286
# finally reboot into os or to fastboot for flashing addons
269287
for line in adb_wait_for_recovery(bin_path):
270288
yield line
@@ -288,7 +306,7 @@ def adb_twrp_wipe_and_install(
288306

289307

290308
def adb_twrp_install_addon(
291-
bin_path: Path, addon_path: str, is_ab: bool
309+
bin_path: Path, addon_path: str, chosen_recovery: str, is_ab: bool
292310
) -> TerminalResponse:
293311
"""Flash addon through adb and twrp.
294312
@@ -300,8 +318,13 @@ def adb_twrp_install_addon(
300318
adb_wait_for_recovery(bin_path=bin_path)
301319
# activate sideload
302320
logger.info("Activate sideload.")
303-
for line in activate_sideload(bin_path=bin_path):
304-
yield line
321+
if chosen_recovery == "twrp":
322+
for line in activate_sideload(bin_path=bin_path):
323+
yield line
324+
else:
325+
for line in activate_sideload_ofox(bin_path=bin_path):
326+
yield line
327+
sleep(5)
305328
logger.info("Sideload and install addon.")
306329
# now flash the addon
307330
for line in adb_sideload(bin_path=bin_path, target=addon_path):
@@ -497,3 +520,30 @@ def search_device(platform: str, bin_path: Path) -> Optional[str]:
497520
except CalledProcessError:
498521
logger.error("Failed to detect a device.")
499522
return None
523+
524+
525+
@add_logging("Flash custom recovery with fastboot.")
526+
def fastboot_flash_recovery(
527+
bin_path: Path, recovery: str, is_ab: bool = True
528+
) -> TerminalResponse:
529+
"""Flash custom recovery with fastboot."""
530+
for line in run_command(
531+
"fastboot flash recovery ", target=f"{recovery}", bin_path=bin_path
532+
):
533+
yield line
534+
if not is_ab:
535+
if (type(line) == bool) and not line:
536+
logger.error("Flashing recovery failed.")
537+
yield False
538+
else:
539+
yield True
540+
541+
542+
@add_logging("Rebooting device to recovery.")
543+
def fastboot_reboot_recovery(bin_path: Path) -> TerminalResponse:
544+
"""
545+
Reboot to recovery with fastboot
546+
WARNING : On some devices, users should perform a key combo
547+
"""
548+
for line in run_command("fastboot reboot recovery", bin_path):
549+
yield line

openandroidinstaller/utils.py

Lines changed: 34 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -60,15 +60,43 @@ def image_works_with_device(supported_device_codes: List[str], image_path: str)
6060
return False
6161

6262

63-
def recovery_works_with_device(device_code: str, recovery_path: str) -> bool:
63+
def recovery_works_with_device(
64+
supported_device_codes: [str], supported_recovery: [str], recovery_path: str
65+
) -> bool:
6466
"""Determine if a recovery works for the given device.
6567
6668
BEWARE: THE RECOVERY PART IS STILL VERY BASIC!
6769
"""
6870
recovery_file_name = recovery_path.split("/")[-1]
69-
if (device_code in recovery_file_name) and ("twrp" in recovery_file_name):
70-
logger.success("Device supported by the selected recovery.")
71-
return True
72-
else:
73-
logger.error(f"Recovery file {recovery_file_name} is not supported.")
71+
if recovery_file_name[-4:] != ".img":
72+
logger.error(f"The file {recovery_file_name} is not a recovery file")
7473
return False
74+
for codename in supported_device_codes:
75+
if (
76+
(codename in recovery_file_name)
77+
and ("twrp" in recovery_file_name or "TWRP" in recovery_file_name)
78+
and ("twrp" in supported_recovery or not supported_recovery)
79+
):
80+
logger.success("Selected recovery supported for this device.")
81+
return True
82+
elif recovery_file_name == "recovery.img" and (
83+
"orangefox" in supported_recovery
84+
):
85+
logger.error("Cannot check recovery. Supposing it is OrangeFox.")
86+
return True
87+
logger.error(f"Recovery file {recovery_file_name} is not supported.")
88+
return False
89+
90+
91+
def which_recovery(recovery_path: str) -> str:
92+
"""Determine which recovery was selected
93+
This does not replace recovery_works_with_device.
94+
BEWARE: THE RECOVERY PART IS STILL VERY BASIC!
95+
"""
96+
recovery_file_name = recovery_path.split("/")[-1]
97+
if "twrp" in recovery_file_name or "TWRP" in recovery_file_name:
98+
return "twrp"
99+
if recovery_file_name == "recovery.img":
100+
return "orangefox"
101+
logger.error("Unable to determine which recovery was selected !")
102+
return None

openandroidinstaller/views/install_addons_view.py

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -172,6 +172,7 @@ def run_install_addons(self, e):
172172
for line in adb_twrp_install_addon(
173173
addon_path=addon_path,
174174
bin_path=self.state.bin_path,
175+
chosen_recovery=self.state.chosen_recovery,
175176
is_ab=self.state.config.is_ab,
176177
):
177178
# write the line to advanced output terminal

openandroidinstaller/views/install_view.py

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -171,7 +171,7 @@ def check_addons_switch(e):
171171

172172
def run_install(self, e):
173173
"""
174-
Run the installation process through twrp.
174+
Run the installation process through recovery.
175175
176176
Some parts of the command are changed by placeholders.
177177
"""
@@ -193,6 +193,7 @@ def run_install(self, e):
193193
bin_path=self.state.bin_path,
194194
install_addons=self.state.install_addons,
195195
is_ab=self.state.config.is_ab,
196+
chosen_recovery=self.state.chosen_recovery,
196197
recovery=self.state.recovery_path,
197198
):
198199
# write the line to advanced output terminal

0 commit comments

Comments
 (0)