Skip to content

Commit 0bbbb0f

Browse files
ABA2396MistEO
andauthored
fix: controller auto detect (#925)
Co-authored-by: MistEO <[email protected]>
1 parent cb0facd commit 0bbbb0f

File tree

7 files changed

+284
-276
lines changed

7 files changed

+284
-276
lines changed

source/MaaAdbControlUnit/General/DeviceInfo.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -37,7 +37,7 @@ std::optional<std::string> DeviceInfo::request_uuid()
3737
}
3838

3939
auto& uuid_str = output_opt.value();
40-
std::erase_if(uuid_str, [](char c) { return !std::isdigit(c) && !std::isalpha(c); });
40+
std::erase_if(uuid_str, [](unsigned char c) { return !std::isdigit(c) && !std::isalpha(c); });
4141

4242
return uuid_str;
4343
}

source/MaaAdbControlUnit/Invoke/InvokeApp.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -95,7 +95,7 @@ std::optional<int> InvokeApp::sdk()
9595
std::string& ret = *output_opt;
9696
string_trim_(ret);
9797

98-
if (!std::ranges::all_of(ret, [](char c) { return std::isdigit(c); })) {
98+
if (!std::ranges::all_of(ret, [](unsigned char c) { return std::isdigit(c); })) {
9999
return std::nullopt;
100100
}
101101
return std::stoi(ret);

source/MaaPiCli/CLI/interactor.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -43,7 +43,7 @@ std::vector<int> input_multi_impl(size_t size, std::string_view prompt)
4343
continue;
4444
}
4545

