Add an option to one click flash current booted TWRP ramdisk

Change-Id: I12303696698a5feaa43401bcac9e30d5b3b99a0c
diff --git a/data.cpp b/data.cpp
index 3d81bf6..f7cd7a2 100755
--- a/data.cpp
+++ b/data.cpp
@@ -763,6 +763,8 @@
 	mPersist.SetValue(TW_TIME_ZONE_GUISEL, "CST6;CDT,M3.2.0,M11.1.0");
 	mPersist.SetValue(TW_TIME_ZONE_GUIOFFSET, "0");
 	mPersist.SetValue(TW_TIME_ZONE_GUIDST, "1");
+        mPersist.SetValue(TW_AUTO_REFLASHTWRP_VAR, "0");
+
 	mData.SetValue(TW_ACTION_BUSY, "0");
 	mData.SetValue("tw_wipe_cache", "0");
 	mData.SetValue("tw_wipe_dalvik", "0");
@@ -1169,4 +1171,4 @@
 	string mainPath = GetCurrentStoragePath();
 	SetValue(TW_RECOVERY_FOLDER_VAR, TWFunc::Check_For_TwrpFolder());
 	mBackingFile = mainPath + GetStrValue(TW_RECOVERY_FOLDER_VAR) + '/' + TW_SETTINGS_FILE;
-}
\ No newline at end of file
+}
diff --git a/gui/action.cpp b/gui/action.cpp
index a623ccd..c63337c 100755
--- a/gui/action.cpp
+++ b/gui/action.cpp
@@ -239,6 +239,7 @@
 		ADD_ACTION(installapp);
 		ADD_ACTION(uninstalltwrpsystemapp);
 		ADD_ACTION(repackimage);
+		ADD_ACTION(reflashtwrp);
 		ADD_ACTION(fixabrecoverybootloop);
 		ADD_ACTION(applycustomtwrpfolder);
 #ifndef TW_EXCLUDE_NANO
@@ -2159,6 +2160,23 @@
 	return 0;
 }
 
