diff --git a/src/MaaCore/Controller/AdbController.cpp b/src/MaaCore/Controller/AdbController.cpp index 6e3745ee14..dba7e5b259 100644 --- a/src/MaaCore/Controller/AdbController.cpp +++ b/src/MaaCore/Controller/AdbController.cpp @@ -915,6 +915,7 @@ bool asst::AdbController::connect(const std::string& adb_path, const std::string // 设置配置 connect、release 命令,即使这里不连接,后续也会需要用到 m_adb.connect = m_conn_ctx.replace_cmd(adb_cfg.connect); m_adb.release = m_conn_ctx.replace_cmd(adb_cfg.release); + m_platform_io->set_adb_serial(address); if (need_connect) { // 如果不包含 `:` 且需要连接,connect 命令也不会成功 if (address.find(':') == std::string::npos) { diff --git a/src/MaaCore/Controller/Platform/AdbLiteIO.cpp b/src/MaaCore/Controller/Platform/AdbLiteIO.cpp index fe7e89ca07..08eaa6959d 100644 --- a/src/MaaCore/Controller/Platform/AdbLiteIO.cpp +++ b/src/MaaCore/Controller/Platform/AdbLiteIO.cpp @@ -62,8 +62,15 @@ std::optional asst::AdbLiteIO::call_command( // adb connect if (boost::regex_match(cmd, match, connect_regex)) { + const std::string serial = match[1].str(); + auto lock = lock_adb_client(serial); + if (!lock) { + ret = std::nullopt; + goto ret_exit; + } + try { - pipe_data = get_adb_client(match[1].str())->connect(); + pipe_data = m_adb_client->connect(); ret = 0; goto ret_exit; } @@ -77,11 +84,18 @@ std::optional asst::AdbLiteIO::call_command( // adb shell if (boost::regex_match(cmd, match, shell_regex)) { + const std::string serial = match[1].str(); std::string command = match[2].str(); remove_quotes(command); + auto lock = lock_adb_client(serial); + if (!lock) { + ret = std::nullopt; + goto ret_exit; + } + try { - pipe_data = get_adb_client(match[1].str())->shell(command); + pipe_data = m_adb_client->shell(command); ret = 0; goto ret_exit; } @@ -94,11 +108,18 @@ std::optional asst::AdbLiteIO::call_command( // adb exec-out if (boost::regex_match(cmd, match, exec_regex)) { + const std::string serial = match[1].str(); std::string command = match[2].str(); remove_quotes(command); + auto lock = lock_adb_client(serial); + if (!lock) { + ret = std::nullopt; + goto ret_exit; + } + try { - pipe_data = get_adb_client(match[1].str())->exec(command); + pipe_data = m_adb_client->exec(command); ret = 0; goto ret_exit; } @@ -111,8 +132,15 @@ std::optional asst::AdbLiteIO::call_command( // adb push if (boost::regex_match(cmd, match, push_regex)) { + const std::string serial = match[1].str(); + auto lock = lock_adb_client(serial); + if (!lock) { + ret = std::nullopt; + goto ret_exit; + } + try { - get_adb_client(match[1].str())->push(match[2].str(), match[3].str(), 0644); + m_adb_client->push(match[2].str(), match[3].str(), 0644); ret = 0; goto ret_exit; } @@ -135,17 +163,35 @@ ret_exit: return ret; } -std::shared_ptr asst::AdbLiteIO::get_adb_client(std::string_view serial) +std::optional> asst::AdbLiteIO::lock_adb_client(std::string_view serial) +{ + std::unique_lock lock(m_adb_client_mutex); + if (!m_adb_client || m_adb_serial != serial) { + Log.error("adb client not initialized for serial:", std::string(serial), "current:", m_adb_serial); + return std::nullopt; + } + + return std::move(lock); +} + +void asst::AdbLiteIO::set_adb_serial(std::string_view serial) { std::lock_guard lock(m_adb_client_mutex); const std::string serial_str(serial); - if (!m_adb_client || m_adb_serial != serial_str) { + if (m_adb_client && m_adb_serial == serial_str) { + return; + } + + try { auto adb_client = adb::client::create(serial_str); m_adb_serial = serial_str; m_adb_client = std::move(adb_client); } - - return m_adb_client; + catch (const std::exception& e) { + Log.error("failed to create adb-lite client for serial:", serial_str, e.what()); + m_adb_serial.clear(); + m_adb_client.reset(); + } } std::shared_ptr asst::AdbLiteIO::interactive_shell(const std::string& cmd) @@ -154,11 +200,17 @@ std::shared_ptr asst::AdbLiteIO::interactive_shell(const std::s boost::smatch match; if (boost::regex_match(cmd, match, shell_regex)) { + const std::string serial = match[1].str(); std::string command = match[2].str(); remove_quotes(command); + auto lock = lock_adb_client(serial); + if (!lock) { + return nullptr; + } + try { - return std::make_shared(get_adb_client(match[1].str())->interactive_shell(command)); + return std::make_shared(m_adb_client->interactive_shell(command)); } catch (const std::exception& e) { Log.error("adb shell failed:", e.what()); @@ -173,18 +225,19 @@ std::shared_ptr asst::AdbLiteIO::interactive_shell(const std::s void asst::AdbLiteIO::release_adb(const std::string& adb_release, int64_t timeout) { - // 只在读取 m_adb_client 时持锁,避免 call_command 内部调用 get_adb_client 时死锁 + bool has_adb_client = false; { std::lock_guard lock(m_adb_client_mutex); - if (!m_adb_client) { - return; - } + has_adb_client = static_cast(m_adb_client); } - std::string pipe_data; - std::string sock_data; - auto start_time = std::chrono::steady_clock::now(); - call_command(adb_release, false, pipe_data, sock_data, timeout, start_time); + if (has_adb_client) { + std::string pipe_data; + std::string sock_data; + auto start_time = std::chrono::steady_clock::now(); + + call_command(adb_release, false, pipe_data, sock_data, timeout, start_time); + } } bool asst::AdbLiteIO::remove_quotes(std::string& data) diff --git a/src/MaaCore/Controller/Platform/AdbLiteIO.h b/src/MaaCore/Controller/Platform/AdbLiteIO.h index 1c6d2c3979..7da811d87a 100644 --- a/src/MaaCore/Controller/Platform/AdbLiteIO.h +++ b/src/MaaCore/Controller/Platform/AdbLiteIO.h @@ -13,6 +13,7 @@ #include "Utils/Logger.hpp" #include +#include #include #include @@ -42,15 +43,17 @@ public: virtual std::shared_ptr interactive_shell(const std::string& cmd) override; + virtual void set_adb_serial(std::string_view serial) override; + virtual void release_adb(const std::string& adb_release, int64_t timeout = 20000) override; private: - std::shared_ptr get_adb_client(std::string_view serial); + std::optional> lock_adb_client(std::string_view serial); static bool remove_quotes(std::string& data); // 保护 m_adb_client / m_adb_serial,防止 call_command 与 interactive_shell 并发访问 - mutable std::mutex m_adb_client_mutex; + std::mutex m_adb_client_mutex; std::shared_ptr m_adb_client = nullptr; std::string m_adb_serial; }; diff --git a/src/MaaCore/Controller/Platform/PlatformIO.h b/src/MaaCore/Controller/Platform/PlatformIO.h index f0f67c4476..112bfd18b5 100644 --- a/src/MaaCore/Controller/Platform/PlatformIO.h +++ b/src/MaaCore/Controller/Platform/PlatformIO.h @@ -4,6 +4,7 @@ #include #include #include +#include namespace asst { @@ -33,6 +34,8 @@ public: virtual std::shared_ptr interactive_shell(const std::string& cmd) = 0; + virtual void set_adb_serial(std::string_view) {} + virtual void release_adb(const std::string& adb_release, int64_t timeout = 20000) = 0; bool m_support_socket = false;