Binder has been widely used in Android for a long time. Binder has been widely used in Android for a long time. Binder has been widely used in Android for a long time It was recorded in split screen mode.

The structure of this paper: 1. Analysis of AIDL related variable methods; 2. Analysis of problems encountered in the process; 3Copy the code

1. AIDL involves related variable method analysis

The following is automatically generated through the interface via AndroidStudio

/* * This file is auto-generated. DO NOT MODIFY. * Original file: /Users/foking/DemoContainer/AIDLDemo/James/src/main/aidl/com/example/foking/aidldemo/JamesChatInterface.aidl */
package com.example.foking.aidldemo;
// Declare any non-default types here with import statements

public interface JamesChatInterface extends android.os.IInterface {
    /** * Local-side IPC implementation stub class. */
    public static abstract class Stub extends android.os.Binder implements com.example.foking.aidldemo.JamesChatInterface {
        private static final java.lang.String DESCRIPTOR = "com.example.foking.aidldemo.JamesChatInterface";

        /** * Construct the stub at attach it to the interface. */
        public Stub(a) {
            this.attachInterface(this, DESCRIPTOR);
        }

        /** * Cast an IBinder object into an com.example.foking.aidldemo.JamesChatInterface interface, * generating a proxy if needed. */
        public static com.example.foking.aidldemo.JamesChatInterface asInterface(android.os.IBinder obj) {
            if ((obj == null)) {
                return null;
            }
            android.os.IInterface iin = obj.queryLocalInterface(DESCRIPTOR);
            if(((iin ! =null) && (iin instanceof com.example.foking.aidldemo.JamesChatInterface))) {
                return ((com.example.foking.aidldemo.JamesChatInterface) iin);
            }
            return new com.example.foking.aidldemo.JamesChatInterface.Stub.Proxy(obj);
        }

        @Override
        public android.os.IBinder asBinder(a) {
            return this;
        }

        @Override
        public boolean onTransact(int code, android.os.Parcel data, android.os.Parcel reply, int flags) throws android.os.RemoteException {
            java.lang.String descriptor = DESCRIPTOR;
            switch (code) {
                case INTERFACE_TRANSACTION: {
                    reply.writeString(descriptor);
                    return true;
                }
                case TRANSACTION_receiveKobeChatContent: {
                    data.enforceInterface(descriptor);
                    java.lang.String _arg0;
                    _arg0 = data.readString();
                    boolean _result = this.receiveKobeChatContent(_arg0);
                    reply.writeNoException();
                    reply.writeInt(((_result) ? (1) : (0)));
                    return true;
                }
                default: {
                    return super.onTransact(code, data, reply, flags); }}}private static class Proxy implements com.example.foking.aidldemo.JamesChatInterface {
            private android.os.IBinder mRemote;

            Proxy(android.os.IBinder remote) {
                mRemote = remote;
            }

            @Override
            public android.os.IBinder asBinder(a) {
                return mRemote;
            }

            public java.lang.String getInterfaceDescriptor(a) {
                return DESCRIPTOR;
            }

            /** * Demonstrates some basic types that you can use as parameters * and return values in AIDL. */
            @Override
            public boolean receiveKobeChatContent(java.lang.String content) throws android.os.RemoteException {
                android.os.Parcel _data = android.os.Parcel.obtain();
                android.os.Parcel _reply = android.os.Parcel.obtain();
                boolean _result;
                try {
                    _data.writeInterfaceToken(DESCRIPTOR);
                    _data.writeString(content);
                    mRemote.transact(Stub.TRANSACTION_receiveKobeChatContent, _data, _reply, 0);
                    _reply.readException();
                    _result = (0! = _reply.readInt()); }finally {
                    _reply.recycle();
                    _data.recycle();
                }
                return_result; }}static final int TRANSACTION_receiveKobeChatContent = (android.os.IBinder.FIRST_CALL_TRANSACTION + 0);
    }

    /** * Demonstrates some basic types that you can use as parameters * and return values in AIDL. */
    public boolean receiveKobeChatContent(java.lang.String content) throws android.os.RemoteException;
}

Copy the code

1.1 TRANSACTION_receiveKobeChatContent

The method in the identification interface generates a constant ID, which is distinguished by the Code when called by the Client

1.2 a Stub

Inherit from Binder is an abstract class that implements the interface of the methods to be provided. It encapsulates two key methods: asInterface,onTransact, and finally our own entity Binder class inherits the subclass and implements the methods in the interface.

1.3 Stub# DESCRIPTOR

Unique identification of Binder entities

1.4 Stub# asInterface ()

The Binder object on the server is converted into an AIDL interface type object required by the client. The conversion process is process-specific. If the client and server are in the same process, the Stub object on the server is returned; otherwise, the system encapsulated stub. proxy object is returned

1.5 Stub# onTransact ()

This method runs in server-side Binder in the thread pool, when the client has launched across processes the request, the remote request will be through the system after the underlying encapsulation method to deal with, the server through the code, what is the method of customer requested can be determined, then the parameters of the target method is read from the data needed, and then execute the target method, when the target method performs If this method returns false, the client’s request will fail. We can use this feature for permission authentication because we don’t want any process to be able to call our service remotely

