Skip to content

Commit e2dac47

Browse files
authored
Refactoring and testing (#40)
This PR adds: - Major refactoring of views - test search device function in tooling - let advanced view toggle in every step independently - refactor call_to_phone method - refactored terminal box - test for TerminalBox - Enable copy_partitions sideloading - config for Motorola moto g7 power (ocean) - config for Motorola moto g5 (cedric)
2 parents b512ae1 + 1cdeafa commit e2dac47

24 files changed

Lines changed: 1526 additions & 890 deletions

Makefile

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,9 @@ lint:
1212
poetry run ruff openandroidinstaller/ --ignore E501
1313

1414
test:
15-
poetry run pytest tests/
15+
poetry run black .
16+
poetry run ruff openandroidinstaller/ --ignore E501
17+
PYTHONPATH=openandroidinstaller:$(PYTHONPATH) poetry run pytest --cov=openandroidinstaller tests/
1618

1719
app:
1820
poetry run python openandroidinstaller/openandroidinstaller.py

README.md

Lines changed: 5 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -44,7 +44,7 @@ Samsung | Galaxy S7 | [herolte](https://wiki.lineageos.org/devices/herolte/) | S
4444
Samsung | Galaxy S9 | [starlte](https://wiki.lineageos.org/devices/starlte/) | | tested
4545
Samsung | Galaxy S10 | beyond1lte | | tested
4646
Google | Pixel 3a | [sargo](https://wiki.lineageos.org/devices/sargo/) | sargo | tested
47-
Google | Pixel 4 | flame | flame | tested
47+
Google | Pixel 4 | [flame](https://wiki.lineageos.org/devices/flame/) | flame | tested
4848
Google | Pixel 4a | sunfish | sunfish | tested
4949
Google | Pixel 5 | redfin | redfin | tested
5050
Google | Pixel 5a | barbet | barbet | tested
@@ -53,8 +53,8 @@ Sony | Xperia Z3 | [z3](https://wiki.lineageos.org/devices/z3/) | | tested
5353
Sony | Xperia ZX | kagura | | planned
5454
Fairphone | Fairphone 2 | [FP2](https://wiki.lineageos.org/devices/FP2/) | | tested
5555
Fairphone | Fairphone 3 | [FP3](https://wiki.lineageos.org/devices/FP3/) | | tested
56-
Motorola | moto G5 | cedric | | planned
57-
Motorola | moto g7 power | ocean | | under development
56+
Motorola | moto G5 | [cedric](https://wiki.lineageos.org/devices/cedric/) | | tested
57+
Motorola | moto g7 power | [ocean](https://wiki.lineageos.org/devices/ocean/) | | tested
5858
OnePlus | 6 | enchilada | | under development
5959
OnePlus | 6T | fajita | | under development
6060
OnePlus | 7T | hotdogb | | under development
@@ -105,7 +105,7 @@ Every step in the config file corresponds to one view in the application. These
105105
- `call_button_with_input`: Display the content text, an input field and a button that runs a given command. The inputtext, can be used in the command by using the `<inputtext>` placeholder in the command field. After the command is run, a confirm button is displayed to allow the user to move to the next step.
106106
- `link_button_with_confirm`: Display a button that opens a browser with a given link, confirm afterwards. Link is given in `link`.
107107
- `content`: str; The content text displayed alongside the action of the step. Used to inform the user about whats going on.
108-
- `command`: [ONLY for call_button* steps] str; The command to run. One of `adb_reboot`, `adb_reboot_bootloader`, `adb_reboot_download`, `adb_sideload`, `adb_twrp_wipe_and_install`, `fastboot_flash_recovery`, `fastboot_unlock_with_code`, `fastboot_unlock`, `fastboot_oem_unlock`, `fastboot_reboot`, `heimdall_flash_recovery`.
108+
- `command`: [ONLY for call_button* steps] str; The command to run. One of `adb_reboot`, `adb_reboot_bootloader`, `adb_reboot_download`, `adb_sideload`, `adb_twrp_wipe_and_install`, `adb_twrp_copy_partitions`, `fastboot_flash_recovery`, `fastboot_unlock_with_code`, `fastboot_unlock`, `fastboot_oem_unlock`, `fastboot_get_unlock_data`, `fastboot_reboot`, `heimdall_flash_recovery`.
109109
- `img`: [OPTIONAL] Display an image on the left pane of the step view. Images are loaded from `openandroidinstaller/assets/imgs/`.
110110
- `allow_skip`: [OPTIONAL] boolean; If a skip button should be displayed to allow skipping this step. Can be useful when the bootloader is already unlocked.
111111
- `link`: [OPTIONAL] Link to use for the link button if type is `link_button_with_confirm`.
@@ -130,6 +130,7 @@ Other phone vendors stops allowing to unlock the bootloader all together. There
130130
- The [Android SDK Platform Tools](https://developer.android.com/studio/releases/platform-tools) (such as adb and fastboot) are [Apache](https://android.googlesource.com/platform/system/adb/+/refs/heads/master/NOTICE)-licensed universal Android utilities
131131
- [Heimdall](https://gitlab.com/BenjaminDobell/Heimdall/) is an [MIT](https://gitlab.com/BenjaminDobell/Heimdall/-/blob/master/LICENSE)-licensed replacement for the leaked ODIN tool to flash Samsung devices.
132132
- [libusb-1.0](https://github.com/libusb/libusb) is a [LGPL-2.1](https://github.com/libusb/libusb/blob/master/COPYING)-licensed library for USB device access from Linux, macOS, Windows and others.
133+
- [copy-partitions-20220613-signed.zip](https://mirrorbits.lineageos.org/tools/copy-partitions-20220613-signed.zip) The copy-partitions script was created by LineageOS developer erfanoabdi and filipepferraz and released under LGPL. It is used when the partitions need to be copied before flashing.
133134

134135

135136
## Acknowledgements

openandroidinstaller/__init__.py

Whitespace-only changes.
Lines changed: 54 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,54 @@
1+
metadata:
2+
maintainer: Tobias Sterbak (tsterbak)
3+
devicename: Moto G5
4+
devicecode: cedric
5+
steps:
6+
unlock_bootloader:
7+
- type: call_button
8+
command: adb_reboot_bootloader
9+
content: >
10+
As a first step, you need to unlock the bootloader of your device. A bootloader is the piece of software, that tells your phone
11+
how to start and run an operating system (like Android). You need to boot into fastboot mode by pressing the 'Confirm and run' button. Then continue.
12+
- type: call_button
13+
command: fastboot_get_unlock_data
14+
content: >
15+
Now you need to get your device ID to get an unlock code from Motorola. Press 'Confirm and run' to get the ID. (You need to toggle 'Advanced Output' here to see it.)
16+
Copy it to a separate file to use it in the next step.
17+
- type: link_button_with_confirm
18+
content: >
19+
Click on the button to open the instructions on Motorola's official unlocking website to generate an unlock code for your bootloader.
20+
Copy the code from the last step to the website and follow the instructions there. Then continue here.
21+
link: https://motorola-global-portal.custhelp.com/app/standalone/bootloader/unlock-your-device-a
22+
- type: confirm_button
23+
content: Connect the device to your PC via USB. And confirm to continue.
24+
- type: call_button_with_input
25+
content: >
26+
Use your code to unlock the bootloader of your device. Type in the full 21 character code you received by email (Example: 5RTSQCYL7ZJKL4NN35MY). Then confirm an run. Afterwards you can continue.
27+
command: fastboot_unlock_with_code
28+
- type: call_button_with_input
29+
content: >
30+
You need to perform the last command again, so reenter the code and run again. Afterwards you can continue.
31+
command: fastboot_unlock_with_code
32+
- type: call_button
33+
content: >
34+
Press the button to reboot. Since the device resets completely, you will need to re-enable USB debugging to continue.
35+
Connect your device to your PC via USB. Then confirm here to continue.
36+
command: fastboot_reboot
37+
flash_recovery:
38+
- type: call_button
39+
content: >
40+
Now you need to flash a custom recovery system on the phone. A recovery is a small subsystem on your phone, that manages updating,
41+
adapting and repairing of the operating system.
42+
Make sure your device is turned on. You need to reboot into the bootloader again by pressing 'Confirm and run' here. Then continue.
43+
command: adb_reboot_bootloader
44+
- type: call_button
45+
content: Flash a custom recovery (temporarily) by pressing 'Confirm and run'. Once it's done continue.
46+
command: fastboot_flash_recovery
47+
install_os:
48+
- type: call_button
49+
content: >
50+
In this last step, you finally flash the selected OS image.
51+
Wait until the TWRP screen appears. Then run the command.
52+
This step will format your phone and wipe all the data. It will also remove encryption and delete all files stored
53+
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.
54+
command: adb_twrp_wipe_and_install
Lines changed: 63 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,63 @@
1+
metadata:
2+
maintainer: Tobias Sterbak (tsterbak)
3+
devicename: Moto G7 power
4+
devicecode: ocean
5+
steps:
6+
unlock_bootloader:
7+
- type: call_button
8+
command: adb_reboot_bootloader
9+
content: >
10+
As a first step, you need to unlock the bootloader of your device. A bootloader is the piece of software, that tells your phone
11+
how to start and run an operating system (like Android). You need to boot into fastboot mode by pressing the 'Confirm and run' button. Then continue.
12+
- type: call_button
13+
command: fastboot_get_unlock_data
14+
content: >
15+
Now you need to get your device ID to get an unlock code from Motorola. Press 'Confirm and run' to get the ID. (You need to toggle 'Advanced Output' here to see it.)
16+
Copy it to a separate file to use it in the next step.
17+
- type: link_button_with_confirm
18+
content: >
19+
Click on the button to open the instructions on Motorola's official unlocking website to generate an unlock code for your bootloader.
20+
Copy the code from the last step to the website and follow the instructions there. Then continue here.
21+
link: https://motorola-global-portal.custhelp.com/app/standalone/bootloader/unlock-your-device-a
22+
- type: confirm_button
23+
content: Connect the device to your PC via USB. And confirm to continue.
24+
- type: call_button_with_input
25+
content: >
26+
Use your code to unlock the bootloader of your device. Type in the full 21 character code you received by email (Example: 5RTSQCYL7ZJKL4NN35MY). Then confirm an run. Afterwards you can continue.
27+
command: fastboot_unlock_with_code
28+
- type: call_button_with_input
29+
content: >
30+
You need to perform the last command again, so reenter the code and run again. Afterwards you can continue.
31+
command: fastboot_unlock_with_code
32+
- type: call_button
33+
content: >
34+
Press the button to reboot. Since the device resets completely, you will need to re-enable USB debugging to continue.
35+
Connect your device to your PC via USB. Then confirm here to continue.
36+
command: fastboot_reboot
37+
flash_recovery:
38+
- type: call_button
39+
content: >
40+
Now you need to flash a custom recovery system on the phone. A recovery is a small subsystem on your phone, that manages updating,
41+
adapting and repairing of the operating system.
42+
Make sure your device is turned on. You need to reboot into the bootloader again by pressing 'Confirm and run' here. Then continue.
43+
command: adb_reboot_bootloader
44+
- type: call_button
45+
content: Flash a custom recovery (temporarily) by pressing 'Confirm and run'. Once it's done continue.
46+
command: fastboot_flash_recovery
47+
- type: call_button
48+
command: adb_twrp_copy_partitions
49+
content: >
50+
In some cases, the inactive slot can be unpopulated or contain much older firmware than the active slot, leading to various issues including a potential hard-brick.
51+
We can ensure none of that will happen by copying the contents of the active slot to the inactive slot. Press 'confirm and run' to to this. Once you are in the bootloader again, continue.
52+
- type: call_button
53+
command: fastboot_flash_recovery
54+
content: >
55+
Now we need to boot into recovery again. Press run and when you see the TWRP screen you can continue.
56+
install_os:
57+
- type: call_button
58+
content: >
59+
In this last step, you finally flash the selected OS image.
60+
Wait until the TWRP screen appears. Then run the command.
61+
This step will format your phone and wipe all the data. It will also remove encryption and delete all files stored
62+
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.
63+
command: adb_twrp_wipe_and_install
3.95 KB
Binary file not shown.

openandroidinstaller/installer_config.py

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -136,7 +136,7 @@ def validate_config(config: str) -> bool:
136136
),
137137
"content": str,
138138
schema.Optional("command"): Regex(
139-
r"adb_reboot|adb_reboot_bootloader|adb_reboot_download|adb_sideload|adb_twrp_wipe_and_install|fastboot_flash_recovery|fastboot_unlock_with_code|fastboot_unlock|fastboot_oem_unlock|fastboot_reboot|heimdall_flash_recovery"
139+
r"adb_reboot|adb_reboot_bootloader|adb_reboot_download|adb_sideload|adb_twrp_wipe_and_install|adb_twrp_copy_partitions|fastboot_flash_recovery|fastboot_unlock_with_code|fastboot_get_unlock_data|fastboot_unlock|fastboot_oem_unlock|fastboot_reboot|heimdall_flash_recovery"
140140
),
141141
schema.Optional("allow_skip"): bool,
142142
schema.Optional("img"): str,
@@ -151,7 +151,7 @@ def validate_config(config: str) -> bool:
151151
"devicecode": str,
152152
},
153153
schema.Optional("requirements"): {
154-
schema.Optional("android"): str,
154+
schema.Optional("android"): schema.Or(str, int),
155155
schema.Optional("firmware"): str,
156156
},
157157
"steps": {

openandroidinstaller/openandroidinstaller.py

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -19,14 +19,12 @@
1919
from pathlib import Path
2020

2121
import flet as ft
22-
from app_state import AppState
2322
from flet import (
2423
AppBar,
2524
Banner,
2625
Column,
2726
Container,
2827
ElevatedButton,
29-
CircleAvatar,
3028
FloatingActionButton,
3129
Icon,
3230
Image,
@@ -39,14 +37,16 @@
3937
icons,
4038
)
4139
from loguru import logger
42-
from views import SelectFilesView, StepView, SuccessView, WelcomeView, RequirementsView
43-
from tool_utils import run_command
40+
41+
from app_state import AppState
42+
from views import SelectFilesView, StepView, SuccessView, StartView, RequirementsView
43+
from tooling import run_command
4444

4545
# where to write the logs
4646
logger.add("openandroidinstaller.log")
4747

4848
# Toggle to True for development purposes
49-
DEVELOPMENT = True
49+
DEVELOPMENT = False
5050
DEVELOPMENT_CONFIG = "sargo" # "a3y17lte" # "sargo"
5151

5252

@@ -76,7 +76,7 @@ def __init__(self):
7676
self.view = Column(expand=True, width=1200)
7777

7878
# create default starter views
79-
welcome_view = WelcomeView(
79+
welcome_view = StartView(
8080
on_confirm=self.confirm,
8181
state=self.state,
8282
)
Lines changed: 58 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -74,14 +74,6 @@ def adb_reboot_bootloader(bin_path: Path) -> bool:
7474
return
7575
sleep(1)
7676
yield True
77-
# TODO: check if in fastboot mode
78-
# for line in run_command("fastboot", ["devices"], bin_path):
79-
# yield line
80-
# if (type(line) == bool) and not line:
81-
# logger.error("No fastboot mode detected. Reboot into bootloader failed.")
82-
# yield False
83-
# else:
84-
# yield True
8577

8678

8779
def adb_reboot_download(bin_path: Path) -> bool:
@@ -109,13 +101,52 @@ def adb_sideload(bin_path: Path, target: str) -> bool:
109101
yield True
110102

111103

104+
def adb_twrp_copy_partitions(bin_path: Path, config_path: Path):
105+
# some devices like one plus 6t or motorola moto g7 power need the partitions copied to prevent a hard brick
106+
logger.info("Sideload copy_partitions script with adb.")
107+
# activate sideload
108+
for line in run_command("adb", ["shell", "twrp", "sideload"], bin_path):
109+
yield line
110+
if (type(line) == bool) and not line:
111+
logger.error("Activating sideload failed.")
112+
yield False
113+
return
114+
# now sideload the script
115+
sleep(5)
116+
logger.info("Sideload the copy_partitions script")
117+
for line in run_command(
118+
"adb",
119+
[
120+
"sideload",
121+
str(config_path.parent) + "/copy-partitions-20220613-signed.zip",
122+
],
123+
bin_path,
124+
):
125+
yield line
126+
if (type(line) == bool) and not line:
127+
logger.error("Sideloading copy-partitions-20220613-signed.zip failed.")
128+
sleep(10)
129+
# reboot into the bootloader again
130+
logger.info("Rebooting device into bootloader with adb.")
131+
for line in run_command("adb", ["reboot", "bootloader"], bin_path):
132+
yield line
133+
if (type(line) == bool) and not line:
134+
logger.error("Reboot into bootloader failed.")
135+
yield False
136+
return
137+
sleep(7)
138+
# Copy partitions end #
139+
return True
140+
141+
112142
def adb_twrp_wipe_and_install(bin_path: Path, target: str, config_path: Path) -> bool:
113143
"""Wipe and format data with twrp, then flash os image with adb.
114144
115145
Only works for twrp recovery.
116146
"""
117147
logger.info("Wipe and format data with twrp, then install os image.")
118148
sleep(7)
149+
# now perform a factory reset
119150
for line in run_command("adb", ["shell", "twrp", "format", "data"], bin_path):
120151
yield line
121152
if (type(line) == bool) and not line:
@@ -161,7 +192,7 @@ def adb_twrp_wipe_and_install(bin_path: Path, target: str, config_path: Path) ->
161192
# TODO: if this fails, a fix can be to just sideload something and then adb reboot
162193
for line in run_command(
163194
"adb",
164-
["sideload", str(config_path.parent.parent) + "/helper.txt"],
195+
["sideload", str(config_path.parent) + "/helper.txt"],
165196
bin_path,
166197
):
167198
yield line
@@ -171,7 +202,7 @@ def adb_twrp_wipe_and_install(bin_path: Path, target: str, config_path: Path) ->
171202
return
172203
break
173204
# finally reboot into os
174-
sleep(5)
205+
sleep(7)
175206
logger.info("Reboot into OS.")
176207
for line in run_command("adb", ["reboot"], bin_path): # "shell", "twrp",
177208
yield line
@@ -219,6 +250,18 @@ def fastboot_oem_unlock(bin_path: Path) -> bool:
219250
yield True
220251

221252

253+
def fastboot_get_unlock_data(bin_path: Path) -> bool:
254+
"""Get the unlock data with fastboot"""
255+
logger.info("Get unlock data with fastboot")
256+
for line in run_command("fastboot", ["oem", "get_unlock_data"], bin_path):
257+
yield line
258+
if (type(line) == bool) and not line:
259+
logger.error("Getting unlock data failed.")
260+
yield False
261+
else:
262+
yield True
263+
264+
222265
def fastboot_reboot(bin_path: Path) -> bool:
223266
"""Reboot with fastboot"""
224267
logger.info("Rebooting device with fastboot.")
@@ -260,6 +303,10 @@ def heimdall_flash_recovery(bin_path: Path, recovery: str) -> bool:
260303
def search_device(platform: str, bin_path: Path) -> Optional[str]:
261304
"""Search for a connected device."""
262305
logger.info(f"Search devices on {platform} with {bin_path}...")
306+
# map some detected device codes to their real code.
307+
device_code_mapping = {
308+
"C6603": "yuga",
309+
}
263310
try:
264311
# read device properties
265312
if platform in ("linux", "darwin"):
@@ -291,7 +338,7 @@ def search_device(platform: str, bin_path: Path) -> Optional[str]:
291338
raise Exception(f"Unknown platform {platform}.")
292339
device_code = output.split("[")[-1].strip()[:-1].strip()
293340
logger.info(device_code)
294-
return device_code
341+
return device_code_mapping.get(device_code, device_code)
295342
except CalledProcessError:
296343
logger.error("Failed to detect a device.")
297344
return None

0 commit comments

Comments
 (0)