Skip to content

Commit ea88b7f

Browse files
committed
Use specific functions to run commands; enable twrp scripting for twrp recoveries
1 parent 20d22fc commit ea88b7f

File tree

4 files changed

+146
-78
lines changed

4 files changed

+146
-78
lines changed

openandroidinstaller/assets/configs/a3y17lte.yaml

Lines changed: 8 additions & 28 deletions
Original file line numberDiff line numberDiff line change
@@ -11,45 +11,25 @@ steps:
1111
As a first step, you need to boot into the bootloader. A bootloader is the piece of software,
1212
that tells your phone who to start and run an operating system (like Android). Your device should be turned on.
1313
Then press 'Confirm and run' to reboot into the bootloader. Continue once it's done.
14-
command: "adb reboot download"
14+
command: adb_reboot_download
1515
- title: "Flash custom recovery"
1616
type: call_button
1717
content: >
1818
In this step, you need to flash a custom recovery on your device.
1919
Press 'Confirm and run' to start the process. Confirm afterwards to continue.
20-
command: "heimdall flash --no-reboot --RECOVERY <recovery>"
20+
command: heimdall_flash_recovery
2121
- title: "Boot into recovery"
2222
type: confirm_button
2323
img: samsung-buttons.png
2424
content: >
2525
Unplug the USB cable from your device. Then manually reboot into recovery by pressing the *Volume Down* + *Power buttons* for
2626
8~10 seconds until the screen turns black & release the buttons immediately when it does, then boot to recovery with the device powered off,
27-
hold *Volume Up* + *Home* + *Power*.
27+
hold *Volume Up* + *Home* + *Power*. Confirm when the recovery screen appears.
2828
install_os:
2929
- title: "Flash LineageOS"
30-
type: confirm_button
31-
content: >
32-
Now swipe right to allow modifications then tap 'Wipe' on your phone. Next tap 'Format Data' and follow
33-
the instructions on your phone to continue with the formatting process. This will remove encryption and delete all files stored
34-
in the internal storage. Confirm to continue once you are done.
35-
- title: "Flash LineageOS"
36-
type: confirm_button
30+
type: call_button
3731
content: >
38-
Return to the previous menu on your phone by going back two times.
39-
Them tap 'Advanced Wipe', and select the 'Cache' and 'System' partitions and then 'Swipe to Wipe'.
40-
Confirm to continue once you are done.
41-
- title: "Flash LineageOS"
42-
type: confirm_button
43-
content: >
44-
Now connect the phone to the computer again with the USB-cable. On the device, go back three times and select “Advanced”,
45-
then “ADB Sideload”. Select 'Wipe cache' and 'Wipe dalvik cache', then swipe to begin sideload. Then confirm here.
46-
- title: "Flash LineageOS"
47-
type: call_button
48-
content: >
49-
Now it's time to flash the LineageOS image. Don't remove the USB-Cable and press 'Confirm and run' to start!
50-
This might take a while. Confirm after it's done.
51-
command: "adb sideload <image>"
52-
- title: "Reboot into LineageOS"
53-
type: call_button
54-
content: As a final step, reboot into LineageOS to finish the installation by pressing the button.
55-
command: "adb reboot"
32+
Connect your device with your computer with the USB-Cable.
33+
This step will format your phone and wipe all the data. It will also remove encryption and delete all files stored
34+
in the internal storage. Then the OS image will be installed. Confirm to run. This might take a while. At the end your phone will boot into the new OS.
35+
command: adb_twrp_wipe_and_install

openandroidinstaller/installer_config.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -120,7 +120,7 @@ def validate_config(config: str) -> bool:
120120
r"text|confirm_button|call_button|call_button_with_input|link_button_with_confirm"
121121
),
122122
"content": str,
123-
schema.Optional("command"): Regex(r"^adb\s|^fastboot\s|^heimdall\s"),
123+
schema.Optional("command"): Regex(r"adb_reboot|adb_reboot_bootloader|adb_reboot_download|adb_sideload|adb_twrp_wipe_and_install|fastboot_unlock_with_code|fastboot_unlock|fastboot_reboot|heimdall_flash_recovery"),
124124
schema.Optional("allow_skip"): bool,
125125
schema.Optional("img"): str,
126126
schema.Optional("link"): str,

