getAcceptedIssuers on system trust manager very slow
Hi there.
I have used your idea of creating a combined TrustManager which you call MyTrustManager.
However, when instantiating MyTrustManager, then the defaultTrustManager's accepted issuers is combined with the local one in this code:
List<X509Certificate> allIssuers = new ArrayList<X509Certificate>();
for (X509Certificate cert : defaultTrustManager.getAcceptedIssuers()) {
allIssuers.add(cert);
}
for (X509Certificate cert : localTrustManager.getAcceptedIssuers()) {
allIssuers.add(cert);
}
acceptedIssuers = allIssuers.toArray(new X509Certificate[allIssuers.size()]);
However, the call to defaultTrustManager.getAcceptedIssuers() is very slow (5-15sec) on the Android platform (at least on my phone).
In my instance, the Apache HttpClient never calls getAcceptedIssuers() and therefore the work is wasted.
I rewrote the implementation to prepare the list only if getAcceptedIssuers() was called:
public X509Certificate[] getAcceptedIssuers() {
Log.d(TAG, "getAcceptedIssuers()...");
if(acceptedIssuers == null) {
synchronized(this) {
if(acceptedIssuers == null) {
List<X509Certificate> allIssuers = new ArrayList<X509Certificate>();
Collections.addAll(allIssuers, defaultTrustManager.getAcceptedIssuers());
Collections.addAll(allIssuers, localTrustManager.getAcceptedIssuers());
acceptedIssuers = allIssuers.toArray(new X509Certificate[allIssuers.size()]);
}
}
}
return acceptedIssuers;
}
It is exactly as slow as your implementation, but if it is not called, the list will not be prepared. Also notice that I used the Collections.addAll utility methods instead of the for loops. It uses the singleton pattern as described on stackoverflow. http://stackoverflow.com/a/11165926/477854
I hope you will incorporate these changes such that other people will not have to deal with this problem.
What phone and Android version are you using? Can you profile the method and find out which part is slow?
HTC One S (Android 4.1.1).
I used a debugger and the getAcceptedIssuers() was the problem. I moved it outside the loop and only fetched it into a variable.
That method does a few things, you need to log how much time each call takes to get an idea what is causing the slowness. The debugger slows things down considerably, so it's not very helpful for profiling.
I know. Which method are you talking about. The getAcceptedIssuers() of defaultTrustManager?
The timings i gave (5-15 sec) was approximately how it felt for the user.
When using the debugger, the times where much more in the range 50sec to 90 sec.
Want me to debug getAcceptedIssusers()? (btw, leaving work at this moment)