2.1 Android IPC Introduction
IPC means inter-process communication or cross-process communication, the thread is the minimum unit of CPU scheduling, is a limited system resources. A process generally refers to an execution unit. Any operating system requires a corresponding IPC mechanism. such as Windows can be done through the Clipboard pipe and mail slots, Linux can be shared by the name of the pipeline content semaphore. The most distinctive inter-process communication in Android is Binder, and it also supports the Socket for communication between any two terminals.
2.2 Multi-process mode in Android
(1) by assigning the android:process attribute to four components, you can turn on multithreaded mode, and the process name of the default process is the package name.
android:process=":sunquan"android:process="cn.sunquan.com.xx"
":" refers to the current process name appended to the current package name, abbreviated way. Next the process name begins with ":" The process belongs to the currently applied private process, the other application components can not be in the same process with it, and the process name does not start with ":" Process belongs to the global process, other applications can be in the Shareuid way and it run into the same process.
(2) The system assigns a unique UID to each application to share the data with the application with the same UID. Two apps running through Shareuid need to have the same shareuid in the same process and have the same signature. In this case, they can access each other's private data, such as the database directory, component information, and so on, regardless of whether they run in the same process. Of course, if they run in the same process, in addition to sharing the data directory, component information, you can also share memory, or they look like two departments of an application.
(3) Android allocates a separate virtual machine for each application, or allocates a separate virtual machine for each process, and different virtual machines have different address spaces on memory allocations, which results in multiple copies of objects accessing the same class on different virtual machines. Therefore, the four components running in different processes, as long as they need to share data through memory, will share the failure, this is the main impact of multi-process.
(4) Multi-process generally causes the following problems:
1. Static members and Singleton modes are completely invalidated: not in the same block of memory
2. The thread synchronization mechanism is completely invalidated: Neither the lock object nor the lock global class can guarantee thread synchronization because different processes lock not an object.
3. Sharepreference Reliability degradation: sharepreference The underlying is implemented by a read/write XML file, and concurrent writes can obviously be problematic. Sharepreference does not support two processes to perform write operations at the same time, otherwise there will be a chance of loss.
4. Application is created several times: When a component runs in a new process, the system creates a new process that allocates a separate virtual machine, and the app restarts once, creating a new application. Components running in the same process belong to the same virtual machine and the same application. Components of different processes do have separate virtual machines, application, and memory space. The different components of the same application operate in different processes, which are not essential to the divisions in which they belong to each of the two applications.
(5) Although it is not possible to share memory directly, it is possible to achieve data interaction through cross-process communication. The way to achieve cross-process: pass data through Intent, share files, Sharepreference, Binder-based Messager and Aidl, and sockets.
2.3 IPC Basic Concept Introduction
(1) Serializable is a serialized interface provided by Java that provides standard serialization and deserialization operations for objects. The Parceable interface is a serialization method provided by Android.
(2) Implement the Serializable interface, and declare a serialversionuid to enable serialization of an object. Serialversionuid is a long-numbered number that is used to assist in the serialization and deserialization process. In principle, the serialversionuid in a serialized number is only as good as the current serialversionuid to be deserialized. Serialversionuid's detailed working mechanism: when serializing, the system writes the serialversionuid of the current class to the serialized file (or other mediations), and when deserialized, the system detects the Serialversionuid in the file, See if it is consistent with the serialversionuid of the current class, such as a consistent description of the version of the serialized class and the current class version, this time the deserialization can be successful, otherwise the current class and the serialized class has undergone some transformations, in general we should specify Serialversionuid's fingers.
Note: 1. Static member variables belong to a class that does not belong to the object and does not participate in the serialization process; 2. member variables marked with the Transient keyword do not participate in the serialization process.
(3) To implement the Parceable interface, an object of a class can be serialized and passed through Intent and Binder. Pacel internal packaging of serializable data, can be freely transferred in Binder, can be directly serialized to have Intent, bundles, Bitmap, List, map, etc., provided that each of their elements are serializable.
(4) The difference between Serializable and parceable: Serializable is a serialized interface in Java, which is simple to use but expensive because of the large number of I/O operations. Parceable is a serialization method in Android, more suitable for Android platforms, the disadvantage is that it is cumbersome to use, but high efficiency. The parceable is mainly used in memory sequences, and is applied to the storage device or after serialization to the network to establish the applicable Serializable.
(5) Binder is a class in Android that implements the binder interface. From the IPC perspective, Binder is a cross-process communication in Android, Binder can also be understood as a virtual physical device, the device driver is/dev/binder, the communication mode is not in Linux, from the Android Framework point of view, Binder is the bridge that ServiceManager connects various managers and corresponding managerservice, and from the Android application layer, Binder is the medium of communication between client and server, and when Bindservice, the server will return Back to a Binder object that contains service-side business calls through which the client can obtain the services or data provided by the server, where services include General Service and AIDL-based services.
In Android development, binders are used primarily in service, including Aidl and Messager, where binders in the general Service do not involve interprocess communication, which is simpler. And the bottom of messager is actually aidl.
(6) The Aidl tool automatically generates the parsing of the Java interface according to the aide file: A method that declares several interfaces, while declaring several integer IDs to identify these interfaces, the ID identifies which method the client is requesting during the Transact process. Then an internal class stub is declared, this stub is a Binder class, when the client and the server is in the same process, it will not go through the process of transact process, if not the same process, the method calls need to go transact process, this logic has Stub inside Agent Proxy to complete the department.
Its core implementation is its internal class stub and stub internal proxy proxies. Several of its methods are analyzed as follows:
1. Asinterface (Android.os.Binder obj): An object used to convert a Binder object on the service side to the Aidl interface type required by the client. If the client and the server are in the same process, this method returns the Stub object itself on the service side, or returns the Stub.proxy object after the system is encapsulated.
2. Asbinder: Used to put back the current Binder object
3. Ontransact: In a Binder thread running on the server, when the client initiates a cross-process request, the remote request is handled by this method after the system's underlying encapsulation. The method is prototyped as public Boolean ontranact (int code, ANDROID.OS.PARCEL data, android.os.Parcel reply, int flags). The server uses code to determine what target method the client is requesting, and then takes the parameters required by the target method (if the target method has parameters) from data and executes the target method. When the target method finishes executing, the return value is written to reply if the target method has a return value. If this method returns false, then the client's request will fail, and permission validation can be done with this feature.
4. Proxy#[method]: Run on the client, when the client calls this method, first creates the input type Parcel object _data, Output type Parcel object _repley and return value object required by the method, writes the parameter information of the method to _data (if there are parameters ), and then call the Transact method to initiate the RPC (remote Procedure Call) request, while the current thread hangs, and then the Ontransact method of the server is called until the RPC process returns, and the current thread resumes execution and removes the return result of the RPC procedure from _reply. Finally, the data in the _reply is returned.
Note: 1. When a client initiates a request, the remote request cannot be initiated in the UI thread because the current thread is suspended until the server process returns data, and if the remote method is time consuming. 2. The binder method on the server runs in the binder's thread pool, regardless of whether the binder method is time-consuming and should be implemented synchronously, because it runs in a thread.
5. The essence of the Aidl file is that the system provides a tool for quickly implementing binders, which can be manually written by ourselves or automatically generated by aidl files.
6. Binder has two important methods: Linktodeath and Unlinktodeath,binder run on the server side, the service side process is terminated abnormally for some reason, and the binder connection on the server is broken, which causes the client remote call to fail. By Linktodeath you can set up a death agent for binder, and when Binder dies, you are notified that the connection request can be re-initiated to restore the connection.
Set Binder death Agent as follows:
First declare a Deathrecipient object, Deathrecipient is an interface, there is only one method inside Binderdied, when Binder dies, the system callback this method, we can remove the binder before the binding Proxy and rebind the remote service.
privatenew IBinder.DeathRecipient() { @Override publicvoidbinderDied() { ifnullreturn; 0); null; // TODO:这里重新绑定远程Service }};
Next, after the client has successfully bound the remote service, set the agent for the death to Binder:
mservice= IMessageBoxManager.Stub.asInterface(binder);binder.linkToDeath0)
The second parameter of Linktodeath is a marker bit, which can be set directly to 0. In addition, Binder method isbinderalive can also determine whether binder die.
2.4 IPC Mode in Android
(1) using bunble:bunble to implement the Parcelable interface, can be transferred between different processes. A type that is not supported by bunble cannot be transferred between processes through it.
(2) using file sharing: Since the Android system based on Linux, concurrent read/write files can be unrestricted, two threads write to the same file is running, but there may be a problem. File sharing is ideal for communicating between processes that require less data synchronization and to properly handle concurrent read/write issues. Sharedpreference is a special case, belonging to a file, but the system to its read/write has a certain cache policy, that is, in memory there will be a copy of the Sharedpreference file cache, so in the multi-process, the system to its read/write becomes unreliable, in the face of high concurrency read/ Write access, Sharedpreference has a great chance of losing data, so it is not recommended to use sharedpreference in interprocess communication.
(3) Using Messenger:messenger is a lightweight IPC scheme whose underlying implementation is aidl, which processes a client-sent message serially, with the service side processing one request at a time without a concurrent execution scenario (for a large number of concurrent requests, Messenger is not suitable for use).
(4) Use AIDL: First the server to create a service to listen to the client connection request, create a aidl file, the interface exposed to the client is declared in this aidl file, the last service implementation of the Aidl interface. The client binds the service-side services and establishes a connection to access the remote server's method.
1. AIDL Supported data types: basic data types (int, long, chat, Boolean, double, etc.); String and Charsequence;list (only support ArrayList, the child elements inside must be aidl supported) ; Map (supports HashMap only, each element inside must be supported by AIDL, including key and value), parcelable (so the object that implements Parcelable interface); Aidl (all aidl interfaces can also be used in aidl files).
2. Custom parcelable objects and Aidl files are explicitly import even if they are in the same package as the current Aidl file.
3. If a custom Parcelable object is used in the Aidl file, you must create a new Aidl file with the same name and declare it as the parcelable type.
4. Aidl In addition to the basic data type, other types of parameters must be marked with direction: In, out, or inout,in for input type parameters, out for output type parameters.
5. Only methods are supported in the Aidl interface, and declaring static constants is not supported. Different from the traditional interface.
6. To facilitate the development of AIDL, it is recommended that all classes and files related to Aidl be placed in the same package, and that when the client is another application, the entire package can be copied directly to the client project.
7. Remotecallbacklist is the system specifically provided to remove the process listener interface, remotecallbacklist is a generic, support the management of arbitrary aidl interface, all AIDL interfaces inherit from the Interface interface, in it Has a map structure that is designed to hold all aidl callbacks, whose map key is the Binder type, and value is the Callback type. When the client process terminates, it can automatically remove the listener registered by the client. In addition, the Remotecallbacklist internal automatically realizes the function of thread synchronization, so when using it for registration and reconciliation, no additional thread synchronization is required. The use of remotecallbacklist requires attention: it is not a List. Traversing remotecallbacklist needs to be done in the following way, where Beginbroadcast and Finishbroadcast must be paired, even if only the number of elements in the remotecallbacklist is obtained:
int N =mListenerList.beginBroadcast(); fori0ii++){ // } mListenerList.finishBroadcast();
- Both the onserviceconnected and onservicedisconnected methods of the client are running in the UI thread, so it is not possible to invoke the service-side time-consuming method directly inside them. The server-side approach itself runs in the Binder thread pool on the server side, so the server-side approach itself can perform a lot of time-consuming operations, and it's time to remember not to thread the asynchronous task in the server-side approach, unless explicitly doing so.
- Binder may die unexpectedly, need to reconnect the service, there are two ways: to set the binder deathrecipient monitoring, death will receive the Binderdied method callback, and then can be re-connected, one is to reconnect in onservicedisconnected. The difference: onservicedisconnected is called back in the client's UI thread, Binderdied is called back in the client's Binder thread pool and cannot access the UI.
- The
- Aidl uses common permissions validation methods: One is to validate in Onbind, and the client cannot bind the service directly without returning NULL. The same approach applies to Messenger, such as using permission authentication and declaring the required permissions (custom permission) in Androidmenifest. Second, in the server-side Ontransact method to verify the permissions, if the validation fails to return false, so that the service side will not terminate the execution of AIDL methods in order to achieve the protection of the service side of the effect, the authentication method can also be used permission, can also use Uid and Pid to do the verification, Get the Uid and Pid of the application to which the client belongs through Getcallinguid and Getcallingpid. This two parameter can be used to do some verification work, such as verifying the package name.
(5) using Contentprovider:contentprovider is provided in Android specifically for data sharing among different applications, and as with Messenger, its underlying implementation is Binder when its implementation process is more than aidl Much simpler. The data is organized primarily in tabular form and can contain multiple tables. It also supports file data, film and video. The structure of the file data and tabular data is different, so processing such data can return a handle to the file in ContentProvider to the outside world so that the file to access the Contentprovider,android system provides Mediastore functionality is the file type ContentProvider. The underlying data of ContentProvider looks like a sqlite database, but ContentProvider does not have any requirements for the underlying data storage, you can use the SQLite database, or you can use normal files. You can even use an object in memory to store data. To observe the data changes in a contentprovider, you can register the observer through the Contentresolver Registercontentobserver method, by Unregistercontentobserver method to dismiss the observer. The
(6) uses Socket:socket, which is called a socket, and is divided into two types: streaming sockets and User datagram sockets. The TCP and UDP protocols that correspond to the transport control layer of the network, respectively.
2.5 Binder Connection Pool
When the project to a certain extent, unlimited increase in service is not right, service is one of the four components, is also a system resource. We need to put all the aidl in the same Service to manage. Working mechanism: Each business module creates its own Aidl interface and implements this interface, there is no coupling between different business modules, all implementation details are separated, and the server side is provided with its own unique identity and its corresponding Binder object. Only one service is required for the server, and the server provides a querybinder interface that can return the Binder objects to them according to the characteristics of the business module. The main function of binder connection pooling is to forward the binder request of each business module to the remote service to execute, thus avoiding the duplication of service creation, after the different business modules get the required binder objects and can make remote method calls. It is recommended to use Binderpool in development. Specific Source view:
Https://github.com/singwhatiwanna/android-art-res/blob/master/Chapter_2/src/com/ryg/chapter_2/binderpool/BinderPool.java
2.6 Using the appropriate IPC method
Android Development Art-chapter II IPC mechanisms