+int GUIAction::reflashtwrp(std::string arg __unused)
+{
+	int op_status = 1;
+	twrpRepacker repacker;
+
+	operation_start("Repack Image");
+	if (!simulate)
+	{
+		if (!repacker.Flash_Current_Twrp())
+		goto exit;
+	} else
+		simulate_progress_bar();
+	op_status = 0;
+exit:
+	operation_end(op_status);
+	return 0;
+}
 int GUIAction::fixabrecoverybootloop(std::string arg __unused)
 {
 	int op_status = 1;
diff --git a/gui/objects.hpp b/gui/objects.hpp
index ec550bb..098c480 100755
--- a/gui/objects.hpp
+++ b/gui/objects.hpp
@@ -372,6 +372,7 @@
 	int installapp(std::string arg);
 	int uninstalltwrpsystemapp(std::string arg);
 	int repackimage(std::string arg);
+	int reflashtwrp(std::string arg);
 	int fixabrecoverybootloop(std::string arg);
 	int enableadb(std::string arg);
 	int enablefastboot(std::string arg);
diff --git a/gui/theme/common/landscape.xml b/gui/theme/common/landscape.xml
index bf8912a..369c4d8 100755
--- a/gui/theme/common/landscape.xml
+++ b/gui/theme/common/landscape.xml
@@ -460,6 +460,13 @@
 				<listitem name="{@skip_digest_zip_chk=Skip Digest check before installing zip}">
 					<data variable="tw_skip_digest_check_zip"/>
 				</listitem>
+				<listitem name="{@auto_reflashtwrp_chk=Automatically Reflash TWRP after flashing a ROM}">
+					<conditions>
+						<condition var1="tw_has_boot_slots" var2="1"/>
+						<condition var1="tw_has_repack_tools" var2="1"/>
+					</conditions>
+					<data variable="tw_auto_reflashtwrp"/>
+				</listitem>
 				<listitem name="{@install_reboot_chk=Reboot after installation is complete}">
 					<data variable="tw_install_reboot"/>
 				</listitem>
@@ -3234,6 +3241,13 @@
 				<listitem name="{@unmount_sys_install=Unmount System before installing a ZIP}">
 					<data variable="tw_unmount_system"/>
 				</listitem>
+				<listitem name="{@auto_reflashtwrp_chk=Automatically Reflash TWRP after flashing a ROM}">
+					<conditions>
+						<condition var1="tw_has_boot_slots" var2="1"/>
+						<condition var1="tw_has_repack_tools" var2="1"/>
+					</conditions>
+					<data variable="tw_auto_reflashtwrp"/>
+				</listitem>
 			</listbox>
 
 			<checkbox>
@@ -3719,6 +3733,22 @@
 						<action function="page">repackselect</action>
 					</actions>
 				</listitem>
+				<listitem name="{@reflash_twrp=Flash Current TWRP}">
+					<conditions>
+						<condition var1="tw_has_boot_slots" var2="1"/>
+						<condition var1="tw_has_repack_tools" var2="1"/>
+					</conditions>
+					<actions>
+						<action function="set">tw_repack_kernel=0</action>
+						<action function="set">tw_back=advanced</action>
+						<action function="set">tw_action=reflashtwrp</action>
+						<action function="set">tw_text1={@reflash_twrp_confirm=Flash Current TWRP?}</action>
+						<action function="set">tw_action_text1={@reflashing_twrp=Flashing TWRP...}</action>
+						<action function="set">tw_complete_text1={@reflash_twrp_complete=Done flashing TWRP}</action>
+						<action function="set">tw_slider_text={@swipe_to_confirm=Swipe to Confirm}</action>
+						<action function="page">confirm_action</action>
+					</actions>
+				</listitem>
 				<listitem name="{@install_kernel=Install Kernel}">
 					<conditions>
 						<condition var1="tw_has_boot_slots" var2="1"/>
diff --git a/gui/theme/common/languages/en.xml b/gui/theme/common/languages/en.xml
index 1dca4f6..2ff27b2 100755
--- a/gui/theme/common/languages/en.xml
+++ b/gui/theme/common/languages/en.xml
@@ -317,6 +317,7 @@
 		<string name="settings_gen_s_hdr">General</string>
 		<string name="settings_gen_btn">General</string>
 		<string name="use_rmrf_chk">Use rm -rf instead of formatting</string>
+		<string name="auto_reflashtwrp_chk">Automatically Reflash TWRP after flashing a ROM</string>
 		<string name="use24clock_chk">Use 24-hour clock</string>
 		<string name="rev_navbar_chk">Reversed navbar layout</string>
 		<string name="simact_chk">Simulate actions for theme testing</string>
@@ -506,9 +507,15 @@
 		<string name="install_complete">Install Complete</string>
 		<string name="unpack_error">Error unpacking image.</string>
 		<string name="repack_error">Error repacking image.</string>
+		<string name="modified_ramdisk_error">ramdisk files have been modified, unable to create ramdisk to flash, fastboot boot twrp and try this option again or use the Install Recovery Ramdisk option.</string>
+		<string name="create_ramdisk_error">failed to create ramdisk to flash.</string>
 		<string name="unpacking_image">Unpacking {1}...</string>
 		<string name="repacking_image">Repacking {1}...</string>
 		<string name="repack_image_hdr">Select Image</string>
+		<string name="reflash_twrp">Flash current TWRP</string>
+		<string name="reflash_twrp_confirm">Flash current TWRP?</string>
+		<string name="reflashing_twrp">Flashing TWRP...</string>
+		<string name="reflash_twrp_complete">Done flashing TWRP</string>
 		<string name="fix_recovery_loop">Fix Recovery Bootloop</string>
 		<string name="fix_recovery_loop_confirm">Fix Recovery Bootloop?</string>
 		<string name="fixing_recovery_loop">Fixing Recovery Bootloop...</string>
diff --git a/gui/theme/common/portrait.xml b/gui/theme/common/portrait.xml
index 9e0fec8..3d6bce7 100755
--- a/gui/theme/common/portrait.xml
+++ b/gui/theme/common/portrait.xml
@@ -412,6 +412,13 @@
 				<listitem name="{@skip_digest_zip_chk=Skip Digest check before installing zip}">
 					<data variable="tw_skip_digest_check_zip"/>
 				</listitem>
+				<listitem name="{@auto_reflashtwrp_chk=Automatically Reflash TWRP after flashing a ROM}">
+					<conditions>
+						<condition var1="tw_has_boot_slots" var2="1"/>
+						<condition var1="tw_has_repack_tools" var2="1"/>
+					</conditions>
+					<data variable="tw_auto_reflashtwrp"/>
+				</listitem>
 				<listitem name="{@install_reboot_chk=Reboot after installation is complete}">
 					<data variable="tw_install_reboot"/>
 				</listitem>
@@ -3408,6 +3415,13 @@
 				<listitem name="{@unmount_sys_install=Unmount System before installing a ZIP}">
 					<data variable="tw_unmount_system"/>
 				</listitem>
+				<listitem name="{@auto_reflashtwrp_chk=Automatically Reflash TWRP after flashing a ROM}">
+					<conditions>
+						<condition var1="tw_has_boot_slots" var2="1"/>
+						<condition var1="tw_has_repack_tools" var2="1"/>
+					</conditions>
+					<data variable="tw_auto_reflashtwrp"/>
+				</listitem>
 			</listbox>
 
 			<button style="main_button_half_height">
@@ -3841,6 +3855,22 @@
 						<action function="page">repackselect</action>
 					</actions>
 				</listitem>
+				<listitem name="{@reflash_twrp=Flash Current TWRP}">
+					<conditions>
+						<condition var1="tw_has_boot_slots" var2="1"/>
+						<condition var1="tw_has_repack_tools" var2="1"/>
+					</conditions>
+					<actions>
+						<action function="set">tw_repack_kernel=0</action>
+						<action function="set">tw_back=advanced</action>
+						<action function="set">tw_action=reflashtwrp</action>
+						<action function="set">tw_text1={@reflash_twrp_confirm=Flash Current TWRP?}</action>
+						<action function="set">tw_action_text1={@reflashing_twrp=Flashing TWRP...}</action>
+						<action function="set">tw_complete_text1={@reflash_twrp_complete=Done Flashing TWRP}</action>
+						<action function="set">tw_slider_text={@swipe_to_confirm=Swipe to Confirm}</action>
+						<action function="page">confirm_action</action>
+						</actions>
+				</listitem>
 				<listitem name="{@install_kernel=Install Kernel}">
 					<conditions>
 						<condition var1="tw_has_boot_slots" var2="1"/>
diff --git a/gui/theme/common/watch.xml b/gui/theme/common/watch.xml
index 1b70547..060d50a 100755
--- a/gui/theme/common/watch.xml
+++ b/gui/theme/common/watch.xml
@@ -568,6 +568,13 @@
 				<listitem name="{@skip_digest_zip_chk=Skip Digest check before installing zip}">
 					<data variable="tw_skip_digest_check_zip"/>
 				</listitem>
+				<listitem name="{@auto_reflashtwrp_chk=Automatically Reflash TWRP after flashing a ROM}">
+					<conditions>
+						<condition var1="tw_has_boot_slots" var2="1"/>
+						<condition var1="tw_has_repack_tools" var2="1"/>
+					</conditions>
+					<data variable="tw_auto_reflashtwrp"/>
+				</listitem>
 				<listitem name="{@install_reboot_chk=Reboot after installation is complete}">
 					<data variable="tw_install_reboot"/>
 				</listitem>
@@ -3766,6 +3773,13 @@
 				<listitem name="{@unmount_sys_install=Unmount System before installing a ZIP}">
 					<data variable="tw_unmount_system"/>
 				</listitem>
+				<listitem name="{@auto_reflashtwrp_chk=Automatically Reflash TWRP after flashing a ROM}">
+					<conditions>
+						<condition var1="tw_has_boot_slots" var2="1"/>
+						<condition var1="tw_has_repack_tools" var2="1"/>
+					</conditions>
+					<data variable="tw_auto_reflashtwrp"/>
+				</listitem>
 			</listbox>
 
 			<action>
@@ -4320,6 +4334,22 @@
 						<action function="page">repackselect</action>
 					</actions>
 				</listitem>
+				<listitem name="{@reflash_twrp=Flash Current TWRP}">
+					<conditions>
+						<condition var1="tw_has_boot_slots" var2="1"/>
+						<condition var1="tw_has_repack_tools" var2="1"/>
+					</conditions>
+					<actions>
+						<action function="set">tw_repack_kernel=0</action>
+						<action function="set">tw_back=advanced</action>
+						<action function="set">tw_action=reflashtwrp</action>
+						<action function="set">tw_text1={@reflash_twrp_confirm=Flash Current TWRP?}</action>
+						<action function="set">tw_action_text1={@reflashing_twrp=Flashing TWRP...}</action>
+						<action function="set">tw_complete_text1={@reflash_twrp_complete=Done Flashing TWRP}</action>
+						<action function="set">tw_slider_text={@swipe_to_confirm=Swipe to Confirm}</action>
+						<action function="page">confirm_action</action>
+						</actions>
+				</listitem>
 				<listitem name="{@install_kernel=Install Kernel}">
 					<conditions>
 						<condition var1="tw_has_boot_slots" var2="1"/>
diff --git a/twrpRepacker.cpp b/twrpRepacker.cpp
index 325ad42..735f302 100755
--- a/twrpRepacker.cpp
+++ b/twrpRepacker.cpp
@@ -129,8 +129,14 @@
 	if (!Backup_Image_For_Repack(part, REPACK_ORIG_DIR, Repack_Options.Backup_First, gui_lookup("repack", "Repack")))
 		return false;
 	DataManager::SetProgress(.25);
-	gui_msg(Msg("unpacking_image=Unpacking {1}...")(Target_Image));
-	image_ramdisk_format = Unpack_Image(Target_Image, REPACK_NEW_DIR, true);
+	if (Repack_Options.Type == REPLACE_RAMDISK_UNPACKED) {
+		if (!Prepare_Empty_Folder(REPACK_NEW_DIR))
+			return false;
+		image_ramdisk_format = "gzip";
+	} else {
+		gui_msg(Msg("unpacking_image=Unpacking {1}...")(Target_Image));
+		image_ramdisk_format = Unpack_Image(Target_Image, REPACK_NEW_DIR, true);
+	}
 	if (image_ramdisk_format.empty())
 		return false;
 	DataManager::SetProgress(.5);
@@ -142,6 +148,16 @@
 			LOGERR("Failed to copy ramdisk\n");
 			return false;
 		}
