From 10ae24ff94396c67e773e3ce967bce82cdb9b4f6 Mon Sep 17 00:00:00 2001 From: that Date: Sat, 26 Dec 2015 20:53:51 +0100 Subject: get rid of console thread for OpenRecoveryScript - CLI commands run in a threaded action "twcmd" - Console is displayed via "singleaction_page" - move ORS execution code from GUI action to OpenRecoveryScript class - remove unused function gui_changePackage - don't change PageManager package in home action - fix that /tmp/openrecoveryscript was not deleted after execution Change-Id: Ic688c0b04647ce09e9db979b0bc5123f47cf4f70 --- gui/action.cpp | 44 ++++---------- gui/gui.cpp | 161 +++++++++++++------------------------------------ gui/gui.h | 1 - gui/objects.hpp | 1 + gui/pages.cpp | 28 +++------ gui/pages.hpp | 6 +- openrecoveryscript.cpp | 68 +++++++++++++++++++++ openrecoveryscript.hpp | 11 +++- 8 files changed, 144 insertions(+), 176 deletions(-) diff --git a/gui/action.cpp b/gui/action.cpp index 20944dac7..081e2d134 100644 --- a/gui/action.cpp +++ b/gui/action.cpp @@ -226,6 +226,7 @@ GUIAction::GUIAction(xml_node<>* node) ADD_ACTION(resize); ADD_ACTION(changefilesystem); ADD_ACTION(flashimage); + ADD_ACTION(twcmd); } // First, get the action @@ -522,7 +523,6 @@ int GUIAction::reboot(std::string arg) int GUIAction::home(std::string arg __unused) { - PageManager::SelectPackage("TWRP"); gui_changePage("main"); return 0; } @@ -1536,41 +1536,12 @@ int GUIAction::adbsideloadcancel(std::string arg __unused) int GUIAction::openrecoveryscript(std::string arg __unused) { - int op_status = 1; - operation_start("OpenRecoveryScript"); if (simulate) { simulate_progress_bar(); operation_end(0); } else { - // Check for the SCRIPT_FILE_TMP first as these are AOSP recovery commands - // that we converted to ORS commands during boot in recovery.cpp. - // Run those first. - int reboot = 0; - if (TWFunc::Path_Exists(SCRIPT_FILE_TMP)) { - gui_msg("running_recovery_commands=Running Recovery Commands"); - if (OpenRecoveryScript::run_script_file() == 0) { - reboot = 1; - op_status = 0; - } - } - // Check for the ORS file in /cache and attempt to run those commands. - if (OpenRecoveryScript::check_for_script_file()) { - gui_msg("running_ors=Running OpenRecoveryScript"); - if (OpenRecoveryScript::run_script_file() == 0) { - reboot = 1; - op_status = 0; - } - } - if (reboot) { - // Disable stock recovery reflashing - TWFunc::Disable_Stock_Recovery_Replace(); - usleep(2000000); // Sleep for 2 seconds before rebooting - TWFunc::tw_reboot(rb_system); - usleep(5000000); // Sleep for 5 seconds to allow reboot to occur - } else { - DataManager::SetValue("tw_page_done", 1); - } + int op_status = OpenRecoveryScript::Run_OpenRecoveryScript_Action(); operation_end(op_status); } return 0; @@ -1743,6 +1714,17 @@ int GUIAction::flashimage(std::string arg __unused) return 0; } +int GUIAction::twcmd(std::string arg) +{ + operation_start("TWRP CLI Command"); + if (simulate) + simulate_progress_bar(); + else + OpenRecoveryScript::Run_CLI_Command(arg.c_str()); + operation_end(0); + return 0; +} + int GUIAction::getKeyByName(std::string key) { if (key == "home") return KEY_HOME; diff --git a/gui/gui.cpp b/gui/gui.cpp index 78e8a7e0c..63baeee92 100644 --- a/gui/gui.cpp +++ b/gui/gui.cpp @@ -69,12 +69,11 @@ using namespace rapidxml; // Global values static gr_surface gCurtain = NULL; static int gGuiInitialized = 0; -static TWAtomicInt gGuiConsoleRunning; -static TWAtomicInt gGuiConsoleTerminate; static TWAtomicInt gForceRender; const int gNoAnimation = 1; blanktimer blankTimer; int ors_read_fd = -1; +static FILE* orsout = NULL; static float scale_theme_w = 1; static float scale_theme_h = 1; @@ -493,13 +492,28 @@ static void setup_ors_command() } } +// callback called after a CLI command was executed +static void ors_command_done() +{ + gui_set_FILE(NULL); + fclose(orsout); + orsout = NULL; + + if (DataManager::GetIntValue("tw_page_done") == 0) { + // 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(); + } +} + static void ors_command_read() { - FILE* orsout; - char command[1024], result[512]; - int set_page_done = 0, read_ret = 0; + char command[1024]; + int read_ret = read(ors_read_fd, &command, sizeof(command)); - if ((read_ret = read(ors_read_fd, &command, sizeof(command))) > 0) { + if (read_ret > 0) { command[1022] = '\n'; command[1023] = '\0'; LOGINFO("Command '%s' received\n", command); @@ -513,61 +527,40 @@ static void ors_command_read() return; } if (DataManager::GetIntValue("tw_busy") != 0) { - strcpy(result, "Failed, operation in progress\n"); - fprintf(orsout, "%s", result); + fputs("Failed, operation in progress\n", orsout); LOGINFO("Command cannot be performed, operation in progress.\n"); + fclose(orsout); } else { if (strlen(command) == 11 && strncmp(command, "dumpstrings", 11) == 0) { - // This cannot be done safely with gui_console_only because gui_console_only updates mCurrentSet - // which makes the resources that we are trying to read unreachable. gui_set_FILE(orsout); PageManager::GetResources()->DumpStrings(); - gui_set_FILE(NULL); - } else if (gui_console_only() == 0) { - LOGINFO("Console started successfully\n"); + ors_command_done(); + } else { + // mirror output messages gui_set_FILE(orsout); - if (strlen(command) > 11 && strncmp(command, "runscript", 9) == 0) { - char* filename = command + 11; - if (OpenRecoveryScript::copy_script_file(filename) == 0) { - LOGINFO("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 (strlen(command) > 9 && strncmp(command, "decrypt", 7) == 0) { - char* pass = command + 8; - gui_msg("decrypt_cmd=Attempting to decrypt data partition via command line."); - 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.set_value(1); + // close orsout and restart listener after command is done + OpenRecoveryScript::Call_After_CLI_Command(ors_command_done); + // run the command in a threaded action... + DataManager::SetValue("tw_action", "twcmd"); + DataManager::SetValue("tw_action_param", command); + // ...and switch back to the current page when finished + std::string currentPage = PageManager::GetCurrentPage(); + DataManager::SetValue("tw_has_action2", "1"); + DataManager::SetValue("tw_action2", "page"); + DataManager::SetValue("tw_action2_param", currentPage); + DataManager::SetValue("tw_action_text1", gui_lookup("running_recovery_commands", "Running Recovery Commands")); + DataManager::SetValue("tw_action_text2", ""); + gui_changePage("singleaction_page"); + // now immediately return to the GUI main loop (the action runs in the background thread) + // put all things that need to be done after the command is finished into ors_command_done, not here } } - 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)); } - return; } +// Get and dispatch input events until it's time to draw the next frame // This special function will return immediately the first time, but then // always returns 1/30th of a second (or immediately if called later) from // the last time it was called @@ -648,7 +641,7 @@ static int runPages(const char *page_name, const int stop_on_page_done) { loopTimer(input_timeout_ms); #ifndef TW_OEM_BUILD - if (ors_read_fd > 0) { + if (ors_read_fd > 0 && !orsout) { // orsout is non-NULL if a command is still running FD_ZERO(&fdset); FD_SET(ors_read_fd, &fdset); timeout.tv_sec = 0; @@ -660,10 +653,6 @@ static int runPages(const char *page_name, const int stop_on_page_done) } #endif - if (gGuiConsoleRunning.get_value()) { - continue; - } - if (!gForceRender.get_value()) { int ret = PageManager::Update(); @@ -748,13 +737,6 @@ int gui_changeOverlay(std::string overlay) return 0; } -int gui_changePackage(std::string newPackage) -{ - PageManager::SelectPackage(newPackage); - gForceRender.set_value(1); - return 0; -} - std::string gui_parse_text(std::string str) { // This function parses text for DataManager values encompassed by %value% in the XML @@ -957,11 +939,6 @@ extern "C" int gui_startPage(const char *page_name, const int allow_commands, in if (!gGuiInitialized) return -1; - gGuiConsoleTerminate.set_value(1); - - while (gGuiConsoleRunning.get_value()) - usleep(10000); - // Set the default package PageManager::SelectPackage("TWRP"); @@ -981,60 +958,6 @@ extern "C" int gui_startPage(const char *page_name, const int allow_commands, in return runPages(page_name, stop_on_page_done); } -static void * console_thread(void *cookie __unused) -{ - PageManager::SwitchToConsole(); - - while (!gGuiConsoleTerminate.get_value()) - { - loopTimer(0); - - if (!gForceRender.get_value()) - { - int ret; - - ret = PageManager::Update(); - if (ret > 1) - PageManager::Render(); - - if (ret > 0) - flip(); - - if (ret < 0) - LOGERR("An update request has failed.\n"); - } - else - { - gForceRender.set_value(0); - PageManager::Render(); - flip(); - } - } - gGuiConsoleRunning.set_value(0); - gForceRender.set_value(1); // this will kickstart the GUI to render again - PageManager::EndConsole(); - LOGINFO("Console stopping\n"); - return NULL; -} - -extern "C" int gui_console_only(void) -{ - if (!gGuiInitialized) - return -1; - - gGuiConsoleTerminate.set_value(0); - - if (gGuiConsoleRunning.get_value()) - return 0; - - gGuiConsoleRunning.set_value(1); - - // Start by spinning off an input handler. - pthread_t t; - pthread_create(&t, NULL, console_thread, NULL); - - return 0; -} extern "C" void set_scale_values(float w, float h) { diff --git a/gui/gui.h b/gui/gui.h index f6f0483a4..034f1cd92 100644 --- a/gui/gui.h +++ b/gui/gui.h @@ -21,7 +21,6 @@ #include -int gui_console_only(); int gui_init(); int gui_loadResources(); int gui_loadCustomResources(); diff --git a/gui/objects.hpp b/gui/objects.hpp index 438905b96..ebf08a8db 100644 --- a/gui/objects.hpp +++ b/gui/objects.hpp @@ -366,6 +366,7 @@ protected: int checkpartitionlifetimewrites(std::string arg); int mountsystemtoggle(std::string arg); int setlanguage(std::string arg); + int twcmd(std::string arg); int simulate; }; diff --git a/gui/pages.cpp b/gui/pages.cpp index 13f3bd7b5..4a65c69e4 100644 --- a/gui/pages.cpp +++ b/gui/pages.cpp @@ -1098,6 +1098,11 @@ int PageSet::IsCurrentPage(Page* page) return ((mCurrentPage && mCurrentPage == page) ? 1 : 0); } +std::string PageSet::GetCurrentPage() const +{ + return mCurrentPage ? mCurrentPage->GetName() : ""; +} + int PageSet::Render(void) { int ret; @@ -1544,6 +1549,11 @@ int PageManager::ChangePage(std::string name) return ret; } +std::string PageManager::GetCurrentPage() +{ + return mCurrentSet ? mCurrentSet->GetCurrentPage() : ""; +} + int PageManager::ChangeOverlay(std::string name) { if (name.empty()) @@ -1560,24 +1570,6 @@ const ResourceManager* PageManager::GetResources() return (mCurrentSet ? mCurrentSet->GetResources() : NULL); } -int PageManager::SwitchToConsole(void) -{ - PageSet* console = new PageSet(NULL); - - mCurrentSet = console; - return 0; -} - -int PageManager::EndConsole(void) -{ - if (mCurrentSet && mBaseSet) { - delete mCurrentSet; - mCurrentSet = mBaseSet; - return 0; - } - return -1; -} - int PageManager::IsCurrentPage(Page* page) { return (mCurrentSet ? mCurrentSet->IsCurrentPage(page) : 0); diff --git a/gui/pages.hpp b/gui/pages.hpp index 5dcc9e0b5..e7ad55e94 100644 --- a/gui/pages.hpp +++ b/gui/pages.hpp @@ -101,6 +101,7 @@ public: // Helper routine for identifing if we're the current page int IsCurrentPage(Page* page); + std::string GetCurrentPage() const; // These are routing routines int Render(void); @@ -144,10 +145,7 @@ public: static int ChangePage(std::string name); static int ChangeOverlay(std::string name); static const ResourceManager* GetResources(); - - // Used for console-only mode - static int SwitchToConsole(void); - static int EndConsole(void); + static std::string GetCurrentPage(); // Helper to identify if a particular page is the active page static int IsCurrentPage(Page* page); diff --git a/openrecoveryscript.cpp b/openrecoveryscript.cpp index b31a7605f..30c03b160 100644 --- a/openrecoveryscript.cpp +++ b/openrecoveryscript.cpp @@ -48,6 +48,8 @@ extern "C" { int TWinstall_zip(const char* path, int* wipe_cache); } +OpenRecoveryScript::VoidFunction OpenRecoveryScript::call_after_cli_command; + #define SCRIPT_COMMAND_SIZE 512 int OpenRecoveryScript::check_for_script_file(void) { @@ -398,6 +400,7 @@ int OpenRecoveryScript::run_script_file(void) { } } fclose(fp); + unlink(SCRIPT_FILE_TMP); gui_msg("done_ors=Done processing script file"); } else { gui_msg(Msg(msg::kError, "error_opening_strerr=Error opening: '{1}' ({2})")(SCRIPT_FILE_TMP)(strerror(errno))); @@ -569,9 +572,11 @@ int OpenRecoveryScript::Backup_Command(string Options) { return 0; } +// this is called by main() void OpenRecoveryScript::Run_OpenRecoveryScript(void) { DataManager::SetValue("tw_back", "main"); DataManager::SetValue("tw_action", "openrecoveryscript"); + DataManager::SetValue("tw_action_param", ""); DataManager::SetValue("tw_has_action2", "0"); DataManager::SetValue("tw_action2", ""); DataManager::SetValue("tw_action2_param", ""); @@ -589,3 +594,66 @@ void OpenRecoveryScript::Run_OpenRecoveryScript(void) { LOGERR("Failed to load OpenRecoveryScript GUI page.\n"); } } + +// this is called by the "openrecoveryscript" GUI action called via action page from Run_OpenRecoveryScript +int OpenRecoveryScript::Run_OpenRecoveryScript_Action() { + int op_status = 1; + // Check for the SCRIPT_FILE_TMP first as these are AOSP recovery commands + // that we converted to ORS commands during boot in recovery.cpp. + // Run those first. + int reboot = 0; + if (TWFunc::Path_Exists(SCRIPT_FILE_TMP)) { + gui_msg("running_recovery_commands=Running Recovery Commands"); + if (OpenRecoveryScript::run_script_file() == 0) { + reboot = 1; + op_status = 0; + } + } + // Check for the ORS file in /cache and attempt to run those commands. + if (OpenRecoveryScript::check_for_script_file()) { + gui_msg("running_ors=Running OpenRecoveryScript"); + if (OpenRecoveryScript::run_script_file() == 0) { + reboot = 1; + op_status = 0; + } + } + if (reboot) { + // Disable stock recovery reflashing + TWFunc::Disable_Stock_Recovery_Replace(); + usleep(2000000); // Sleep for 2 seconds before rebooting + TWFunc::tw_reboot(rb_system); + usleep(5000000); // Sleep for 5 seconds to allow reboot to occur + } else { + DataManager::SetValue("tw_page_done", 1); + } + return op_status; +} + +// this is called by the "twcmd" GUI action when a command is received via FIFO from the "twrp" command line tool +void OpenRecoveryScript::Run_CLI_Command(const char* command) { + if (strlen(command) > 11 && strncmp(command, "runscript", 9) == 0) { + const char* filename = command + 10; + if (OpenRecoveryScript::copy_script_file(filename) == 0) { + LOGINFO("Unable to copy script file\n"); + } else { + OpenRecoveryScript::run_script_file(); + } + } else if (strlen(command) > 5 && strncmp(command, "get", 3) == 0) { + const char* varname = command + 4; + string value; + DataManager::GetValue(varname, value); + gui_print("%s = %s\n", varname, value.c_str()); + } else if (strlen(command) > 9 && strncmp(command, "decrypt", 7) == 0) { + const char* pass = command + 8; + gui_msg("decrypt_cmd=Attempting to decrypt data partition via command line."); + if (PartitionManager.Decrypt_Device(pass) == 0) { + // set_page_done = 1; // done by singleaction_page anyway + } + } else if (OpenRecoveryScript::Insert_ORS_Command(command)) { + OpenRecoveryScript::run_script_file(); + } + + // let the GUI close the output fd and restart the command listener + call_after_cli_command(); + LOGINFO("Done reading ORS command from command line\n"); +} diff --git a/openrecoveryscript.hpp b/openrecoveryscript.hpp index c3eabf6df..38311959b 100644 --- a/openrecoveryscript.hpp +++ b/openrecoveryscript.hpp @@ -23,18 +23,23 @@ using namespace std; -// Partition class class OpenRecoveryScript { -public: + typedef void (*VoidFunction)(); + static VoidFunction call_after_cli_command; // callback to GUI after Run_CLI_Command + static int check_for_script_file(); // Checks to see if the ORS file is present in /cache static int copy_script_file(string filename); // Copies a script file to the temp folder static int run_script_file(); // Executes the commands in the ORS file - static int Insert_ORS_Command(string Command); // Inserts the Command into the SCRIPT_FILE_TMP file static int Install_Command(string Zip); // Installs a zip static string Locate_Zip_File(string Path, string File); // Attempts to locate the zip file in storage static int Backup_Command(string Options); // Runs a backup +public: + static int Insert_ORS_Command(string Command); // Inserts the Command into the SCRIPT_FILE_TMP file static void Run_OpenRecoveryScript(); // Starts the GUI Page for running OpenRecoveryScript + static int Run_OpenRecoveryScript_Action(); // Actually runs the ORS scripts for the GUI action + static void Call_After_CLI_Command(VoidFunction fn) { call_after_cli_command = fn; } + static void Run_CLI_Command(const char* command); // Runs a command for orscmd (twrp binary) }; #endif // _OPENRECOVERYSCRIPT_HPP -- cgit v1.2.3