From 531eb19b1dfad07b90a1e87b5745db877870f7c7 Mon Sep 17 00:00:00 2001 From: Ingo-FP-Angel Date: Fri, 7 Aug 2020 18:39:07 +0200 Subject: [PATCH 01/24] Add files necessary for FP2 support (WIP) --- build.gradle | 5 + .../linux/fp3_install-from-recovery.sh | 80 +++++++++++++++ .../linux/install-recovery-from-fastboot.sh | 40 ++++++++ flash-scripts/linux/wait-fastboot.sh | 38 +++++++ flash-scripts/windows/wait-fastboot.bat | 41 ++++++++ .../easy/installer/helpers/DeviceHelper.java | 1 + .../imageName_en_EN_0009.properties | 36 +++++++ src/main/resources/yaml/FP2.yml | 99 +++++++++++++++++++ src/main/resources/yaml/FP2_fs.yml | 82 +++++++++++++++ 9 files changed, 422 insertions(+) create mode 100755 flash-scripts/linux/fp3_install-from-recovery.sh create mode 100755 flash-scripts/linux/install-recovery-from-fastboot.sh create mode 100644 flash-scripts/linux/wait-fastboot.sh create mode 100644 flash-scripts/windows/wait-fastboot.bat create mode 100644 src/main/resources/instructions/imageName_en_EN_0009.properties create mode 100644 src/main/resources/yaml/FP2.yml create mode 100644 src/main/resources/yaml/FP2_fs.yml diff --git a/build.gradle b/build.gradle index ac4696b5..955758c1 100644 --- a/build.gradle +++ b/build.gradle @@ -74,6 +74,11 @@ ext { jlink { imageZip = project.file("${buildDir}/distributions/${appPackaging}.zip") options = ['--strip-debug', '--compress', '2', '--no-header-files', '--no-man-pages'] + mergedModule { + requires "java.logging" + requires "java.naming" + requires "java.xml" + } targetPlatform(linuxPlatform) { jdkHome = "buildSrc/linux/jdk-11.0.2" addExtraModulePath("buildSrc/linux/javafx-jmods-13.0.1") diff --git a/flash-scripts/linux/fp3_install-from-recovery.sh b/flash-scripts/linux/fp3_install-from-recovery.sh new file mode 100755 index 00000000..869d4b97 --- /dev/null +++ b/flash-scripts/linux/fp3_install-from-recovery.sh @@ -0,0 +1,80 @@ +#!/bin/bash + +# Copyright (C) 2019 ECORP SAS - Author: Romain Hunault +# Copyright (C) 2020 ECORP SAS - Author: Vincent Bourgmayer +# +# This program is free software: you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program. If not, see . + +# Parameter +# $1: DEVICE_ID device identifier +# $2: ARCHIVE_PATH path to the /e/ archive to flash +# $3: ADB_FOLDER_PATH: the path where runnable adb is stored + +# Exit status +# - 0 : /e/ installed +# - 1 : Problems occurred (adb returns only 1 if an error occurs) +# - 2 : Problems occurred during file transfer +# - 3 : Problems occurred /e/ installation +# - 101 : DEVICE_ID missing +# - 102 : ARCHIVE_PATH missing + +DEVICE_ID=$1 +ARCHIVE_PATH=$2 +ARCHIVE_NAME=$(basename "$2") +ADB_FOLDER_PATH=$3 +ADB_PATH=${ADB_FOLDER_PATH}"adb" + + +echo "adb path : $ADB_PATH" +if [ -z "$DEVICE_ID" ] +then + exit 101 +fi + +if [ -z "$ARCHIVE_PATH" ] +then + exit 102 +fi + +sleep 10 + +"$ADB_PATH" -s "$DEVICE_ID" shell "twrp wipe system" ; + +echo "system wiped" + +sleep 10 + +"$ADB_PATH" -s "$DEVICE_ID" shell "twrp wipe cache" ; + +echo "cache wiped" + +sleep 10 +"$ADB_PATH" -s "$DEVICE_ID" shell "twrp wipe data" ; + +echo "data wiped" + +sleep 10 + + +if ! "$ADB_PATH" -s "$DEVICE_ID" push "$ARCHIVE_PATH" /sdcard ; +then exit 2 ; fi + +if ! "$ADB_PATH" -s "$DEVICE_ID" shell twrp install /sdcard/"$ARCHIVE_NAME" ; +then exit 3 ; fi + +sleep 1 + +"$ADB_PATH" -s "$DEVICE_ID" shell rm /sdcard/"$ARCHIVE_NAME" ; + +sleep 1 diff --git a/flash-scripts/linux/install-recovery-from-fastboot.sh b/flash-scripts/linux/install-recovery-from-fastboot.sh new file mode 100755 index 00000000..15adb591 --- /dev/null +++ b/flash-scripts/linux/install-recovery-from-fastboot.sh @@ -0,0 +1,40 @@ +#!/bin/bash + +# Copyright (C) 2019 ECORP SAS - Author: Romain Hunault +# Copyright (C) 2020 ECORP SAS - Author: Vincent Bourgmayer +# +# This program is free software: you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program. If not, see . + +# Parameter +# $1: TWRP_IMAGE_PATH need twrp path (${TWRP_FOLDER}/${TWRP}) +# $2: The folder where fastboot runnable is stored + +# Exit status +# - 0 : Recovery installed +# - 1 : No problems occurred +# - 101 : TWRP_IMAGE_PATH missing + +TWRP_IMAGE_PATH=$1 +FASTBOOT_FOLDER_PATH=$2 +FASTBOOT_PATH=${FASTBOOT_FOLDER_PATH}"fastboot" + +echo "fastboot path: $FASTBOOT_PATH" + +if [ -z "$TWRP_IMAGE_PATH" ] +then + echo "TWRP Image path is empty" + exit 101 +fi + +"$FASTBOOT_PATH" flash recovery "$TWRP_IMAGE_PATH" diff --git a/flash-scripts/linux/wait-fastboot.sh b/flash-scripts/linux/wait-fastboot.sh new file mode 100644 index 00000000..3cc7928a --- /dev/null +++ b/flash-scripts/linux/wait-fastboot.sh @@ -0,0 +1,38 @@ +#!/bin/bash + +# Copyright (C) 2019 ECORP SAS - Author: Romain Hunault +# Copyright (C) 2020 ECORP SAS - Author: Vincent Bourgmayer +# +# This program is free software: you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program. If not, see . + +# TODO: What if 2 devices detected? +# Parameter +# $1: The folder where fastboot runnable is stored + +# Exit status +# - 0 : Device in fastboot mode detected +# - 1 : Error + +FASTBOOT_FOLDER_PATH=$1 +FASTBOOT_PATH=${FASTBOOT_FOLDER_PATH}"fastboot" + +echo "fastboot path: $FASTBOOT_PATH" + +while [ "$($FASTBOOT_PATH devices | grep -q fastboot; echo $?)" = 1 ] +do + sleep 1s +done + +sleep 5s +echo "fastboot mode detected" \ No newline at end of file diff --git a/flash-scripts/windows/wait-fastboot.bat b/flash-scripts/windows/wait-fastboot.bat new file mode 100644 index 00000000..47e2233a --- /dev/null +++ b/flash-scripts/windows/wait-fastboot.bat @@ -0,0 +1,41 @@ +::!/bin/bash + +:: Copyright (C) 2019 ECORP SAS - Author: Romain Hunault +:: +:: This program is free software: you can redistribute it and/or modify +:: it under the terms of the GNU General Public License as published by +:: the Free Software Foundation, either version 3 of the License, or +:: (at your option) any later version. +:: +:: This program is distributed in the hope that it will be useful, +:: but WITHOUT ANY WARRANTY; without even the implied warranty of +:: MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +:: GNU General Public License for more details. +:: +:: You should have received a copy of the GNU General Public License +:: along with this program. If not, see . + +:: TODO: What if 2 devices detected? +:: $1: The folder where fastboot runnable is stored + +:: Exit status +:: - 0 : Device in fastboot mode detected +:: - 1 : Error + +set "FASTBOOT_FOLDER_PATH=%1" +set "FASTBOOT_PATH=%FASTBOOT_FOLDER_PATH%fastboot" +echo "FASTBOOT_PATH path:"%FASTBOOT_PATH% + +:fastboot_detect +%FASTBOOT_PATH% devices 2>&1 | findstr fastboot +if errorLevel 1 ( + timeout 1 >nul 2>&1 + goto :fastboot_detect +) + +call fastboot_detect + +timeout 5 >nul +echo "fastboot mode detected" + +exit /b 0 diff --git a/src/main/java/ecorp/easy/installer/helpers/DeviceHelper.java b/src/main/java/ecorp/easy/installer/helpers/DeviceHelper.java index 62ff0c61..f819626a 100644 --- a/src/main/java/ecorp/easy/installer/helpers/DeviceHelper.java +++ b/src/main/java/ecorp/easy/installer/helpers/DeviceHelper.java @@ -29,6 +29,7 @@ public class DeviceHelper { put("zeroflte", "0005"); put("dream2lte", "0006"); put("dreamlte", "0007"); + put("FP2", "0009"); }}; diff --git a/src/main/resources/instructions/imageName_en_EN_0009.properties b/src/main/resources/instructions/imageName_en_EN_0009.properties new file mode 100644 index 00000000..f1f30bed --- /dev/null +++ b/src/main/resources/instructions/imageName_en_EN_0009.properties @@ -0,0 +1,36 @@ +# Copyright 2019-2020 - ECORP SAS + +# This program is free software: you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. + +# You should have received a copy of the GNU General Public License +# along with this program. If not, see . + +#install_instr_turnOff +install_instr_startDownload=galaxyS7_Download_mode_400px.png +install_instr_acceptWarning=galaxyS7_Accept_warning_400px.png +#install_instr_oemUnlock +#install_instr_recoveryInstall +install_instr_leaveDownload=galaxyS7_Download_mode_400px.png +install_instr_startRecovery=galaxyS7_Recovery_mode_400px.png +install_instr_tapWipe=TWRP_wipe.png +install_instr_tapReboot=TWRP_reboot.png +#install_instr_swipeTwrp +#install_instr_eosInstall +install_instr_tapAdvancedWipe=TWRP_advanceWipe.png +install_instr_tickData=TWRP_checkData.png +install_instr_tapRepairChangeFs=TWRP_repairchangeFS.png +install_instr_tapChangeFs=TWRP_changeFS.png +install_instr_tapExt3=TWRP_toEXT3.png +install_instr_swipeForOk=TWRP_toEXT3_swipe.png +install_instr_backX2=TWRP_tapback.png +install_instr_resizeFs=TWRP_resizeFS.png +#install_instr_tapRebootSystem +install_instr_doNotInstall=TWRP_doNotInstall.png \ No newline at end of file diff --git a/src/main/resources/yaml/FP2.yml b/src/main/resources/yaml/FP2.yml new file mode 100644 index 00000000..96a74017 --- /dev/null +++ b/src/main/resources/yaml/FP2.yml @@ -0,0 +1,99 @@ +## Copyright 2019-2020 - ECORP SAS + +## This program is free software: you can redistribute it and/or modify +## it under the terms of the GNU General Public License as published by +## the Free Software Foundation, either version 3 of the License, or +## (at your option) any later version. +## +## This program is distributed in the hope that it will be useful, +## but WITHOUT ANY WARRANTY; without even the implied warranty of +## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +## GNU General Public License for more details. + +## You should have received a copy of the GNU General Public License +## along with this program. If not, see . +## Author: Vincent Bourgmayer +--- +name: FP2 +flash: + f1: + script: wait-fastboot + parameters: + fastboot_folder_path: ${ADB_FOLDER_PATH} + codes: + ok: + 0: ~ + ko: + 1: script_error_waitDownload_1 + output: ~ + succeed: f4 + failed: ~ + f4: + script: install-recovery-from-fastboot + parameters: + twrp_image_path: ${TWRP_IMAGE_PATH} + fastboot_folder_path: ${ADB_FOLDER_PATH} + codes: + ok: + 0: ~ + ko: + 1: script_error_unknown + 101: script_error_installRecovery_101 + output: ~ + succeed: f5 + failed: ~ + f5: + script: wait-recovery + parameters: + device_id: ${DEVICE_ID} + adb_folder_path: ${ADB_FOLDER_PATH} + codes: + ok: + 0: ~ + ko: + 1: script_error_waitRecovery_1 + 101: script_error_waitRecovery_101 + 102: script_error_waitRecovery_102 + output: ~ + succeed: f6 + failed: ~ + f6: + script: fp3_install-from-recovery + parameters: + device_id: ${DEVICE_ID} + archive_path: ${ARCHIVE_PATH} + adb_folder_path: ${ADB_FOLDER_PATH} + codes: + ok: + 0: ~ + ko: + 1: script_error_installFromRecovery_1 + 2: script_error_installFromRecovery_2 + 3: script_error_installFromRecovery_3 + 101: script_error_installFromRecovery_101 + 102: script_error_installFromRecovery_102 + output: ~ + succeed: f7 + failed: ~ + f7: + script: askAccount + parameters: ~ + codes: ~ + output: ~ + succeed: f8 + failed: ~ + f8: + script: wait-reboot + parameters: + device_id: ${DEVICE_ID} + adb_folder_path: ${ADB_FOLDER_PATH} + codes: + ok: + 0: ~ + ko: + 1: script_error_unknown + 10: script_error_waitReboot_10 + 101: script_error_waitReboot_101 + output: ~ + succeed: ~ + failed: ~ \ No newline at end of file diff --git a/src/main/resources/yaml/FP2_fs.yml b/src/main/resources/yaml/FP2_fs.yml new file mode 100644 index 00000000..6c27e3f0 --- /dev/null +++ b/src/main/resources/yaml/FP2_fs.yml @@ -0,0 +1,82 @@ +## Copyright 2019-2020 - ECORP SAS + +## This program is free software: you can redistribute it and/or modify +## it under the terms of the GNU General Public License as published by +## the Free Software Foundation, either version 3 of the License, or +## (at your option) any later version. +## +## This program is distributed in the hope that it will be useful, +## but WITHOUT ANY WARRANTY; without even the implied warranty of +## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +## GNU General Public License for more details. + +## You should have received a copy of the GNU General Public License +## along with this program. If not, see . +## Author: Vincent Bourgmayer +--- +sources: + rom: + url: https://images.ecloud.global/dev/FP2/e-0.10-p-2020080666687-dev-FP2.zip + filePath: e-0.10-p-2020080666687-dev-FP2.zip + twrp: + url: https://dl.twrp.me/FP2/twrp-3.4.0-0-FP2.img.html + filePath: twrp-3.4.0-0-FP2.img.html +flash: + f1: + ui: + type: action + title: stepTitle1On7 + instruction: + - install_instr_turnOff + - install_instr_startDownload + - install_instr_acceptWarning + stepNumber: 1/7 + titleIcon: icon-download.png + f4: + ui: + type: load + title: stepTitle4On7 + instruction: + - install_instr_recoveryInstall + stepNumber: 4/7 + averageTime: 6 + f5: + ui: + type: action + title: stepTitle5On7 + instruction: + - install_instr_leaveDownload + - install_instr_startRecovery + - install_instr_swipeTwrp + stepNumber: 5/7 + titleIcon: icon-download.png + f6: + ui: + type: load + title: stepTitle6On7 + instruction: + - install_instr_eosInstall + stepNumber: 6/7 + averageTime: 475 + f7: + ui: + type: askAccount + f8: + ui: + type: action + title: stepTitle7On7 + instruction: + - install_instr_tapWipe + - install_instr_tapAdvancedWipe + - install_instr_tickData + - install_instr_tapRepairChangeFs + - install_instr_tapChangeFs + - install_instr_tapExt3 + - install_instr_swipeForOk + - install_instr_backX2 + - install_instr_resizeFs + - install_instr_swipeForOk + - install_instr_tapRebootSystem + - install_instr_doNotInstall + stepNumber: 7/7 + titleIcon: icon-search.png \ No newline at end of file -- GitLab From b3c767278bcf006c285603fad1afa72dbd15284f Mon Sep 17 00:00:00 2001 From: Ingo-FP-Angel Date: Fri, 7 Aug 2020 19:50:59 +0200 Subject: [PATCH 02/24] Make script executable --- flash-scripts/linux/wait-fastboot.sh | 0 1 file changed, 0 insertions(+), 0 deletions(-) mode change 100644 => 100755 flash-scripts/linux/wait-fastboot.sh diff --git a/flash-scripts/linux/wait-fastboot.sh b/flash-scripts/linux/wait-fastboot.sh old mode 100644 new mode 100755 -- GitLab From 7a25035e35d308f96f66ae8dd75af07a2082e0ef Mon Sep 17 00:00:00 2001 From: Ingo-FP-Angel Date: Fri, 7 Aug 2020 19:53:56 +0200 Subject: [PATCH 03/24] Remove ".html" from file name --- src/main/resources/yaml/FP2_fs.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/main/resources/yaml/FP2_fs.yml b/src/main/resources/yaml/FP2_fs.yml index 6c27e3f0..dbdeacdc 100644 --- a/src/main/resources/yaml/FP2_fs.yml +++ b/src/main/resources/yaml/FP2_fs.yml @@ -19,8 +19,8 @@ sources: url: https://images.ecloud.global/dev/FP2/e-0.10-p-2020080666687-dev-FP2.zip filePath: e-0.10-p-2020080666687-dev-FP2.zip twrp: - url: https://dl.twrp.me/FP2/twrp-3.4.0-0-FP2.img.html - filePath: twrp-3.4.0-0-FP2.img.html + url: https://dl.twrp.me/FP2/twrp-3.4.0-0-FP2.img + filePath: twrp-3.4.0-0-FP2.img flash: f1: ui: -- GitLab From a57ff50fdcb6b63db74bb6b6a65742904d89f7a3 Mon Sep 17 00:00:00 2001 From: Ingo-FP-Angel Date: Fri, 7 Aug 2020 20:08:46 +0200 Subject: [PATCH 04/24] Create /cache/recovery before installing the ZIP --- flash-scripts/linux/fp3_install-from-recovery.sh | 13 ++++++++++++- 1 file changed, 12 insertions(+), 1 deletion(-) diff --git a/flash-scripts/linux/fp3_install-from-recovery.sh b/flash-scripts/linux/fp3_install-from-recovery.sh index 869d4b97..c660d5c9 100755 --- a/flash-scripts/linux/fp3_install-from-recovery.sh +++ b/flash-scripts/linux/fp3_install-from-recovery.sh @@ -66,15 +66,26 @@ echo "data wiped" sleep 10 +echo "start installing ZIP archive" -if ! "$ADB_PATH" -s "$DEVICE_ID" push "$ARCHIVE_PATH" /sdcard ; +"$ADB_PATH" -s "$DEVICE_ID" shell "mkdir /cache/recovery" ; + +echo "created /cache/recovery" + +if ! "$ADB_PATH" -s "$DEVICE_ID" push "$ARCHIVE_PATH" /sdcard ; then exit 2 ; fi +echo "pushed ZIP archive" + if ! "$ADB_PATH" -s "$DEVICE_ID" shell twrp install /sdcard/"$ARCHIVE_NAME" ; then exit 3 ; fi +echo "installed ZIP archive" + sleep 1 "$ADB_PATH" -s "$DEVICE_ID" shell rm /sdcard/"$ARCHIVE_NAME" ; +echo "removed ZIP archive" + sleep 1 -- GitLab From 3a398879f3e163be733cb6c3a220a5f0cf707365 Mon Sep 17 00:00:00 2001 From: Ingo-FP-Angel Date: Sat, 15 Aug 2020 13:58:08 +0200 Subject: [PATCH 05/24] Adapt instructions for FP2 and add some images --- .../images/FP2_fastboot_mode_400px.png | Bin 0 -> 11331 bytes .../images/FP2_recovery_mode_400px.png | Bin 0 -> 12025 bytes .../imageName_en_EN_0009.properties | 22 ++------------- .../resources/lang/translation.properties | 2 ++ src/main/resources/yaml/FP2_fs.yml | 26 +++++------------- 5 files changed, 11 insertions(+), 39 deletions(-) create mode 100644 src/main/resources/images/FP2_fastboot_mode_400px.png create mode 100644 src/main/resources/images/FP2_recovery_mode_400px.png diff --git a/src/main/resources/images/FP2_fastboot_mode_400px.png b/src/main/resources/images/FP2_fastboot_mode_400px.png new file mode 100644 index 0000000000000000000000000000000000000000..5d681b8f8f13e687126766f1e1ab99b3de13b896 GIT binary patch literal 11331 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 literal 0 HcmV?d00001 diff --git a/src/main/resources/instructions/imageName_en_EN_0009.properties b/src/main/resources/instructions/imageName_en_EN_0009.properties index f1f30bed..56247dff 100644 --- a/src/main/resources/instructions/imageName_en_EN_0009.properties +++ b/src/main/resources/instructions/imageName_en_EN_0009.properties @@ -13,24 +13,6 @@ # You should have received a copy of the GNU General Public License # along with this program. If not, see . -#install_instr_turnOff -install_instr_startDownload=galaxyS7_Download_mode_400px.png -install_instr_acceptWarning=galaxyS7_Accept_warning_400px.png -#install_instr_oemUnlock -#install_instr_recoveryInstall -install_instr_leaveDownload=galaxyS7_Download_mode_400px.png -install_instr_startRecovery=galaxyS7_Recovery_mode_400px.png -install_instr_tapWipe=TWRP_wipe.png -install_instr_tapReboot=TWRP_reboot.png -#install_instr_swipeTwrp -#install_instr_eosInstall -install_instr_tapAdvancedWipe=TWRP_advanceWipe.png -install_instr_tickData=TWRP_checkData.png -install_instr_tapRepairChangeFs=TWRP_repairchangeFS.png -install_instr_tapChangeFs=TWRP_changeFS.png -install_instr_tapExt3=TWRP_toEXT3.png -install_instr_swipeForOk=TWRP_toEXT3_swipe.png -install_instr_backX2=TWRP_tapback.png -install_instr_resizeFs=TWRP_resizeFS.png -#install_instr_tapRebootSystem +install_instr_startFastboot2=FP2_fastboot_mode_400px.png +install_instr_startRecovery2=FP2_recovery_mode_400px.png install_instr_doNotInstall=TWRP_doNotInstall.png \ No newline at end of file diff --git a/src/main/resources/lang/translation.properties b/src/main/resources/lang/translation.properties index 71b19885..68262717 100644 --- a/src/main/resources/lang/translation.properties +++ b/src/main/resources/lang/translation.properties @@ -109,12 +109,14 @@ install_btn_sendLogSuccess=Log sent install_instr_turnOff=Turn off the phone install_instr_turnOffAgain=Turn off the phone again install_instr_startDownload=Keep pressing simultaneously "Power" & "Home" & "Volume Down" until a blue screen appear to access Download Mode +install_instr_startFastboot2=Keep pressing simultaneously "Power" & "Volume Down" until a screen with the "Powered by Android" boot logo appears install_instr_acceptWarning=Accept warning by pressing on "Volume Up" install_instr_verifyHeimdall=Verify Heimdall install_instr_oemUnlock=OEM Unlocking install_instr_recoveryInstall=Recovery installation install_instr_leaveDownload=Keep pressing simultaneously "Power" & "Home" & "Volume Down" until device turns off install_instr_startRecovery=Keep pressing simultaneously "Power" & "Home" & "Volume Up" until 'teamwin' screen appears +install_instr_startRecovery2=Keep pressing simultaneously "Power" & "Volume Up" until 'teamwin' screen appears install_instr_keepReadOnly=Tap on 'Keep Read Only' install_instr_tapWipe=Tap on 'Wipe' install_instr_tapFormatData=Tap on 'Format Data' diff --git a/src/main/resources/yaml/FP2_fs.yml b/src/main/resources/yaml/FP2_fs.yml index dbdeacdc..167b5b4f 100644 --- a/src/main/resources/yaml/FP2_fs.yml +++ b/src/main/resources/yaml/FP2_fs.yml @@ -28,9 +28,8 @@ flash: title: stepTitle1On7 instruction: - install_instr_turnOff - - install_instr_startDownload - - install_instr_acceptWarning - stepNumber: 1/7 + - install_instr_startFastboot2 + stepNumber: 1/5 titleIcon: icon-download.png f4: ui: @@ -38,17 +37,16 @@ flash: title: stepTitle4On7 instruction: - install_instr_recoveryInstall - stepNumber: 4/7 + stepNumber: 2/5 averageTime: 6 f5: ui: type: action title: stepTitle5On7 instruction: - - install_instr_leaveDownload - - install_instr_startRecovery + - install_instr_startRecovery2 - install_instr_swipeTwrp - stepNumber: 5/7 + stepNumber: 3/5 titleIcon: icon-download.png f6: ui: @@ -56,7 +54,7 @@ flash: title: stepTitle6On7 instruction: - install_instr_eosInstall - stepNumber: 6/7 + stepNumber: 4/5 averageTime: 475 f7: ui: @@ -66,17 +64,7 @@ flash: type: action title: stepTitle7On7 instruction: - - install_instr_tapWipe - - install_instr_tapAdvancedWipe - - install_instr_tickData - - install_instr_tapRepairChangeFs - - install_instr_tapChangeFs - - install_instr_tapExt3 - - install_instr_swipeForOk - - install_instr_backX2 - - install_instr_resizeFs - - install_instr_swipeForOk - install_instr_tapRebootSystem - install_instr_doNotInstall - stepNumber: 7/7 + stepNumber: 5/5 titleIcon: icon-search.png \ No newline at end of file -- GitLab From 0d96b5ae89cee2e9d889270d12111dcc123deafd Mon Sep 17 00:00:00 2001 From: Ingo-FP-Angel Date: Sat, 15 Aug 2020 15:13:20 +0200 Subject: [PATCH 06/24] Make script executable --- src/main/resources/lang/translation.properties | 3 +++ src/main/resources/yaml/FP2_fs.yml | 6 ++++-- 2 files changed, 7 insertions(+), 2 deletions(-) diff --git a/src/main/resources/lang/translation.properties b/src/main/resources/lang/translation.properties index 68262717..7ac5b2e8 100644 --- a/src/main/resources/lang/translation.properties +++ b/src/main/resources/lang/translation.properties @@ -124,6 +124,7 @@ install_instr_writeYes=Write 'yes' install_instr_validate=Validate install_instr_backX3=Tap 'Back' 3 times install_instr_tapReboot=Tap on 'Reboot' +install_instr_tapSystem=Tap on 'System' install_instr_tapRebootRecovery=Tap on 'Recovery' install_instr_doNotInstall=Tap on 'Do not install' install_instr_swipeTwrp=If asked, swipe the arrowed bar at the bottom of the screen from left to right @@ -136,6 +137,7 @@ install_instr_tapRepairChangeFs=Tap on 'Repair or Change File System' install_instr_tapChangeFs=Tap on 'Change File System' install_instr_tapExt3=Tap on 'EXT3' install_instr_swipeForOk=Swipe the arrowed bar at the bottom of the screen from left to right to confirm +install_instr_swipeForUnlock=Swipe the arrowed bar at the bottom of the screen from left to right to unlock install_instr_backX2=Tap on 'Back' 2 times install_instr_resizeFs=Tap on 'Resize file System' install_instr_tapRebootSystem=Tap on 'Reboot System' @@ -215,6 +217,7 @@ installationTitle = Installation # Title stepTitle1On7 = Connect device and start Download mode +stepTitle11n7 = Connect device and start Fastboot mode stepTitle2On7 = Unlock OEM stepTitle3On7 = Restart device in Download mode stepTitle4On7 = Recovery installation diff --git a/src/main/resources/yaml/FP2_fs.yml b/src/main/resources/yaml/FP2_fs.yml index 167b5b4f..0e770ebd 100644 --- a/src/main/resources/yaml/FP2_fs.yml +++ b/src/main/resources/yaml/FP2_fs.yml @@ -25,7 +25,7 @@ flash: f1: ui: type: action - title: stepTitle1On7 + title: stepTitle11n7 instruction: - install_instr_turnOff - install_instr_startFastboot2 @@ -64,7 +64,9 @@ flash: type: action title: stepTitle7On7 instruction: - - install_instr_tapRebootSystem + - install_instr_swipeForUnlock + - install_instr_tapReboot + - install_instr_tapSystem - install_instr_doNotInstall stepNumber: 5/5 titleIcon: icon-search.png \ No newline at end of file -- GitLab From 78ba8512e9d7cab37e921226c2f353d6066a955e Mon Sep 17 00:00:00 2001 From: Ingo-FP-Angel Date: Sat, 15 Aug 2020 15:15:25 +0200 Subject: [PATCH 07/24] Make code handle downloads from TRWP official site plus configurable file extension for checksum files --- .../subcontrollers/DownloadSrcController.java | 9 +++++---- .../easy/installer/threads/DownloadTask.java | 17 ++++++++++++----- .../easy/installer/threads/ThreadFactory.java | 12 +++++++++--- src/main/resources/yaml/FP2_fs.yml | 1 + 4 files changed, 27 insertions(+), 12 deletions(-) diff --git a/src/main/java/ecorp/easy/installer/controllers/subcontrollers/DownloadSrcController.java b/src/main/java/ecorp/easy/installer/controllers/subcontrollers/DownloadSrcController.java index 698f80e0..911e6586 100644 --- a/src/main/java/ecorp/easy/installer/controllers/subcontrollers/DownloadSrcController.java +++ b/src/main/java/ecorp/easy/installer/controllers/subcontrollers/DownloadSrcController.java @@ -30,6 +30,7 @@ import javafx.fxml.FXML; import javafx.scene.control.Button; import javafx.scene.control.Label; import javafx.scene.control.ProgressBar; +import javafx.util.Pair; import org.slf4j.Logger; import org.slf4j.LoggerFactory; @@ -45,8 +46,8 @@ public class DownloadSrcController extends AbstractSubController { @FXML Label progressTitle; @FXML Button restartDownloadBtn; - private Map sourcesToDownload; - private Iterator> taskIterator; + private Map> sourcesToDownload; + private Iterator>> taskIterator; private DownloadTask currentTask; @Override @@ -71,8 +72,8 @@ public class DownloadSrcController extends AbstractSubController { logger.info("startNextDownload()"); logger.debug("taskIterator has next ? {} "+taskIterator.hasNext()); if(taskIterator.hasNext()){ - Map.Entry sources = taskIterator.next(); - currentTask = new DownloadTask(sources.getKey(), sources.getValue(), i18n); + Map.Entry> sources = taskIterator.next(); + currentTask = new DownloadTask(sources.getKey(), sources.getValue().getKey(), i18n, sources.getValue().getValue()); currentTask.setOnSucceeded((WorkerStateEvent eh)->{ diff --git a/src/main/java/ecorp/easy/installer/threads/DownloadTask.java b/src/main/java/ecorp/easy/installer/threads/DownloadTask.java index 15868620..fd1d06fb 100644 --- a/src/main/java/ecorp/easy/installer/threads/DownloadTask.java +++ b/src/main/java/ecorp/easy/installer/threads/DownloadTask.java @@ -56,31 +56,34 @@ public class DownloadTask extends Task{ final private ResourceBundle i18n; final private String targetUrl; final private String fileName; - + final private String checkSumExt; + /** * COnstruction of the download task * @param targetUrl the web path to the resource * @param fileName name of the file * @param resources used to send already translated message + * @param checkSumExt (optional) file extension for the checksum file */ - public DownloadTask(String targetUrl, String fileName, ResourceBundle resources){ + public DownloadTask(String targetUrl, String fileName, ResourceBundle resources, String checkSumExt){ this.targetUrl = targetUrl; this.fileName = fileName; this.i18n = resources; + this.checkSumExt = checkSumExt; } @Override protected Boolean call() throws Exception { final String localFilePath = AppConstants.getSourcesFolderPath()+fileName; - final String checksumFilePath = localFilePath+".sha256sum"; + final String checksumFilePath = localFilePath+checkSumExt; if(isCancelled()) return false; - this.updateTitle("Downloading "+fileName+".sha256sum"); + this.updateTitle("Downloading "+fileName+checkSumExt); // Download checksum. If file not downloaded return false and stop downloadin because integrity isn't guaranteed - if( !downloadFile(targetUrl+".sha256sum", checksumFilePath) ){ + if( !downloadFile(targetUrl+checkSumExt, checksumFilePath) ){ this.updateMessage(i18n.getString("download_lbl_cantcheckIntegrity")); return false; } @@ -117,6 +120,10 @@ public class DownloadTask extends Task{ HttpURLConnection connect = (HttpURLConnection) new URL(fileURL).openConnection(); connect.setReadTimeout(30000); connect.setConnectTimeout(30000); + if (fileURL.contains("dl.twrp.me")) { + // direct download from official TWRP site just redirects to itself + connect.setRequestProperty("Referer", fileURL + ".html"); + } if(connect.getResponseCode() != HttpURLConnection.HTTP_OK){ //return false it resources is unreachable return false; diff --git a/src/main/java/ecorp/easy/installer/threads/ThreadFactory.java b/src/main/java/ecorp/easy/installer/threads/ThreadFactory.java index 0ad19acc..4eda9564 100644 --- a/src/main/java/ecorp/easy/installer/threads/ThreadFactory.java +++ b/src/main/java/ecorp/easy/installer/threads/ThreadFactory.java @@ -30,6 +30,8 @@ import java.util.List; import java.util.Map; import java.util.Set; import java.util.HashMap; + +import javafx.util.Pair; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.yaml.snakeyaml.Yaml; @@ -44,7 +46,7 @@ import org.yaml.snakeyaml.Yaml; public class ThreadFactory { private final static Logger logger = LoggerFactory.getLogger(ThreadFactory.class); private ProcessMould flashMould; - private final HashMap sourcesToDownload; + private final HashMap> sourcesToDownload; private Device device; private final String yamlFolderPath; @@ -198,11 +200,15 @@ public class ThreadFactory { if(key.equals("twrp")){ AppConstants.setTwrpImgPath((String) source.get("filePath")); } - sourcesToDownload.put((String) source.get("url"), (String) source.get("filePath")); + var filePathAndCheckSumExt = new Pair( + (String) source.get("filePath"), + source.containsKey("checkSumExt") ? "."+(String) source.get("checkSumExt") : ".sha256sum" + ); + sourcesToDownload.put((String) source.get("url"), filePathAndCheckSumExt); } } - public HashMap getSourcesToDownload(){ + public HashMap> getSourcesToDownload(){ return sourcesToDownload; } diff --git a/src/main/resources/yaml/FP2_fs.yml b/src/main/resources/yaml/FP2_fs.yml index 0e770ebd..382c2eb3 100644 --- a/src/main/resources/yaml/FP2_fs.yml +++ b/src/main/resources/yaml/FP2_fs.yml @@ -21,6 +21,7 @@ sources: twrp: url: https://dl.twrp.me/FP2/twrp-3.4.0-0-FP2.img filePath: twrp-3.4.0-0-FP2.img + checkSumExt: sha256 flash: f1: ui: -- GitLab From cc06f905bfd47f581e35d8d0dc25bab7fefc30bb Mon Sep 17 00:00:00 2001 From: Ingo-FP-Angel Date: Wed, 30 Sep 2020 19:18:48 +0200 Subject: [PATCH 08/24] Revert "Make code handle downloads from TRWP official site plus configurable file extension for checksum files" This reverts commit 78ba8512 --- .../subcontrollers/DownloadSrcController.java | 9 ++++----- .../easy/installer/threads/DownloadTask.java | 17 +++++------------ .../easy/installer/threads/ThreadFactory.java | 12 +++--------- src/main/resources/yaml/FP2_fs.yml | 1 - 4 files changed, 12 insertions(+), 27 deletions(-) diff --git a/src/main/java/ecorp/easy/installer/controllers/subcontrollers/DownloadSrcController.java b/src/main/java/ecorp/easy/installer/controllers/subcontrollers/DownloadSrcController.java index 911e6586..698f80e0 100644 --- a/src/main/java/ecorp/easy/installer/controllers/subcontrollers/DownloadSrcController.java +++ b/src/main/java/ecorp/easy/installer/controllers/subcontrollers/DownloadSrcController.java @@ -30,7 +30,6 @@ import javafx.fxml.FXML; import javafx.scene.control.Button; import javafx.scene.control.Label; import javafx.scene.control.ProgressBar; -import javafx.util.Pair; import org.slf4j.Logger; import org.slf4j.LoggerFactory; @@ -46,8 +45,8 @@ public class DownloadSrcController extends AbstractSubController { @FXML Label progressTitle; @FXML Button restartDownloadBtn; - private Map> sourcesToDownload; - private Iterator>> taskIterator; + private Map sourcesToDownload; + private Iterator> taskIterator; private DownloadTask currentTask; @Override @@ -72,8 +71,8 @@ public class DownloadSrcController extends AbstractSubController { logger.info("startNextDownload()"); logger.debug("taskIterator has next ? {} "+taskIterator.hasNext()); if(taskIterator.hasNext()){ - Map.Entry> sources = taskIterator.next(); - currentTask = new DownloadTask(sources.getKey(), sources.getValue().getKey(), i18n, sources.getValue().getValue()); + Map.Entry sources = taskIterator.next(); + currentTask = new DownloadTask(sources.getKey(), sources.getValue(), i18n); currentTask.setOnSucceeded((WorkerStateEvent eh)->{ diff --git a/src/main/java/ecorp/easy/installer/threads/DownloadTask.java b/src/main/java/ecorp/easy/installer/threads/DownloadTask.java index fd1d06fb..15868620 100644 --- a/src/main/java/ecorp/easy/installer/threads/DownloadTask.java +++ b/src/main/java/ecorp/easy/installer/threads/DownloadTask.java @@ -56,34 +56,31 @@ public class DownloadTask extends Task{ final private ResourceBundle i18n; final private String targetUrl; final private String fileName; - final private String checkSumExt; - + /** * COnstruction of the download task * @param targetUrl the web path to the resource * @param fileName name of the file * @param resources used to send already translated message - * @param checkSumExt (optional) file extension for the checksum file */ - public DownloadTask(String targetUrl, String fileName, ResourceBundle resources, String checkSumExt){ + public DownloadTask(String targetUrl, String fileName, ResourceBundle resources){ this.targetUrl = targetUrl; this.fileName = fileName; this.i18n = resources; - this.checkSumExt = checkSumExt; } @Override protected Boolean call() throws Exception { final String localFilePath = AppConstants.getSourcesFolderPath()+fileName; - final String checksumFilePath = localFilePath+checkSumExt; + final String checksumFilePath = localFilePath+".sha256sum"; if(isCancelled()) return false; - this.updateTitle("Downloading "+fileName+checkSumExt); + this.updateTitle("Downloading "+fileName+".sha256sum"); // Download checksum. If file not downloaded return false and stop downloadin because integrity isn't guaranteed - if( !downloadFile(targetUrl+checkSumExt, checksumFilePath) ){ + if( !downloadFile(targetUrl+".sha256sum", checksumFilePath) ){ this.updateMessage(i18n.getString("download_lbl_cantcheckIntegrity")); return false; } @@ -120,10 +117,6 @@ public class DownloadTask extends Task{ HttpURLConnection connect = (HttpURLConnection) new URL(fileURL).openConnection(); connect.setReadTimeout(30000); connect.setConnectTimeout(30000); - if (fileURL.contains("dl.twrp.me")) { - // direct download from official TWRP site just redirects to itself - connect.setRequestProperty("Referer", fileURL + ".html"); - } if(connect.getResponseCode() != HttpURLConnection.HTTP_OK){ //return false it resources is unreachable return false; diff --git a/src/main/java/ecorp/easy/installer/threads/ThreadFactory.java b/src/main/java/ecorp/easy/installer/threads/ThreadFactory.java index 4eda9564..0ad19acc 100644 --- a/src/main/java/ecorp/easy/installer/threads/ThreadFactory.java +++ b/src/main/java/ecorp/easy/installer/threads/ThreadFactory.java @@ -30,8 +30,6 @@ import java.util.List; import java.util.Map; import java.util.Set; import java.util.HashMap; - -import javafx.util.Pair; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.yaml.snakeyaml.Yaml; @@ -46,7 +44,7 @@ import org.yaml.snakeyaml.Yaml; public class ThreadFactory { private final static Logger logger = LoggerFactory.getLogger(ThreadFactory.class); private ProcessMould flashMould; - private final HashMap> sourcesToDownload; + private final HashMap sourcesToDownload; private Device device; private final String yamlFolderPath; @@ -200,15 +198,11 @@ public class ThreadFactory { if(key.equals("twrp")){ AppConstants.setTwrpImgPath((String) source.get("filePath")); } - var filePathAndCheckSumExt = new Pair( - (String) source.get("filePath"), - source.containsKey("checkSumExt") ? "."+(String) source.get("checkSumExt") : ".sha256sum" - ); - sourcesToDownload.put((String) source.get("url"), filePathAndCheckSumExt); + sourcesToDownload.put((String) source.get("url"), (String) source.get("filePath")); } } - public HashMap> getSourcesToDownload(){ + public HashMap getSourcesToDownload(){ return sourcesToDownload; } diff --git a/src/main/resources/yaml/FP2_fs.yml b/src/main/resources/yaml/FP2_fs.yml index 382c2eb3..0e770ebd 100644 --- a/src/main/resources/yaml/FP2_fs.yml +++ b/src/main/resources/yaml/FP2_fs.yml @@ -21,7 +21,6 @@ sources: twrp: url: https://dl.twrp.me/FP2/twrp-3.4.0-0-FP2.img filePath: twrp-3.4.0-0-FP2.img - checkSumExt: sha256 flash: f1: ui: -- GitLab From 48531945d619fc82a0702420c71d7dd23891e957 Mon Sep 17 00:00:00 2001 From: Ingo-FP-Angel Date: Wed, 30 Sep 2020 19:22:40 +0200 Subject: [PATCH 09/24] Update to newest image and replace twrp with /e/ recovery (untested) --- src/main/resources/yaml/FP2_fs.yml | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/src/main/resources/yaml/FP2_fs.yml b/src/main/resources/yaml/FP2_fs.yml index 0e770ebd..d0e342ef 100644 --- a/src/main/resources/yaml/FP2_fs.yml +++ b/src/main/resources/yaml/FP2_fs.yml @@ -16,11 +16,11 @@ --- sources: rom: - url: https://images.ecloud.global/dev/FP2/e-0.10-p-2020080666687-dev-FP2.zip - filePath: e-0.10-p-2020080666687-dev-FP2.zip + url: https://images.ecloud.global/dev/FP2/e-0.11-p-2020082870302-dev-FP2.zip + filePath: e-0.11-p-2020082870302-dev-FP2.zip twrp: - url: https://dl.twrp.me/FP2/twrp-3.4.0-0-FP2.img - filePath: twrp-3.4.0-0-FP2.img + url: https://images.ecloud.global/dev/FP2/recovery-e-0.11-q-2020090772203-dev-FP2.img + filePath: recovery-e-0.11-q-2020090772203-dev-FP2.img flash: f1: ui: -- GitLab From bac334ed6ae447d7abd7a34d6d7fba7281233ad9 Mon Sep 17 00:00:00 2001 From: Ingo-FP-Angel Date: Tue, 17 Nov 2020 19:42:32 +0100 Subject: [PATCH 10/24] Make code handle downloads from TRWP official site plus configurable file extension for checksum files This is a better approach than last time I tried --- .../subcontrollers/DownloadSrcController.java | 35 ++++--- .../installer/models/SourceToDownload.java | 29 ++++++ .../easy/installer/tasks/DownloadTask.java | 44 ++++----- .../easy/installer/threads/ThreadFactory.java | 92 ++++++++++--------- src/main/resources/yaml/FP2_fs.yml | 9 +- 5 files changed, 123 insertions(+), 86 deletions(-) create mode 100644 src/main/java/ecorp/easy/installer/models/SourceToDownload.java diff --git a/src/main/java/ecorp/easy/installer/controllers/subcontrollers/DownloadSrcController.java b/src/main/java/ecorp/easy/installer/controllers/subcontrollers/DownloadSrcController.java index 7d6c951a..2b640396 100644 --- a/src/main/java/ecorp/easy/installer/controllers/subcontrollers/DownloadSrcController.java +++ b/src/main/java/ecorp/easy/installer/controllers/subcontrollers/DownloadSrcController.java @@ -18,12 +18,14 @@ package ecorp.easy.installer.controllers.subcontrollers; import ecorp.easy.installer.controllers.MainWindowController; +import ecorp.easy.installer.models.SourceToDownload; import ecorp.easy.installer.tasks.DownloadTask; import java.net.URL; import java.util.Arrays; import java.util.Iterator; -import java.util.Map; +import java.util.List; import java.util.ResourceBundle; + import javafx.concurrent.Service; import javafx.concurrent.Task; import javafx.concurrent.Worker.State; @@ -45,9 +47,8 @@ public class DownloadSrcController extends AbstractSubController { private @FXML Label progressLabel; private @FXML Label progressTitle; private @FXML Button restartDownloadBtn; - - private Map sourcesToDownload; - private Iterator> taskIterator; + + private Iterator taskIterator; private DownloadService currentService; @Override @@ -60,18 +61,18 @@ public class DownloadSrcController extends AbstractSubController { @Override public void setParentController(MainWindowController parentController){ super.setParentController(parentController); - sourcesToDownload = parentController.getThreadFactory().getSourcesToDownload(); - taskIterator = sourcesToDownload.entrySet().iterator(); + List sourcesToDownload = parentController.getThreadFactory().getSourcesToDownload(); + taskIterator = sourcesToDownload.iterator(); startNextDownload(); } private boolean startNextDownload(){ logger.info("startNextDownload()"); - logger.debug("taskIterator has next ? {} "+taskIterator.hasNext()); + logger.debug("taskIterator has next ? {} ", taskIterator.hasNext()); if(taskIterator.hasNext()){ - Map.Entry source = taskIterator.next(); + SourceToDownload sourceToDownload = taskIterator.next(); - currentService = new DownloadService(source.getKey(), source.getValue()); + currentService = new DownloadService(sourceToDownload); bindProgressUIToService(currentService); currentService.start(); return true; @@ -101,7 +102,7 @@ public class DownloadSrcController extends AbstractSubController { /** * Bind UI properties to Service, and start the download Service - * @param DownloadService + * @param service */ private void bindProgressUIToService(DownloadService service){ logger.info("bindProgressUIToService()"); @@ -153,18 +154,16 @@ public class DownloadSrcController extends AbstractSubController { */ private class DownloadService extends Service{ - private final String url; - private final String fileName; - - public DownloadService(String url, String fileName){ - this.url = url; - this.fileName = fileName; + private final SourceToDownload sourceToDownload; + + public DownloadService(SourceToDownload sourceToDownload) { + this.sourceToDownload = sourceToDownload; } @Override protected Task createTask() { - logger.info("DownloadService.createTask({},{})", url, fileName); - return new DownloadTask(url, fileName, i18n); + logger.info("DownloadService.createTask({},{},{})", sourceToDownload.getUrl(), sourceToDownload.getFilePath(), sourceToDownload.getCheckSumExt()); + return new DownloadTask(sourceToDownload, i18n); } @Override diff --git a/src/main/java/ecorp/easy/installer/models/SourceToDownload.java b/src/main/java/ecorp/easy/installer/models/SourceToDownload.java new file mode 100644 index 00000000..3321092d --- /dev/null +++ b/src/main/java/ecorp/easy/installer/models/SourceToDownload.java @@ -0,0 +1,29 @@ +package ecorp.easy.installer.models; + +/** + * + * @author Ingo + */ +public class SourceToDownload { + private final String url; + private final String filePath; + private final String checkSumExt; + + public SourceToDownload(String url, String filePath, String checkSumExt) { + this.url = url; + this.filePath = filePath; + this.checkSumExt = checkSumExt; + } + + public String getUrl() { + return url; + } + + public String getFilePath() { + return filePath; + } + + public String getCheckSumExt() { + return checkSumExt; + } +} diff --git a/src/main/java/ecorp/easy/installer/tasks/DownloadTask.java b/src/main/java/ecorp/easy/installer/tasks/DownloadTask.java index 5c9b5c9e..f24e8e29 100644 --- a/src/main/java/ecorp/easy/installer/tasks/DownloadTask.java +++ b/src/main/java/ecorp/easy/installer/tasks/DownloadTask.java @@ -17,6 +17,7 @@ package ecorp.easy.installer.tasks; import ecorp.easy.installer.AppConstants; +import ecorp.easy.installer.models.SourceToDownload; import java.io.BufferedReader; import java.io.File; import java.io.FileInputStream; @@ -34,15 +35,14 @@ import java.nio.channels.ReadableByteChannel; import java.security.MessageDigest; import java.security.NoSuchAlgorithmException; import java.text.DecimalFormat; -import java.text.SimpleDateFormat; import java.time.Instant; -import java.time.LocalDate; import java.time.ZoneId; import java.time.format.DateTimeFormatter; import java.util.Date; import java.util.Locale; import java.util.ResourceBundle; import java.util.Scanner; + import javafx.concurrent.Task; import org.slf4j.Logger; import org.slf4j.LoggerFactory; @@ -53,7 +53,6 @@ import org.slf4j.LoggerFactory; * @author Ingo */ public class DownloadTask extends Task{ - private final static String checkSumExtension = ".sha256sum"; private final static Logger logger = LoggerFactory.getLogger(DownloadTask.class); /** * Constant size @@ -65,40 +64,37 @@ public class DownloadTask extends Task{ private static final String[] CST_UNITS = {"KB", "MB", "GB", "TB"}; final private ResourceBundle i18n; - final private String targetUrl; - final private String fileName; - + private final SourceToDownload sourceToDownload; + /** - * COnstruction of the download task - * @param targetUrl the web path to the resource - * @param fileName name of the file + * Construction of the download task + * @param sourceToDownload url to download, target filename, extension of the checksum file * @param resources used to send already translated message */ - public DownloadTask(String targetUrl, String fileName, ResourceBundle resources){ - this.targetUrl = targetUrl; - this.fileName = fileName; + public DownloadTask(SourceToDownload sourceToDownload, ResourceBundle resources){ this.i18n = resources; + this.sourceToDownload = sourceToDownload; } @Override protected Boolean call() throws Exception { //build local filePath - final String localFilePath = AppConstants.getSourcesFolderPath()+fileName; + final String localFilePath = AppConstants.getSourcesFolderPath() + sourceToDownload.getFilePath(); //Check if already exist and integrity - final String checksumFilePath = localFilePath+checkSumExtension; + final String checksumFilePath = localFilePath + sourceToDownload.getCheckSumExt(); if(isCancelled()) return false; - this.updateTitle("Downloading "+fileName+checkSumExtension); + this.updateTitle("Downloading " + sourceToDownload.getFilePath() + sourceToDownload.getCheckSumExt()); - File checksumLmdFile = new File(AppConstants.getSourcesFolderPath()+"lmd."+fileName+checkSumExtension); + File checksumLmdFile = new File(AppConstants.getSourcesFolderPath() + "lmd." + sourceToDownload.getFilePath() + sourceToDownload.getCheckSumExt()); checksumLmdFile.createNewFile(); // Download checksum. If file not downloaded return false and stop downloadin because integrity isn't guaranteed - if( !downloadFile(targetUrl+checkSumExtension, checksumFilePath,checksumLmdFile) ){ + if(!downloadFile(sourceToDownload.getUrl() + sourceToDownload.getCheckSumExt(), checksumFilePath, checksumLmdFile)) { updateMessage(i18n.getString("download_lbl_cantcheckIntegrity")); return false; } @@ -112,14 +108,14 @@ public class DownloadTask extends Task{ if(isCancelled()) return false; - this.updateTitle("Downloading "+fileName); + this.updateTitle("Downloading " + sourceToDownload.getFilePath()); - final String tmpFilePath = AppConstants.getSourcesFolderPath()+"tmp."+fileName; + final String tmpFilePath = AppConstants.getSourcesFolderPath()+"tmp." + sourceToDownload.getFilePath(); - File lmdFile = new File(AppConstants.getSourcesFolderPath()+"lmd."+fileName); //used to Store last modified Date of remote content + File lmdFile = new File(AppConstants.getSourcesFolderPath() + "lmd." + sourceToDownload.getFilePath()); //used to Store last modified Date of remote content lmdFile.createNewFile(); - if ( downloadFile(targetUrl, tmpFilePath, lmdFile) )//Download file + if (downloadFile(sourceToDownload.getUrl(), tmpFilePath, lmdFile))//Download file { logger.debug("Downloaded succeed. Rename temp file to right fileName"); File tmpFile = new File(tmpFilePath); @@ -181,7 +177,11 @@ public class DownloadTask extends Task{ HttpURLConnection connect = (HttpURLConnection) new URL(fileURL).openConnection(); connect.setReadTimeout(30000); connect.setConnectTimeout(30000); - + if (fileURL.contains("dl.twrp.me")) { + // direct download from official TWRP site just redirects to itself + connect.setRequestProperty("Referer", fileURL + ".html"); + } + File localFile = new File(localFilePath); if(localFile.exists()){ previouslyDownloadedAmount = localFile.length(); diff --git a/src/main/java/ecorp/easy/installer/threads/ThreadFactory.java b/src/main/java/ecorp/easy/installer/threads/ThreadFactory.java index 771e68e7..8834b00c 100644 --- a/src/main/java/ecorp/easy/installer/threads/ThreadFactory.java +++ b/src/main/java/ecorp/easy/installer/threads/ThreadFactory.java @@ -1,11 +1,11 @@ /* - * Copyright 2019-2020 - ECORP SAS + * Copyright 2019-2020 - ECORP SAS * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. - * + * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the @@ -15,28 +15,30 @@ * along with this program. If not, see . */ package ecorp.easy.installer.threads; -import ecorp.easy.installer.models.StepUi; + import ecorp.easy.installer.AppConstants; +import ecorp.easy.installer.models.StepUi; import ecorp.easy.installer.models.Command; import ecorp.easy.installer.models.Device; import ecorp.easy.installer.models.ProcessMould; +import ecorp.easy.installer.models.SourceToDownload; import ecorp.easy.installer.models.Step; import ecorp.easy.installer.utils.IFlashHandler; import java.io.IOException; import java.io.InputStream; import java.security.InvalidParameterException; +import java.util.ArrayList; import java.util.LinkedHashMap; //used instead of HashMap to conserve order import java.util.List; import java.util.Map; import java.util.Set; -import java.util.HashMap; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.yaml.snakeyaml.Yaml; /** * This is the class in charge of Thread's creation - * @TODO: in BuildFlashThread Method, let the Steps load from yaml to be a kind of static ressource used as mould. + * @TODO: in BuildFlashThread Method, let the Steps load from yaml to be a kind of static ressource used as mould. * And create parameters field in Command so the Parameters of Step object stay unchanged and aren't specific to each Thread. * We'll safe memory by doing that. * @author Vincent @@ -44,15 +46,15 @@ import org.yaml.snakeyaml.Yaml; public class ThreadFactory { private final static Logger logger = LoggerFactory.getLogger(ThreadFactory.class); private ProcessMould flashMould; - private final HashMap sourcesToDownload; + private final List sourcesToDownload; private Device device; private final String yamlFolderPath; - + public ThreadFactory(String yamlFolderPath){ this.yamlFolderPath = yamlFolderPath; - this.sourcesToDownload = new HashMap<>(); + this.sourcesToDownload = new ArrayList<>(); } - + /** * Prepare the Factory to build thread for another model * @param device Device object that encapsulate data about the device to flash @@ -61,12 +63,12 @@ public class ThreadFactory { */ public boolean changeMould(Device device){ if(device == null) return false; - + this.device = device; - + return loadYAMLFile(); } - + /** * Load the YAMLFile for the device's model to flash * @return false if there is an issue or if no flashMould is built @@ -77,33 +79,33 @@ public class ThreadFactory { if(modelName == null || modelName.isEmpty()){ return false; } - + try{ Yaml yaml = new Yaml (); - + //load config file InputStream is = getClass().getResourceAsStream(yamlFolderPath+modelName+".yml"); Map yamLContent= (Map)yaml.load(is); - + if(yamLContent == null) throw new NullPointerException("flash content load from yaml is empty"); flashMould = new ProcessMould(modelName); - + loadFlashProcess((Map) yamLContent.get("flash")); is.close(); - + //Load config file specific to Flash station //DO NOT USE classLoader() to load resource! is = getClass().getResourceAsStream(yamlFolderPath+modelName+"_fs.yml"); yamLContent= (Map)yaml.load(is); if(yamLContent == null) throw new NullPointerException("extra content load from yaml is empty"); - + loadFlashExtra((Map) yamLContent.get("flash")); - - loadSourcesToDownload((Map) yamLContent.get("sources")); - + + loadSourcesToDownload((Map) yamLContent.get("sources")); + is.close(); - + }catch(IOException | NullPointerException e){ logger.error("modelName = {}, error= {}", modelName, e.toString()); @@ -111,7 +113,7 @@ public class ThreadFactory { } return true; } - + /** * Load FlashProcess element from yaml file loaded * @param steps Map containing data from YAML @@ -121,15 +123,15 @@ public class ThreadFactory { if(steps == null || steps.isEmpty()){ throw new InvalidParameterException("Flash steps loaded from YAML are invalid"); } - + Set keys = steps.keySet(); - - String scriptExtension = AppConstants.OsName.toLowerCase().contains("windows") ? ".bat" : ".sh"; + + String scriptExtension = AppConstants.OsName.toLowerCase().contains("windows") ? ".bat" : ".sh"; for(String key: keys){ logger.debug("Key = "+key); Map stepData = (Map) steps.get(key); Step step = new Step(); - + step.setScript((String) stepData.get("script")+scriptExtension); Map codes = (Map) stepData.get("codes"); @@ -145,7 +147,7 @@ public class ThreadFactory { this.flashMould.addStep(key, step); } } - + /** * Load extra element for Flash process (it contains mainly UI's element) * @TODO: make entries's key a final static to be store only at one place @@ -170,7 +172,7 @@ public class ThreadFactory { String title = (String) uiProperties.get("title"); String titleIconName= (String)uiProperties.get("titleIcon"); String stepNumber = (String)uiProperties.get("stepNumber"); - Integer averageTime = (Integer) uiProperties.get("averageTime"); + Integer averageTime = (Integer) uiProperties.get("averageTime"); stepUI = new StepUi(type, instructions, title, titleIconName, stepNumber, averageTime != null ? averageTime:-1); } @@ -180,33 +182,39 @@ public class ThreadFactory { } } } - + /** * Load Preparation steps from yaml * @param sources Map containing steps of preparation */ protected void loadSourcesToDownload( Map sources){ logger.info("loadSourcesToDownload(...)"); - + if(sources == null || sources.isEmpty()){ throw new InvalidParameterException("Preparation steps loaded from YAML are invalid"); } - + for(String key : (Set) sources.keySet() ){ - Map source = (Map) sources.get(key); + Map source = (Map) sources.get(key); if(key.equals("rom")){ AppConstants.setEArchivePath((String) source.get("filePath")); } if(key.equals("twrp")){ AppConstants.setTwrpImgPath((String) source.get("filePath")); } - sourcesToDownload.put((String) source.get("url"), (String) source.get("filePath")); + sourcesToDownload.add( + new SourceToDownload( + (String) source.get("url"), + (String) source.get("filePath"), + source.containsKey("checkSumExt") ? "." + source.get("checkSumExt") : ".sha256sum" + ) + ); } } - - public HashMap getSourcesToDownload(){ + + public List getSourcesToDownload(){ return sourcesToDownload; } - + /** * Build a FlashThread * @param application The element that handle exchange with the thread @@ -214,18 +222,18 @@ public class ThreadFactory { * @return FlashThread */ public FlashThread buildFlashThread( IFlashHandler application, Object pauseLock){ - + if(flashMould == null || flashMould.getSteps() == null || device == null) return null; - + FlashThread result = new FlashThread(application, "f1", pauseLock, device); - - + + flashMould.getSteps().entrySet().forEach((entry) -> { result.addCommand(entry.getKey(), new Command(AppConstants.getScriptsFolderPath(), new Step( entry.getValue() ) ) ); }); return result; } - + /** * get the number of steps inside the current ProcessMould * @return 0 if processMould is null diff --git a/src/main/resources/yaml/FP2_fs.yml b/src/main/resources/yaml/FP2_fs.yml index d0e342ef..8d9d9b29 100644 --- a/src/main/resources/yaml/FP2_fs.yml +++ b/src/main/resources/yaml/FP2_fs.yml @@ -16,11 +16,12 @@ --- sources: rom: - url: https://images.ecloud.global/dev/FP2/e-0.11-p-2020082870302-dev-FP2.zip - filePath: e-0.11-p-2020082870302-dev-FP2.zip + url: https://images.ecloud.global/dev/FP2/e-0.12-p-2020102981459-dev-FP2.zip + filePath: e-0.12-p-2020102981459-dev-FP2.zip twrp: - url: https://images.ecloud.global/dev/FP2/recovery-e-0.11-q-2020090772203-dev-FP2.img - filePath: recovery-e-0.11-q-2020090772203-dev-FP2.img + url: https://dl.twrp.me/FP2/twrp-3.4.0-0-FP2.img + filePath: twrp-3.4.0-0-FP2.img + checkSumExt: sha256 flash: f1: ui: -- GitLab From 2cb1159f8cdf4df5e3629788800a4a5b458a7a7c Mon Sep 17 00:00:00 2001 From: Ingo-FP-Angel Date: Sun, 21 Feb 2021 12:21:14 +0100 Subject: [PATCH 11/24] Update version to flash to 0.i14-q --- src/main/resources/yaml/FP2_fs.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/main/resources/yaml/FP2_fs.yml b/src/main/resources/yaml/FP2_fs.yml index 8d9d9b29..94093233 100644 --- a/src/main/resources/yaml/FP2_fs.yml +++ b/src/main/resources/yaml/FP2_fs.yml @@ -16,8 +16,8 @@ --- sources: rom: - url: https://images.ecloud.global/dev/FP2/e-0.12-p-2020102981459-dev-FP2.zip - filePath: e-0.12-p-2020102981459-dev-FP2.zip + url: https://images.ecloud.global/dev/FP2/e-0.14-q-2021012598290-dev-FP2.zip + filePath: e-0.14-q-2021012598290-dev-FP2.zip twrp: url: https://dl.twrp.me/FP2/twrp-3.4.0-0-FP2.img filePath: twrp-3.4.0-0-FP2.img -- GitLab From 9a4dd41d85b29c3c96dfee3484276a33a977283d Mon Sep 17 00:00:00 2001 From: Ingo-FP-Angel Date: Thu, 13 May 2021 18:18:11 +0200 Subject: [PATCH 12/24] Fix title of the last screen for FP2 --- src/main/resources/yaml/FP2_fs.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/main/resources/yaml/FP2_fs.yml b/src/main/resources/yaml/FP2_fs.yml index 94093233..a2a12099 100644 --- a/src/main/resources/yaml/FP2_fs.yml +++ b/src/main/resources/yaml/FP2_fs.yml @@ -63,7 +63,7 @@ flash: f8: ui: type: action - title: stepTitle7On7 + title: stepTitle_rebootDevice instruction: - install_instr_swipeForUnlock - install_instr_tapReboot -- GitLab From e9c93c0c1b57de2ffdd2d0ffea9be61c1322aeb5 Mon Sep 17 00:00:00 2001 From: Ingo-FP-Angel Date: Thu, 13 May 2021 18:18:31 +0200 Subject: [PATCH 13/24] Add missing German translations --- src/main/resources/lang/translation_de.properties | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/src/main/resources/lang/translation_de.properties b/src/main/resources/lang/translation_de.properties index 8e06a86a..f373f6ff 100644 --- a/src/main/resources/lang/translation_de.properties +++ b/src/main/resources/lang/translation_de.properties @@ -28,6 +28,7 @@ install_instr_tapRebootSystem=Tippe auf „Reboot System“ (System neustarten) install_instr_resizeFs=Tippe auf „Resize File System“ (Dateisystemgröße ändern) install_instr_backX2=Tippe zweimal auf „Back“ (Zurück) install_instr_swipeForOk=Wische den blauen Pfeil-Schalter am unteren Bildschirmrand von links nach rechts +install_instr_swipeForUnlock=Wische den blauen Pfeil-Schalter am unteren Bildschirmrand von links nach rechts (wenn nötig) install_instr_tapExt3=Tippe auf „EXT3“ install_instr_tapChangeFs=Tippe auf „Change File System“ (Dateisystem ändern) install_instr_tapRepairChangeFs=Tippe auf „Repair or Change File System“ (Dateisystem reparieren oder ändern) @@ -40,6 +41,7 @@ install_instr_swipeTwrp=Falls du gefragt wirst, wische den blauen Pfeil-Schalter install_instr_doNotInstall=Tippe auf „Do not install“ (Nicht Installieren) install_instr_tapRebootRecovery=Tippe auf „Recovery“ (Wiederherstellen) install_instr_tapReboot=Tippe auf „Reboot“ (Neustart) +install_instr_tapSystemTippe auf „System“ install_instr_backX3=Tippe dreimal auf „Zurück“ install_instr_validate=Bestätige install_instr_writeYes=Schreibe „Yes“ (Ja) @@ -47,10 +49,12 @@ install_instr_tapFormatData=Tippe auf „Format Data“ (Daten formatieren) install_instr_tapWipe=Tippe auf „Wipe“ (Löschen) install_instr_keepReadOnly=Tippe auf „Keep Read Only“ (Nur Lesezugriff) install_instr_startRecovery=Drücke gleichzeitig „An“, „Home“ und „Lautstärke lauter“, bis das „Teamwin“-Symbol erscheint +install_instr_startRecovery2=Drücke gleichzeitig „An“ und „Lautstärke lauter“, bis das „Teamwin“-Symbol erscheint install_instr_leaveDownload=Drücke gleichzeitig „An“, „Home“ und „Lautstärke leiser“, bis sich das Gerät ausschaltet install_instr_recoveryInstall=Installation des Wiederherstellungs-Modus install_instr_acceptWarning=Akzeptiere die Warnung, indem du „Lautstärke lauter“ drückst install_instr_startFastboot=Drücke gleichzeitig „An“ und „Lautstärke leiser“, bis ein grünes „START“ erscheint, um in den Fastboot-Modus zu gelangen +install_instr_startFastboot2=Drücke gleichzeitig „An“ und „Lautstärke leiser“, bis das "Powered by Android" Boot-Logo erscheint install_instr_turnOffAgain=Telefon nochmals ausschalten install_instr_turnOff=Telefon ausschalten install_btn_sendLogSuccess=Protokoll gesendet @@ -160,7 +164,8 @@ stepTitle6On7=/e/-Installation stepTitle5On7=Starte das Gerät neu in den Wiederstellungs-Modus stepTitle4On7=Installation des Wiederherstellungs-Programms stepTitle3On7FP3=Entsperre den Bootloader und starte das Gerät neu in den Fastboot-Modus -### Flash +stepTitle11n7 = Verbinde das Gerät und starte es neu in den Fastboot-Modus +### Flash installationTitle=Installation feedback_btn_sendTryAgain=Fehler. Bitte sende die Rückmeldung nochmals. feedback_btn_leave=Verlassen -- GitLab From b173b0d1cb918850b95870a35a4d2a3f732d35e9 Mon Sep 17 00:00:00 2001 From: vincent Bourgmayer Date: Thu, 27 May 2021 10:57:06 +0200 Subject: [PATCH 14/24] update fp2 config file, update fp2's script. Add windows script for fp2 --- ...covery.sh => fp2_install-from-recovery.sh} | 6 +- ...t.sh => fp2_install-twrp-from-fastboot.sh} | 10 ++- .../windows/fp2_install-from-recovery.bat | 78 +++++++++++++++++++ .../fp2_install-twrp-from-fastboot.bat | 39 ++++++++++ src/main/resources/yaml/FP2.yml | 24 +++--- src/main/resources/yaml/FP2_fs.yml | 10 +-- 6 files changed, 144 insertions(+), 23 deletions(-) rename flash-scripts/linux/{fp3_install-from-recovery.sh => fp2_install-from-recovery.sh} (94%) rename flash-scripts/linux/{install-recovery-from-fastboot.sh => fp2_install-twrp-from-fastboot.sh} (85%) create mode 100644 flash-scripts/windows/fp2_install-from-recovery.bat create mode 100644 flash-scripts/windows/fp2_install-twrp-from-fastboot.bat diff --git a/flash-scripts/linux/fp3_install-from-recovery.sh b/flash-scripts/linux/fp2_install-from-recovery.sh similarity index 94% rename from flash-scripts/linux/fp3_install-from-recovery.sh rename to flash-scripts/linux/fp2_install-from-recovery.sh index c660d5c9..038bd8a5 100755 --- a/flash-scripts/linux/fp3_install-from-recovery.sh +++ b/flash-scripts/linux/fp2_install-from-recovery.sh @@ -1,7 +1,7 @@ #!/bin/bash -# Copyright (C) 2019 ECORP SAS - Author: Romain Hunault -# Copyright (C) 2020 ECORP SAS - Author: Vincent Bourgmayer +# Copyright (C) 2021 Author: Ingo +# Copyright (C) 2021 ECORP SAS - Author: Vincent Bourgmayer # # This program is free software: you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by @@ -88,4 +88,4 @@ sleep 1 echo "removed ZIP archive" -sleep 1 +sleep 1 \ No newline at end of file diff --git a/flash-scripts/linux/install-recovery-from-fastboot.sh b/flash-scripts/linux/fp2_install-twrp-from-fastboot.sh similarity index 85% rename from flash-scripts/linux/install-recovery-from-fastboot.sh rename to flash-scripts/linux/fp2_install-twrp-from-fastboot.sh index 15adb591..cf0a6dda 100755 --- a/flash-scripts/linux/install-recovery-from-fastboot.sh +++ b/flash-scripts/linux/fp2_install-twrp-from-fastboot.sh @@ -1,7 +1,7 @@ #!/bin/bash -# Copyright (C) 2019 ECORP SAS - Author: Romain Hunault -# Copyright (C) 2020 ECORP SAS - Author: Vincent Bourgmayer +# Copyright (C) 2021 Author: Ingo +# Copyright (C) 2021 ECORP SAS - Author: Vincent Bourgmayer # # This program is free software: you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by @@ -37,4 +37,8 @@ then exit 101 fi -"$FASTBOOT_PATH" flash recovery "$TWRP_IMAGE_PATH" +if ! "$FASTBOOT_PATH" flash recovery "$TWRP_IMAGE_PATH" +then + exit 2 +fi +echo "flashed recovery" \ No newline at end of file diff --git a/flash-scripts/windows/fp2_install-from-recovery.bat b/flash-scripts/windows/fp2_install-from-recovery.bat new file mode 100644 index 00000000..3b14459d --- /dev/null +++ b/flash-scripts/windows/fp2_install-from-recovery.bat @@ -0,0 +1,78 @@ +:: Copyright (C) 2021 ECORP SAS - Author: Vincent Bourgmayer +:: +:: This program is free software: you can redistribute it and/or modify +:: it under the terms of the GNU General Public License as published by +:: the Free Software Foundation, either version 3 of the License, or +:: (at your option) any later version. +:: +:: This program is distributed in the hope that it will be useful, +:: but WITHOUT ANY WARRANTY; without even the implied warranty of +:: MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +:: GNU General Public License for more details. +:: +:: You should have received a copy of the GNU General Public License +:: along with this program. If not, see . + +:: Parameter +:: $1: DEVICE_ID device identifier +:: $2: ARCHIVE_PATH path to the /e/ archive to flash +:: $3: ADB_FOLDER_PATH: the path where runnable adb is stored +:: Exit status +:: - 0 : /e/ installed +:: - 1 : Problems occurred (adb returns only 1 if an error occurs) +:: - 2 : Problems occurred during file transfer +:: - 3 : Problems occurred /e/ installation +:: - 101 : DEVICE_ID missing +:: - 102 : ARCHIVE_PATH missing + +set DEVICE_ID="%1" +set ARCHIVE_PATH="%~2" +set ADB_FOLDER_PATH=%~3 +set ADB_PATH="%ADB_FOLDER_PATH%adb" +:: get basename of archive +for %%a in ("%ARCHIVE_PATH%") do ( + set "ARCHIVE_NAME=%%~nxa" + echo %ARCHIVE_NAME% +) + +if not defined %DEVICE_ID ( + exit /b 101 +) + +if not defined %ARCHIVE_PATH ( + exit /b 102 +) + +%ADB_PATH% -s %DEVICE_ID% shell "twrp wipe system" +echo "system wiped" +ping 127.0.0.1 -n 10 -w 1000 >NUL + +%ADB_PATH% -s %DEVICE_ID% shell "twrp wipe cache" +echo "cache wiped" +ping 127.0.0.1 -n 10 -w 1000 >NUL + +%ADB_PATH% -s %DEVICE_ID% shell "twrp wipe data" +echo "data wiped" +ping 127.0.0.1 -n 10 -w 1000 >NUL + +echo "start installing ZIP archive" + +%ADB_PATH% -s %DEVICE_ID% shell "mkdir /cache/recovery" ; + +echo "created /cache/recovery" + +%ADB_PATH% -s %DEVICE_ID% push %ARCHIVE_PATH% /sdcard +if errorLevel 1 ( exit /b 2 ) +echo "pushed ZIP archive" + +%ADB_PATH% -s %DEVICE_ID% shell twrp install /sdcard/%ARCHIVE_NAME% +if errorLevel 1 ( exit /b 3 ) +echo "installed ZIP archive" +::Timeout 1 +ping 127.0.0.1 -n 2 -w 1000 >NUL + +%ADB_PATH% -s %DEVICE_ID% shell rm /sdcard/%ARCHIVE_NAME% +echo "removed ZIP archive" +ping 127.0.0.1 -n 2 -w 1000 >NUL + +exit /b 0 \ No newline at end of file diff --git a/flash-scripts/windows/fp2_install-twrp-from-fastboot.bat b/flash-scripts/windows/fp2_install-twrp-from-fastboot.bat new file mode 100644 index 00000000..02869649 --- /dev/null +++ b/flash-scripts/windows/fp2_install-twrp-from-fastboot.bat @@ -0,0 +1,39 @@ +:: Copyright (C) 2020 ECORP SAS - Author: Vincent Bourgmayer +:: +:: This program is free software: you can redistribute it and/or modify +:: it under the terms of the GNU General Public License as published by +:: the Free Software Foundation, either version 3 of the License, or +:: (at your option) any later version. +:: +:: This program is distributed in the hope that it will be useful, +:: but WITHOUT ANY WARRANTY; without even the implied warranty of +:: MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +:: GNU General Public License for more details. +:: +:: You should have received a copy of the GNU General Public License +:: along with this program. If not, see . + +:: Parameter +:: $1: TWRP_IMAGE_PATH need twrp path (${TWRP_FOLDER}/${TWRP}) +:: $2: The folder where heimdall runnable is stored +:: Exit status +:: - 0 : Recovery installed +:: - 1 : No problems occurred (heimdall returns only 1 if an error occurs) +:: - 101 : TWRP_IMAGE_PATH missing + +set TWRP_IMAGE_PATH=%1 +set FASTBOOT_FOLDER_PATH=%~2 +set FASTBOOT_PATH="%FASTBOOT_FOLDER_PATH%fastboot" + +echo "fastboot path: $FASTBOOT_PATH" + +if not defined %TWRP_IMAGE_PATH ( + echo "TWRP Image path is empty" + exit /b 101 +) + +%FASTBOOT_PATH% flash recovery %TWRP_IMAGE_PATH% +if errorLevel 1 ( exit /b 2 ) +echo "flashed recovery" + +exit /b 0 \ No newline at end of file diff --git a/src/main/resources/yaml/FP2.yml b/src/main/resources/yaml/FP2.yml index 96a74017..863165fd 100644 --- a/src/main/resources/yaml/FP2.yml +++ b/src/main/resources/yaml/FP2.yml @@ -26,10 +26,10 @@ flash: ko: 1: script_error_waitDownload_1 output: ~ - succeed: f4 + succeed: f2 failed: ~ - f4: - script: install-recovery-from-fastboot + f2: + script: fp2_install-twrp-from-fastboot parameters: twrp_image_path: ${TWRP_IMAGE_PATH} fastboot_folder_path: ${ADB_FOLDER_PATH} @@ -40,9 +40,9 @@ flash: 1: script_error_unknown 101: script_error_installRecovery_101 output: ~ - succeed: f5 + succeed: f3 failed: ~ - f5: + f3: script: wait-recovery parameters: device_id: ${DEVICE_ID} @@ -55,10 +55,10 @@ flash: 101: script_error_waitRecovery_101 102: script_error_waitRecovery_102 output: ~ - succeed: f6 + succeed: f4 failed: ~ - f6: - script: fp3_install-from-recovery + f4: + script: fp2_install-from-recovery parameters: device_id: ${DEVICE_ID} archive_path: ${ARCHIVE_PATH} @@ -73,16 +73,16 @@ flash: 101: script_error_installFromRecovery_101 102: script_error_installFromRecovery_102 output: ~ - succeed: f7 + succeed: f5 failed: ~ - f7: + f5: script: askAccount parameters: ~ codes: ~ output: ~ - succeed: f8 + succeed: f6 failed: ~ - f8: + f6: script: wait-reboot parameters: device_id: ${DEVICE_ID} diff --git a/src/main/resources/yaml/FP2_fs.yml b/src/main/resources/yaml/FP2_fs.yml index a2a12099..877e2ddb 100644 --- a/src/main/resources/yaml/FP2_fs.yml +++ b/src/main/resources/yaml/FP2_fs.yml @@ -32,7 +32,7 @@ flash: - install_instr_startFastboot2 stepNumber: 1/5 titleIcon: icon-download.png - f4: + f2: ui: type: load title: stepTitle4On7 @@ -40,7 +40,7 @@ flash: - install_instr_recoveryInstall stepNumber: 2/5 averageTime: 6 - f5: + f3: ui: type: action title: stepTitle5On7 @@ -49,7 +49,7 @@ flash: - install_instr_swipeTwrp stepNumber: 3/5 titleIcon: icon-download.png - f6: + f4: ui: type: load title: stepTitle6On7 @@ -57,10 +57,10 @@ flash: - install_instr_eosInstall stepNumber: 4/5 averageTime: 475 - f7: + f5: ui: type: askAccount - f8: + f6: ui: type: action title: stepTitle_rebootDevice -- GitLab From f1208dd3c52ec5f0802575db42f4163128b35949 Mon Sep 17 00:00:00 2001 From: Ingo-FP-Angel Date: Sat, 29 May 2021 16:37:38 +0200 Subject: [PATCH 15/24] Make some instruction strings FP2 specific --- .../resources/instructions/imageName_en_EN_0010.properties | 4 ++-- src/main/resources/lang/translation.properties | 4 ++-- src/main/resources/lang/translation_de.properties | 4 ++-- src/main/resources/yaml/FP2_fs.yml | 4 ++-- 4 files changed, 8 insertions(+), 8 deletions(-) diff --git a/src/main/resources/instructions/imageName_en_EN_0010.properties b/src/main/resources/instructions/imageName_en_EN_0010.properties index 56247dff..53f6eb22 100644 --- a/src/main/resources/instructions/imageName_en_EN_0010.properties +++ b/src/main/resources/instructions/imageName_en_EN_0010.properties @@ -13,6 +13,6 @@ # You should have received a copy of the GNU General Public License # along with this program. If not, see . -install_instr_startFastboot2=FP2_fastboot_mode_400px.png -install_instr_startRecovery2=FP2_recovery_mode_400px.png +install_instr_startFastbootFP2=FP2_fastboot_mode_400px.png +install_instr_startRecoveryFP2=FP2_recovery_mode_400px.png install_instr_doNotInstall=TWRP_doNotInstall.png \ No newline at end of file diff --git a/src/main/resources/lang/translation.properties b/src/main/resources/lang/translation.properties index 1c2c4a55..4b544dea 100644 --- a/src/main/resources/lang/translation.properties +++ b/src/main/resources/lang/translation.properties @@ -121,14 +121,14 @@ install_instr_turnOffAgain=Turn off the phone again install_instr_startDownload=Keep pressing simultaneously "Power" & "Home" & "Volume Down" until a blue screen appear to access Download Mode install_instr_startFastboot=Keep pressing simultaneously "Power" & "Volume Down" until a screen with green "START" appears to access Fastboot Mode install_instr_startFastbootFromOptions=From options menu use "Volume Up/Down" to select "Fastboot" and "Power" to confirm -install_instr_startFastboot2=Keep pressing simultaneously "Power" & "Volume Down" until a screen with the "Powered by Android" boot logo appears +install_instr_startFastbootFP2=Keep pressing simultaneously "Power" & "Volume Down" until a screen with the "Powered by Android" boot logo appears install_instr_acceptWarning=Accept warning by pressing on "Volume Up" install_instr_verifyHeimdall=Verify Heimdall install_instr_oemUnlock=OEM Unlocking install_instr_recoveryInstall=Recovery installation install_instr_leaveDownload=Keep pressing simultaneously "Power" & "Home" & "Volume Down" until device turns off install_instr_startRecovery=Keep pressing simultaneously "Power" & "Home" & "Volume Up" until 'teamwin' screen appears -install_instr_startRecovery2=Keep pressing simultaneously "Power" & "Volume Up" until 'teamwin' screen appears +install_instr_startRecoveryFP2=Keep pressing simultaneously "Power" & "Volume Up" until 'teamwin' screen appears install_instr_keepReadOnly=Tap on 'Keep Read Only' install_instr_tapWipe=Tap on 'Wipe' install_instr_tapFormatData=Tap on 'Format Data' diff --git a/src/main/resources/lang/translation_de.properties b/src/main/resources/lang/translation_de.properties index f373f6ff..388decb1 100644 --- a/src/main/resources/lang/translation_de.properties +++ b/src/main/resources/lang/translation_de.properties @@ -49,12 +49,12 @@ install_instr_tapFormatData=Tippe auf „Format Data“ (Daten formatieren) install_instr_tapWipe=Tippe auf „Wipe“ (Löschen) install_instr_keepReadOnly=Tippe auf „Keep Read Only“ (Nur Lesezugriff) install_instr_startRecovery=Drücke gleichzeitig „An“, „Home“ und „Lautstärke lauter“, bis das „Teamwin“-Symbol erscheint -install_instr_startRecovery2=Drücke gleichzeitig „An“ und „Lautstärke lauter“, bis das „Teamwin“-Symbol erscheint +install_instr_startRecoveryFP2=Drücke gleichzeitig „An“ und „Lautstärke lauter“, bis das „Teamwin“-Symbol erscheint install_instr_leaveDownload=Drücke gleichzeitig „An“, „Home“ und „Lautstärke leiser“, bis sich das Gerät ausschaltet install_instr_recoveryInstall=Installation des Wiederherstellungs-Modus install_instr_acceptWarning=Akzeptiere die Warnung, indem du „Lautstärke lauter“ drückst install_instr_startFastboot=Drücke gleichzeitig „An“ und „Lautstärke leiser“, bis ein grünes „START“ erscheint, um in den Fastboot-Modus zu gelangen -install_instr_startFastboot2=Drücke gleichzeitig „An“ und „Lautstärke leiser“, bis das "Powered by Android" Boot-Logo erscheint +install_instr_startFastbootFP2=Drücke gleichzeitig „An“ und „Lautstärke leiser“, bis das "Powered by Android" Boot-Logo erscheint install_instr_turnOffAgain=Telefon nochmals ausschalten install_instr_turnOff=Telefon ausschalten install_btn_sendLogSuccess=Protokoll gesendet diff --git a/src/main/resources/yaml/FP2_fs.yml b/src/main/resources/yaml/FP2_fs.yml index 877e2ddb..89ef2349 100644 --- a/src/main/resources/yaml/FP2_fs.yml +++ b/src/main/resources/yaml/FP2_fs.yml @@ -29,7 +29,7 @@ flash: title: stepTitle11n7 instruction: - install_instr_turnOff - - install_instr_startFastboot2 + - install_instr_startFastbootFP2 stepNumber: 1/5 titleIcon: icon-download.png f2: @@ -45,7 +45,7 @@ flash: type: action title: stepTitle5On7 instruction: - - install_instr_startRecovery2 + - install_instr_startRecoveryFP2 - install_instr_swipeTwrp stepNumber: 3/5 titleIcon: icon-download.png -- GitLab From 2180cd1ce3b9cd655aff050e39702f65932ba8ab Mon Sep 17 00:00:00 2001 From: Ingo-FP-Angel Date: Sat, 29 May 2021 16:49:24 +0200 Subject: [PATCH 16/24] Correct buttons on right side of FP2 --- .../images/FP2_fastboot_mode_400px.png | Bin 11331 -> 12961 bytes .../images/FP2_recovery_mode_400px.png | Bin 12025 -> 12883 bytes 2 files changed, 0 insertions(+), 0 deletions(-) diff --git a/src/main/resources/images/FP2_fastboot_mode_400px.png b/src/main/resources/images/FP2_fastboot_mode_400px.png index 5d681b8f8f13e687126766f1e1ab99b3de13b896..a01ff563a1d5d848e76bb8fc8f47916cfb10168a 100644 GIT binary patch literal 12961 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 Wq`3A+M}+E literal 11331 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 literal 12025 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 -- GitLab From b8c2684ba5b8b34e24552ba047275d44fe2eed0c Mon Sep 17 00:00:00 2001 From: Ingo-FP-Angel Date: Sat, 29 May 2021 17:03:32 +0200 Subject: [PATCH 17/24] Add checks that asb/fastboot path is not empty --- flash-scripts/linux/fp2_install-from-recovery.sh | 8 +++++++- flash-scripts/linux/fp2_install-twrp-from-fastboot.sh | 7 +++++++ src/main/resources/lang/translation.properties | 3 ++- src/main/resources/lang/translation_de.properties | 1 + src/main/resources/yaml/FP2.yml | 2 ++ 5 files changed, 19 insertions(+), 2 deletions(-) diff --git a/flash-scripts/linux/fp2_install-from-recovery.sh b/flash-scripts/linux/fp2_install-from-recovery.sh index 038bd8a5..32b9f95c 100755 --- a/flash-scripts/linux/fp2_install-from-recovery.sh +++ b/flash-scripts/linux/fp2_install-from-recovery.sh @@ -28,6 +28,7 @@ # - 3 : Problems occurred /e/ installation # - 101 : DEVICE_ID missing # - 102 : ARCHIVE_PATH missing +# - 103 : ADB_FOLDER_PATH missing DEVICE_ID=$1 ARCHIVE_PATH=$2 @@ -35,8 +36,8 @@ ARCHIVE_NAME=$(basename "$2") ADB_FOLDER_PATH=$3 ADB_PATH=${ADB_FOLDER_PATH}"adb" - echo "adb path : $ADB_PATH" + if [ -z "$DEVICE_ID" ] then exit 101 @@ -47,6 +48,11 @@ then exit 102 fi +if [ -z "$ADB_FOLDER_PATH" ] +then + exit 103 +fi + sleep 10 "$ADB_PATH" -s "$DEVICE_ID" shell "twrp wipe system" ; diff --git a/flash-scripts/linux/fp2_install-twrp-from-fastboot.sh b/flash-scripts/linux/fp2_install-twrp-from-fastboot.sh index cf0a6dda..e9f085a0 100755 --- a/flash-scripts/linux/fp2_install-twrp-from-fastboot.sh +++ b/flash-scripts/linux/fp2_install-twrp-from-fastboot.sh @@ -24,6 +24,7 @@ # - 0 : Recovery installed # - 1 : No problems occurred # - 101 : TWRP_IMAGE_PATH missing +# - 102 : FASTBOOT_FOLDER_PATH missing TWRP_IMAGE_PATH=$1 FASTBOOT_FOLDER_PATH=$2 @@ -37,6 +38,12 @@ then exit 101 fi +if [ -z "$FASTBOOT_FOLDER_PATH" ] +then + exit 102 +fi + + if ! "$FASTBOOT_PATH" flash recovery "$TWRP_IMAGE_PATH" then exit 2 diff --git a/src/main/resources/lang/translation.properties b/src/main/resources/lang/translation.properties index 4b544dea..ff855a67 100644 --- a/src/main/resources/lang/translation.properties +++ b/src/main/resources/lang/translation.properties @@ -196,7 +196,8 @@ script_error_waitReboot_10 = No device's serial number provided script_error_waitReboot_101 = Can't run instruction on the device script_error_waitRebootFromFastboot_101 = Can't run instruction on the device script_error_serialNumber_missing=No device's serial number provided -script_error_fastboot_path_missing= No fastboot tool path provided +script_error_adb_path_missing=No adb tool path provided +script_error_fastboot_path_missing=No fastboot tool path provided script_error_fastboot_flashingUnlock_failed=Could not unlock flashing script_error_unknown= The installation encounter an error java_error_unknow= The installation encounter an internal error diff --git a/src/main/resources/lang/translation_de.properties b/src/main/resources/lang/translation_de.properties index 388decb1..256ba027 100644 --- a/src/main/resources/lang/translation_de.properties +++ b/src/main/resources/lang/translation_de.properties @@ -218,6 +218,7 @@ eAccount_lbl_dontuseEmail=Keine „@e.email“-Adresse benutzen eAccount_lbl_alreadyAccount=Tippe auf „Weiter“ script_error_fastboot_flashingUnlock_failed=Die „OEM-Entsperrung“ ist fehlgeschlagen script_error_fastboot_path_missing=Der Pfad zu „fastboot“ wurde nicht angegeben +script_error_adb_path_missing=Der Pfad zu „adb“ wurde nicht angegeben stepTitle_verifyHeimdall=Überprüfung von Heimdall stepTitle_installRecovery=Installation des Wiederherstellungs-Programms stepTitle_oemUnlock=OEM-Entsperrung diff --git a/src/main/resources/yaml/FP2.yml b/src/main/resources/yaml/FP2.yml index 863165fd..d1b7c36e 100644 --- a/src/main/resources/yaml/FP2.yml +++ b/src/main/resources/yaml/FP2.yml @@ -39,6 +39,7 @@ flash: ko: 1: script_error_unknown 101: script_error_installRecovery_101 + 102: script_error_fastboot_path_missing output: ~ succeed: f3 failed: ~ @@ -72,6 +73,7 @@ flash: 3: script_error_installFromRecovery_3 101: script_error_installFromRecovery_101 102: script_error_installFromRecovery_102 + 103: script_error_adb_path_missing output: ~ succeed: f5 failed: ~ -- GitLab From 5fed8425d430760013e1070937756c13f154a285 Mon Sep 17 00:00:00 2001 From: Ingo-FP-Angel Date: Sat, 29 May 2021 17:05:30 +0200 Subject: [PATCH 18/24] Update version to be installed --- src/main/resources/yaml/FP2_fs.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/main/resources/yaml/FP2_fs.yml b/src/main/resources/yaml/FP2_fs.yml index 89ef2349..93cb9647 100644 --- a/src/main/resources/yaml/FP2_fs.yml +++ b/src/main/resources/yaml/FP2_fs.yml @@ -16,8 +16,8 @@ --- sources: rom: - url: https://images.ecloud.global/dev/FP2/e-0.14-q-2021012598290-dev-FP2.zip - filePath: e-0.14-q-2021012598290-dev-FP2.zip + url: https://images.ecloud.global/dev/FP2/e-0.16-q-20210424112062-dev-FP2.zip + filePath: e-0.16-q-20210424112062-dev-FP2.zip twrp: url: https://dl.twrp.me/FP2/twrp-3.4.0-0-FP2.img filePath: twrp-3.4.0-0-FP2.img -- GitLab From 4be7f7ea5783241fc8d1a72477b25925af812d85 Mon Sep 17 00:00:00 2001 From: Ingo-FP-Angel Date: Sat, 31 Jul 2021 16:25:30 +0200 Subject: [PATCH 19/24] Take TWRP from ecloud.gobal now --- src/main/resources/yaml/FP2_fs.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/main/resources/yaml/FP2_fs.yml b/src/main/resources/yaml/FP2_fs.yml index 93cb9647..44184353 100644 --- a/src/main/resources/yaml/FP2_fs.yml +++ b/src/main/resources/yaml/FP2_fs.yml @@ -19,8 +19,8 @@ sources: url: https://images.ecloud.global/dev/FP2/e-0.16-q-20210424112062-dev-FP2.zip filePath: e-0.16-q-20210424112062-dev-FP2.zip twrp: - url: https://dl.twrp.me/FP2/twrp-3.4.0-0-FP2.img - filePath: twrp-3.4.0-0-FP2.img + url: https://images.ecloud.global/stable/twrp/FP2/twrp-3.5.2_9-0-FP2.img + filePath: twrp-3.5.2_9-0-FP2.img checkSumExt: sha256 flash: f1: -- GitLab From 5dad409d90e2032b1f5aee5d7fc7e802cf410613 Mon Sep 17 00:00:00 2001 From: Vincent Bourgmayer Date: Sat, 31 Jul 2021 14:27:18 +0000 Subject: [PATCH 20/24] Add note that it might take a while --- src/main/resources/lang/translation.properties | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/main/resources/lang/translation.properties b/src/main/resources/lang/translation.properties index 60ae2d2c..d8fabcf8 100644 --- a/src/main/resources/lang/translation.properties +++ b/src/main/resources/lang/translation.properties @@ -140,7 +140,7 @@ install_instr_oemUnlock=OEM Unlocking install_instr_recoveryInstall=Recovery installation install_instr_leaveDownload=Keep pressing simultaneously "Power" & "Home" & "Volume Down" until device turns off install_instr_startRecovery=Keep pressing simultaneously "Power" & "Home" & "Volume Up" until 'teamwin' screen appears -install_instr_startRecoveryFP2=Keep pressing simultaneously "Power" & "Volume Up" until 'teamwin' screen appears +install_instr_startRecoveryFP2=Keep pressing simultaneously "Power" & "Volume Up" until 'teamwin' screen appears. It can take more 20 seconds. install_instr_keepReadOnly=Tap on 'Keep Read Only' install_instr_tapWipe=Tap on 'Wipe' install_instr_tapFormatData=Tap on 'Format Data' -- GitLab From 3db0585915d3e2bb2e8dcd45b51494ca28c6ef05 Mon Sep 17 00:00:00 2001 From: Ingo-FP-Angel Date: Sat, 31 Jul 2021 16:28:20 +0200 Subject: [PATCH 21/24] Switch to stable version --- src/main/resources/yaml/FP2_fs.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/main/resources/yaml/FP2_fs.yml b/src/main/resources/yaml/FP2_fs.yml index 44184353..7715455a 100644 --- a/src/main/resources/yaml/FP2_fs.yml +++ b/src/main/resources/yaml/FP2_fs.yml @@ -16,8 +16,8 @@ --- sources: rom: - url: https://images.ecloud.global/dev/FP2/e-0.16-q-20210424112062-dev-FP2.zip - filePath: e-0.16-q-20210424112062-dev-FP2.zip + url: https://images.ecloud.global/stable/FP2/e-latest-FP2.zip + filePath: e-latest-FP2.zip twrp: url: https://images.ecloud.global/stable/twrp/FP2/twrp-3.5.2_9-0-FP2.img filePath: twrp-3.5.2_9-0-FP2.img -- GitLab From a585ffcde8d6a9f903d7ba75297251cd94093d66 Mon Sep 17 00:00:00 2001 From: Ingo-FP-Angel Date: Sat, 31 Jul 2021 16:30:24 +0200 Subject: [PATCH 22/24] Switch to /e/ recovery --- src/main/resources/yaml/FP2_fs.yml | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/src/main/resources/yaml/FP2_fs.yml b/src/main/resources/yaml/FP2_fs.yml index 7715455a..429a712a 100644 --- a/src/main/resources/yaml/FP2_fs.yml +++ b/src/main/resources/yaml/FP2_fs.yml @@ -19,9 +19,8 @@ sources: url: https://images.ecloud.global/stable/FP2/e-latest-FP2.zip filePath: e-latest-FP2.zip twrp: - url: https://images.ecloud.global/stable/twrp/FP2/twrp-3.5.2_9-0-FP2.img - filePath: twrp-3.5.2_9-0-FP2.img - checkSumExt: sha256 + url: https://images.ecloud.global/stable/FP2/recovery-e-latest-FP2.img + filePath: recovery-e-latest-FP2.img flash: f1: ui: -- GitLab From 44787b28923e51193ff29c9b571287860f790a58 Mon Sep 17 00:00:00 2001 From: Ingo-FP-Angel Date: Sat, 31 Jul 2021 16:47:52 +0200 Subject: [PATCH 23/24] Revert "Switch to /e/ recovery" This reverts commit a585ffcde8d6a9f903d7ba75297251cd94093d66. --- src/main/resources/yaml/FP2_fs.yml | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/src/main/resources/yaml/FP2_fs.yml b/src/main/resources/yaml/FP2_fs.yml index 429a712a..7715455a 100644 --- a/src/main/resources/yaml/FP2_fs.yml +++ b/src/main/resources/yaml/FP2_fs.yml @@ -19,8 +19,9 @@ sources: url: https://images.ecloud.global/stable/FP2/e-latest-FP2.zip filePath: e-latest-FP2.zip twrp: - url: https://images.ecloud.global/stable/FP2/recovery-e-latest-FP2.img - filePath: recovery-e-latest-FP2.img + url: https://images.ecloud.global/stable/twrp/FP2/twrp-3.5.2_9-0-FP2.img + filePath: twrp-3.5.2_9-0-FP2.img + checkSumExt: sha256 flash: f1: ui: -- GitLab From b6ca2488fd5007e4ed6694c52bc4c0cecf8ec125 Mon Sep 17 00:00:00 2001 From: Ingo-FP-Angel Date: Sat, 31 Jul 2021 17:08:14 +0200 Subject: [PATCH 24/24] Don't need to override suffix anymore --- src/main/resources/yaml/FP2_fs.yml | 1 - 1 file changed, 1 deletion(-) diff --git a/src/main/resources/yaml/FP2_fs.yml b/src/main/resources/yaml/FP2_fs.yml index 7715455a..9ca737cb 100644 --- a/src/main/resources/yaml/FP2_fs.yml +++ b/src/main/resources/yaml/FP2_fs.yml @@ -21,7 +21,6 @@ sources: twrp: url: https://images.ecloud.global/stable/twrp/FP2/twrp-3.5.2_9-0-FP2.img filePath: twrp-3.5.2_9-0-FP2.img - checkSumExt: sha256 flash: f1: ui: -- GitLab