openandroidinstaller/openandroidinstaller.py

Lines changed: 38 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -51,7 +51,20 @@
5151
)
5252
from installer_config import Step, _load_config
5353
from loguru import logger
54-
from tool_utils import call_tool_with_command, search_device
54+
from tool_utils import (
55+
call_tool_with_command,
56+
search_device,
57+
adb_reboot,
58+
adb_reboot_bootloader,
59+
adb_reboot_download,
60+
adb_sideload,
61+
adb_twrp_wipe_and_install,
62+
fastboot_reboot,
63+
fastboot_flash_recovery,
64+
fastboot_unlock,
65+
fastboot_unlock_with_code,
66+
heimdall_flash_recovery
67+
)
5568
from utils import AppState, get_download_link, image_recovery_works_with_device
5669
from widgets import call_button, confirm_button, get_title, link_button
5770

@@ -556,11 +569,10 @@ def build(self):
556569
Text(f"{self.step.content}"),
557570
]
558571
# basic view depending on step.type
572+
self.confirm_button = confirm_button(self.on_confirm)
559573
if self.step.type == "confirm_button":
560-
self.confirm_button = confirm_button(self.on_confirm)
561574
self.right_view.controls.append(Row([self.confirm_button]))
562575
elif self.step.type == "call_button":
563-
self.confirm_button = confirm_button(self.on_confirm)
564576
self.confirm_button.disabled = True
565577
self.call_button = call_button(
566578
self.call_to_phone, command=self.step.command
@@ -569,7 +581,6 @@ def build(self):
569581
Row([self.call_button, self.confirm_button])
570582
)
571583
elif self.step.type == "call_button_with_input":
572-
self.confirm_button = confirm_button(self.on_confirm)
573584
self.confirm_button.disabled = True
574585
self.call_button = call_button(
575586
self.call_to_phone, command=self.step.command
@@ -578,7 +589,6 @@ def build(self):
578589
[self.inputtext, Row([self.call_button, self.confirm_button])]
579590
)
580591
elif self.step.type == "link_button_with_confirm":
581-
self.confirm_button = confirm_button(self.on_confirm)
582592
self.right_view.controls.extend(
583593
[Row([link_button(self.step.link, "Open Link"), self.confirm_button])]
584594
)
@@ -609,11 +619,6 @@ def call_to_phone(self, e, command: str):
609619
610620
Some parts of the command are changed by placeholders.
611621
"""
612-
# replace placeholders by the required values
613-
command = command.replace("<recovery>", self.recovery_path)
614-
command = command.replace("<image>", self.image_path)
615-
command = command.replace("<inputtext>", self.inputtext.value)
616-
617622
# display a progress ring to show something is happening
618623
self.right_view.controls.append(
619624
Row(
@@ -622,8 +627,29 @@ def call_to_phone(self, e, command: str):
622627
)
623628
)
624629
self.right_view.update()
625-
# run the command
626-
success = call_tool_with_command(command=command, bin_path=BIN_PATH)
630+
631+
# run the right command
632+
if command == "adb_reboot":
633+
success = adb_reboot(bin_path=BIN_PATH)
634+
elif command == "adb_reboot_bootloader":
635+
success = adb_reboot_bootloader(bin_path=BIN_PATH)
636+
elif command == "adb_reboot_download":
637+
success = adb_reboot_download(bin_path=BIN_PATH)
638+
elif command == "adb_sideload":
639+
success = adb_sideload(bin_path=BIN_PATH, target=self.image_path)
640+
elif command == "adb_twrp_wipe_and_install":
641+
success = adb_twrp_wipe_and_install(bin_path=BIN_PATH, target=self.image_path)
642+
elif command == "fastboot_unlock_with_code":
643+
success = fastboot_unlock_with_code(bin_path=BIN_PATH, unlock_code=self.inputtext.value)
644+
elif command == "fastboot_unlock":
645+
success = fastboot_unlock(bin_path=BIN_PATH)
646+
elif command == "fastboot_reboot":
647+
success = fastboot_reboot(bin_path=BIN_PATH)
648+
elif command == "heimdall_flash_recovery":
649+
success = heimdall_flash_recovery(bin_path=BIN_PATH, recovery=self.recovery_path)
650+
else:
651+
raise Exception(f"Unknown command type: {command}. Stopping.")
652+
627653
# update the view accordingly
628654
if not success:
629655
# pop the progress ring

openandroidinstaller/tool_utils.py

Lines changed: 99 additions & 37 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,7 @@
1515

1616
import sys
1717
from pathlib import Path
18+
from time import sleep
1819
from subprocess import STDOUT, CalledProcessError, call, check_output, PIPE, run, CompletedProcess
1920
from typing import Optional, List
2021

@@ -30,9 +31,9 @@ def run_command(tool: str, command: List[str], bin_path: Path) -> CompletedProce
3031
if tool not in ["adb", "fastboot", "heimdall"]:
3132
raise Exception(f"Unknown tool {tool}. Use adb, fastboot or heimdall.")
3233
if PLATFORM == "win32":
33-
full_command = [str(bin_path + f"{tool}.exe")] + command
34+
full_command = [str(bin_path.joinpath(Path(f"{tool}"))) + ".exe"] + command
3435
else:
35-
full_command = [str(bin_path + f"{tool}")] + command
36+
full_command = [str(bin_path.joinpath(Path(f"{tool}")))] + command
3637

3738
logger.info(f"Run command: {full_command}")
3839
result = run(full_command, stdout=PIPE, stderr=PIPE, universal_newlines=True)
@@ -79,7 +80,6 @@ def adb_reboot_download(bin_path: Path) -> bool:
7980
return True
8081

8182

82-
8383
def adb_sideload(bin_path: Path, target: str) -> bool:
8484
"""Sideload the target to device and return success."""
8585
logger.info("Rebooting device into bootloader with adb.")
@@ -90,40 +90,102 @@ def adb_sideload(bin_path: Path, target: str) -> bool:
9090
return True
9191

9292

93-
def call_tool_with_command(command: str, bin_path: Path) -> bool:
94-
"""Call an executable with a specific command."""
95-
if PLATFORM == "win32":
96-
command = re.sub(
97-
r"^adb", re.escape(str(bin_path.joinpath(Path("adb")))) + ".exe", command
98-
)
99-
command = re.sub(
100-
r"^fastboot",
101-
re.escape(str(bin_path.joinpath(Path("fastboot.exe")))) + ".exe",
102-
command,
103-
)
104-
command = re.sub(
105-
r"^heimdall",
106-
re.escape(str(bin_path.joinpath(Path("heimdall.exe")))) + ".exe",
107-
command,
108-
)
109-
else:
110-
command = re.sub(
111-
r"^adb", re.escape(str(bin_path.joinpath(Path("adb")))), command
112-
)
113-
command = re.sub(
114-
r"^fastboot", re.escape(str(bin_path.joinpath(Path("fastboot")))), command
115-
)
116-
command = re.sub(
117-
r"^heimdall", re.escape(str(bin_path.joinpath(Path("heimdall")))), command
118-
)
119-
120-
logger.info(f"Run command: {command}")
121-
res = call(f"{command}", shell=True)
122-
if res == 0:
123-
logger.info("Success.")
124-
return True
125-
logger.info(f"Command {command} failed.")
126-
return False
93+
def adb_twrp_wipe_and_install(bin_path: Path, target: str) -> bool:
94+
"""Wipe and format data with twrp, then flash os image with adb.
95+
96+
Only works for twrp recovery.
97+
"""
98+
logger.info("Wipe and format data with twrp, then install os image.")
99+
sleep(1)
100+
result = run_command("adb", ["shell", "twrp", "format", "data"], bin_path)
101+
if result.returncode != 0:
102+
logger.info("Formatting data failed.")
103+
return False
104+
# wipe some partitions
105+
for partition in ["cache", "system", "dalvik"]:
106+
result = run_command("adb", ["shell", "twrp", "wipe", partition], bin_path)
107+
if result.returncode != 0:
108+
logger.info(f"Wiping {partition} failed.")
109+
return False
110+
# activate sideload
111+
logger.info("Wiping is done, now activate sideload.")
112+
result = run_command("adb", ["shell", "twrp", "sideload"], bin_path)
113+
if result.returncode != 0:
114+
logger.info("Activating sideload failed.")
115+
return False
116+
# now flash os image
117+
sleep(1)
118+
logger.info("Sideload and install os image.")
119+
result = run_command("adb", ["sideload", f"{target}"], bin_path)
120+
if result.returncode != 0:
121+
logger.info(f"Sideloading {target} failed.")
122+
return False
123+
# wipe some cache partitions
124+
sleep(1)
125+
for partition in ["cache", "dalvik"]:
126+
result = run_command("adb", ["shell", "twrp", "wipe", partition], bin_path)
127+
if result.returncode != 0:
128+
logger.info(f"Wiping {partition} failed.")
129+
return False
130+
# finally reboot into os
131+
sleep(1)
132+
logger.info("Reboot into OS.")
133+
result = run_command("adb", ["shell", "twrp", "reboot"], bin_path)
134+
if result.returncode != 0:
135+
logger.info("Rebooting with twrp failed.")
136+
return False
137+
138+
return True
139+
140+
141+
def fastboot_unlock_with_code(bin_path: Path, unlock_code: str) -> bool:
142+
"""Unlock the device with fastboot and code given."""
143+
logger.info(f"Unlock the device with fastboot and code: {unlock_code}.")
144+
result = run_command("fastboot", ["oem", "unlock", f"{unlock_code}"], bin_path)
145+
if result.returncode != 0:
146+
logger.info(f"Unlocking with code {unlock_code} failed.")
147+
return False
148+
return True
149+
150+
151+
def fastboot_unlock(bin_path: Path) -> bool:
152+
"""Unlock the device with fastboot and without code."""
153+
logger.info(f"Unlock the device with fastboot.")
154+
result = run_command("fastboot", ["flashing", "unlock"] , bin_path)
155+
if result.returncode != 0:
156+
logger.info(f"Unlocking failed.")
157+
return False
158+
return True
159+
160+
161+
def fastboot_reboot(bin_path: Path) -> bool:
162+
"""Reboot with fastboot"""
163+
logger.info(f"Rebooting device with fastboot.")
164+
result = run_command("fastboot", ["reboot"] , bin_path)
165+
if result.returncode != 0:
166+
logger.info(f"Rebooting with fastboot failed.")
167+
return False
168+
return True
169+
170+
171+
def fastboot_flash_recovery(bin_path: Path, recovery: str) -> bool:
172+
"""Temporarily, flash custom recovery with fastboot."""
173+
logger.info(f"Flash custom recovery with fastboot.")
174+
result = run_command("fastboot", ["flash", "boot", f"{recovery}"] , bin_path)
175+
if result.returncode != 0:
176+
logger.info(f"Flashing recovery failed.")
177+
return False
178+
return True
179+
180+
181+
def heimdall_flash_recovery(bin_path: Path, recovery: str) -> bool:
182+
"""Temporarily, flash custom recovery with heimdall."""
183+
logger.info(f"Flash custom recovery with heimdall.")
184+
result = run_command("heimdall", ["flash", "--no-reboot", "--RECOVERY", f"{recovery}"] , bin_path)
185+
if result.returncode != 0:
186+
logger.info(f"Flashing recovery failed.")
187+
return False
188+
return True
127189

128190

129191
def search_device(platform: str, bin_path: Path) -> Optional[str]:

0 commit comments

Comments
 (0)