From 7bc3d823db5648f2284c5344015c9662c55bfd54 Mon Sep 17 00:00:00 2001 From: zzyyyl Date: Sat, 17 Sep 2022 16:59:14 +0800 Subject: [PATCH 1/9] =?UTF-8?q?fix:=20=E4=BF=AE=E5=A4=8D=20Controller=20?= =?UTF-8?q?=E4=B8=AD=20m=5Finstance=5Fcount=20=E4=B8=80=E5=AE=9A=E4=BC=9A?= =?UTF-8?q?=E5=87=8F=E5=88=B0=E8=B4=9F=E6=95=B0=E7=9A=84=E9=97=AE=E9=A2=98?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 满是bug的代码居然正常的跑起来了.jpg --- src/MeoAssistant/Controller.cpp | 126 +++++++++++++++++--------------- src/MeoAssistant/Controller.h | 6 +- 2 files changed, 70 insertions(+), 62 deletions(-) diff --git a/src/MeoAssistant/Controller.cpp b/src/MeoAssistant/Controller.cpp index 863e959452..f63f75ac89 100644 --- a/src/MeoAssistant/Controller.cpp +++ b/src/MeoAssistant/Controller.cpp @@ -40,14 +40,10 @@ asst::Controller::Controller(AsstCallback callback, void* callback_arg) #ifdef _WIN32 - m_support_socket = false; - do { - if (!WsaHelper::get_instance()()) { - Log.error("WSA not supports"); - break; - } - m_support_socket = true; - } while (false); + m_support_socket = WsaHelper::get_instance()(); + if (!m_support_socket) { + Log.error("WSA not supports"); + } #else int pipe_in_ret = pipe(m_pipe_in); @@ -76,9 +72,7 @@ asst::Controller::~Controller() m_cmd_thread.join(); } - if (--m_instance_count) { - release(); - } + try_release(); #ifndef _WIN32 close(m_pipe_in[PIPE_READ]); @@ -185,7 +179,8 @@ void asst::Controller::pipe_working_proc() } } -std::optional asst::Controller::call_command(const std::string& cmd, int64_t timeout, bool recv_by_socket) +std::optional asst::Controller::call_command(const std::string& cmd, int64_t timeout, bool recv_by_socket, + bool allow_reconnect) { using namespace std::chrono_literals; using namespace std::chrono; @@ -424,10 +419,7 @@ std::optional asst::Controller::call_command(const std::string& cmd if (!exit_ret) { return recv_by_socket ? sock_data : pipe_data; } - else if (m_inited) { - // 这里用 m_inited 限制了仅递归一层,修改需要注意下 - m_inited = false; - + else if (allow_reconnect) { // 之前可以运行,突然运行不了了,这种情况多半是 adb 炸了。所以重新连接一下 json::value reconnect_info = json::object { { "uuid", m_uuid }, @@ -448,20 +440,18 @@ std::optional asst::Controller::call_command(const std::string& cmd callback(AsstMsg::ConnectionInfo, reconnect_info); std::this_thread::sleep_for(10s); - auto reconnect_ret = call_command(m_adb.connect, 60LL * 1000); + auto reconnect_ret = call_command(m_adb.connect, 60LL * 1000, false /* 禁止重连避免无限递归 */); bool is_reconnect_success = false; if (reconnect_ret) { auto& reconnect_str = reconnect_ret.value(); is_reconnect_success = reconnect_str.find("error") == std::string::npos; } if (is_reconnect_success) { - auto recall_ret = call_command(cmd, timeout, recv_by_socket); + auto recall_ret = call_command(cmd, timeout, recv_by_socket, false /* 禁止重连避免无限递归 */); if (recall_ret) { // 重连并成功执行了 - m_inited = true; reconnect_info["what"] = "Reconnected"; callback(AsstMsg::ConnectionInfo, reconnect_info); - return recall_ret; } } @@ -475,7 +465,7 @@ std::optional asst::Controller::call_command(const std::string& cmd { "cmd", m_adb.connect }, } }, }; - m_inited = false; + try_release(); // 重连失败,释放 callback(AsstMsg::ConnectionInfo, info); } @@ -564,7 +554,7 @@ void asst::Controller::random_delay() const void asst::Controller::clear_info() noexcept { - m_inited = false; + try_release(); m_adb = decltype(m_adb)(); m_uuid.clear(); m_width = 0; @@ -578,7 +568,6 @@ void asst::Controller::clear_info() noexcept } m_server_started = false; #endif - --m_instance_count; } int asst::Controller::push_cmd(const std::string& cmd) @@ -705,7 +694,7 @@ bool asst::Controller::screencap() case AdbProperty::ScreencapMethod::UnknownYet: { using namespace std::chrono; Log.info("Try to find the fastest way to screencap"); - m_inited = false; + try_release(); // 这个地方应该是 inited() == false 的,不会 release,因为 connect 函数调用前会 clear_info auto min_cost = milliseconds(LLONG_MAX); auto start_time = high_resolution_clock::now(); @@ -713,7 +702,7 @@ bool asst::Controller::screencap() auto duration = duration_cast(high_resolution_clock::now() - start_time); if (duration < min_cost) { m_adb.screencap_method = AdbProperty::ScreencapMethod::RawByNc; - m_inited = true; + set_inited(); min_cost = duration; } Log.info("RawByNc cost", duration.count(), "ms"); @@ -728,7 +717,7 @@ bool asst::Controller::screencap() auto duration = duration_cast(high_resolution_clock::now() - start_time); if (duration < min_cost) { m_adb.screencap_method = AdbProperty::ScreencapMethod::RawWithGzip; - m_inited = true; + set_inited(); min_cost = duration; } Log.info("RawWithGzip cost", duration.count(), "ms"); @@ -743,7 +732,7 @@ bool asst::Controller::screencap() auto duration = duration_cast(high_resolution_clock::now() - start_time); if (duration < min_cost) { m_adb.screencap_method = AdbProperty::ScreencapMethod::Encode; - m_inited = true; + set_inited(); min_cost = duration; } Log.info("Encode cost", duration.count(), "ms"); @@ -753,7 +742,7 @@ bool asst::Controller::screencap() } Log.info("The fastest way is", static_cast(m_adb.screencap_method), ", cost:", min_cost.count(), "ms"); clear_lf_info(); - return m_inited; + return inited(); } break; case AdbProperty::ScreencapMethod::RawByNc: { return screencap(m_adb.screencap_raw_by_nc, decode_raw, true); @@ -793,7 +782,7 @@ bool asst::Controller::screencap(const std::string& cmd, const DecodeFunc& decod } if (decode_func(data)) [[likely]] { - if (m_adb.screencap_end_of_line == AdbProperty::ScreencapEndOfLine::UnknownYet) { + if (m_adb.screencap_end_of_line == AdbProperty::ScreencapEndOfLine::UnknownYet) [[unlikely]] { Log.info("screencap_end_of_line is LF"); m_adb.screencap_end_of_line = AdbProperty::ScreencapEndOfLine::LF; } @@ -802,31 +791,29 @@ bool asst::Controller::screencap(const std::string& cmd, const DecodeFunc& decod else { Log.info("data is not empty, but image is empty"); - if (!tried_conversion) { - Log.info("try to cvt lf"); - if (!convert_lf(data)) { // 没找到 "\r\n",data 没有变化,不必重试 - Log.error("skip retry decoding and decode failed!"); - return false; - } - - if (decode_func(data)) { - if (m_adb.screencap_end_of_line == AdbProperty::ScreencapEndOfLine::UnknownYet) { - Log.info("screencap_end_of_line is CRLF"); - } - else { - Log.info("screencap_end_of_line is changed to CRLF"); - } - m_adb.screencap_end_of_line = AdbProperty::ScreencapEndOfLine::CRLF; - return true; - } - else { - Log.error("convert lf and retry decode failed!"); - } - } - else { // 已经转换过行尾,再次转换 data 不会变化,不必重试 + if (tried_conversion) { // 已经转换过行尾,再次转换 data 不会变化,不必重试 Log.error("skip retry decoding and decode failed!"); + return false; } - return false; + + Log.info("try to cvt lf"); + if (!convert_lf(data)) { // 没找到 "\r\n",data 没有变化,不必重试 + Log.error("no `\\r\\n` found, skip retry decode"); + return false; + } + if (!decode_func(data)) { + Log.error("convert lf and retry decode failed!"); + return false; + } + + if (m_adb.screencap_end_of_line == AdbProperty::ScreencapEndOfLine::UnknownYet) { + Log.info("screencap_end_of_line is CRLF"); + } + else { + Log.info("screencap_end_of_line is changed to CRLF"); + } + m_adb.screencap_end_of_line = AdbProperty::ScreencapEndOfLine::CRLF; + return true; } } @@ -928,10 +915,8 @@ int asst::Controller::swipe(const Rect& r1, const Rect& r2, int duration, bool b int asst::Controller::swipe_without_scale(const Point& p1, const Point& p2, int duration, bool block, int extra_delay, bool extra_swipe) { - int x1 = p1.x; - int y1 = p1.y; - int x2 = p2.x; - int y2 = p2.y; + int x1 = p1.x, y1 = p1.y; + int x2 = p2.x, y2 = p2.y; // 起点不能在屏幕外,但是终点可以 if (x1 < 0 || x1 >= m_width || y1 < 0 || y1 >= m_height) { @@ -990,7 +975,7 @@ bool asst::Controller::connect(const std::string& adb_path, const std::string& a #ifdef ASST_DEBUG if (config == "DEBUG") { - m_inited = true; + set_inited(); return true; } #endif @@ -1221,9 +1206,30 @@ bool asst::Controller::connect(const std::string& adb_path, const std::string& a } // try to find the fastest way - screencap(); + if (!screencap()) { + Log.error("Cannot find a proper way to screencap!"); + return false; + } - ++m_instance_count; + return true; +} + +void asst::Controller::set_inited() noexcept +{ + if (!m_inited) { + m_inited = true; + ++m_instance_count; + } +} + +bool asst::Controller::try_release() +{ + if (m_inited) { + m_inited = false; + if (!--m_instance_count) { // 所有实例全部释放,才执行最终的 release 函数 + return release(); + } + } return true; } @@ -1275,7 +1281,7 @@ cv::Mat asst::Controller::get_image(bool raw) // 有些模拟器adb偶尔会莫名其妙截图失败,多试几次 static constexpr int MaxTryCount = 20; bool success = false; - for (int i = 0; i < MaxTryCount && m_inited; ++i) { + for (int i = 0; i < MaxTryCount && inited(); ++i) { if (need_exit()) { break; } diff --git a/src/MeoAssistant/Controller.h b/src/MeoAssistant/Controller.h index 5c777965bd..2c7d6dd832 100644 --- a/src/MeoAssistant/Controller.h +++ b/src/MeoAssistant/Controller.h @@ -35,7 +35,7 @@ namespace asst ~Controller(); bool connect(const std::string& adb_path, const std::string& address, const std::string& config); - bool release(); + bool try_release(); bool inited() const noexcept; void set_exit_flag(bool* flag); @@ -76,8 +76,10 @@ namespace asst bool need_exit() const; void pipe_working_proc(); std::optional call_command(const std::string& cmd, int64_t timeout = 20000, - bool recv_by_socket = false); + bool recv_by_socket = false, bool allow_reconnect = true); int push_cmd(const std::string& cmd); + bool release(); + void set_inited() noexcept; std::optional try_to_init_socket(const std::string& local_address); From 57eb9c39754ceac6628902f22067517566a2a0f6 Mon Sep 17 00:00:00 2001 From: zzyyyl Date: Sun, 18 Sep 2022 02:29:09 +0800 Subject: [PATCH 2/9] fix: fix typo --- src/MeoAssistant/Controller.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/MeoAssistant/Controller.cpp b/src/MeoAssistant/Controller.cpp index f63f75ac89..65eff39e56 100644 --- a/src/MeoAssistant/Controller.cpp +++ b/src/MeoAssistant/Controller.cpp @@ -440,7 +440,7 @@ std::optional asst::Controller::call_command(const std::string& cmd callback(AsstMsg::ConnectionInfo, reconnect_info); std::this_thread::sleep_for(10s); - auto reconnect_ret = call_command(m_adb.connect, 60LL * 1000, false /* 禁止重连避免无限递归 */); + auto reconnect_ret = call_command(m_adb.connect, 60LL * 1000, false, false /* 禁止重连避免无限递归 */); bool is_reconnect_success = false; if (reconnect_ret) { auto& reconnect_str = reconnect_ret.value(); From 62e3e036eb2e902af4bd79e8e215171256020d9c Mon Sep 17 00:00:00 2001 From: zzyyyl Date: Sun, 18 Sep 2022 12:26:15 +0800 Subject: [PATCH 3/9] =?UTF-8?q?feat:=20=E5=88=A0=E9=99=A4=20`screencap()`?= =?UTF-8?q?=20=E9=87=8C=E7=9A=84=20`try=5Frelease()`?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/MeoAssistant/Controller.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/MeoAssistant/Controller.cpp b/src/MeoAssistant/Controller.cpp index 65eff39e56..f782c238af 100644 --- a/src/MeoAssistant/Controller.cpp +++ b/src/MeoAssistant/Controller.cpp @@ -694,8 +694,8 @@ bool asst::Controller::screencap() case AdbProperty::ScreencapMethod::UnknownYet: { using namespace std::chrono; Log.info("Try to find the fastest way to screencap"); - try_release(); // 这个地方应该是 inited() == false 的,不会 release,因为 connect 函数调用前会 clear_info auto min_cost = milliseconds(LLONG_MAX); + clear_lf_info(); auto start_time = high_resolution_clock::now(); if (m_support_socket && m_server_started && screencap(m_adb.screencap_raw_by_nc, decode_raw, true)) { @@ -742,7 +742,7 @@ bool asst::Controller::screencap() } Log.info("The fastest way is", static_cast(m_adb.screencap_method), ", cost:", min_cost.count(), "ms"); clear_lf_info(); - return inited(); + return m_adb.screencap_method != AdbProperty::ScreencapMethod::UnknownYet; } break; case AdbProperty::ScreencapMethod::RawByNc: { return screencap(m_adb.screencap_raw_by_nc, decode_raw, true); From 9e9395f5e8c141cacd202ba91e9bea21f7373262 Mon Sep 17 00:00:00 2001 From: zzyyyl Date: Sun, 18 Sep 2022 12:57:58 +0800 Subject: [PATCH 4/9] =?UTF-8?q?feat:=20core=20=E4=B8=8D=E5=AF=B9=E8=BF=9E?= =?UTF-8?q?=E6=8E=A5=E7=9A=84=20call=5Fcommand=20=E8=BF=9B=E8=A1=8C?= =?UTF-8?q?=E9=87=8D=E8=AF=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/MeoAssistant/Controller.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/MeoAssistant/Controller.cpp b/src/MeoAssistant/Controller.cpp index f782c238af..054d311b00 100644 --- a/src/MeoAssistant/Controller.cpp +++ b/src/MeoAssistant/Controller.cpp @@ -1021,7 +1021,7 @@ bool asst::Controller::connect(const std::string& adb_path, const std::string& a /* connect */ { m_adb.connect = cmd_replace(adb_cfg.connect); - auto connect_ret = call_command(m_adb.connect, 60LL * 1000); + auto connect_ret = call_command(m_adb.connect, 60LL * 1000, false, false /* adb 连接时不允许重试 */); // 端口即使错误,命令仍然会返回0,TODO 对connect_result进行判断 bool is_connect_success = false; if (connect_ret) { @@ -1040,7 +1040,7 @@ bool asst::Controller::connect(const std::string& adb_path, const std::string& a /* get uuid (imei) */ { - auto uuid_ret = call_command(cmd_replace(adb_cfg.uuid)); + auto uuid_ret = call_command(cmd_replace(adb_cfg.uuid), 20000, false, false /* adb 连接时不允许重试 */); if (!uuid_ret) { json::value info = get_info_json() | json::object { { "what", "ConnectFailed" }, From a724e97c7817dca7b4bf9a20def53ebd64140501 Mon Sep 17 00:00:00 2001 From: zzyyyl Date: Sun, 18 Sep 2022 19:20:00 +0800 Subject: [PATCH 5/9] =?UTF-8?q?perf:=20socket=20init/close=20=E7=9A=84?= =?UTF-8?q?=E4=B8=80=E4=BA=9B=E9=80=BB=E8=BE=91=E8=B0=83=E6=95=B4?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/MeoAssistant/Controller.cpp | 32 ++++++++++++++++---------------- src/MeoAssistant/Controller.h | 5 +++-- 2 files changed, 19 insertions(+), 18 deletions(-) diff --git a/src/MeoAssistant/Controller.cpp b/src/MeoAssistant/Controller.cpp index 054d311b00..ab6f50d814 100644 --- a/src/MeoAssistant/Controller.cpp +++ b/src/MeoAssistant/Controller.cpp @@ -561,13 +561,6 @@ void asst::Controller::clear_info() noexcept m_height = 0; m_control_scale = 1.0; m_scale_size = { WindowWidthDefault, WindowHeightDefault }; -#ifdef _WIN32 - if (m_server_sock) { - ::closesocket(m_server_sock); - m_server_sock = 0U; - } - m_server_started = false; -#endif } int asst::Controller::push_cmd(const std::string& cmd) @@ -580,14 +573,27 @@ int asst::Controller::push_cmd(const std::string& cmd) return static_cast(++m_push_id); } +void asst::Controller::try_to_close_socket() noexcept +{ +#ifdef _WIN32 + if (m_server_sock != INVALID_SOCKET) { + ::closesocket(m_server_sock); + m_server_sock = INVALID_SOCKET; + } + m_server_started = false; +#endif +} + std::optional asst::Controller::try_to_init_socket(const std::string& local_address) { LogTraceFunction; #ifdef _WIN32 - m_server_sock = ::socket(PF_INET, SOCK_STREAM, IPPROTO_TCP); if (m_server_sock == INVALID_SOCKET) { - return std::nullopt; + m_server_sock = ::socket(PF_INET, SOCK_STREAM, IPPROTO_TCP); + if (m_server_sock == INVALID_SOCKET) { + return std::nullopt; + } } DWORD dummy; @@ -1235,13 +1241,7 @@ bool asst::Controller::try_release() bool asst::Controller::release() { -#ifdef _WIN32 - if (m_server_sock) { - m_server_started = false; - ::closesocket(m_server_sock); - m_server_sock = 0U; - } -#endif + try_to_close_socket(); #ifndef _WIN32 if (m_child) diff --git a/src/MeoAssistant/Controller.h b/src/MeoAssistant/Controller.h index 2c7d6dd832..90faa88727 100644 --- a/src/MeoAssistant/Controller.h +++ b/src/MeoAssistant/Controller.h @@ -81,11 +81,12 @@ namespace asst bool release(); void set_inited() noexcept; + void try_to_close_socket() noexcept; std::optional try_to_init_socket(const std::string& local_address); using DecodeFunc = std::function; bool screencap(); - bool screencap(const std::string& cmd, const DecodeFunc& decode_func, bool by_nc = false); + bool screencap(const std::string& cmd, const DecodeFunc& decode_func, bool by_socket = false); void clear_lf_info(); cv::Mat get_resized_image() const; @@ -110,7 +111,7 @@ namespace asst ASST_AUTO_DEDUCED_ZERO_INIT_START WSADATA m_wsa_data {}; - SOCKET m_server_sock = 0ULL; + SOCKET m_server_sock = INVALID_SOCKET; sockaddr_in m_server_addr {}; LPFN_ACCEPTEX m_AcceptEx = nullptr; ASST_AUTO_DEDUCED_ZERO_INIT_END From bef151660e414d4654c3256f1e97e20eb54cc093 Mon Sep 17 00:00:00 2001 From: zzyyyl Date: Sun, 18 Sep 2022 19:21:30 +0800 Subject: [PATCH 6/9] =?UTF-8?q?perf:=20set=5Finited()=20=E4=B8=8E=20try=5F?= =?UTF-8?q?release()=20=E5=90=88=E5=B9=B6?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/MeoAssistant/Controller.cpp | 38 +++++++++++++++++---------------- src/MeoAssistant/Controller.h | 3 +-- 2 files changed, 21 insertions(+), 20 deletions(-) diff --git a/src/MeoAssistant/Controller.cpp b/src/MeoAssistant/Controller.cpp index ab6f50d814..b0fc49d2a6 100644 --- a/src/MeoAssistant/Controller.cpp +++ b/src/MeoAssistant/Controller.cpp @@ -72,7 +72,7 @@ asst::Controller::~Controller() m_cmd_thread.join(); } - try_release(); + set_inited(false); #ifndef _WIN32 close(m_pipe_in[PIPE_READ]); @@ -465,7 +465,7 @@ std::optional asst::Controller::call_command(const std::string& cmd { "cmd", m_adb.connect }, } }, }; - try_release(); // 重连失败,释放 + set_inited(false); // 重连失败,释放 callback(AsstMsg::ConnectionInfo, info); } @@ -554,7 +554,7 @@ void asst::Controller::random_delay() const void asst::Controller::clear_info() noexcept { - try_release(); + set_inited(false); m_adb = decltype(m_adb)(); m_uuid.clear(); m_width = 0; @@ -708,7 +708,7 @@ bool asst::Controller::screencap() auto duration = duration_cast(high_resolution_clock::now() - start_time); if (duration < min_cost) { m_adb.screencap_method = AdbProperty::ScreencapMethod::RawByNc; - set_inited(); + set_inited(true); min_cost = duration; } Log.info("RawByNc cost", duration.count(), "ms"); @@ -723,7 +723,7 @@ bool asst::Controller::screencap() auto duration = duration_cast(high_resolution_clock::now() - start_time); if (duration < min_cost) { m_adb.screencap_method = AdbProperty::ScreencapMethod::RawWithGzip; - set_inited(); + set_inited(true); min_cost = duration; } Log.info("RawWithGzip cost", duration.count(), "ms"); @@ -738,7 +738,7 @@ bool asst::Controller::screencap() auto duration = duration_cast(high_resolution_clock::now() - start_time); if (duration < min_cost) { m_adb.screencap_method = AdbProperty::ScreencapMethod::Encode; - set_inited(); + set_inited(true); min_cost = duration; } Log.info("Encode cost", duration.count(), "ms"); @@ -981,7 +981,7 @@ bool asst::Controller::connect(const std::string& adb_path, const std::string& a #ifdef ASST_DEBUG if (config == "DEBUG") { - set_inited(); + set_inited(true); return true; } #endif @@ -1220,19 +1220,21 @@ bool asst::Controller::connect(const std::string& adb_path, const std::string& a return true; } -void asst::Controller::set_inited() noexcept +bool asst::Controller::set_inited(bool inited) { - if (!m_inited) { - m_inited = true; + Log.trace(__FUNCTION__, "|", inited, ", m_inited =", m_inited, ", m_instance_count =", m_instance_count); + + if (inited == m_inited) { + return true; + } + m_inited = inited; + + if (inited) { ++m_instance_count; } -} - -bool asst::Controller::try_release() -{ - if (m_inited) { - m_inited = false; - if (!--m_instance_count) { // 所有实例全部释放,才执行最终的 release 函数 + else { + // 所有实例全部释放,执行最终的 release 函数 + if (!--m_instance_count) { return release(); } } @@ -1251,7 +1253,7 @@ bool asst::Controller::release() return true; } else { - return call_command(m_adb.release).has_value(); + return call_command(m_adb.release, 20000, false, false).has_value(); } } } diff --git a/src/MeoAssistant/Controller.h b/src/MeoAssistant/Controller.h index 90faa88727..acfed957ee 100644 --- a/src/MeoAssistant/Controller.h +++ b/src/MeoAssistant/Controller.h @@ -35,7 +35,6 @@ namespace asst ~Controller(); bool connect(const std::string& adb_path, const std::string& address, const std::string& config); - bool try_release(); bool inited() const noexcept; void set_exit_flag(bool* flag); @@ -79,7 +78,7 @@ namespace asst bool recv_by_socket = false, bool allow_reconnect = true); int push_cmd(const std::string& cmd); bool release(); - void set_inited() noexcept; + bool set_inited(bool inited); void try_to_close_socket() noexcept; std::optional try_to_init_socket(const std::string& local_address); From c8fb6e3c3b45a6d960c4267ecc533098b4d609bd Mon Sep 17 00:00:00 2001 From: zzyyyl Date: Sun, 18 Sep 2022 19:23:07 +0800 Subject: [PATCH 7/9] =?UTF-8?q?feat:=20=E5=A2=9E=E5=8A=A0=20kill=5Fadb=5Fd?= =?UTF-8?q?aemon()=20=E4=BD=BF=E5=BE=97=E5=9C=A8=E6=B2=A1=E8=BF=9E?= =?UTF-8?q?=E4=B8=8A=E6=A8=A1=E6=8B=9F=E5=99=A8=E7=9A=84=E6=97=B6=E5=80=99?= =?UTF-8?q?=20adb=20daemon=20=E4=B9=9F=E8=83=BD=E9=80=80=E5=87=BA?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/MeoAssistant/Controller.cpp | 23 ++++++++++++++++++++++- src/MeoAssistant/Controller.h | 3 +++ 2 files changed, 25 insertions(+), 1 deletion(-) diff --git a/src/MeoAssistant/Controller.cpp b/src/MeoAssistant/Controller.cpp index b0fc49d2a6..af838d8a58 100644 --- a/src/MeoAssistant/Controller.cpp +++ b/src/MeoAssistant/Controller.cpp @@ -73,6 +73,7 @@ asst::Controller::~Controller() } set_inited(false); + kill_adb_daemon(); #ifndef _WIN32 close(m_pipe_in[PIPE_READ]); @@ -1033,6 +1034,10 @@ bool asst::Controller::connect(const std::string& adb_path, const std::string& a if (connect_ret) { auto& connect_str = connect_ret.value(); is_connect_success = connect_str.find("error") == std::string::npos; + if (connect_str.find("daemon started successfully") != std::string::npos && + connect_str.find("daemon still not running") == std::string::npos) { + m_adb_release = cmd_replace(adb_cfg.release); + } } if (!is_connect_success) { json::value info = get_info_json() | json::object { @@ -1176,7 +1181,7 @@ bool asst::Controller::connect(const std::string& adb_path, const std::string& a m_adb.swipe = cmd_replace(adb_cfg.swipe); m_adb.screencap_raw_with_gzip = cmd_replace(adb_cfg.screencap_raw_with_gzip); m_adb.screencap_encode = cmd_replace(adb_cfg.screencap_encode); - m_adb.release = cmd_replace(adb_cfg.release); + m_adb_release = m_adb.release = cmd_replace(adb_cfg.release); m_adb.start = cmd_replace(adb_cfg.start); m_adb.stop = cmd_replace(adb_cfg.stop); @@ -1241,6 +1246,22 @@ bool asst::Controller::set_inited(bool inited) return true; } +void asst::Controller::kill_adb_daemon() { + if (m_instance_count) return; +#ifndef _WIN32 + if (m_child) +#endif + { + if (!m_adb_release.empty()) { + call_command(m_adb_release, 20000, false, false); + m_adb_release.clear(); + } + else if (!m_adb.release.empty()) { + call_command(m_adb.release, 20000, false, false); + } + } +} + bool asst::Controller::release() { try_to_close_socket(); diff --git a/src/MeoAssistant/Controller.h b/src/MeoAssistant/Controller.h index acfed957ee..e53292dcdd 100644 --- a/src/MeoAssistant/Controller.h +++ b/src/MeoAssistant/Controller.h @@ -78,6 +78,7 @@ namespace asst bool recv_by_socket = false, bool allow_reconnect = true); int push_cmd(const std::string& cmd); bool release(); + void kill_adb_daemon(); bool set_inited(bool inited); void try_to_close_socket() noexcept; @@ -158,6 +159,8 @@ namespace asst } m_adb; std::string m_uuid; + inline static std::string m_adb_release; // 开了 adb daemon,但是没连上模拟器的时候, + // m_adb 并不会存下 release 的命令,但最后仍然需要一次释放。 std::pair m_scale_size = { WindowWidthDefault, WindowHeightDefault }; double m_control_scale = 1.0; int m_width = 0; From e58a3401e090afbece628e6a6368e9c87857265d Mon Sep 17 00:00:00 2001 From: zzyyyl Date: Sun, 18 Sep 2022 02:31:21 +0800 Subject: [PATCH 8/9] =?UTF-8?q?feat:=20TaskQueue=20=E7=95=8C=E9=9D=A2=20St?= =?UTF-8?q?op()=20=E4=B9=9F=E4=B8=BA=E5=BC=82=E6=AD=A5=E5=87=BD=E6=95=B0?= =?UTF-8?q?=EF=BC=8C=E5=87=8F=E5=B0=91=20connect=20=E9=98=B6=E6=AE=B5=20St?= =?UTF-8?q?op=20=E7=9A=84=E5=8D=A1=E9=A1=BF=E6=97=B6=E9=97=B4?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/MeoAssistant/Assistant.cpp | 9 ++++- src/MeoAssistant/Controller.cpp | 33 ++++++++++++++++++- src/MeoAsstGui/Helper/AsstProxy.cs | 10 ++++++ .../Resources/Localizations/en-us.xaml | 1 + .../Resources/Localizations/ja-jp.xaml | 1 + .../Resources/Localizations/ko-kr.xaml | 3 +- .../Resources/Localizations/pallas.xaml | 1 + .../Resources/Localizations/zh-cn.xaml | 1 + .../Resources/Localizations/zh-tw.xaml | 1 + .../ViewModels/TaskQueueViewModel.cs | 32 +++++++++++++++--- src/MeoAsstGui/Views/TaskQueueView.xaml | 5 +-- 11 files changed, 88 insertions(+), 9 deletions(-) diff --git a/src/MeoAssistant/Assistant.cpp b/src/MeoAssistant/Assistant.cpp index b955d40dc2..ae815cc80a 100644 --- a/src/MeoAssistant/Assistant.cpp +++ b/src/MeoAssistant/Assistant.cpp @@ -62,12 +62,19 @@ bool asst::Assistant::connect(const std::string& adb_path, const std::string& ad std::unique_lock lock(m_mutex); - stop(false); + // 仍有任务进行,connect 前需要 stop + if (!m_thread_idle) { + return false; + } + + m_thread_idle = false; bool ret = m_ctrler->connect(adb_path, address, config.empty() ? "General" : config); if (ret) { m_uuid = m_ctrler->get_uuid(); } + + m_thread_idle = true; return ret; } diff --git a/src/MeoAssistant/Controller.cpp b/src/MeoAssistant/Controller.cpp index af838d8a58..6386d98cdb 100644 --- a/src/MeoAssistant/Controller.cpp +++ b/src/MeoAssistant/Controller.cpp @@ -263,6 +263,9 @@ std::optional asst::Controller::call_command(const std::string& cmd } while (true) { + if (need_exit()) { + break; + } wait_handles.clear(); if (process_running) wait_handles.push_back(process_info.hProcess); if (!pipe_eof) wait_handles.push_back(pipeov.hEvent); @@ -272,7 +275,7 @@ std::optional asst::Controller::call_command(const std::string& cmd if (wait_handles.empty()) break; auto elapsed = steady_clock::now() - start_time; auto wait_time = - (std::min)(timeout - duration_cast(elapsed).count(), process_running ? 0xFFFFFFFELL : 0LL); + (std::min)(timeout - duration_cast(elapsed).count(), process_running ? 5LL * 1000 : 0LL); if (wait_time < 0) break; auto wait_result = WaitForMultipleObjectsEx((DWORD)wait_handles.size(), &wait_handles[0], FALSE, (DWORD)wait_time, TRUE); @@ -440,7 +443,11 @@ std::optional asst::Controller::call_command(const std::string& cmd reconnect_info["details"]["times"] = i; callback(AsstMsg::ConnectionInfo, reconnect_info); + // TODO: 应该有外部中断 sleep 的写法吧?现在只能在开始或者结束 sleep 的时候判断( std::this_thread::sleep_for(10s); + if (need_exit()) { + break; + } auto reconnect_ret = call_command(m_adb.connect, 60LL * 1000, false, false /* 禁止重连避免无限递归 */); bool is_reconnect_success = false; if (reconnect_ret) { @@ -1025,6 +1032,10 @@ bool asst::Controller::connect(const std::string& adb_path, const std::string& a }); }; + if (need_exit()) { + return false; + } + /* connect */ { m_adb.connect = cmd_replace(adb_cfg.connect); @@ -1049,6 +1060,10 @@ bool asst::Controller::connect(const std::string& adb_path, const std::string& a } } + if (need_exit()) { + return false; + } + /* get uuid (imei) */ { auto uuid_ret = call_command(cmd_replace(adb_cfg.uuid), 20000, false, false /* adb 连接时不允许重试 */); @@ -1073,6 +1088,10 @@ bool asst::Controller::connect(const std::string& adb_path, const std::string& a callback(AsstMsg::ConnectionInfo, info); } + if (need_exit()) { + return false; + } + // 按需获取display ID 信息 if (!adb_cfg.display_id.empty()) { auto display_id_ret = call_command(cmd_replace(adb_cfg.display_id)); @@ -1092,6 +1111,10 @@ bool asst::Controller::connect(const std::string& adb_path, const std::string& a display_id.pop_back(); } + if (need_exit()) { + return false; + } + /* display */ { auto display_ret = call_command(cmd_replace(adb_cfg.display)); @@ -1150,6 +1173,10 @@ bool asst::Controller::connect(const std::string& adb_path, const std::string& a } } + if (need_exit()) { + return false; + } + /* calc ratio */ { constexpr double DefaultRatio = @@ -1205,6 +1232,10 @@ bool asst::Controller::connect(const std::string& adb_path, const std::string& a } } + if (need_exit()) { + return false; + } + auto socket_opt = try_to_init_socket(bind_address); if (socket_opt) { nc_port = socket_opt.value(); diff --git a/src/MeoAsstGui/Helper/AsstProxy.cs b/src/MeoAsstGui/Helper/AsstProxy.cs index 0992a3f14f..5083b78195 100644 --- a/src/MeoAsstGui/Helper/AsstProxy.cs +++ b/src/MeoAsstGui/Helper/AsstProxy.cs @@ -371,6 +371,11 @@ namespace MeoAsstGui case "Disconnect": connected = false; mainModel.AddLog(Localization.GetString("ReconnectFailed"), LogColor.Error); + if (mainModel.Idle) + { + break; + } + AsstStop(); var settingsModel = _container.Get(); @@ -1002,6 +1007,11 @@ namespace MeoAsstGui { foreach (var address in settings.DefaultAddress[settings.ConnectConfig]) { + if (settings.Idle) + { + break; + } + ret = AsstConnect(_handle, settings.AdbPath, address, settings.ConnectConfig); if (ret) { diff --git a/src/MeoAsstGui/Resources/Localizations/en-us.xaml b/src/MeoAsstGui/Resources/Localizations/en-us.xaml index 9584f61ea4..d6310825df 100644 --- a/src/MeoAsstGui/Resources/Localizations/en-us.xaml +++ b/src/MeoAsstGui/Resources/Localizations/en-us.xaml @@ -235,6 +235,7 @@ Connecting to emulator... Unselected task Running... + Stopping... Has stopped Unknown error occurred Set successfully diff --git a/src/MeoAsstGui/Resources/Localizations/ja-jp.xaml b/src/MeoAsstGui/Resources/Localizations/ja-jp.xaml index e9a070783a..49c367854a 100644 --- a/src/MeoAsstGui/Resources/Localizations/ja-jp.xaml +++ b/src/MeoAsstGui/Resources/Localizations/ja-jp.xaml @@ -235,6 +235,7 @@ エミュレータ接続中…… タスクが選択されていません 動作中…… + 動作停止中…… 動作停止 不明なエラーが発生しました 設定に成功しました diff --git a/src/MeoAsstGui/Resources/Localizations/ko-kr.xaml b/src/MeoAsstGui/Resources/Localizations/ko-kr.xaml index e3b0fe7604..6e981f1f4b 100644 --- a/src/MeoAsstGui/Resources/Localizations/ko-kr.xaml +++ b/src/MeoAsstGui/Resources/Localizations/ko-kr.xaml @@ -234,7 +234,8 @@ 에뮬레이터에 연결중... 선택된 작업이 없다 실행중... - 정지됐다 + 멎는... + 멈췄다 예상치 못한 오류가 발생했습니다 설정 성공 설정 실패 diff --git a/src/MeoAsstGui/Resources/Localizations/pallas.xaml b/src/MeoAsstGui/Resources/Localizations/pallas.xaml index 3e9bfae033..6c6ec740b9 100644 --- a/src/MeoAsstGui/Resources/Localizations/pallas.xaml +++ b/src/MeoAsstGui/Resources/Localizations/pallas.xaml @@ -234,6 +234,7 @@ 🍸🕺🍻💃🕺 🍺🍸🍻 🍷🍻🍷🍺 + 🍷💃🍸 💃🍺 🕺🍸🍻🍷 🍸🍸🍺 diff --git a/src/MeoAsstGui/Resources/Localizations/zh-cn.xaml b/src/MeoAsstGui/Resources/Localizations/zh-cn.xaml index fa94880da8..8a5dcf2f30 100644 --- a/src/MeoAsstGui/Resources/Localizations/zh-cn.xaml +++ b/src/MeoAsstGui/Resources/Localizations/zh-cn.xaml @@ -235,6 +235,7 @@ 正在连接模拟器…… 未选择任务 正在运行中…… + 正在停止…… 已停止 出现未知错误 设置成功 diff --git a/src/MeoAsstGui/Resources/Localizations/zh-tw.xaml b/src/MeoAsstGui/Resources/Localizations/zh-tw.xaml index c117d6b0b6..5f12971ca1 100644 --- a/src/MeoAsstGui/Resources/Localizations/zh-tw.xaml +++ b/src/MeoAsstGui/Resources/Localizations/zh-tw.xaml @@ -235,6 +235,7 @@ 正在連接模擬器…… 未選擇任務 正在運行中…… + 正在停止…… 已停止 出現未知錯誤 設定成功 diff --git a/src/MeoAsstGui/ViewModels/TaskQueueViewModel.cs b/src/MeoAsstGui/ViewModels/TaskQueueViewModel.cs index 02076f282c..38b2cb4256 100644 --- a/src/MeoAsstGui/ViewModels/TaskQueueViewModel.cs +++ b/src/MeoAsstGui/ViewModels/TaskQueueViewModel.cs @@ -624,6 +624,13 @@ namespace MeoAsstGui return asstProxy.AsstConnect(ref errMsg, true); }); bool caught = await task; + + // 一般是点了“停止”按钮了 + if (Idle) + { + return; + } + if (!caught) { AddLog(errMsg, LogColor.Error); @@ -732,12 +739,18 @@ namespace MeoAsstGui /// /// Stops. /// - public void Stop() + public async void Stop() { - var asstProxy = _container.Get(); - asstProxy.AsstStop(); + Idle = true; // 提前将 Idle 置为 true + Stopping = true; + AddLog(Localization.GetString("Stopping")); + var task = Task.Run(() => + { + return _container.Get().AsstStop(); + }); + await task; AddLog(Localization.GetString("Stopped")); - Idle = true; + Stopping = false; } private bool appendStart() @@ -1254,6 +1267,17 @@ namespace MeoAsstGui } } + private bool _stopping = false; + + /// + /// Gets or sets a value indicating whether `stop` is awaiting. + /// + public bool Stopping + { + get => _stopping; + set => SetAndNotify(ref _stopping, value); + } + private bool _fightTaskRunning = false; /// diff --git a/src/MeoAsstGui/Views/TaskQueueView.xaml b/src/MeoAsstGui/Views/TaskQueueView.xaml index 7a82531ac8..6ff2b590ff 100644 --- a/src/MeoAsstGui/Views/TaskQueueView.xaml +++ b/src/MeoAsstGui/Views/TaskQueueView.xaml @@ -140,14 +140,15 @@ Command="{s:Action LinkStart}" Content="{DynamicResource LinkStart}" IsEnabled="{Binding Inited}" - Visibility="{c:Binding Path='Idle or !Inited'}" /> + Visibility="{c:Binding Path='(Idle and !Stopping) or !Inited'}" />