diff --git a/qrenderdoc/Code/Interface/PersistantConfig.cpp b/qrenderdoc/Code/Interface/PersistantConfig.cpp index 7ded03c40..3923080fd 100644 --- a/qrenderdoc/Code/Interface/PersistantConfig.cpp +++ b/qrenderdoc/Code/Interface/PersistantConfig.cpp @@ -197,14 +197,12 @@ void PersistantConfig::AddAndroidHosts() { RemoteHost *host = NULL; - QString fullHostname = lit("adb:") + hostName; - - if(oldHosts.contains(fullHostname)) - host = oldHosts.take(fullHostname); + if(oldHosts.contains(hostName)) + host = oldHosts.take(hostName); else host = new RemoteHost(); - host->Hostname = fullHostname; + host->Hostname = hostName; rdctype::str friendly; RENDERDOC_GetAndroidFriendlyName(hostName.toUtf8().data(), friendly); host->FriendlyName = ToQStr(friendly); diff --git a/qrenderdoc/Code/Interface/RemoteHost.cpp b/qrenderdoc/Code/Interface/RemoteHost.cpp index 367ed036f..255216ee8 100644 --- a/qrenderdoc/Code/Interface/RemoteHost.cpp +++ b/qrenderdoc/Code/Interface/RemoteHost.cpp @@ -109,7 +109,7 @@ void RemoteHost::Launch() if(IsHostADB()) { - RENDERDOC_StartAndroidRemoteServer(); + RENDERDOC_StartAndroidRemoteServer(Hostname.toUtf8().data()); QThread::msleep(WAIT_TIME); return; } diff --git a/qrenderdoc/Windows/MainWindow.cpp b/qrenderdoc/Windows/MainWindow.cpp index 8795d81a8..2edb20cf9 100644 --- a/qrenderdoc/Windows/MainWindow.cpp +++ b/qrenderdoc/Windows/MainWindow.cpp @@ -1523,11 +1523,6 @@ void MainWindow::on_action_Manage_Remote_Servers_triggered() rm->closeWhenFinished(); } -void MainWindow::on_action_Start_Android_Remote_Server_triggered() -{ - RENDERDOC_StartAndroidRemoteServer(); -} - void MainWindow::on_action_Settings_triggered() { SettingsDialog about(m_Ctx, this); diff --git a/qrenderdoc/Windows/MainWindow.h b/qrenderdoc/Windows/MainWindow.h index 4181ec283..7061776f0 100644 --- a/qrenderdoc/Windows/MainWindow.h +++ b/qrenderdoc/Windows/MainWindow.h @@ -113,7 +113,6 @@ private slots: void on_action_Resolve_Symbols_triggered(); void on_action_Attach_to_Running_Instance_triggered(); void on_action_Manage_Remote_Servers_triggered(); - void on_action_Start_Android_Remote_Server_triggered(); void on_action_Settings_triggered(); void on_action_View_Documentation_triggered(); void on_action_View_Diagnostic_Log_File_triggered(); diff --git a/qrenderdoc/Windows/MainWindow.ui b/qrenderdoc/Windows/MainWindow.ui index 2fe3b6af5..527003872 100644 --- a/qrenderdoc/Windows/MainWindow.ui +++ b/qrenderdoc/Windows/MainWindow.ui @@ -53,8 +53,6 @@ - - @@ -390,11 +388,6 @@ Statisti&cs Viewer - - - Start &Android Remote Server - - Show Tips diff --git a/renderdoc/api/replay/renderdoc_replay.h b/renderdoc/api/replay/renderdoc_replay.h index d4e3d8d97..c2e047db1 100644 --- a/renderdoc/api/replay/renderdoc_replay.h +++ b/renderdoc/api/replay/renderdoc_replay.h @@ -1434,4 +1434,4 @@ DOCUMENT("Internal function for enumerating android devices."); extern "C" RENDERDOC_API void RENDERDOC_CC RENDERDOC_EnumerateAndroidDevices(rdctype::str *deviceList); DOCUMENT("Internal function for starting an android remote server."); -extern "C" RENDERDOC_API void RENDERDOC_CC RENDERDOC_StartAndroidRemoteServer(); +extern "C" RENDERDOC_API void RENDERDOC_CC RENDERDOC_StartAndroidRemoteServer(const char *device); diff --git a/renderdoc/core/remote_server.cpp b/renderdoc/core/remote_server.cpp index d8b731e8e..ca82b3444 100644 --- a/renderdoc/core/remote_server.cpp +++ b/renderdoc/core/remote_server.cpp @@ -829,7 +829,11 @@ public: if(Android::IsHostADB(m_hostname.c_str())) { - string adbStdout = Android::adbExecCommand("shell pm list packages -3"); + int index = 0; + std::string deviceID; + Android::extractDeviceIDAndIndex(m_hostname, index, deviceID); + + string adbStdout = Android::adbExecCommand(deviceID, "shell pm list packages -3"); using namespace std; istringstream stdoutStream(adbStdout); string line; @@ -1223,10 +1227,14 @@ RENDERDOC_CreateRemoteServerConnection(const char *host, uint32_t port, IRemoteS { s = "127.0.0.1"; - if(port == RENDERDOC_GetDefaultRemoteServerPort()) - port += RenderDoc_AndroidPortOffset; + int index = 0; + std::string deviceID; + Android::extractDeviceIDAndIndex(host, index, deviceID); - // could parse out an (optional) device name from host+4 here. + // each subsequent device gets a new range of ports. The deviceID isn't needed since we already + // forwarded the ports to the right devices. + if(port == RENDERDOC_GetDefaultRemoteServerPort()) + port += RenderDoc_AndroidPortOffset * (index + 1); } Network::Socket *sock = NULL; diff --git a/renderdoc/core/target_control.cpp b/renderdoc/core/target_control.cpp index d3053fe4c..c31c8c5bd 100644 --- a/renderdoc/core/target_control.cpp +++ b/renderdoc/core/target_control.cpp @@ -735,7 +735,8 @@ extern "C" RENDERDOC_API ITargetControl *RENDERDOC_CC RENDERDOC_CreateTargetCont android = true; s = "127.0.0.1"; - // could parse out an (optional) device name from host+4 here. + // we don't need the index or device ID here, because the port is already the right one + // forwarded to the right device. } Network::Socket *sock = Network::CreateClientSocket(s.c_str(), ident & 0xffff, 750); diff --git a/renderdoc/os/os_specific.h b/renderdoc/os/os_specific.h index 7dc5e983e..3f27a566c 100644 --- a/renderdoc/os/os_specific.h +++ b/renderdoc/os/os_specific.h @@ -411,5 +411,6 @@ namespace Android { bool IsHostADB(const char *hostname); uint32_t StartAndroidPackageForCapture(const char *host, const char *package); -string adbExecCommand(const string &args); +string adbExecCommand(const string &deviceID, const string &args); +void extractDeviceIDAndIndex(const string &hostname, int &index, string &deviceID); } diff --git a/renderdoc/replay/entry_points.cpp b/renderdoc/replay/entry_points.cpp index b13a7d400..f449a35db 100644 --- a/renderdoc/replay/entry_points.cpp +++ b/renderdoc/replay/entry_points.cpp @@ -448,13 +448,17 @@ extern "C" RENDERDOC_API uint32_t RENDERDOC_CC RENDERDOC_EnumerateRemoteTargets( uint32_t lastIdent = RenderDoc_LastTargetControlPort; if(host != NULL && Android::IsHostADB(host)) { + int index = 0; + std::string deviceID; + Android::extractDeviceIDAndIndex(host, index, deviceID); + + // each subsequent device gets a new range of ports. The deviceID isn't needed since we already + // forwarded the ports to the right devices. if(nextIdent == RenderDoc_FirstTargetControlPort) - nextIdent += RenderDoc_AndroidPortOffset; - lastIdent += RenderDoc_AndroidPortOffset; + nextIdent += RenderDoc_AndroidPortOffset * (index + 1); + lastIdent += RenderDoc_AndroidPortOffset * (index + 1); s = "127.0.0.1"; - - // could parse out an (optional) device name from host+4 here. } for(; nextIdent <= lastIdent; nextIdent++) @@ -547,7 +551,29 @@ bool IsHostADB(const char *hostname) { return !strncmp(hostname, "adb:", 4); } -string adbExecCommand(const string &args) +void extractDeviceIDAndIndex(const string &hostname, int &index, string &deviceID) +{ + if(!IsHostADB(hostname.c_str())) + return; + + const char *c = hostname.c_str(); + c += 4; + + index = atoi(c); + + c = strchr(c, ':'); + + if(!c) + { + index = 0; + return; + } + + c++; + + deviceID = c; +} +string adbExecCommand(const string &device, const string &args) { string adbExePath = RenderDoc::Inst().GetConfigSetting("adbExePath"); if(adbExePath.empty()) @@ -561,36 +587,53 @@ string adbExecCommand(const string &args) adbExePath.append("adb"); } Process::ProcessResult result; - Process::LaunchProcess(adbExePath.c_str(), "", args.c_str(), &result); + string deviceArgs; + if(device.empty()) + deviceArgs = args; + else + deviceArgs = StringFormat::Fmt("-s %s %s", device.c_str(), args.c_str()); + Process::LaunchProcess(adbExePath.c_str(), "", deviceArgs.c_str(), &result); RDCLOG("COMMAND: adb %s", args.c_str()); if(result.strStdout.length()) // This could be an error (i.e. no package), or just regular output from adb devices. RDCLOG("STDOUT:\n%s", result.strStdout.c_str()); return result.strStdout; } -void adbForwardPorts() +string adbGetDeviceList() { - adbExecCommand(StringFormat::Fmt("forward tcp:%i tcp:%i", - RenderDoc_RemoteServerPort + RenderDoc_AndroidPortOffset, + return adbExecCommand("", "devices"); +} +void adbForwardPorts(int index, const std::string &deviceID) +{ + int offs = RenderDoc_AndroidPortOffset * (index + 1); + adbExecCommand(deviceID, + StringFormat::Fmt("forward tcp:%i tcp:%i", RenderDoc_RemoteServerPort + offs, RenderDoc_RemoteServerPort)); - adbExecCommand(StringFormat::Fmt("forward tcp:%i tcp:%i", - RenderDoc_FirstTargetControlPort + RenderDoc_AndroidPortOffset, + adbExecCommand(deviceID, + StringFormat::Fmt("forward tcp:%i tcp:%i", RenderDoc_FirstTargetControlPort + offs, RenderDoc_FirstTargetControlPort)); } uint32_t StartAndroidPackageForCapture(const char *host, const char *package) { + int index = 0; + std::string deviceID; + Android::extractDeviceIDAndIndex(host, index, deviceID); + string packageName = basename(string(package)); // Remove leading '/' if any - adbExecCommand("shell am force-stop " + packageName); - adbForwardPorts(); - adbExecCommand("shell setprop debug.vulkan.layers VK_LAYER_RENDERDOC_Capture"); - adbExecCommand("shell pm grant " + packageName + - " android.permission.WRITE_EXTERNAL_STORAGE"); // Creating the capture file - adbExecCommand("shell pm grant " + packageName + - " android.permission.READ_EXTERNAL_STORAGE"); // Reading the capture thumbnail - adbExecCommand("shell monkey -p " + packageName + " -c android.intent.category.LAUNCHER 1"); + adbExecCommand(deviceID, "shell am force-stop " + packageName); + adbForwardPorts(index, deviceID); + adbExecCommand(deviceID, "shell setprop debug.vulkan.layers VK_LAYER_RENDERDOC_Capture"); + // Creating the capture file + adbExecCommand(deviceID, + "shell pm grant " + packageName + " android.permission.WRITE_EXTERNAL_STORAGE"); + // Reading the capture thumbnail + adbExecCommand(deviceID, + "shell pm grant " + packageName + " android.permission.READ_EXTERNAL_STORAGE"); + adbExecCommand(deviceID, + "shell monkey -p " + packageName + " -c android.intent.category.LAUNCHER 1"); - uint32_t ret = RenderDoc_FirstTargetControlPort + RenderDoc_AndroidPortOffset; + uint32_t ret = RenderDoc_FirstTargetControlPort + RenderDoc_AndroidPortOffset * (index + 1); uint32_t elapsed = 0, timeout = 1000 * RDCMAX(5, atoi(RenderDoc::Inst().GetConfigSetting("MaxConnectTimeout").c_str())); @@ -609,7 +652,7 @@ uint32_t StartAndroidPackageForCapture(const char *host, const char *package) } // Let the app pickup the setprop before we turn it back off for replaying. - adbExecCommand("shell setprop debug.vulkan.layers :"); + adbExecCommand(deviceID, "shell setprop debug.vulkan.layers :"); return ret; } @@ -619,13 +662,24 @@ using namespace Android; extern "C" RENDERDOC_API void RENDERDOC_CC RENDERDOC_GetAndroidFriendlyName(const rdctype::str &device, rdctype::str &friendly) { - string manuf = adbExecCommand( - StringFormat::Fmt("-s %s shell getprop ro.product.manufacturer", device.c_str())); - string model = - adbExecCommand(StringFormat::Fmt("-s %s shell getprop ro.product.model", device.c_str())); + if(!IsHostADB(device.c_str())) + { + RDCERR("Calling RENDERDOC_GetAndroidFriendlyName with non-android device: %s", device.c_str()); + return; + } - manuf = trim(manuf); - model = trim(model); + int index = 0; + std::string deviceID; + Android::extractDeviceIDAndIndex(device.c_str(), index, deviceID); + + if(deviceID.empty()) + { + RDCERR("Failed to get android device and index from: %s", device.c_str()); + return; + } + + string manuf = trim(adbExecCommand(deviceID, "shell getprop ro.product.manufacturer")); + string model = trim(adbExecCommand(deviceID, "shell getprop ro.product.model")); std::string combined; @@ -646,7 +700,9 @@ extern "C" RENDERDOC_API void RENDERDOC_CC RENDERDOC_GetAndroidFriendlyName(cons extern "C" RENDERDOC_API void RENDERDOC_CC RENDERDOC_EnumerateAndroidDevices(rdctype::str *deviceList) { - string adbStdout = adbExecCommand("devices"); + string adbStdout = adbGetDeviceList(); + + int idx = 0; using namespace std; istringstream stdoutStream(adbStdout); @@ -660,23 +716,33 @@ extern "C" RENDERDOC_API void RENDERDOC_CC RENDERDOC_EnumerateAndroidDevices(rdc { if(ret.length()) ret += ","; - ret += tokens[0]; + + ret += StringFormat::Fmt("adb:%d:%s", idx, tokens[0].c_str()); + + // Forward the ports so we can see if a remoteserver/captured app is already running. + adbForwardPorts(idx, tokens[0]); + + idx++; } } - if(ret.size()) - adbForwardPorts(); // Forward the ports so we can see if a remoteserver/captured app is - // already running. - *deviceList = ret; } -extern "C" RENDERDOC_API void RENDERDOC_CC RENDERDOC_StartAndroidRemoteServer() +extern "C" RENDERDOC_API void RENDERDOC_CC RENDERDOC_StartAndroidRemoteServer(const char *device) { - adbExecCommand("shell am force-stop org.renderdoc.renderdoccmd"); - adbForwardPorts(); - adbExecCommand("shell setprop debug.vulkan.layers :"); + int index = 0; + std::string deviceID; + + // legacy code - delete when C# UI is gone. Handle a NULL or empty device string + if(device || device[0] == '\0') + Android::extractDeviceIDAndIndex(device, index, deviceID); + + adbExecCommand(deviceID, "shell am force-stop org.renderdoc.renderdoccmd"); + adbForwardPorts(index, deviceID); + adbExecCommand(deviceID, "shell setprop debug.vulkan.layers :"); adbExecCommand( + deviceID, "shell am start -n org.renderdoc.renderdoccmd/.Loader -e renderdoccmd remoteserver"); } diff --git a/renderdocui/Code/PersistantConfig.cs b/renderdocui/Code/PersistantConfig.cs index 302d99523..263d9705d 100644 --- a/renderdocui/Code/PersistantConfig.cs +++ b/renderdocui/Code/PersistantConfig.cs @@ -425,7 +425,7 @@ namespace renderdocui.Code foreach(string hostName in androidHosts) { RemoteHost host = new RemoteHost(); - host.Hostname = "adb:" + hostName; + host.Hostname = hostName; RemoteHosts.Add(host); } } diff --git a/renderdocui/Interop/StaticExports.cs b/renderdocui/Interop/StaticExports.cs index 4e237c586..02282c287 100644 --- a/renderdocui/Interop/StaticExports.cs +++ b/renderdocui/Interop/StaticExports.cs @@ -114,7 +114,7 @@ namespace renderdoc private static extern ReplaySupport RENDERDOC_EnumerateAndroidDevices(IntPtr driverName); [DllImport("renderdoc.dll", CharSet = CharSet.Unicode, CallingConvention = CallingConvention.Cdecl)] - private static extern ReplaySupport RENDERDOC_StartAndroidRemoteServer(); + private static extern ReplaySupport RENDERDOC_StartAndroidRemoteServer(IntPtr device); [DllImport("renderdoc.dll", CharSet = CharSet.Unicode, CallingConvention = CallingConvention.Cdecl)] private static extern void RENDERDOC_StartSelfHostCapture(IntPtr dllname); @@ -410,9 +410,13 @@ namespace renderdoc return driverList.Split(new char[]{','}, StringSplitOptions.RemoveEmptyEntries); } - public static void StartAndroidRemoteServer() + public static void StartAndroidRemoteServer(string device) { - RENDERDOC_StartAndroidRemoteServer(); + IntPtr device_mem = CustomMarshal.MakeUTF8String(device); + + RENDERDOC_StartAndroidRemoteServer(device_mem); + + CustomMarshal.Free(device_mem); } } } diff --git a/renderdocui/Windows/MainWindow.cs b/renderdocui/Windows/MainWindow.cs index 37f5c9781..1f4699dc6 100644 --- a/renderdocui/Windows/MainWindow.cs +++ b/renderdocui/Windows/MainWindow.cs @@ -74,6 +74,8 @@ namespace renderdocui.Windows private List m_LiveCaptures = new List(); + private RemoteHost m_SelectedHost = null; + private string InformationalVersion { get @@ -1203,7 +1205,9 @@ namespace renderdocui.Windows { ToolStripItem item = sender as ToolStripItem; - if(item == null) + m_SelectedHost = null; + + if (item == null) return; RemoteHost host = item.Tag as RemoteHost; @@ -1264,6 +1268,8 @@ namespace renderdocui.Windows statusText.Text = "Checking remote server status..."; + m_SelectedHost = host; + Thread th = Helpers.NewThread(new ThreadStart(() => { // see if the server is up @@ -2022,7 +2028,10 @@ namespace renderdocui.Windows private void startAndroidRemoteServerToolStripMenuItem_Click(object sender, EventArgs e) { - StaticExports.StartAndroidRemoteServer(); + string device = ""; + if (m_SelectedHost != null) + device = m_SelectedHost.Hostname; + StaticExports.StartAndroidRemoteServer(device); } } }