Merge "Create a flag to include resetprop in the TWRP" into android-9.0
diff --git a/data.cpp b/data.cpp
index 088dbda..b1e8404 100755
--- a/data.cpp
+++ b/data.cpp
@@ -783,6 +783,7 @@
 #else
 	mPersist.SetValue(TW_NO_SHA2, "1");
 #endif
+	mPersist.SetValue(TW_UNMOUNT_SYSTEM, "1");
 
 #ifdef TW_NO_SCREEN_TIMEOUT
 	mConst.SetValue("tw_screen_timeout_secs", "0");
diff --git a/gui/theme/common/landscape.xml b/gui/theme/common/landscape.xml
index 8244c46..230b72f 100755
--- a/gui/theme/common/landscape.xml
+++ b/gui/theme/common/landscape.xml
@@ -2937,6 +2937,9 @@
 					<condition var1="tw_no_sha2" var2="0"/>
 					<data variable="tw_use_sha2"/>
 				</listitem>
+				<listitem name="{@unmount_sys_install=Unmount System before installing a ZIP}">
+					<data variable="tw_unmount_system"/>
+				</listitem>
 			</listbox>
 
 			<checkbox>
diff --git a/gui/theme/common/languages/en.xml b/gui/theme/common/languages/en.xml
index 4a0ac7f..3769da5 100755
--- a/gui/theme/common/languages/en.xml
+++ b/gui/theme/common/languages/en.xml
@@ -719,5 +719,8 @@
 		<string name="include_kernel_log">Include Kernel Log</string>
 		<string name="sha2_chk">Use SHA2 for hashing</string>
 		<string name="unable_set_boot_slot">Error changing bootloader boot slot to {1}</string>
+		<string name="unmount_sys_install">Unmount System before installing a ZIP</string>
+		<string name="unmount_system">Unmounting System...</string>
+		<string name="unmount_system_err">Failed unmounting System</string>
 	</resources>
 </language>
diff --git a/gui/theme/common/portrait.xml b/gui/theme/common/portrait.xml
index e014cc5..8370414 100755
--- a/gui/theme/common/portrait.xml
+++ b/gui/theme/common/portrait.xml
@@ -3150,6 +3150,9 @@
 					<condition var1="tw_no_sha2" var2="0"/>
 					<data variable="tw_use_sha2"/>
 				</listitem>
+				<listitem name="{@unmount_sys_install=Unmount System before installing a ZIP}">
+					<data variable="tw_unmount_system"/>
+				</listitem>
 			</listbox>
 
 			<button style="main_button_half_height">
diff --git a/gui/theme/common/watch.xml b/gui/theme/common/watch.xml
index f5d3222..05b7bd2 100755
--- a/gui/theme/common/watch.xml
+++ b/gui/theme/common/watch.xml
@@ -3640,6 +3640,9 @@
 					<condition var1="tw_no_sha2" var2="0"/>
 					<data variable="tw_use_sha2"/>
 				</listitem>
+				<listitem name="{@unmount_sys_install=Unmount System before installing a ZIP}">
+					<data variable="tw_unmount_system"/>
+				</listitem>
 			</listbox>
 
 			<action>
diff --git a/openrecoveryscript.cpp b/openrecoveryscript.cpp
index 1de0870..6d76298 100755
--- a/openrecoveryscript.cpp
+++ b/openrecoveryscript.cpp
@@ -301,6 +301,8 @@
 					strcat(mount, value);
 				} else
 					strcpy(mount, value);
+				if (!strcmp(mount, "/system"))
+					strcpy(mount, PartitionManager.Get_Android_Root_Path().c_str());
 				if (PartitionManager.Mount_By_Path(mount, true))
 					gui_msg(Msg("mounted=Mounted '{1}'")(mount));
 			} else if (strcmp(command, "unmount") == 0 || strcmp(command, "umount") == 0) {
@@ -311,6 +313,8 @@
 					strcat(mount, value);
 				} else
 					strcpy(mount, value);
+				if (!strcmp(mount, "/system"))
+					strcpy(mount, PartitionManager.Get_Android_Root_Path().c_str());
 				if (PartitionManager.UnMount_By_Path(mount, true))
 					gui_msg(Msg("unmounted=Unounted '{1}'")(mount));
 			} else if (strcmp(command, "set") == 0) {
diff --git a/partition.cpp b/partition.cpp
index beb4a81..646959c 100644
--- a/partition.cpp
+++ b/partition.cpp
@@ -272,7 +272,7 @@
 	// Do nothing
 }
 
