[guardian-dev] InputStreams across Services

Abel Luck abel at guardianproject.info
Fri Dec 6 10:33:14 EST 2013


Mark Murphy:
> 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.
> 


Alrighty. I've created a little test project to test these assumptions.

     https://github.com/abeluck/android-streams-ipc

So far it just tests a variation of Flow's two techniques:

1. Passing PFDs in method as parameters
2. Returning PFD from a method

Re #1: Data flow Client <--> Service. The client is responsible for all the PFDs.

Reading from a PersonalFlotationDevice passed as a param, works, but writing to one seems
to write into a black hole. However, the thread in question isn't completing, so I think
something isn't getting close()d properly, but I can't see what :S

Good news is, I didn't encounter the error Flow did [0].

Re #2: Data flow Client --> Service. The service returns a PFD that the client writes
into, and then the service reads from later.

This works!

TODO: Test the case when the Service writes into a PFD that is then returned to the client
where she reads it. Try Mark's List<ParcelFileDescriptor> suggestion.

TODO: Write Content[Provider,Resolver] example.

TODO: Test this with File backed PFDs and not just ByteArrays-through-a-pipe

TODO: redo all these tests on different android versions

TODO: will any of this change when we start using "oneway" methods?

[0]:
http://stackoverflow.com/questions/18212152/transfer-inputstream-to-another-service-across-process-boundaries-with-parcelf

~abel




More information about the Guardian-dev mailing list