[guardian-dev] InputStreams across Services
Mark Murphy
mmurphy at commonsware.com
Wed Dec 4 14:19:02 EST 2013
On Wed, Dec 4, 2013, at 10:36, Abel Luck wrote:
> We're collaborating with Dominik on an OpenPGP Crypto Provider API, which
> is a generic PGP
> AIDL interface that a provider app will implement in a remote background
> service.
I am coming into this completely cold and have zero experience with
OpenPGP other than knowing its name and general role. Hence, imagine a
grain of salt approximately 25cm on a side, and take that grain of salt
with my input... :-)
> Our question is: how should we pass InputStreams across the service
> interface?
>
> See the short example outlined here [0], and the "Open Questions"
> section below it.
>
> Our main questions have to to with the "ParcelFileDescriptor". I assumed
> it was some sort
> of magic Input/OuputStream wrapper for fds, byte[], etc. But I don't
> think that's the case.
>
> Also, importantly, I'm not sure we can pass ParcelFileDescriptor in a
> service method.
>
> I saw your ContentProvider/Pipe example, but how would you use that
> across an AIDL Service?
Off the cuff, I would have expected your proposed use of
ParcelFileDescriptor to have worked. The analysis in the SO question you
link to suggests otherwise. I would have gone about it the same way Flow
did.
Personally, I have never tried to pass a stream across an AIDL
interface. I avoid service binding like the plague, let alone AIDL.
Yours seems like a legit use case for it, though I would recommend
documenting the heck out of using it, to deal with configuration changes
and all that fun stuff that service binding makes challenging.
Here are a couple of possible workarounds, off the top of my head:
- oneway List<ParcelFileDescriptor> sign(in IOpenPgpCallback callback);
This takes Flow at his(?) word that the service can return
ParcelFileDescriptor objects successfully. In this case, rather than
having the client dictate the ParcelFileDescriptors to use, the service
does. The List<ParcelFileDescriptor> would be a two-element ArrayList,
with one being the input and one being the output
- oneway Uri sign(in Uri input, in IOpenPgpCallback callback);
In this case, the client supplies a Uri to a ContentProvider-served
stream that provides the input, following the recipe you've seen (though
probably using a variant that employs permissions better). The service
returns a Uri to a ContentProvider-served stream that provides the
output.
Yet another possibility is to poke through the innards of Android and
try to determine how ContentProvider, ContentResolver, and streams work.
At the end of the day, that should be using Binder for IPC and a
ParcelFileDescriptor. It may be that the net is that the service is
returning the ParcelFileDescriptor all of the time, which is why that
works.
Let me know if you need additional help.
--
Mark Murphy (a Commons Guy)
http://commonsware.com | http://github.com/commonsguy
http://commonsware.com/blog | http://twitter.com/commonsguy
_The Busy Coder's Guide to Android Development_: 2,500+ Pages, Updated
Frequently!
More information about the Guardian-dev
mailing list