1.6 the Proxy

Local proxy objects for client Binder

1.7 Proxy# receiveKobeChatContent ()

The method runs on the client side, and when the client calls the method remotely, it internally creates the input Parcel object _data, output Parcel object _reply, and return value result for the method, writes the method’s parameters to _data, and then calls Transa The CT initiates the request, the requesting thread is suspended, and the onTransact method on the server is called until the request completes, the current thread continues to execute, retrieves the returned result from _REPLY, and finally returns the data for _reply

2. Analysis of problems encountered in the process

2.1 the “Java. Lang. IllegalArgumentException: Service Intent must be explicit”

Intent Intent =new Intent("foking.kobe"); bindService(intent, mServiceConnection, Context.BIND_AUTO_CREATE); Intent Intent =new Intent("foking.kobe");
intent.setPackage("com.example.kobe"); bindService(intent, mServiceConnection, Context.BIND_AUTO_CREATE); Displays the specified Action and Package (the Package name of the called application).Copy the code

2.2 Supported Data Types

  1. All primitive types in the Java programming language (such as int, long, CHAR, Boolean, and so on)
  2. String, CharSequence, List, Map
The delivery object needs to implement the Parcel interface and, when used, a direction tag indicating where the data is going. Can bein, out, or inout, the default primitive isinIt can't be any other direction.Copy the code

The directional tag in AIDL represents the flow of data in cross-process communication, where IN indicates that data can only flow from client to server, out indicates that data can only flow from server to client, and inout indicates that data can flow in both directions between server and client. Where the data flow is for the object passing the method in the client. In indicates that the server will receive the complete data of the object, but the object on the client will not change as the server changes the parameter. Out indicates that the server will receive the object with an empty parameter, but the client will synchronize the change after the server has made any changes to the received empty object. When inout is tag oriented, the server will receive complete information about the object from the client, and the client will synchronize any changes the server makes to the object. Do you really understand in, out, inout in AIDL?

3. Knowledge of Binder mechanism

3.1 Virtual Memory

Virtual memory is a technology of memory management in computer system. It makes an application think it has contiguously available memory (a contiguous complete address space), when in reality it is usually split into physical memory fragments, with some temporarily stored on external disk storage for data exchange as needed. Systems that use virtual memory make it easier to write large programs and use real physical memory, such as RAM, more efficiently than systems that do not use virtual memory. This concept is important, and a more in-depth understanding of virtual memory can be found in this article: Understanding Linux Virtual Memory and physical Memory.

3.2 User space and Memory space

We know that today’s operating systems use virtual storage, so for a 32-bit operating system, the addressing space (virtual storage) is 4G (2 ^ 32). The core of the worry system is the kernel, which is independent of ordinary applications and has access to the protected memory space as well as all permissions to the underlying hardware devices. In order to ensure that the user process cannot operate the kernel directly and ensure the security of the kernel, the system divides the virtual space into two parts, one is the kernel space and the other is the user space. For Linux, the highest 1G byte (from virtual addresses 0xC0000000 to 0xFFFFFFFF) is used by the kernel and is called kernel space, while the lower 3G byte (from virtual addresses 0x00000000 to 0xBfffff) is used by various processes and is called user space. Each process can enter the kernel through a system call, so the Linux kernel is shared by all processes within the system. Thus, from a process-specific perspective, each process can have 4 gigabytes of virtual space.

3.3 Kernel and user mode

When a task (process) executes a system call into kernel code, the process is said to be kernel-running (kernel-state). The processor executes in kernel code with the highest privilege (level 0). When a process is in kernel state, the kernel code executed uses the kernel stack of the current process. Each process has its own kernel stack. When a process is executing the user’s own code, it is said to be in user mode (user mode). At this point the processor runs in the lowest privilege level (level 3) of user code. When executing a user program is suddenly interrupted by an interrupt program, the user program can also be said to be in kernel state symbolically. Because the interrupt handler will use the kernel stack of the current process.

3.4 Binder in Android

Binder drivers: Binder Dirver modules run in the Android kernel space and are responsible for communication between user processes.

In addition, Linux itself is not driven by Binder, which is the Loadable Kernel Module (LKM) mechanism of Linux. A module is a self-contained program that can be compiled separately but cannot be run independently. It is linked to the kernel at run time and runs as part of the kernel.

A complete Binder IPC communication process:

  1. The Binder driver first creates a data receive cache in kernel space
  2. Then, a kernel cache is created in the kernel space, and the mapping relationship between the kernel cache and the kernel data receiving cache, as well as the mapping relationship between the kernel data receiving cache and the user space address of the receiving process is established.
  3. The sender process uses the system call copyfromuser() to copy the data to the kernel cache in the kernel. Since there is memory mapping between the kernel cache and the user space of the receiving process, the data is sent to the user space of the receiving process, thus completing an inter-process communication.

Binder communication model:

Client, Service, ServiceManager, and Binder drivers

Process:

  1. Service processes register with ServiceManager Binder entities (Binder entities in Server) using Binder drivers to provide external services
  2. The Client process uses the Binder driver to obtain the server Binder reference from the ServiceManager
  3. This application allows access to the Service side