+	} else if (Repack_Options.Type == REPLACE_RAMDISK_UNPACKED) {
+			if (TWFunc::copy_file(Target_Image, REPACK_ORIG_DIR "ramdisk.cpio", 0644)) {
+				LOGERR("Failed to copy ramdisk\n");
+				return false;
+			}
+			if (TWFunc::copy_file(Target_Image, REPACK_NEW_DIR "ramdisk.cpio", 0644)) {
+				LOGERR("Failed to copy ramdisk\n");
+				return false;
+			}
+		path = REPACK_ORIG_DIR;
 	} else if (Repack_Options.Type == REPLACE_RAMDISK) {
 		// Repack the ramdisk
 		if (TWFunc::copy_file(REPACK_NEW_DIR "ramdisk.cpio", REPACK_ORIG_DIR "ramdisk.cpio", 0644)) {
@@ -192,7 +208,7 @@
 	}
 	DataManager::SetProgress(1);
 	TWFunc::removeDir(REPACK_ORIG_DIR, false);
-	if (part->Is_SlotSelect() && Repack_Options.Type == REPLACE_RAMDISK) {
+	if (part->Is_SlotSelect()) { if (Repack_Options.Type == REPLACE_RAMDISK || Repack_Options.Type == REPLACE_RAMDISK_UNPACKED) {
 		LOGINFO("Switching slots to flash ramdisk to both partitions\n");
 		string Current_Slot = PartitionManager.Get_Active_Slot_Display();
 		if (Current_Slot == "A")
@@ -241,7 +257,33 @@
 		}
 		DataManager::SetProgress(1);
 		TWFunc::removeDir(REPACK_ORIG_DIR, false);
-	}
+	}}
 	TWFunc::removeDir(REPACK_NEW_DIR, false);
 	return true;
 }
