Move ORS command line into main thread

Also eliminate the mostly similar runPage function in favor of
using a single runPages function to avoid code duplication.

Change-Id: I46ef414beb4009fee16d4de13d8a5ab2b9678409
diff --git a/gui/gui.cpp b/gui/gui.cpp
index 61e5de1..9b918f0 100644
--- a/gui/gui.cpp
+++ b/gui/gui.cpp
@@ -68,8 +68,8 @@
 pthread_mutex_t gForceRendermutex;
 static int gNoAnimation = 1;
 static int gGuiInputRunning = 0;
-static int gCmdLineRunning = 0;
 blanktimer blankTimer;
+int ors_read_fd = -1;
 
 // Needed by pages.cpp too
 int gGuiRunning = 0;
@@ -407,83 +407,97 @@
 	return NULL;
 }
 
-static void * command_thread(void *cookie)
+static void setup_ors_command()
 {
-	int read_fd;
-	FILE* orsout;
-	char command[1024], result[512];
-
-	LOGINFO("Starting command line thread\n");
+	ors_read_fd = -1;
 
 	unlink(ORS_INPUT_FILE);
 	if (mkfifo(ORS_INPUT_FILE, 06660) != 0) {
 		LOGINFO("Unable to mkfifo %s\n", ORS_INPUT_FILE);
-		return 0;
+		return;
 	}
 	unlink(ORS_OUTPUT_FILE);
 	if (mkfifo(ORS_OUTPUT_FILE, 06666) != 0) {
 		LOGINFO("Unable to mkfifo %s\n", ORS_OUTPUT_FILE);
 		unlink(ORS_INPUT_FILE);
-		return 0;
+		return;
 	}
 
-	read_fd = open(ORS_INPUT_FILE, O_RDONLY);
-	if (read_fd < 0) {
+	ors_read_fd = open(ORS_INPUT_FILE, O_RDONLY | O_NONBLOCK);
+	if (ors_read_fd < 0) {
 		LOGINFO("Unable to open %s\n", ORS_INPUT_FILE);
 		unlink(ORS_INPUT_FILE);
 		unlink(ORS_OUTPUT_FILE);
-		return 0;
 	}
+}
 
-	while (!gGuiRunning)
-		sleep(1);
+static void ors_command_read()
+{
+	FILE* orsout;
+	char command[1024], result[512];
+	int set_page_done = 0, read_ret = 0;
 
-	for (;;) {
-		while (read(read_fd, &command, sizeof(command)) > 0) {
-			command[1022] = '\n';
-			command[1023] = '\0';
-			LOGINFO("Command '%s' received\n", command);
-			orsout = fopen(ORS_OUTPUT_FILE, "w");
-			if (!orsout) {
-				close(read_fd);
-				LOGINFO("Unable to fopen %s\n", ORS_OUTPUT_FILE);
-				unlink(ORS_INPUT_FILE);
-				unlink(ORS_OUTPUT_FILE);
-				return 0;
-			}
-			if (DataManager::GetIntValue("tw_busy") != 0) {
-				strcpy(result, "Failed, operation in progress\n");
-				fprintf(orsout, "%s", result);
-				LOGINFO("Command cannot be performed, operation in progress.\n");
-			} else {
-				if (gui_console_only() == 0) {
-					LOGINFO("Console started successfully\n");
-					gui_set_FILE(orsout);
-					if (strlen(command) > 11 && strncmp(command, "runscript", 9) == 0) {
-						char* filename = command + 11;
-						if (OpenRecoveryScript::copy_script_file(filename) == 0) {
-							LOGERR("Unable to copy script file\n");
-						} else {
-							OpenRecoveryScript::run_script_file();
-						}
-					} else if (strlen(command) > 5 && strncmp(command, "get", 3) == 0) {
-						char* varname = command + 4;
-						string temp;
-						DataManager::GetValue(varname, temp);
-						gui_print("%s = %s\n", varname, temp.c_str());
-					} else if (OpenRecoveryScript::Insert_ORS_Command(command)) {
+	if ((read_ret = read(ors_read_fd, &command, sizeof(command))) > 0) {
+		command[1022] = '\n';
+		command[1023] = '\0';
+		LOGINFO("Command '%s' received\n", command);
+		orsout = fopen(ORS_OUTPUT_FILE, "w");
+		if (!orsout) {
+			close(ors_read_fd);
+			ors_read_fd = -1;
+			LOGINFO("Unable to fopen %s\n", ORS_OUTPUT_FILE);
+			unlink(ORS_INPUT_FILE);
+			unlink(ORS_OUTPUT_FILE);
+			return;
+		}
+		if (DataManager::GetIntValue("tw_busy") != 0) {
+			strcpy(result, "Failed, operation in progress\n");
+			fprintf(orsout, "%s", result);
+			LOGINFO("Command cannot be performed, operation in progress.\n");
+		} else {
+			if (gui_console_only() == 0) {
+				LOGINFO("Console started successfully\n");
+				gui_set_FILE(orsout);
+				if (strlen(command) > 11 && strncmp(command, "runscript", 9) == 0) {
+					char* filename = command + 11;
+					if (OpenRecoveryScript::copy_script_file(filename) == 0) {
+						LOGERR("Unable to copy script file\n");
+					} else {
 						OpenRecoveryScript::run_script_file();
 					}
-					gui_set_FILE(NULL);
-					gGuiConsoleTerminate = 1;
+				} else if (strlen(command) > 5 && strncmp(command, "get", 3) == 0) {
+					char* varname = command + 4;
+					string temp;
+					DataManager::GetValue(varname, temp);
+					gui_print("%s = %s\n", varname, temp.c_str());
+				} else if (strlen(command) > 9 && strncmp(command, "decrypt", 7) == 0) {
+					char* pass = command + 8;
+					gui_print("Attempting to decrypt data partition via command line.\n");
+					if (PartitionManager.Decrypt_Device(pass) == 0) {
+						set_page_done = 1;
+					}
+				} else if (OpenRecoveryScript::Insert_ORS_Command(command)) {
+					OpenRecoveryScript::run_script_file();
 				}
+				gui_set_FILE(NULL);
+				gGuiConsoleTerminate = 1;
 			}
-			fclose(orsout);
 		}
+		fclose(orsout);
+		LOGINFO("Done reading ORS command from command line\n");
+		if (set_page_done) {
+			DataManager::SetValue("tw_page_done", 1);
+		} else {
+			// The select function will return ready to read and the
+			// read function will return errno 19 no such device unless
+			// we set everything up all over again.
+			close(ors_read_fd);
+			setup_ors_command();
+		}
+	} else {
+		LOGINFO("ORS command line read returned an error: %i, %i, %s\n", read_ret, errno, strerror(errno));
 	}
-	close(read_fd);
-	LOGINFO("Command thread exiting\n");
-	return 0;
+	return;
 }
 
 // This special function will return immediately the first time, but then
@@ -521,8 +535,11 @@
 	} while (1);
 }
 
-static int runPages(void)
+static int runPages(const char *page_name, const int stop_on_page_done)
 {
+	if (page_name)
+		gui_changePage(page_name);
+
 	// Raise the curtain
 	if (gCurtain != NULL)
 	{
@@ -542,10 +559,27 @@
 	timespec start, end;
 	int32_t render_t, flip_t;
 #endif
+#ifndef TW_OEM_BUILD
+	struct timeval timeout;
+	fd_set fdset;
+	int has_data = 0;
+#endif
 
 	for (;;)
 	{
 		loopTimer();
+#ifndef TW_OEM_BUILD
+		if (ors_read_fd > 0) {
+			FD_ZERO(&fdset);
+			FD_SET(ors_read_fd, &fdset);
+			timeout.tv_sec = 0;
+			timeout.tv_usec = 1;
+			has_data = select(ors_read_fd+1, &fdset, NULL, NULL, &timeout);
+			if (has_data > 0) {
+				ors_command_read();
+			}
+		}
+#endif
 
 		if (gGuiConsoleRunning) {
 			continue;
@@ -591,64 +625,17 @@
 		}
 
 		blankTimer.checkForTimeout();
-		if (DataManager::GetIntValue("tw_gui_done") != 0)
-			break;
-	}
-
-	gGuiRunning = 0;
-	return 0;
-}
-
-static int runPage(const char *page_name)
-{
-	gui_changePage(page_name);
-
-	// Raise the curtain
-	if (gCurtain != NULL)
-	{
-		gr_surface surface;
-
-		PageManager::Render();
-		gr_get_surface(&surface);
-		curtainRaise(surface);
-		gr_free_surface(surface);
-	}
-
-	gGuiRunning = 1;
-
-	DataManager::SetValue("tw_loaded", 1);
-
-	for (;;)
-	{
-		loopTimer();
-
-		if (!gForceRender)
-		{
-			int ret;
-
-			ret = PageManager::Update();
-			if (ret > 1)
-				PageManager::Render();
-
-			if (ret > 0)
-				flip();
-		}
-		else
-		{
-			pthread_mutex_lock(&gForceRendermutex);
-			gForceRender = 0;
-			pthread_mutex_unlock(&gForceRendermutex);
-			PageManager::Render();
-			flip();
-		}
-		blankTimer.checkForTimeout();
-		if (DataManager::GetIntValue("tw_page_done") != 0)
+		if (stop_on_page_done && DataManager::GetIntValue("tw_page_done") != 0)
 		{
 			gui_changePage("main");
 			break;
 		}
+		if (DataManager::GetIntValue("tw_gui_done") != 0)
+			break;
 	}
-
+	if (ors_read_fd > 0)
+		close(ors_read_fd);
+	ors_read_fd = -1;
 	gGuiRunning = 0;
 	return 0;
 }
@@ -839,37 +826,10 @@
 
 extern "C" int gui_start(void)
 {
-	if (!gGuiInitialized)
-		return -1;
-
-	gGuiConsoleTerminate = 1;
-
-	while (gGuiConsoleRunning)
-		loopTimer();
-
-	// Set the default package
-	PageManager::SelectPackage("TWRP");
-
-	if (!gGuiInputRunning)
-	{
-		// Start by spinning off an input handler.
-		pthread_t t;
-		pthread_create(&t, NULL, input_thread, NULL);
-		gGuiInputRunning = 1;
-	}
-#ifndef TW_OEM_BUILD
-	if (!gCmdLineRunning)
-	{
-		// Start by spinning off an input handler.
-		pthread_t t;
-		pthread_create(&t, NULL, command_thread, NULL);
-		gCmdLineRunning = 1;
-	}
-#endif
-	return runPages();
+	return gui_startPage(NULL, 1, 0);
 }
 
-extern "C" int gui_startPage(const char *page_name)
+extern "C" int gui_startPage(const char *page_name, const int allow_commands, int stop_on_page_done)
 {
 	if (!gGuiInitialized)
 		return -1;
@@ -889,9 +849,20 @@
 		pthread_create(&t, NULL, input_thread, NULL);
 		gGuiInputRunning = 1;
 	}
-
+#ifndef TW_OEM_BUILD
+	if (allow_commands)
+	{
+		if (ors_read_fd < 0)
+			setup_ors_command();
+	} else {
+		if (ors_read_fd >= 0) {
+			close(ors_read_fd);
+			ors_read_fd = -1;
+		}
+	}
+#endif
 	DataManager::SetValue("tw_page_done", 0);
-	return runPage(page_name);
+	return runPages(page_name, stop_on_page_done);
 }
 
 static void * console_thread(void *cookie)