-bool TWPartition::Process_Fstab_Line(const char *fstab_line, bool Display_Error, std::map<string, Flags_Map> *twrp_flags) {
+bool TWPartition::Process_Fstab_Line(const char *fstab_line, bool Display_Error, std::map<string, Flags_Map> *twrp_flags, bool Sar_Detect) {
 	char full_line[MAX_FSTAB_LINE_LENGTH];
 	char twflags[MAX_FSTAB_LINE_LENGTH] = "";
 	char* ptr;
@@ -309,11 +309,12 @@
 			Mount_Point = ptr;
 			if (fstab_version == 2) {
 				additional_entry = PartitionManager.Find_Partition_By_Path(Mount_Point);
-				if (additional_entry) {
+				if (!Sar_Detect && additional_entry) {
 					LOGINFO("Found an additional entry for '%s'\n", Mount_Point.c_str());
 				}
 			}
-			LOGINFO("Processing '%s'\n", Mount_Point.c_str());
+			if(!Sar_Detect)
+				LOGINFO("Processing '%s'\n", Mount_Point.c_str());
 			Backup_Path = Mount_Point;
 			Storage_Path = Mount_Point;
 			Display_Name = ptr + 1;
@@ -410,7 +411,12 @@
 	if (Primary_Block_Device.find("*") != string::npos)
 		Wildcard_Block_Device = true;
 
-	if (Mount_Point == "auto") {
+	if (Sar_Detect) {
+		if(Is_File_System(Fstab_File_System) && (Mount_Point == "/" || Mount_Point == "/system" || Mount_Point == "/system_root"))
+			Find_Actual_Block_Device();
+		else
+			return true;
+	} else if (Mount_Point == "auto") {
 		Mount_Point = "/auto";
 		char autoi[5];
 		sprintf(autoi, "%i", auto_index);
@@ -436,7 +442,7 @@
 	} else if (Is_File_System(Fstab_File_System)) {
 		Find_Actual_Block_Device();
 		Setup_File_System(Display_Error);
-		if (Mount_Point == PartitionManager.Get_Android_Root_Path()) {
+		if (Mount_Point == "/" || Mount_Point == "/system" || Mount_Point == "/system_root") {
 			Display_Name = "System";
 			Backup_Display_Name = Display_Name;
 			Storage_Name = Display_Name;
@@ -598,6 +604,19 @@
 		}
 	}
 
+	if (Is_File_System(Fstab_File_System) && (Mount_Point == "/" || Mount_Point == "/system" || Mount_Point == "/system_root")) {
+		if (Sar_Detect) {
+			Mount_Point = "/s";
+			Mount_Read_Only = true;
+			Can_Be_Mounted = true;
+		} else {
+			Mount_Point = PartitionManager.Get_Android_Root_Path();
+			Backup_Path = Mount_Point;
+			Storage_Path = Mount_Point;
+			Make_Dir(Mount_Point, Display_Error);
+		}
+	}
+
 	return true;
 }
 
@@ -1525,10 +1544,23 @@
 		string Command = "mount -o bind '" + Symlink_Path + "' '" + Symlink_Mount_Point + "'";
 		TWFunc::Exec_Cmd(Command);
 	}
+
+	if (Mount_Point == "/system_root") {
+		unlink("/system");
+		mkdir("/system", 0755);
+		mount("/system_root/system", "/system", "auto", MS_BIND, NULL);
+	}
+
 	return true;
 }
 
 bool TWPartition::UnMount(bool Display_Error) {
+	if (Mount_Point == "/system_root") {
+		if (umount("/system") == -1)
+			umount2("/system", MNT_DETACH);
+		rmdir("/system");
+		symlink("/system_root/system", "/system");
+	}
 	if (Is_Mounted()) {
 		int never_unmount_system;
 
@@ -2895,7 +2927,7 @@
 		TWPartition *part = new TWPartition;
 		char buffer[MAX_FSTAB_LINE_LENGTH];
 		sprintf(buffer, "%s %s-%i auto defaults defaults", item.c_str(), Mount_Point.c_str(), ++mount_point_index);
-		part->Process_Fstab_Line(buffer, false, NULL);
+		part->Process_Fstab_Line(buffer, false, NULL, false);
 		char display[MAX_FSTAB_LINE_LENGTH];
 		sprintf(display, "%s %i", Storage_Name.c_str(), mount_point_index);
 		part->Storage_Name = display;
diff --git a/partitionmanager.cpp b/partitionmanager.cpp
index 3c2b1c6..f63b3f3 100755
--- a/partitionmanager.cpp
+++ b/partitionmanager.cpp
@@ -111,7 +111,7 @@
 #endif
 }
 
-int TWPartitionManager::Process_Fstab(string Fstab_Filename, bool Display_Error) {
+int TWPartitionManager::Process_Fstab(string Fstab_Filename, bool Display_Error, bool Sar_Detect) {
 	FILE *fstabFile;
 	char fstab_line[MAX_FSTAB_LINE_LENGTH];
 	TWPartition* settings_partition = NULL;
@@ -198,7 +198,7 @@
 			fstab_line[line_size] = '\n';
 
 		TWPartition* partition = new TWPartition();
-		if (partition->Process_Fstab_Line(fstab_line, Display_Error, &twrp_flags))
+		if (partition->Process_Fstab_Line(fstab_line, Display_Error, &twrp_flags, Sar_Detect))
 			Partitions.push_back(partition);
 		else
 			delete partition;
@@ -213,7 +213,7 @@
 		for (std::map<string, Flags_Map>::iterator mapit=twrp_flags.begin(); mapit!=twrp_flags.end(); mapit++) {
 			if (Find_Partition_By_Path(mapit->first) == NULL) {
 				TWPartition* partition = new TWPartition();
-				if (partition->Process_Fstab_Line(mapit->second.fstab_line, Display_Error, NULL))
+				if (partition->Process_Fstab_Line(mapit->second.fstab_line, Display_Error, NULL, Sar_Detect))
 					Partitions.push_back(partition);
 				else
 					delete partition;
@@ -227,6 +227,13 @@
 
 	std::vector<TWPartition*>::iterator iter;
 	for (iter = Partitions.begin(); iter != Partitions.end(); iter++) {
+		if (Sar_Detect) {
+			if ((*iter)->Mount_Point == "/s")
+				return true;
+			else
+				continue;
+		}
+
 		(*iter)->Partition_Post_Processing(Display_Error);
 
 		if ((*iter)->Is_Storage) {
@@ -2840,10 +2847,9 @@
 }
 
 string TWPartitionManager::Get_Android_Root_Path() {
-	std::string Android_Root = getenv("ANDROID_ROOT");
-	if (Android_Root == "")
-		Android_Root = "/system";
-	return Android_Root;
+	if (property_get_bool("ro.twrp.sar", false))
+		return "/system_root";
+	return "/system";
 }
 
 void TWPartitionManager::Remove_Uevent_Devices(const string& Mount_Point) {
diff --git a/partitions.hpp b/partitions.hpp
index 4071b94..92970d9 100644
--- a/partitions.hpp
+++ b/partitions.hpp
@@ -178,7 +178,7 @@
 	void Setup_Data_Media();                                                  // Sets up a partition as a /data/media emulated storage partition
 
 private:
-	bool Process_Fstab_Line(const char *fstab_line, bool Display_Error, std::map<string, Flags_Map> *twrp_flags); // Processes a fstab line
+	bool Process_Fstab_Line(const char *fstab_line, bool Display_Error, std::map<string, Flags_Map> *twrp_flags, bool Sar_Detect); // Processes a fstab line
 	void Setup_Data_Partition(bool Display_Error);                            // Setup data partition after fstab processed
 	void Setup_Cache_Partition(bool Display_Error);                           // Setup cache partition after fstab processed
 	bool Find_Wildcard_Block_Devices(const string& Device);                   // Searches for and finds wildcard block devices
@@ -305,7 +305,7 @@
 	~TWPartitionManager() {}
 
 public:
-	int Process_Fstab(string Fstab_Filename, bool Display_Error);             // Parses the fstab and populates the partitions
+	int Process_Fstab(string Fstab_Filename, bool Display_Error, bool Sar_Detect);             // Parses the fstab and populates the partitions
 	int Write_Fstab();                                                        // Creates /etc/fstab file that's used by the command line for mount commands
 	void Output_Partition_Logging();                                          // Outputs partition information to the log
 	void Output_Partition(TWPartition* Part);                                 // Outputs partition details to the log
diff --git a/twinstall.cpp b/twinstall.cpp
index d659b47..92af497 100755
--- a/twinstall.cpp
+++ b/twinstall.cpp
@@ -339,7 +339,7 @@
 }
 
 int TWinstall_zip(const char* path, int* wipe_cache) {
-	int ret_val, zip_verify = 1;
+	int ret_val, zip_verify = 1, unmount_system = 1;
 
 	if (strcmp(path, "error") == 0) {
 		LOGERR("Failed to get adb sideload file: '%s'\n", path);
@@ -359,6 +359,8 @@
 		}
 	}
 
+	DataManager::GetValue(TW_UNMOUNT_SYSTEM, unmount_system);
+
 #ifndef TW_OEM_BUILD
 	DataManager::GetValue(TW_SIGNED_ZIP_VERIFY_VAR, zip_verify);
 #endif
@@ -410,6 +412,14 @@
 		return INSTALL_CORRUPT;
 	}
 
+	if (unmount_system) {
+		gui_msg("unmount_system=Unmounting System...");
+		if(!PartitionManager.UnMount_By_Path(PartitionManager.Get_Android_Root_Path(), true)) {
+			gui_err("unmount_system_err=Failed unmounting System");
+			return -1;
+		}
+	}
+
 	time_t start, stop;
 	time(&start);
 	if (Zip.EntryExists(ASSUMED_UPDATE_BINARY_NAME)) {
diff --git a/twrp.cpp b/twrp.cpp
index dac0093..bb062f7 100755
--- a/twrp.cpp
+++ b/twrp.cpp
@@ -117,8 +117,50 @@
 	if (!TWFunc::Path_Exists(fstab_filename)) {
 		fstab_filename = "/etc/recovery.fstab";
 	}
+
+	// Begin SAR detection
+	{
+		TWPartitionManager SarPartitionManager;
+		printf("=> Processing %s for SAR-detection\n", fstab_filename.c_str());
+		if (!SarPartitionManager.Process_Fstab(fstab_filename, 1, 1)) {
+			LOGERR("Failing out of recovery due to problem with fstab.\n");
+			return -1;
+		}
+
+		mkdir("/s", 0755);
+
+#if defined(AB_OTA_UPDATER) || defined(__ANDROID_API_Q__)
+		bool fallback_sar = true;
+#else
+		bool fallback_sar = property_get_bool("ro.build.system_root_image", false);
+#endif
+
+		if(SarPartitionManager.Mount_By_Path("/s", false)) {
+			if (TWFunc::Path_Exists("/s/build.prop")) {
+				LOGINFO("SAR-DETECT: Non-SAR System detected\n");
+				property_set("ro.twrp.sar", "0");
+				rmdir("/system_root");
+			} else if (TWFunc::Path_Exists("/s/system/build.prop")) {
+				LOGINFO("SAR-DETECT: SAR System detected\n");
+				property_set("ro.twrp.sar", "1");
+			} else {
+				LOGINFO("SAR-DETECT: No build.prop found, falling back to %s\n", fallback_sar ? "SAR" : "Non-SAR");
+				property_set("ro.twrp.sar", fallback_sar ? "1" : "0");
+			}
+			SarPartitionManager.UnMount_By_Path("/s", false);
+		} else {
+			LOGINFO("SAR-DETECT: Could not mount system partition, falling back to %s\n", fallback_sar ? "SAR":"Non-SAR");
+			property_set("ro.twrp.sar", fallback_sar ? "1" : "0");
+		}
+
+		rmdir("/s");
+
+		TWFunc::check_and_run_script("/sbin/sarsetup.sh", "boot");
+	}
+	// End SAR detection
+
 	printf("=> Processing %s\n", fstab_filename.c_str());
-	if (!PartitionManager.Process_Fstab(fstab_filename, 1)) {
+	if (!PartitionManager.Process_Fstab(fstab_filename, 1, 0)) {
 		LOGERR("Failing out of recovery due to problem with fstab.\n");
 		return -1;
 	}
diff --git a/variables.h b/variables.h
index 76da715..24cde92 100644
--- a/variables.h
+++ b/variables.h
@@ -140,6 +140,7 @@
 #define TW_MILITARY_TIME            "tw_military_time"
 #define TW_USE_SHA2                 "tw_use_sha2"
 #define TW_NO_SHA2                  "tw_no_sha2"
+#define TW_UNMOUNT_SYSTEM           "tw_unmount_system"
 
 // Also used:
 //   tw_boot_is_mountable