1

For the Application object, I call bindService(). The onServiceConnected() callback receives an IBinder object, and I hand that to an AsyncTask.

There, I get my service object by calling ServiceClass.Stub.asInterface(iBinderObject) and call some method using this service object.

It's a synchronous method and I cannot influence the service's timeout setting (and who knows whether its timeout implementation is reliable). So, beforehand, I postDelayed() my own timeout handler on a separate thread.

The timeout code calls unbindService() to unbind the Application from the service and yields a timeout result.

I haven't found a way to interrupt the service call if the timeout runs first. The unbindService() has no visible effect wrt this. Calling AsyncTask.cancel(true) changes nothing, either. The IBinder object does not seem to provide any obvious method which could be of any help.

What I observe is that the AsyncTask keeps waiting for the service call to return, which can delay the start of the next AsyncTask significantly with the standard Executor.

Any experiences? Ideas?

class stacker
  • 5,357
  • 2
  • 32
  • 65
  • Did you have any Check inside your AsyncTask that keeps an eye on whether it is cancelled using AsyncTask.isCancelled(). If you use that , you can simply finish your AsyncTask, – Gaurav Arora Feb 12 '13 at 15:20
  • @GauravArora Thank you for your comment. As I said, I want to interrupt a synchronous service call, the code of which I cannot influence. – class stacker Feb 12 '13 at 15:22
  • As a general rule, Synchronous calls can not be cancelled. That's why they are Synchronous. But you can possibly try stopping the service after your timeout handler kicks in. – Gaurav Arora Feb 12 '13 at 15:32
  • @GauravArora Thanks for your promising suggestion to try and stop the service after unbindig it in the timeout handler. It doesn't change a thing, presumably due to the method call being processed. Of course, it wouldn't work anyway if another app has bound to the service. But it would have been valuable still. -- Binding to a service and calling a service method involves a binder thread and interprocess communication, so in my view, there was a certain probability that interrupting the call might work. Despite the reference claiming that `DeadObjectException` is the only exception thrown. – class stacker Feb 12 '13 at 16:53
  • ...so, looking at a couple of API references, it seems the only destructive Android way to end something is to kill a process. In other words, the only ways to avoid AsyncTask jams due to unresponsive services (if the app were to continue) would be to either use `THREAD_POOL_EXECUTOR` for the AsyncTasks or create minimal threads (referencing as few resources as possible) for the service calls, such that those can wait a long time for the result without causing too much harm? – class stacker Feb 12 '13 at 17:08
  • Probably last option from my side, stopService() should give you a call in Service.onDestroy(). Can you set a flag inside onDestroy() and stop whatever synchronous process is happening inside Service? – Gaurav Arora Feb 12 '13 at 19:44
  • @GauravArora Thank you for not giving up on this easily. Unfortunately, I forgot to mention explicitly that the service is not "mine" (hence the fact that I cannot control its timeout setting). So I can't change its code. -- I think I will isolate critical service calls in detachable Threads and live with their potential zombiefication... Thanks again. – class stacker Feb 13 '13 at 07:47
  • Alright, In that case, the only option for you is to have a error-resilient AsyncTask/Thread handling all the Service Interaction and keep it safe from any anomalies from the service. – Gaurav Arora Feb 13 '13 at 14:25

1 Answers1

1

As others have noted, a synchronous call cannot be interrupted.

If this is a concern, and you have any input in the design of the service API, you can perform asynchronous operations using a pair of one-way AIDL interfaces, like this:

package sample;
oneway interface IServer {
    void doWork(IClient cb);
}

and

package sample;
oneway interface IClient {
    void reportResult(String result);
}
j__m
  • 9,392
  • 1
  • 32
  • 56