Introduction
If you have been debugging some Android apps on an HTC phone, you have probably noticed the annoying message that is shown when you try to debug a phone over USB on a computer running HTC Sync:
adb server is out of date. killing...
* daemon started successfully *
The message is usually accompanied by 3-5 seconds of waiting time and can appear several times before you manage to start debugging. The worst thing is that sometimes it does not manage to restart the daemon and aborts the launching after 10-20 seconds of waiting with a message like that:
adb server is out of date. killing...
* daemon started successfully *
** daemon still not runningerror: cannot connect to daemon
Although the problem seems almost random, there is a simple explanation to it and a clean way of fixing it.
The ADB Server
ADB stands for Android Debug Bridge. It is a tool that is used by Android environment to do a variety of tasks: list connected devices, transfer files between them, establish TCP/IP connections… The last feature is directly used by the HTC Sync application to communicate with the phone over USB.
Let’s now see what exactly happens when you connect your phone and try to debug it.
- HTC Sync (more specifically, htcUPCTLoader.exe continuously running in the background) detects that you have connected a device and tries to forward a TCP/IP port to it. To do so, it runs the adb.exe from its own folder and tells it to start mapping the port. The adb.exe keeps on running in the background providing the port map for HTC Sync.
- When you start debugging with the Android SDK, it does several minor jobs (e.g. lists devices, deploys your App, etc) each involving a call to its own adb.exe. When this happens, the newer adb.exe detects that the older adb.exe from HTC Sync is running and terminates it, then it runs its own instance.
- The HTC Sync running in the background detects that the port mapping has been broken and tries to restart it. What happens then? Right, adb.exe from Android SDK gets kicked off. If this happens before the adb.exe from SDK manages to complete, you get an error message and your debugging fails.
The Solution
First of all, we need to find the old instance of adb.exe that interferes with Android SDK. This can be done by opening Task Manager, finding adb.exe there and selecting “Properties”. Do not forget to connect your phone to USB before doing that.
A trivial solution then would be to delete/rename the adb.exe used by HTC Sync. However, this would break HTC Sync.
Another one is to kill or suspend htcUPCTLoader.exe for the time you are debugging your app. This will prevent it from interfering with the adb.exe from the Android SDK.
Finally, you can make a simple stub that reads the location of the real ADB.exe from the Registry and runs it with the original command line:
#include "stdafx.h"
#include <bzscore/Win32/registry.h>
using namespace BazisLib;
int _tmain(int argc, _TCHAR* argv[])
{
wchar_t *p = GetCommandLineW();
if (p[0] == '\"')
p = wcschr(p+1,'\"');
else
p = wcschr(p, ' ');
if (!p)
p = L"";
else
p+=2;
wchar_t *pwsz = new wchar_t[512 + wcslen(p)];
String ADBPath = RegistryKey(HKEY_CURRENT_USER,
L"SOFTWARE\\Sysprogs\\ADBFix", 0, false)[L"SDKPath"];
if (ADBPath.empty())
ADBPath = L"adb_noadbfix.exe";
else
ADBPath += L"\\platform-tools\\adb.exe";
swprintf(pwsz, L"\"%s\" %s", ADBPath.c_str(), p);
STARTUPINFO info = {sizeof(info), };
PROCESS_INFORMATION PI;
CreateProcess(0, pwsz, 0, 0, 0, 0, 0, 0, &info, &PI);
WaitForSingleObject(PI.hProcess, INFINITE);
DWORD exitCode = -1;
GetExitCodeProcess(PI.hProcess, &exitCode);
return exitCode;
}
You can rename the adb.exe in the HTC Sync directory to adb_noadbfix.exe and put the stub instead of the original file.