+
+bool twrpRepacker::Flash_Current_Twrp() {
+if (!TWFunc::Path_Exists("/ramdisk-files.txt")) {
+			LOGERR("can not find ramdisk-files.txt");
+			return false;
+		}
+		Repack_Options_struct Repack_Options;
+		Repack_Options.Disable_Verity = false;
+		Repack_Options.Disable_Force_Encrypt = false;
+		Repack_Options.Type = REPLACE_RAMDISK_UNPACKED;
+		Repack_Options.Backup_First = DataManager::GetIntValue("tw_repack_backup_first") != 0;
+		std::string verifyfiles = "cd / && sha256sum --status -c ramdisk-files.sha256sum";
+		if (TWFunc::Exec_Cmd(verifyfiles) != 0) {
+		gui_msg(Msg(msg::kError, "modified_ramdisk_error=ramdisk files have been modified, unable to create ramdisk to flash, fastboot boot twrp and try this option again or use the Install Recovery Ramdisk option."));
+			return false;
+		}
+		std::string command = "cd / && /system/bin/cpio -H newc -o < ramdisk-files.txt > /tmp/currentramdisk.cpio && /system/bin/gzip -f /tmp/currentramdisk.cpio";
+		if (TWFunc::Exec_Cmd(command) != 0) {
+			gui_msg(Msg(msg::kError, "create_ramdisk_error=failed to create ramdisk to flash."));
+			return false;
+		}
+		if (!Repack_Image_And_Flash("/tmp/currentramdisk.cpio.gz", Repack_Options))
+			return false;
+       else
+       return true;
+}
diff --git a/twrpRepacker.hpp b/twrpRepacker.hpp
index 346229b..e71f3dc 100755
--- a/twrpRepacker.hpp
+++ b/twrpRepacker.hpp
@@ -1,48 +1,50 @@
-/*

-	Copyright 2014 to 2020 TeamWin

-	This file is part of TWRP/TeamWin Recovery Project.

-

-	TWRP 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.

-

-	TWRP 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 TWRP.  If not, see <http://www.gnu.org/licenses/>.

-*/

