I am wondering if there'll be an extra cost to query the content provider within the same process. I'm aware that the Content Provider is transacting data by the binder, and all the data transition between binder service and binder client will be passing by binder driver in kernel space.
I suspect if it still uses the same approach while we use the content provider in the same process and therefore causes extra overhead such as latency, extra computing...etc.
Here's the scenario - in the multi-process app, you will normally require your storage system to use the binder system to pass data between processes, but at the same time, you will also need to pass data within the same process.
What's the common approach if you have a multiprocess android app? For now, I know a third-party solution MMKV but I am not sure if there's an official solution to avoid this kind of overhead (if it even exists).
I am wondering if there'll be extra cost to query content provider within the same process
There definitely will be overhead incurred by using ContentProvider, compared with simply calling methods on an object. Inter-process communication (IPC) is not free. This is one of the reasons for the complaints about performance of the Storage Access Framework, which relies heavily on ContentProvider.
The fact that the ContentProvider is in the same process as the consumer should not eliminate this overhead.
Related
Binders are used for Inter(not intra) Process Communication/Remote Method Invocation so why/how the communication between Activity and Service is possible via binders where there are no different processes involvement.
When the very first component of an app is initialized a request to the kernal is triggeres (I think via ActivityManagerService(Native)-AMS > AMN) (running in system_process) for a new process fork if no corresponding process exists. Once the process is created then any other component (say a Service) belongs to the same process unless specified. Now this service wants to communicate to an Activity of the same process. Then why IBinder is one of the option?
Doesn't that violate the underlying principle on which Binders are created?
Interprocess communication is done by writing data to some source such as a socket or pipe, and another process reading it. There's no reason that the same process can't read and write though- it's less efficient than other means of passing data within a process, but it still works.
As for why would you use it in the same process- the alternative would be for Android to have two ways of communicating with services, one way for if they're the same process, and one way for it they aren't. That would complicate things for the framework for minimal gain. It would greatly complicate things for Services where the client may or may not be in the same process (say a service that is used by both the client app and other apps by the same company). So they just use the same method for both.
Binders are intended to be a construct of an IPC - this is true but, if used in the same process to communicate between an Activity and a Service, there is no performance cost, i.e, it is converted into a direct call instead of an RPC.
Don't assume that Binders will only be used for IPC but it is a general purpose communication mechanism in Android.
You won't find this documented normally anywhere. I found it in one of the discussion between Commonsware and Dianne Hackborne(designer of the binder concept in the Android team).
I know Android's ContentProvider is known for multiple write from multi-process/multi-thread without throwing lock exception. In multithreaded environment it might have synchronized the method using read-write lock. But what about multi process where multiple object will be created. Can any one let me internal working of ContenProvider.
A ContentProvider is a manifest declared component, it is instantiated by the OS and is tied to the main process (unless the attribute process is specified differently). Therefore only a single instance of a declared ContentProvider is created during the life time of that application process. Other processes that wish to interact with it must go through the ContentResolver which in turn just communicate with that single provider created.
Note that when a provider is used from another process it is communicating via IPC (via Binders specifically), which means a provider's methods will be invoked in a BinderThread during an IPC call. There is a pool of binder threads so that there can be some concurrent communication with multiple application, meaning appropriate synchronization should be done.
In summary, content providers are safe for multi-process & multi-thread interactions because:
They are a Singleton.
Multi-thread safety is guarantee by the developer with appropriate synchronization of shared state.
Multi-process safety is guarantee by the ContentProvider.
The ContentProvider's definition has return types that are suitable for IPC interaction. (They are Parcelable, like AssetFileDescriptor, or they are a SQLiteCursor which is backed by allocated shared memory using ashmem).
What is the advantage of using Binder for IPC over (Semaphores , Message Queue, PIPES) in Android stack?
Old question (and likely unmonitored by the poster), but worth answering:
A) All filesystem-based or filesystem-representable IPC mechanisms (notably pipes), can't be used because of a lack of a world-writable directory, where all processes can mkfifo/create the filesystem/socket representation of their IPC port (/dev/socket notwithstanding, which is used for system processes, e.g. rile, zygote, and their ilk).
B) None of the suggested mechanisms have the capability of "service location" which is required for Android. In UNIX, there's an RPC portmapper, and Android needs similar functionality. Enter: The ServiceManager, which can use binder to register as a context manager, to register/lookup service handles on the fly
C) There is an extensive need for serialization - be it intents, or other messages. Binder provides the parcel abstraction, which can be used for data marshaling by the Parcel.java.
D) SysV has other issues than Mr. Lambada's answer which are more paramount, notably race conditions, and lack of authorization.
E) Message queues and pipes can't pass descriptors. UNIX Domain sockets may, but can't be used because of (A) (again, unless you're root/system, like zygote, rild, installd..)
F) Binder is really lightweight, and has built-in authorization mechanisms. It also has nifty features like waking up the recipient process, as well as memory sharing, which the other mechanisms simply don't have. (and remember, no mmap(2), because of the file problem in (A) for named mappings).
and - let's not forget
G) Binder was started at Palm (ah, nostalgia) (q.v. OpenBinder). Ex-palmers got to Android, and brought their code in with them.
From the ndk's docs/system/libc/SYSV-IPC.html file:
Android does not support System V IPCs, i.e. the facilities provided by the following standard Posix headers:
<sys/sem.h> /* SysV semaphores */
<sys/shm.h> /* SysV shared memory segments */
<sys/msg.h> /* SysV message queues */
<sys/ipc.h> /* General IPC definitions */
The reason for this is due to the fact that, by design, they lead to global kernel resource leakage.
For example, there is no way to automatically release a SysV semaphore allocated in the kernel when:
a buggy or malicious process exits
a non-buggy and non-malicious process crashes or is explicitly killed.
Killing processes automatically to make room for new ones is an important part of Android's application lifecycle implementation. This means
that, even assuming only non-buggy and non-malicious code, it is very likely that over time, the kernel global tables used to implement SysV IPCs will fill
up.
At that point, strange failures are likely to occur and prevent programs that use them to run properly until the next reboot of the system.
Binders are used to to communicate over process boundaries since different processes don't share a common VM context => no more direct access to each others Objects (memory). Both parties within the same process (usually things that are within the same app) means (imho) that you should not use Binders since they slow down / complexify things unnecessary.
Binders are usually not used directly but rather via the "Service" or the "Messenger" classes. While communication with a Service is done via a full api of functions, the communication with a Messenger has to use "Message"s. Messengers a lot simpler to implement.
Apart from using Binders you can use anything that is available from any VM instance like "LocalSocket"s, Files, ContentProviders, Intents, ...
Binders are not ideal for transferring large data streams (like audio/video) since every object has to be converted to (and back from) a Parcel. All the conversion takes time. Much better in that case would be a LocalSocket for example.
Binders are used to enable remote procedure calls. You could implement RPC using the synchronization tools you mention but you would also need to write a lot of code to make it come together... with a Binder (normally only used within an Android Service) you have much less code to write; barely more than your actual remote functions.
Is the interprocess communication provided by Binder in Android protected against man in the middle attacks? Is there any documentation that provides this info?
Binder uses a capability-based security model. Each binder object represents a capability; handing that object to another process grants the process access to that capability. From that perspective, you prevent man in the middle attacks by not handing an important binder object to the man in the middle. If a process doesn't get handed a binder object, it can not access it in any way.
Regarding the "cross-binder reference forgery" issue discussed in the paper, if I am understanding the specific scenario they are talking about, I think their addendum about user space is a little weaker than I would agree with. They make the mistake I think of looking at the special C code written for the ServiceManager. Formally, I would consider the C++ user space code (consisting in particular of Parcel) as being part of the Binder architecture. This code in particular makes sure to deal with such attempts at spoofing when you call its readBinder() and related methods.
I don't agree with the statement that it is a flaw that the kernel is not completely ensuring integrity of the data. The only way I could imagine for it to do that would be to defined a standard typed data structure for binder transactions, so that it could read and verify the contents of the parcel. This puts too much knowledge in the kernel in my opinion, and for no real benefit. No matter how much you put there, user space will need to do some kind of validation of the incoming transaction to ensure it matches its expectations. Today this is done at the level of validating that primitive data read operations on Parcel (readBinder(), readString16(), readInt(), etc) are written to avoid attacks. Pushing more validation to the kernel will still require validation in user space that data types are correct, and now you have actually moved some opportunities for attacks (due to bugs in this code) from user space to the kernel.
One final thing about binder security is that it is important to realize that at the platform level there is another important security model implemented on top of the binder infrastructure. This is the permission/uid-based system, where services can check the uid of incoming calls to verify them against their allowed permissions.
This security model has another spoofing vulnerability that it must deal with. A typical scenario would be an application receiving the IBinder for the Activity Manager Service (since everyone can get that). The API of the Activity Manager Service is deeply based on checking the uid of incoming calls to determine what is allowed -- for example if a call to bindService() is made, it will check to see if that uid has permission to bind to the given service. A malicious app could try to play games here by handing the activity manager IBinder to another system service, for example as an IWindow to the window manager. If it knows the transactions that the second system service will make, it could set things up so that it makes a call that it thinks is say resizeWindow() but actually ends up becoming a call to bindService() when it comes put in the activity manager (if those two calls are mapped to the same transaction ID).
This vulnerability exists because the binder system is not typed in any way, "method" calls are simply transactions being sent with an integer transaction code and data buffer.
To protect against this, the user space typed interfaces generated by aidl always put at the start of their transaction buffer the name of the interface they are intending to call, and the receiving code of the transaction checks the interface name at the front of the buffer to ensure that it matches its own interace. This way the spoofer in the scenario above will be caught when the activity manager sees that it has an incoming call whose interface was for a window.
Anyway, for most practical use by Android developers, uid-based security is just as relevant as the core binder capability model. In some cases you will enforce security by restricting which processes get access to a binder. An example for this would be how there is an IBinder representing each activity, which only the system process and the process running the activity share.
In other cases and IBinder object will be shared with any interested processes, but enforce security at point of call based on uid. If you are using aidl to supply your standard implementation of such interfaces, your own implementation of such security can be done based on what meaning you want to apply to uids. For example, you could use the standard facility to associated permissions with uids and ask the package manager if the incoming uid has a permission.
The Binder has one identified security flaw which may make it susceptible to a MITM attack: http://crypto.hyperlink.cz/files/xbinder.pdf . To quote TFA:
the attacker can manage the target to further pass on or call its “protected” binder (that the attacker is not invited to call directly). We call this a cross-binder reference forgery (XBRF)
The author goes on to say that there are defenses in Android against this attack, but that
in some situations, a careful manipulation with the transaction data prepared by an attacking process may still lead to a successful XBRF exploit
One gets the impression that Binder seems to be relatively secure for carefully-written code, but there is some risk.
Will any one please tell me what are all the IPC mechanisms that are present in Android.
To my knowledge are:
Intents
Binders
IPC is inter-process communication. It describes the mechanisms used by different types of android components to communicate with one another.
1) Intents are messages which components can send and receive. It is a universal mechanism of passing data between processes. With help of the intents one can start services or activities, invoke broadcast receivers and so on.
2) Bundles are entities of data that is passed through. It is similar to the serialization of an object, but much faster on android. Bundle can be read from intent via the getExtras() method.
3) Binders are the entities which allow activities and services to obtain a reference to another service. It allows not simply sending messages to services but directly invoking methods on them.
There are three types of IPC mechanism in Android:
Intents (along with Bundles)
Binders
ASHMEM (Anonymous Shared Memory) - The main difference between Linux shared memory and this shared memory is, in Linux other processes can't free the shared memory but here if other processes require memory this memory can be freed by Android OS.
All the answers are good and concise in this post. But I would like to light upon which IPC mechanism should we use. First of all IPC means Inter Process communication where two applications or processes will communicate with each other by passing some data between them. Since android is meant for embedded and small devices, we should not use serialization for IPC, rather we can use BINDERs which internally uses parcels. Parcel is a sort of light weight serialization by using shared memory concept.
There are many differences between Binder IPC and Serialization IPC:
1. Serialization is very heavy to use in embedded devices, communication will be very slow.
2. Binders uses Parcels to make IPC very fast.
3. Binders internally uses Shared memory concept which uses less memory while sharing data between two processes.
Bottom Line: Binders uses less memory, and quite fast as it uses parcels. Serialization is very heavy, takes time to send and receive data, and also it takes more memory compared to binders.
Note: To pass data between activities, services, and receivers use only Bundles. Don't go for either serialization or binders. Binders are specifically used only for binder services where 2 processes will communicate.
Hope this Helps :)
As written on Android Developers page, IPC mechanisms in Android include:
Intents (with Bundles included)
Binders or Messengers with a Service
BroadcastReceivers
There are three types of the IPC mechanisms:
handler
implementing binder
AIDL
The tree specific inter-process communications in Android are:
AIDL which is a two way with concurrent operation.
Messanger aa a two way but not concurrent
Broadcast as a one way
Also, you can use sockets but it's not recommended.
Another solution that worked for me was using the Internal files:
https://developer.android.com/training/data-storage#filesInternal
Write from one process, close file, read from another.