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
9387void 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-
14292std::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-
213119bool 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
272247MAA_TOOLKIT_NS_END
0 commit comments