-

-#include <string>

-#include "partitions.hpp"

-

-#ifndef TWRP_REPACKER

-#define TWRP_REPACKER

-

-enum Repack_Type {

-	REPLACE_NONE = 0,

-	REPLACE_RAMDISK = 1,

-	REPLACE_KERNEL = 2,

-};

-

-struct Repack_Options_struct {

-	Repack_Type Type;

-	bool Backup_First;

-	bool Disable_Verity;

-	bool Disable_Force_Encrypt;

-};

-

-class twrpRepacker {

-    public:

-        bool Backup_Image_For_Repack(TWPartition* Part, const std::string& Temp_Folder_Destination, const bool Create_Backup, const std::string& Backup_Name); // Prepares an image for repacking by unpacking it to the temp folder destination

-        std::string Unpack_Image(const std::string& Source_Path, const std::string& Temp_Folder_Destination, const bool Copy_Source, const bool Create_Destination = true); // Prepares an image for repacking by unpacking it to the temp folder destination and return the ramdisk format

-        bool Repack_Image_And_Flash(const std::string& Target_Image, const struct Repack_Options_struct& Repack_Options); // Repacks the boot image with a new kernel or a new ramdisk

-    private:

-    	bool Prepare_Empty_Folder(const std::string& Folder); // Creates an empty folder at Folder. If the folder already exists, the folder is deleted, then created

-    	std::string original_ramdisk_format;                  // Ramdisk format of boot partition

-	    std::string image_ramdisk_format;                     // Ramdisk format of boot image to repack from

-};