46-
if (!std::ranges::all_of(buffer, [](char c) { return std::isdigit(c) || std::isspace(c); })) {
46+
if (!std::ranges::all_of(buffer, [](unsigned char c) { return std::isdigit(c) || std::isspace(c); })) {
4747
fail();
4848
continue;
4949
}

source/MaaToolkit/AdbDevice/AdbDeviceFinder.cpp

Lines changed: 118 additions & 143 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@
22

33
#include <filesystem>
44
#include <ranges>
5+
#include <unordered_set>
56

67
#include "ControlUnit/ControlUnitAPI.h"
78
#include "LibraryHolder/ControlUnit.h"
@@ -15,32 +16,42 @@ std::vector<AdbDevice> AdbDeviceFinder::find() const
1516
LogFunc;
1617

1718
std::vector<AdbDevice> result;
19+
std::unordered_set<std::string> accurate_serials;
1820

1921
auto all_emulators = find_emulators();
2022
for (const Emulator& e : all_emulators) {
21-
std::filesystem::path adb_path = get_adb_path(e.const_data, e.process.pid);
22-
std::vector<std::string> serials = find_adb_serials(adb_path, e);
23-
24-
for (const std::string& ser : serials) {
25-
AdbDevice device;
26-
device.name = e.name;
27-
device.adb_path = adb_path;
28-
device.serial = ser;
29-
device.screencap_methods = MaaAdbScreencapMethod_Default;
30-
device.input_methods = MaaAdbInputMethod_Default;
31-
device.config = {};
23+
auto res = find_by_emulator_tool(e);
24+
bool found = !res.empty();
25+
for (auto& dev : res) {
26+
accurate_serials.emplace(dev.serial);
27+
result.emplace_back(std::move(dev));
28+
}
29+
if (found) {
30+
continue;
31+
}
3232

33-
request_device_config(e, device);
33+
if (e.adb_path.empty() || !std::filesystem::exists(e.adb_path)) {
34+
LogWarn << "adb_path is empty or does not exist" << VAR(e.adb_path);
35+
continue;
36+
}
3437

35-
result.emplace_back(std::move(device));
38+
res = find_specified(e.adb_path);
39+
for (auto& dev : res) {
40+
if (accurate_serials.count(dev.serial)) {
41+
continue;
42+
}
43+
result.emplace_back(std::move(dev));
3644
}
3745
}
3846

39-
auto env_adb = boost::process::search_path("adb");
40-
41-
if (std::filesystem::exists(env_adb)) {
42-
auto env_adb_devices = find_specified(env_adb);
43-
result.insert(result.end(), std::make_move_iterator(env_adb_devices.begin()), std::make_move_iterator(env_adb_devices.end()));
47+
if (auto env_adb = boost::process::search_path("adb"); std::filesystem::exists(env_adb)) {
48+
auto res = find_specified(env_adb);
49+
for (auto& dev : res) {
50+
if (accurate_serials.count(dev.serial)) {
51+
continue;
52+
}
53+
result.emplace_back(std::move(dev));
54+
}
4455
}
4556

4657
LogInfo << VAR(result);
@@ -56,89 +67,28 @@ std::vector<AdbDevice> AdbDeviceFinder::find_specified(const std::filesystem::pa
5667
auto serials = find_serials_by_adb_command(adb_path);
5768

5869
for (const std::string& ser : serials) {
59-
AdbDevice device;
60-
device.name = path_to_utf8_string(adb_path);
61-
device.adb_path = adb_path;
62-
device.serial = ser;
63-
device.screencap_methods = MaaAdbScreencapMethod_Default;
64-
device.input_methods = MaaAdbInputMethod_Default;
65-
device.config = {};
66-
67-
request_device_config({}, device);
68-
69-
result.emplace_back(std::move(device));
70+
auto res_opt = try_device(adb_path, ser);
71+
if (!res_opt) {
72+
continue;
73+
}
74+
result.emplace_back(std::move(*res_opt));
7075
}
7176

7277
LogInfo << VAR(result);
7378
return result;
7479
}
7580

76-
std::vector<std::string> AdbDeviceFinder::find_adb_serials(const std::filesystem::path& adb_path, const Emulator& emulator) const
81+
std::vector<AdbDevice> AdbDeviceFinder::find_by_emulator_tool(const Emulator& emulator) const
7782
{
78-
auto serials = emulator.const_data.adb_common_serials;
79-
80-
auto requested = find_serials_by_adb_command(adb_path);
81-
82-
serials.insert(serials.end(), std::make_move_iterator(requested.begin()), std::make_move_iterator(requested.end()));
83-
84-
// Deduplication
85-
std::sort(serials.begin(), serials.end());
86-
serials.erase(std::unique(serials.begin(), serials.end()), serials.end());
87-
88-
serials = check_available_adb_serials(adb_path, serials);
89-
90-
return serials;
83+
std::ignore = emulator;
84+
return {};
9185
}
9286

9387
void AdbDeviceFinder::set_emulator_const_data(std::unordered_map<std::string, EmulatorConstantData> data)
9488
{
9589
const_data_ = std::move(data);
9690
}
9791

98-
std::vector<AdbDeviceFinder::Emulator> AdbDeviceFinder::find_emulators() const
99-
{
100-
std::vector<Emulator> result;
101-
102-
auto all_processes = list_processes();
103-
for (const auto& process : all_processes) {
104-
auto find_it = std::ranges::find_if(const_data_, [&process](const auto& pair) -> bool {
105-
return process.name.find(pair.second.keyword) != std::string::npos;
106-
});
107-
if (find_it == const_data_.cend()) {
108-
continue;
109-
}
110-
111-
Emulator emulator {
112-
.name = find_it->first,
113-
.process = process,
114-
.const_data = find_it->second,
115-
};
116-
result.emplace_back(std::move(emulator));
117-
}
118-
119-
LogInfo << VAR(result);
120-
121-
return result;
122-
}
123-
124-
std::filesystem::path AdbDeviceFinder::get_adb_path(const EmulatorConstantData& emulator, os_pid pid) const
125-
{
126-
auto path_opt = get_process_path(pid);
127-
if (!path_opt) {
128-
return {};
129-
}
130-
auto dir = path_opt->parent_path();
131-
132-
for (const auto& adb_rel_path : emulator.adb_candidate_paths) {
133-
auto adb_path = dir / adb_rel_path;
134-
if (!std::filesystem::exists(adb_path)) {
135-
continue;
136-
}
137-
return std::filesystem::canonical(adb_path);
138-
}
139-
return {};
140-
}
141-
14292
std::vector<std::string> AdbDeviceFinder::find_serials_by_adb_command(const std::filesystem::path& adb_path) const
14393
{
14494
LogFunc << VAR(adb_path);
@@ -166,50 +116,6 @@ std::vector<std::string> AdbDeviceFinder::find_serials_by_adb_command(const std:
166116
return devices;
167117
}
168118

169-
bool AdbDeviceFinder::request_adb_connect(const std::filesystem::path& adb_path, const std::string& serial) const
170-
{
171-
LogFunc << VAR(adb_path) << VAR(serial);
172-
173-
std::string str_adb = path_to_utf8_string(adb_path);
174-
std::string str_serial = serial;
175-
176-
auto control_unit = AdbControlUnitLibraryHolder::create_control_unit(
177-
str_adb.c_str(),
178-
str_serial.c_str(),
179-
MaaAdbScreencapMethod_None,
180-
MaaAdbInputMethod_None,
181-
"{}",
182-
"");
183-
184-
if (!control_unit) {
185-
LogError << "Failed to create control unit";
186-
return false;
187-
}
188-
189-
auto connected = control_unit->connect();
190-
191-
if (!connected) {
192-
return false;
193-
}
194-
195-
return true;
196-
}
197-
198-
std::vector<std::string>
199-
AdbDeviceFinder::check_available_adb_serials(const std::filesystem::path& adb_path, const std::vector<std::string>& serials) const
200-
{
201-
LogFunc;
202-
203-
std::vector<std::string> available;
204-
for (const std::string& ser : serials) {
205-
if (!request_adb_connect(adb_path, ser)) {
206-
continue;
207-
}
208-
available.emplace_back(ser);
209-
}
210-
return available;
211-
}
212-
213119
bool request_waydroid_config(std::shared_ptr<MAA_CTRL_UNIT_NS::AdbControlUnitAPI> control_unit, AdbDevice& device)
214120
{
215121
if (!control_unit) {
@@ -234,39 +140,108 @@ bool request_waydroid_config(std::shared_ptr<MAA_CTRL_UNIT_NS::AdbControlUnitAPI
234140
"{ADB}", "-s", "{ADB_SERIAL}", "shell", "am start -n {INTENT} --windowingMode 4",
235141
};
236142

237-
LogInfo << "waydroid" << VAR(device.adb_path) << VAR(device.serial) << VAR(device.config);
143+
LogInfo << "waydroid" << VAR(device);
238144
return true;
239145
}
240146

241-
void AdbDeviceFinder::request_device_config(const Emulator& emulator, AdbDevice& device) const
147+
std::optional<AdbDevice> AdbDeviceFinder::try_device(const std::filesystem::path& adb_path, const std::string& serial) const
242148
{
243-
std::ignore = emulator;
244-
245-
LogFunc << VAR(device.adb_path) << VAR(device.serial);
149+
LogFunc << VAR(adb_path) << VAR(serial);
246150

247-
std::string str_adb = path_to_utf8_string(device.adb_path);
248-
std::string str_serial = device.serial;
151+
std::string str_adb = path_to_utf8_string(adb_path);
249152

250153
auto control_unit = AdbControlUnitLibraryHolder::create_control_unit(
251154
str_adb.c_str(),
252-
str_serial.c_str(),
155+
serial.c_str(),
253156
MaaAdbScreencapMethod_None,
254157
MaaAdbInputMethod_None,
255158
"{}",
256159
"");
257160

258161
if (!control_unit) {
259162
LogError << "Failed to create control unit";
260-
return;
163+
return std::nullopt;
261164
}
262165
if (!control_unit->connect()) {
263-
LogError << "Failed to connect";
264-
return;
166+
LogError << "Failed to connect" << VAR(serial);
167+
return std::nullopt;
265168
}
266169

170+
AdbDevice device;
171+
device.name = std::format("{} {}", path_to_utf8_string(adb_path), serial);
172+
device.adb_path = adb_path;
173+
device.serial = serial;
174+
device.screencap_methods = MaaAdbScreencapMethod_Default;
175+
device.input_methods = MaaAdbInputMethod_Default;
176+
device.config = {};
177+
267178
if (request_waydroid_config(control_unit, device)) {
268-
return;
269179
}
180+
// else if (request_xxx_config(control_unit, device)) {
181+
// }
182+
else {
183+
}
184+
185+
return device;
186+
}
187+
188+
std::vector<AdbDeviceFinder::Emulator> AdbDeviceFinder::find_emulators() const
189+
{
190+
LogFunc;
191+
192+
std::vector<Emulator> result;
193+
std::unordered_set<std::filesystem::path> seen_process_paths;
194+
195+
auto all_processes = list_processes();
196+
for (const auto& process : all_processes) {
197+
auto find_it = std::ranges::find_if(const_data_, [&process](const auto& pair) -> bool {
198+
return process.name.find(pair.second.keyword) != std::string::npos;
199+
});
200+
if (find_it == const_data_.cend()) {
201+
continue;
202+
}
203+
204+
auto process_path = get_process_path(process.pid);
205+
if (!process_path) {
206+
continue;
207+
}
208+
209+
// Deduplicate by process_path to distinguish multiple instances or installations
210+
if (!seen_process_paths.insert(*process_path).second) {
211+
continue;
212+
}
213+
214+
auto adb_path = get_emulator_adb_path(find_it->second, process.pid);
215+
216+
Emulator emulator {
217+
.name = find_it->first,
218+
.process_path = *process_path,
219+
.adb_path = adb_path,
220+
};
221+
result.emplace_back(std::move(emulator));
222+
}
223+
224+
LogInfo << VAR(result);
225+
226+
return result;
227+
}
228+
229+
std::filesystem::path AdbDeviceFinder::get_emulator_adb_path(const EmulatorConstantData& emulator, os_pid pid) const
230+
{
231+
auto path_opt = get_process_path(pid);
232+
if (!path_opt) {
233+
return {};
234+
}
235+
auto dir = path_opt->parent_path();
236+
237+
for (const auto& adb_rel_path : emulator.adb_candidate_paths) {
238+
auto adb_path = dir / adb_rel_path;
239+
if (!std::filesystem::exists(adb_path)) {
240+
continue;
241+
}
242+
return std::filesystem::canonical(adb_path);
243+
}
244+
return {};
270245
}
271246

272247
MAA_TOOLKIT_NS_END

0 commit comments

Comments
 (0)