Android remote bound service interface - android

I am facing this kind of problem:
I have a remote (different process) bound service which defines an IntentFilter with action String.
My client binds to it using the same action String in its bindService(..) call.
Now when I implement another service with completely different AIDL interface but with the same IntentFilter defined, install this service and remove the old one:
my client is still able to bind
my client is even able to call the desired method (say void print(Payload)) the client side does not complain, nor the server
side
My question: is there a way how to check at runtime the interface the remote service is implementing?
The only possible way I've found is to check the ComponentName in the ServiceConnection.
This has however one implication:
I will not be able to exchange the implementation of the service in the future.
Or am I missing something?

As I understand you want to do one of two things:
a) Connect to a service which implements required interface (and you don't care how the service is implemented)
In this case, you use intent filters. And in such case, each service should have different internt filter. Generally speaking, when you are defining the same intent filter you are saying that these two services are compatible (and they aren't, because of different AIDL's).
So, you should have different intent filters here.
b) Connect to a very particular service (It's not substitutable by any other service).
In such case, when you do bindService, you should specify expilicit component name in the intent, which you pass to bindService.

Related

How to run a singleton (shared) service in a library for multiple applications?

I've written a library starting a service in the background. It runs perfectly in all applications.
In order to reduce the RAM usage, I want to avoid running multiple services for different applications. Actually, it's pretty enough to use only one service to get things done.
Firstly, I've written an AIDL file to make IPC between applications/libraries. Defined the service as exported/enabled with signature permission. Since all applications are the exactly the same service, it's not possible to check if any one is up or down. While binding the service to check the condition of the service, it always creates and destroys the own service because of the nature of BIND_AUTO_CREATE flag. That's why not possible to get any kind of info from the exported service if it's really up and running.
Then, I tried to define a Content Provider to the manifest of the library. My aim is to share the service info through it. It's really good mechanism to communicate between exported service and application main process. But it is not usable for multiple instances. Because applications which gets the content provider info from the library use the same authority and so it's not possible to install the second one. It gives an DUPLICATE_PROVIDER_AUTHORITY error.
What's your suggestion about the issue? Is there any option to create a master/slave mechanism? Is it possible to make the service singleton for the application uses the library project?
P.S: Tried broadcast and shared preferences techniques. But they're not effective to listen the callback from the exported service.
You need to put the Service in an APK of its own. It needs to have its own unique package name (in the manifest) which is different from the package names of any of the applications that use it. This is how you make the Service behave as a singleton. Now you can use AIDL and bind to the Service in order to have two-way communication.
Note that in more recent versions of Android, it has become necessary to start a Service using an explicit Intent (ie: the Component must be explicitly specified, you can't use just an ACTION).
Alternative 1:
If the use case permits I think you should not implement the Service.
Make your client implement a service a call your library code. This
is how MediaPlayer and other default android APIs work.
Alternative 2:
Host the service in a separate app..and download the app when the
first call is made from any client. From here onwards there will be
single service handling all the client request.This is how some APIs like adobe
air/ MDM solutions from Airwatch works.
There is no good way you can control a component which is running in other app,unless using broadcast receivers and all.

Where is ICCs handled in the Android stack?

I was assigned to do a project in which I should write an app for Android to intercept all communicating Intents passing around in the framework. In fact, I would like to intercept all ICCs (inter-component communication) going on now in a device including all IPCs.
AFAIK, there are two general ways to do an ICC in Android listed below.
Intent passing (between Activities, Services and Receivers).
Bound Services to which Activities can bind themselves.
For getting this project done, should I manipulate Android framework to hook some specific modules? (Although I would not to do so).
I rather more interested in creating an app to intercept all ICCs without manipulating the framework. Is it possible at all?
If I should touch the framework, please tell me at which module(s)/component(s) all ICCs would be handled?
Should I manipulate Android framework to hook some specific modules?
Yes. Because of process sand-boxing feature of Linux kernel, your app cannot access other apps' information or what is going on there.
I rather more interested in creating an app to intercept all ICCs without manipulating the framework. Is it possible at all?
Absolutely No.
If I should touch the framework, please tell me at which module(s)/component(s) all ICCs would be handled?
For intercepting all ICCs, including starting Activities, starting Services, binding to services and sending broadcasts, you could manipulate Activity Manager service.
Whenever in your app, you call startActivity() (and of all its flavors e.g. startActivityForResult()), sendBroadcast(), startService and bindService (of which both RPC and using Messenger), the following steps will be taken. (behind the hood !)
Your app contact Service Manager through Binder mechanism presented in the Kernel.
Service Manager acts like an index to registered system services. So it would return back a handle to the Activity Manager to your app via Binder mechanism.
Your app now call the method specified on the Activity Manager instance it just got.
In Activity Manager further steps will be taken, such as: Intent resolution (via resolveIntent() method of Package Manager) and also Permission checking.
Two options for your case:
Manipulate Activity Manager codes directly.
Define your own a system service that acts like a proxy for the Activity Manager and register it to Service Manager. Recommended

binding Service using AIDL vs binding using action?

According documentaion on Developer's forum, this is how I can bind my service using AIDL:
/* Establish a couple connections with the service, binding by interface names.This allows other applications to be installed that replace the remote service by implementingthe same interface.*/
bindService(new Intent(IRemoteService.class.getName()),mConnection, Context.BIND_AUTO_CREATE);
Now I have application A, which has Service class and AIDL interfaces.
And I have application B through which I wish to access Service class of Application A , using methods exposed ny AIDL in application A.
So I have created exactly same pacakge for AIDLs inside application B and have pasted AIDLs from App A.
But when I'm trying to bind service using above mechanism mentioned in documentation it tells me:
Unable to start service Intent { act com.example.service.MyService
} U=0: not found
In App A Service
exported="true".
Now Insted of this approach I added Intent Filter to my service in app A and tried to specify explicit intent using
intent.setClassName(String packageName, String className)
And now it is working!
So is there something I missed out while referring original documentation ? when that approached will be used?
After discusing with pskink in above comments I got the answer for this question. The anser lies in my new implementation.
Check the constructor for Intent used in above example in documentation. It tells that IRemoteService.class.getName() passed inside Intent constructor is nothing but an 'Action'. So if I want my code should be able to find the service I wish to bind then the String returned by IRemoteService.class.getName() should be mentioned as an Action inside intent filter for my service.
Two points to be considered here will be:
This won't follow standard naming convention for actions.
Starting service using Implicit intent gives waring as implicit intents with startService are not safe for obvious reason that if the same Action is used by multiple services then it will be a problem.

Android remote service callbacks

(I have a remote service with an AIDL interface that is used by several client apps. I would like to add an asynchronous method to the interface for calls that take some time, but I need the solution to be secure, meaning that only my applications can communicate with the service. The client applications are signed with the same signature as the service app. Currently the apps just bind to the service and call a single interface method to perform various operations.
One option is broadcasting an Intent from the service when the operation is complete and using a BroadcastReceiver in the client application, but (Question #1) can this be done in a way that ensures only my apps can receive the Intent? setPackage() seems to do this, but I need to support Gingerbread devices, which seems to rule out that approach according to the answer here: setPackage for intent in gingerbread
So it seems I need to add a second .aidl interface with the callback interface for the service to use, implemented by the client. I have seen examples that use listeners here, but I am not sure what the difference is versus the client just passing in the second interface object as an argument (as used in the IScript / IScriptResult example from this answer: Service call backs to activity in android)
Question #2, what is the benefit of using a listener here vs. a callback method?
A callback method/listener is the right thing to do. (As CommonsWare says, it's pretty much the same thing). I would say it's much simpler than fiddling around with BroadcastReceivers, since you're already using aidl.
Something like this:
IAsyncThing.aidl:
package com.my.thingy;
import com.my.thingy.IAsyncThingListener;
interface IAsyncThing {
void doSomething(IAsyncThingListener listener);
}
IAsyncThingListener.aidl:
package com.my.thingy;
import com.my.thingy.IAsyncThingListener;
interface IAsyncThingListener {
void onAsyncThingDone(int resultCodeIfYouLike);
}
You can enforce that only your apps can bind to the service by using a signature-level permission on your service (see the note on 'service permissions' here: http://developer.android.com/guide/topics/security/permissions.html). Specifically:
Declare a permission in your service's AndroidManifest.xml. Ensure it is signature level.
Add that permission in your service tag
In all the other apps, use uses-permission to use it.
A couple of other things to bear in mind:
In the caller, you'll need to subclass IAsyncThingListener.Stub. Your calling application code may already be subclassing something else, so that means you'd have to use an extra (probably inner) class to receive the completion notification. I mention this only because this might be the answer to question #2 - which I don't fully understand.
If the service is potentially in different processes from the caller, each should register for death notification of the other using IBinder.linkToDeath.

Android communication between two services

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.

Categories

Resources