feat.增加了adb炸了之后的重连机制及错误回调

This commit is contained in:
MistEO
2022-06-07 23:55:59 +08:00
parent 1b0890ad43
commit 422a2bb2af
4 changed files with 78 additions and 8 deletions

View File

@@ -81,6 +81,10 @@ Todo
分辨率不被支持
- `ResolutionError`
分辨率获取错误
- `Disconnect`
连接断开adb / 模拟器 炸了,且已经重试过一次)
- `CommandExecFailed`
命令执行失败adb / 模拟器 炸了,且已经重试过一次)
#### AllTasksCompleted

View File

@@ -248,8 +248,6 @@ std::optional<std::vector<unsigned char>> asst::Controller::call_command(const s
std::vector<uchar> pipe_data;
std::unique_lock<std::mutex> pipe_lock(m_pipe_mutex);
auto start_time = std::chrono::steady_clock::now();
auto check_timeout = [&]() -> bool {
return timeout &&
@@ -268,6 +266,7 @@ std::optional<std::vector<unsigned char>> asst::Controller::call_command(const s
if (!recv_by_socket) {
DWORD peek_num = 0;
DWORD read_num = 0;
std::unique_lock<std::mutex> pipe_lock(m_pipe_mutex);
do {
//DWORD write_num = 0;
//WriteFile(parent_write, cmd.c_str(), cmd.size(), &write_num, nullptr);
@@ -279,6 +278,7 @@ std::optional<std::vector<unsigned char>> asst::Controller::call_command(const s
} while (::WaitForSingleObject(process_info.hProcess, 0) == WAIT_TIMEOUT && !check_timeout());
}
else {
std::unique_lock<std::mutex> pipe_lock(m_pipe_mutex);
fd_set fdset = { 0 };
FD_SET(m_server_sock, &fdset);
timeval select_timeout = { 3, 0 };
@@ -327,6 +327,7 @@ std::optional<std::vector<unsigned char>> asst::Controller::call_command(const s
else if (m_child > 0) {
// parent process
// LogTraceScope("Parent process: " + cmd);
std::unique_lock<std::mutex> pipe_lock(m_pipe_mutex);
do {
ssize_t read_num = read(m_pipe_out[PIPE_READ], m_pipe_buffer.get(), PipeBuffSize);
@@ -350,9 +351,48 @@ std::optional<std::vector<unsigned char>> asst::Controller::call_command(const s
if (!exit_ret) {
return pipe_data;
}
else {
return std::nullopt;
else if (m_inited) {
// 之前可以运行,突然运行不了了,这种情况多半是 adb 炸了。所以重新连接一下
m_inited = false;
auto reconnect_ret = call_command(m_adb.connect, 60 * 1000);
bool is_reconnect_success = false;
if (reconnect_ret) {
auto& reconnect_val = reconnect_ret.value();
std::string reconnect_str(
std::make_move_iterator(reconnect_val.begin()),
std::make_move_iterator(reconnect_val.end()));
is_reconnect_success = reconnect_str.find("error") == std::string::npos;
}
if (is_reconnect_success) {
auto recall_ret = call_command(cmd, timeout, recv_by_socket);
if (recall_ret) {
m_inited = true;
return recall_ret;
}
else {
json::value info = json::object{
{ "uuid", m_uuid},
{ "what", "CommandExecFailed" },
{ "why", "I dont fucking know, go look at the log!" },
{ "details", json::object {
{ "cmd", cmd },
{ "recv_by_socket", recv_by_socket}
}} };
m_callback(AsstMsg::ConnectionInfo, info, m_callback_arg);
}
}
else {
json::value info = json::object{
{ "uuid", m_uuid},
{ "what", "Disconnect" },
{ "why", "Reconnect failed" },
{ "details", json::object {
{ "cmd", m_adb.connect }
}} };
m_callback(AsstMsg::ConnectionInfo, info, m_callback_arg);
}
}
return std::nullopt;
}
void asst::Controller::convert_lf(std::vector<unsigned char>& data)
@@ -433,6 +473,7 @@ void asst::Controller::random_delay() const
void asst::Controller::clear_info() noexcept
{
m_inited = false;
m_adb = decltype(m_adb)();
m_uuid.clear();
m_width = 0;
@@ -590,16 +631,19 @@ bool asst::Controller::screencap()
screencap(m_adb.screencap_raw_by_nc, decode_raw, true)) {
m_adb.screencap_method = AdbProperty::ScreencapMethod::RawByNc;
Log.info("screencap by RawByNc");
m_inited = true;
return true;
}
else if (screencap(m_adb.screencap_raw_with_gzip, decode_raw_with_gzip)) {
m_adb.screencap_method = AdbProperty::ScreencapMethod::RawWithGzip;
Log.info("screencap by RawWithGzip");
m_inited = true;
return true;
}
else if (screencap(m_adb.screencap_encode, decode_encode)) {
m_adb.screencap_method = AdbProperty::ScreencapMethod::Encode;
Log.info("screencap by Encode");
m_inited = true;
return true;
}
else {
@@ -864,9 +908,18 @@ bool asst::Controller::connect(const std::string& adb_path, const std::string& a
/* connect */
{
auto connect_ret = call_command(cmd_replace(adb_cfg.connect), 60 * 1000);
m_adb.connect = cmd_replace(adb_cfg.connect);
auto connect_ret = call_command(m_adb.connect, 60 * 1000);
// 端口即使错误命令仍然会返回0TODO 对connect_result进行判断
if (!connect_ret) {
bool is_connect_success = false;
if (connect_ret) {
auto& connect_val = connect_ret.value();
std::string connect_str(
std::make_move_iterator(connect_val.begin()),
std::make_move_iterator(connect_val.end()));
is_connect_success = connect_str.find("error") == std::string::npos;
}
if (!is_connect_success) {
json::value info = get_info_json() |
json::object{
{ "what", "ConnectFailed" },
@@ -1085,11 +1138,16 @@ const std::string& asst::Controller::get_uuid() const
cv::Mat asst::Controller::get_image(bool raw)
{
bool inited = m_inited;
// 有些模拟器adb偶尔会莫名其妙截图失败多试几次
for (int i = 0; i != 20; ++i) {
if (screencap()) {
break;
}
// 截图之前正常,截图之后不正常了,说明截图过程中发现 adb 炸了
if (inited && !m_inited) {
break;
}
}
if (raw) {

View File

@@ -114,6 +114,7 @@ namespace asst
struct AdbProperty
{
/* command */
std::string connect;
std::string click;
std::string swipe;
@@ -150,6 +151,7 @@ namespace asst
int m_height = 0;
bool m_support_socket = false;
bool m_server_started = false;
bool m_inited = false;
inline static int m_instance_count = 0;

View File

@@ -170,11 +170,17 @@ namespace MeoAsstGui
break;
case "UnsupportedResolution":
mainModel.AddLog("分辨率过低\n请设置为 720p 或更高", "darkred");
mainModel.AddLog("分辨率过低请设置为 720p 或更高", "darkred");
break;
case "ResolutionError":
mainModel.AddLog("分辨率获取失败\n建议重启电脑\n或更换模拟器后再试", "darkred");
mainModel.AddLog("分辨率获取失败建议重启电脑或更换模拟器后再试", "darkred");
break;
case "Disconnect":
case "CommandExecFailed":
mainModel.AddLog("错误!连接断开!", "darkred");
AsstStop();
break;
}
}