Support remote-android with multiple connected devices.
Summary:
This change introduces a new URL scheme for `platform connect`:
```
adb://device-id:port
```
Reviewers: vharron, tberghammer, clayborg, ovyalov
Reviewed By: ovyalov
Subscribers: tberghammer, lldb-commits
Differential Revision: http://reviews.llvm.org/D9358
llvm-svn: 236321
diff --git a/lldb/source/Plugins/Platform/Android/AdbClient.cpp b/lldb/source/Plugins/Platform/Android/AdbClient.cpp
index 36f8eadc..8c45616 100644
--- a/lldb/source/Plugins/Platform/Android/AdbClient.cpp
+++ b/lldb/source/Plugins/Platform/Android/AdbClient.cpp
@@ -31,27 +31,28 @@
} // namespace
Error
-AdbClient::CreateByDeviceID (const char* device_id, AdbClient &adb)
+AdbClient::CreateByDeviceID(const std::string &device_id, AdbClient &adb)
{
DeviceIDList connect_devices;
- auto error = adb.GetDevices (connect_devices);
- if (error.Fail ())
+ auto error = adb.GetDevices(connect_devices);
+ if (error.Fail())
return error;
- if (device_id)
+ if (device_id.empty())
{
- auto find_it = std::find(connect_devices.begin (), connect_devices.end (), device_id);
- if (find_it == connect_devices.end ())
- return Error ("Device \"%s\" not found", device_id);
+ if (connect_devices.size() != 1)
+ return Error("Expected a single connected device, got instead %" PRIu64,
+ static_cast<uint64_t>(connect_devices.size()));
- adb.SetDeviceID (*find_it);
+ adb.SetDeviceID(connect_devices.front());
}
else
{
- if (connect_devices.size () != 1)
- return Error ("Expected a single connected device, got instead %" PRIu64, static_cast<uint64_t>(connect_devices.size ()));
+ auto find_it = std::find(connect_devices.begin(), connect_devices.end(), device_id);
+ if (find_it == connect_devices.end())
+ return Error("Device \"%s\" not found", device_id.c_str());
- adb.SetDeviceID (connect_devices.front ());
+ adb.SetDeviceID(*find_it);
}
return error;
}
diff --git a/lldb/source/Plugins/Platform/Android/AdbClient.h b/lldb/source/Plugins/Platform/Android/AdbClient.h
index 3dcc006..235fc56 100644
--- a/lldb/source/Plugins/Platform/Android/AdbClient.h
+++ b/lldb/source/Plugins/Platform/Android/AdbClient.h
@@ -32,7 +32,7 @@
using DeviceIDList = std::list<std::string>;
static Error
- CreateByDeviceID (const char* device_id, AdbClient &adb);
+ CreateByDeviceID(const std::string &device_id, AdbClient &adb);
AdbClient () = default;
explicit AdbClient (const std::string &device_id);
diff --git a/lldb/source/Plugins/Platform/Android/PlatformAndroid.cpp b/lldb/source/Plugins/Platform/Android/PlatformAndroid.cpp
index 7bc3287..3bd628b 100644
--- a/lldb/source/Plugins/Platform/Android/PlatformAndroid.cpp
+++ b/lldb/source/Plugins/Platform/Android/PlatformAndroid.cpp
@@ -13,6 +13,7 @@
#include "lldb/Core/Log.h"
#include "lldb/Core/PluginManager.h"
#include "lldb/Host/HostInfo.h"
+#include "Utility/UriParser.h"
// Project includes
#include "AdbClient.h"
@@ -171,9 +172,9 @@
}
Error
-PlatformAndroid::ConnectRemote (Args& args)
+PlatformAndroid::ConnectRemote(Args& args)
{
- m_device_id.clear ();
+ m_device_id.clear();
if (IsHost())
{
@@ -183,17 +184,25 @@
if (!m_remote_platform_sp)
m_remote_platform_sp = PlatformSP(new PlatformAndroidRemoteGDBServer());
- auto error = PlatformLinux::ConnectRemote (args);
- if (error.Success ())
+ int port;
+ std::string scheme, host, path;
+ const char *url = args.GetArgumentAtIndex(0);
+ if (!url)
+ return Error("URL is null.");
+ if (!UriParser::Parse(url, scheme, host, port, path))
+ return Error("Invalid URL: %s", url);
+ if (scheme == "adb")
+ m_device_id = host;
+
+ auto error = PlatformLinux::ConnectRemote(args);
+ if (error.Success())
{
- // Fetch the device list from ADB and if only 1 device found then use that device
- // TODO: Handle the case when more device is available
AdbClient adb;
- error = AdbClient::CreateByDeviceID (nullptr, adb);
- if (error.Fail ())
+ error = AdbClient::CreateByDeviceID(m_device_id, adb);
+ if (error.Fail())
return error;
- m_device_id = adb.GetDeviceID ();
+ m_device_id = adb.GetDeviceID();
}
return error;
}
diff --git a/lldb/source/Plugins/Platform/Android/PlatformAndroidRemoteGDBServer.cpp b/lldb/source/Plugins/Platform/Android/PlatformAndroidRemoteGDBServer.cpp
index 2cb487a..213c3b2 100644
--- a/lldb/source/Plugins/Platform/Android/PlatformAndroidRemoteGDBServer.cpp
+++ b/lldb/source/Plugins/Platform/Android/PlatformAndroidRemoteGDBServer.cpp
@@ -27,18 +27,16 @@
{
Log *log(GetLogIfAllCategoriesSet (LIBLLDB_LOG_PLATFORM));
- // Fetch the device list from ADB and if only 1 device found then use that device
- // TODO: Handle the case when more device is available
AdbClient adb;
- auto error = AdbClient::CreateByDeviceID (nullptr, adb);
+ auto error = AdbClient::CreateByDeviceID(device_id, adb);
if (error.Fail ())
return error;
- device_id = adb.GetDeviceID ();
+ device_id = adb.GetDeviceID();
if (log)
log->Printf("Connected to Android device \"%s\"", device_id.c_str ());
- return adb.SetPortForwarding (port);
+ return adb.SetPortForwarding(port);
}
static Error
@@ -55,9 +53,7 @@
PlatformAndroidRemoteGDBServer::~PlatformAndroidRemoteGDBServer ()
{
for (const auto& it : m_port_forwards)
- {
- DeleteForwardPortWithAdb (it.second.first, it.second.second);
- }
+ DeleteForwardPortWithAdb(it.second, m_device_id);
}
uint16_t
@@ -67,12 +63,11 @@
if (port == 0)
return port;
- std::string device_id;
- Error error = ForwardPortWithAdb (port, device_id);
+ Error error = ForwardPortWithAdb(port, m_device_id);
if (error.Fail ())
return 0;
- m_port_forwards[pid] = std::make_pair (port, device_id);
+ m_port_forwards[pid] = port;
return port;
}
@@ -87,23 +82,28 @@
Error
PlatformAndroidRemoteGDBServer::ConnectRemote (Args& args)
{
- if (args.GetArgumentCount () != 1)
- return Error ("\"platform connect\" takes a single argument: <connect-url>");
-
+ m_device_id.clear();
+
+ if (args.GetArgumentCount() != 1)
+ return Error("\"platform connect\" takes a single argument: <connect-url>");
+
int port;
std::string scheme, host, path;
const char *url = args.GetArgumentAtIndex (0);
+ if (!url)
+ return Error("URL is null.");
if (!UriParser::Parse (url, scheme, host, port, path))
- return Error ("invalid uri");
+ return Error("Invalid URL: %s", url);
+ if (scheme == "adb")
+ m_device_id = host;
- std::string device_id;
- Error error = ForwardPortWithAdb (port, device_id);
- if (error.Fail ())
+ Error error = ForwardPortWithAdb(port, m_device_id);
+ if (error.Fail())
return error;
- m_port_forwards[g_remote_platform_pid] = std::make_pair (port, device_id);
+ m_port_forwards[g_remote_platform_pid] = port;
- error = PlatformRemoteGDBServer::ConnectRemote (args);
+ error = PlatformRemoteGDBServer::ConnectRemote(args);
if (error.Fail ())
DeleteForwardPort (g_remote_platform_pid);
@@ -120,18 +120,18 @@
void
PlatformAndroidRemoteGDBServer::DeleteForwardPort (lldb::pid_t pid)
{
- Log *log(GetLogIfAllCategoriesSet (LIBLLDB_LOG_PLATFORM));
+ Log *log(GetLogIfAllCategoriesSet(LIBLLDB_LOG_PLATFORM));
- auto it = m_port_forwards.find (pid);
- if (it == m_port_forwards.end ())
+ auto it = m_port_forwards.find(pid);
+ if (it == m_port_forwards.end())
return;
- const auto& forward_val = it->second;
- const auto error = DeleteForwardPortWithAdb (forward_val.first, forward_val.second);
- if (error.Fail ()) {
+ const auto port = it->second;
+ const auto error = DeleteForwardPortWithAdb(port, m_device_id);
+ if (error.Fail()) {
if (log)
- log->Printf ("Failed to delete port forwarding (pid=%" PRIu64 ", port=%d, device=%s): %s",
- pid, forward_val.first, forward_val.second.c_str (), error.AsCString ());
+ log->Printf("Failed to delete port forwarding (pid=%" PRIu64 ", port=%d, device=%s): %s",
+ pid, port, m_device_id.c_str(), error.AsCString());
}
- m_port_forwards.erase (it);
+ m_port_forwards.erase(it);
}
diff --git a/lldb/source/Plugins/Platform/Android/PlatformAndroidRemoteGDBServer.h b/lldb/source/Plugins/Platform/Android/PlatformAndroidRemoteGDBServer.h
index 1959bb8..e549435 100644
--- a/lldb/source/Plugins/Platform/Android/PlatformAndroidRemoteGDBServer.h
+++ b/lldb/source/Plugins/Platform/Android/PlatformAndroidRemoteGDBServer.h
@@ -37,7 +37,8 @@
DisconnectRemote () override;
protected:
- std::map<lldb::pid_t, std::pair<uint16_t, std::string>> m_port_forwards;
+ std::string m_device_id;
+ std::map<lldb::pid_t, uint16_t> m_port_forwards;
uint16_t
LaunchGDBserverAndGetPort (lldb::pid_t &pid) override;