Code Painters The Art of Coding

23Jan/100

Android’s HTTPS implementation slow under debugger

Update: I've just discovered that the problem described below only affects Android 1.5 (which is the target platform for my project). Thus another solution is to use AVD configured with Android 1.6 or higher for debugging, and use version 1.5 otherwise to ensure compatibility.

The project I'm working on now communicates with server via custom protocol on top of HTTP and HTTPS (using org.apache.http.client.HttpClient as a HTTP/HTTPS implementation provider). Recently I've observed interesting problem of HTTPS requests taking ages to complete if application is executing under debugger control. It makes debugging the code quite frustrating.

To investigate the problem let's use the following code snippet:

		HttpResponse response = null;
		HttpClient httpClient = new DefaultHttpClient();
		HttpContext localContext = new BasicHttpContext();

		Log.d("-----", "1. Sending http request");
		try {
			response = httpClient.execute(new HttpGet("http://www.apache-ssl.org/"), localContext);
		} catch (Exception e) {
			Log.d("-----", "Request failed", e);
		}
		Log.d("-----", "2. Request finished, status = " + response.getStatusLine().getStatusCode());

		Log.d("-----", "3. Sending https request");
		try {
			response = httpClient.execute(new HttpGet("https://www.apache-ssl.org/"), localContext);
		} catch (Exception e) {
			Log.d("-----", "Request failed", e);
		}
		Log.d("-----", "4. Request finished, status = " + response.getStatusLine().getStatusCode());

This code snippet has been executed on Android emulator (I've no device at hand at the moment to try it), platform version 1.5, running on Windows Vista. To make results more dependable the code has been executed five times and average times have been calculated. Sure, it's not a serious benchmark of any kind, but we only want to have a rough idea what's going on, right?

A bit of log post-processing reveals the following average times:

  • HTTP, no debugger: 0.80s
  • HTTPS, no debugger: 3.32s
  • HTTP, with debugger: 3.15s
  • HTTPS, with debugger: 142.16s

HTTPS request takes ~45 times longer to complete compared to HTTP, with debugger attached. Without debugger the factor is ~4, which is acceptable.

For the time being I have no explanation for such a big difference. Looking at the stack trace of the thread paused while performing the HTTPS request shows a lot of classes from Bouncy Castle project, as well as classes from org.apache.harmony.xnet.provider.jsse package - JNI interface to OpenSSL library. Some profiling would be necessary...

In case of my application (which always connects to the same, HTTPS-only server) I've decided to use the good old stunnel running on my Linux box. It is enough to change the URL in the example above to http://linuxbox:8888 and start stunnel as follows:

czajnik@czajnik:~$ sudo stunnel -c -d 8888 -r www.apache-ssl.org:443

However, it only works for hosts that accept Host: HTTP header value different from actual host name. Ideally, we should be able to leave the original URL and only redirect the socket connection to a different IP and port. And in fact we are, using HttpClient's proxy settings:

		HttpParams params = httpClient.getParams();
		params.setParameter(ConnRoutePNames.DEFAULT_PROXY, new HttpHost("linuxbox", 8888));

With this setting HttpClient connects to our stunnel process, but still uses original URL - exactly what we need. Of course, URL has to be changed from https:// to http://, as the connection between HttpClient and stunnel is obviously not encrypted. Also, resist the temptation to use localhost ;)

Share:
  • Facebook
  • Digg
  • del.icio.us
  • Twitter
  • LinkedIn
  • Google Bookmarks
  • Reddit
  • StumbleUpon
Comments (0) Trackbacks (0)

No comments yet.


Add Comment Register



Leave a comment

No trackbacks yet.