-#endif // TWRP_REPACKER
\ No newline at end of file
+/*
+	Copyright 2014 to 2020 TeamWin
+	This file is part of TWRP/TeamWin Recovery Project.
+
+	TWRP 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.
+
+	TWRP 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 TWRP.  If not, see <http://www.gnu.org/licenses/>.
+*/
+
+#include <string>
+#include "partitions.hpp"
+
+#ifndef TWRP_REPACKER
+#define TWRP_REPACKER
+
+enum Repack_Type {
+	REPLACE_NONE = 0,
+	REPLACE_RAMDISK = 1,
+	REPLACE_KERNEL = 2,
+	REPLACE_RAMDISK_UNPACKED = 3,
+};
+
+struct Repack_Options_struct {
+	Repack_Type Type;
+	bool Backup_First;
+	bool Disable_Verity;
+	bool Disable_Force_Encrypt;
+};
+
+class twrpRepacker {
+    public:
+        bool Backup_Image_For_Repack(TWPartition* Part, const std::string& Temp_Folder_Destination, const bool Create_Backup, const std::string& Backup_Name); // Prepares an image for repacking by unpacking it to the temp folder destination
+        std::string Unpack_Image(const std::string& Source_Path, const std::string& Temp_Folder_Destination, const bool Copy_Source, const bool Create_Destination = true); // Prepares an image for repacking by unpacking it to the temp folder destination and return the ramdisk format
+        bool Repack_Image_And_Flash(const std::string& Target_Image, const struct Repack_Options_struct& Repack_Options); // Repacks the boot image with a new kernel or a new ramdisk
+        bool Flash_Current_Twrp();
+    private:
+    	bool Prepare_Empty_Folder(const std::string& Folder); // Creates an empty folder at Folder. If the folder already exists, the folder is deleted, then created
+    	std::string original_ramdisk_format;                  // Ramdisk format of boot partition
+	    std::string image_ramdisk_format;                     // Ramdisk format of boot image to repack from
+};
+#endif // TWRP_REPACKER
diff --git a/twrpinstall/twinstall.cpp b/twrpinstall/twinstall.cpp
index 139e983..7f9e8c0 100755
--- a/twrpinstall/twinstall.cpp
+++ b/twrpinstall/twinstall.cpp
@@ -55,6 +55,7 @@
 #include "gui/pages.hpp"
 #include "twinstall.h"
 #include "installcommand.h"
+#include "../twrpRepacker.hpp"
 extern "C" {
 	#include "gui/gui.h"
 }
@@ -242,7 +243,7 @@
 }
 
 int TWinstall_zip(const char* path, int* wipe_cache, bool check_for_digest) {
-	int ret_val, zip_verify = 1, unmount_system = 1;
+	int ret_val, zip_verify = 1, unmount_system = 1, reflashtwrp = 0;
 
 	gui_msg(Msg("installing_zip=Installing zip file '{1}'")(path));
 	if (strlen(path) < 9 || strncmp(path, "/sideload", 9) != 0) {
@@ -350,6 +351,11 @@
 				gui_warn("mount_vab_partitions=Devices on super may not mount until rebooting recovery.");
 			}
 			gui_warn("flash_ab_reboot=To flash additional zips, please reboot recovery to switch to the updated slot.");
+			DataManager::GetValue(TW_AUTO_REFLASHTWRP_VAR, reflashtwrp);
+			if (reflashtwrp) {
+			twrpRepacker repacker;
+			repacker.Flash_Current_Twrp();
+			}
 		} else {
 			std::string binary_name("ui.xml");
 			ZipEntry binary_entry;
diff --git a/variables.h b/variables.h
index d1f3786..52ce4fc 100755
--- a/variables.h
+++ b/variables.h
@@ -147,6 +147,7 @@
 #define TW_NO_SHA2                  "tw_no_sha2"
 #define TW_UNMOUNT_SYSTEM           "tw_unmount_system"
 #define TW_IS_SUPER                 "tw_is_super"
+#define TW_AUTO_REFLASHTWRP_VAR     "tw_auto_reflashtwrp"
 
 // Also used:
 //   tw_boot_is_mountable