I know that an activity can communicate with a local service using the IBinder interface; I am trying to find a way for communication between two services.
Specifically, I have my main service starting an IntentService to handle file uploads. I want this IntentService to inform back to the main service once it is done uploading, and before it dies.
Any ideas about how this would happen?
You have to use BroadcastReceiver to receive intents, and when you want to communicate simply make an Intent with appropriate values.
This way you should be able to make a 2-way communication between any component.
In Android, there is a special way of completing tasks like yours. Look at AIDL (it's not well documented in official docs, but there are some extra sources on the web). This is a way of implementing two-way communication between any components placed in separate processes. In comparison to BroadcastReceivers, using this you'd get direct calls and callbacks, that will be less dirty than relying on something would come from somewhere in BroadcastReceiver.
To reach the needed effect, you'll have to define an interface for a callback and an interface for performing actions (with a callback supplied, or register/unregister methods). Than, after you received some command using the second interface, you should perform the job and post back the result through callback. To reach the asynchronous completion add a key work "oneway" before method signature (return type). To separate in and out params (if you need it), use "in", "out" and "inout" keywords near params.
As it comes to restrictions, only primitives, arrays and parcelables (and parcelable arrays) might be transferred between processes.
To control your callbacks lifecycle and operations atomicity, use RemoteCallbacksList for storing registered callbacks and notifying recipients using the duplicate of your list got from beginBroadcast.
If you have any troubles, you're free to ask here.