Binder通信机制与AIDL的使用

本文讲解了了AIDL的使用以及Binder通信机制在JAVA层的理解,native层的Binder架构以及binder驱动原理见后续文章的分析。

Binder通信机制:是Android中使用最广泛的进程间通信(Inter-Process Communication, IPC)机制,是一种client/server结构。

AIDL(Android Interface Define Language):Android接口定义语言,帮助开发者自动生成实现Binder通信机制所需的相关模板代码。(如果你够牛逼的话,也可以不用AIDL生成代码,自己直接写相关java代码,当然也可以复制一份AIDL生成的代码到java目录下,用于分析Binder通信机制)。

下面通过一个实例讲解Binder机制以及AIDL的使用。
实例说明:Client进程传两个整数a和b给Server进程,Server进程进行加法运算,然后把相加后的结果返回给Client进程。

创建工程

步骤1:创建Client工程和Server工程,两个工程都创建IAdd.aidl文件,IAdd.aidl文件内容:

interface IAdd {

  int add(int a, int b);

}

Client工程的目录结构:
在这里插入图片描述
Server工程的目录结构:
在这里插入图片描述

Client工程和Server工程中的aidl文件的名字,内容,以及所在的包名都要一模一样,最好就是在Client工程中写好了aidl文件后直接把整个aidl文件夹拷贝一份到Server的相同目录下即可,具体见上图。

aidl文件写好后,进行编译,编译后会自动生成IAdd类的源码:

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

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

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

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

        @Override
        public boolean onTransact(int code, android.os.Parcel data, android.os.Parcel reply, int flags) throws android.os.RemoteException {
            switch (code) {
                case INTERFACE_TRANSACTION: {
                    reply.writeString(DESCRIPTOR);
                    return true;
                }
                case TRANSACTION_add: {
                    data.enforceInterface(DESCRIPTOR);
                    int _arg0;
                    _arg0 = data.readInt();
                    int _arg1;
                    _arg1 = data.readInt();
                    int _result = this.add(_arg0, _arg1);
                    reply.writeNoException();
                    reply.writeInt(_result);
                    return true;
                }
            }
            return super.onTransact(code, data, reply, flags);
        }

        private static class Proxy implements com.binder.aidl.IAdd {
            private android.os.IBinder mRemote;

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

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

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

            @Override
            public int add(int a, int b) throws android.os.RemoteException {
                android.os.Parcel _data = android.os.Parcel.obtain();
                android.os.Parcel _reply = android.os.Parcel.obtain();
                int _result;
                try {
                    _data.writeInterfaceToken(DESCRIPTOR);
                    _data.writeInt(a);
                    _data.writeInt(b);
                    mRemote.transact(Stub.TRANSACTION_add, _data, _reply, 0);
                    _reply.readException();
                    _result = _reply.readInt();
                } finally {
                    _reply.recycle();
                    _data.recycle();
                }
                return _result;
            }
        }

        static final int TRANSACTION_add = (android.os.IBinder.FIRST_CALL_TRANSACTION + 0);
    }

    public int add(int a, int b) throws android.os.RemoteException;
}

步骤2. Client工程的MainActivity代码如下:

public class MainActivity extends AppCompatActivity {

    Button btnPay;

    private IBinder binder;

    private IAdd iAdd;

    ServiceConnection serviceConnection = new ServiceConnection() {
        @Override
        public void onServiceConnected(ComponentName componentName, IBinder iBinder) {

            binder = iBinder;
            iAdd = IAdd.Stub.asInterface(iBinder);

        }

        @Override
        public void onServiceDisconnected(ComponentName componentName) {

        }
    };

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

        Intent intent = new Intent();
        intent.setAction("com.binder.server.MyService");

        /*android5.0之后,如果service不在同一个App的包中,
         需要设置service所在程序的包名,(包名可以到App的清单文件AndroidManifest中查看)*/
        intent.setPackage("com.binder.server");
        bindService(intent, serviceConnection, BIND_AUTO_CREATE);//开启Service


        btnPay = (Button) findViewById(R.id.btnPay);
        btnPay.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View view) {
                try {
                    int result = iAdd.add(1, 2);
                    Toast.makeText(getApplicationContext(), "result=" + result, Toast.LENGTH_SHORT).show();
                } catch (RemoteException e) {
                    //因为是跨程序调用服务,可能会出现远程异常
                    e.printStackTrace();
                }
            }
        });


    }


}

Server工程的MyService的代码如下:

public class MyService extends Service {

    private String TAG = "MyService";


    public MyService() {
    }

    @Override
    public IBinder onBind(Intent intent) {
        Log.i(TAG, "onBind()");
        iBinder = new MyBinder();
        Log.i(TAG, "onBind(), iBinder=" + iBinder);
        return iBinder;//return MyBinder, 从而通过ServiceConnection在activity中拿到MyBinder
    }

    @Override
    public int onStartCommand(Intent intent, int flags, int startId) {

        return super.onStartCommand(intent, flags, startId);
    }

    public int addFunction(int a, int b) {
        Log.i(TAG, "(), a=" + a + " ,b=" + b );
        int result = a + b;
        return result;
    }

    private IBinder iBinder;

    class MyBinder extends IAdd.Stub {

        @Override
        public int add(int a, int b) throws RemoteException {
            int result =  addFunction(a, b);
            return result;
        } //通过Binder实例将service中的方法暴露出去
    }

}

项目源码:https://github.com/helloyzp/BinderAplusB

源码分析

Client端调用iAdd.add(1, 2);最终是如何调用Server端的addFunction()方法的

客户端Client通过ServiceConnectio获得Server的IBinder对象

    ServiceConnection serviceConnection = new ServiceConnection() {
        @Override
        public void onServiceConnected(ComponentName componentName, IBinder iBinder) {

            binder = iBinder;
            iAdd = IAdd.Stub.asInterface(iBinder);

        }

        @Override
        public void onServiceDisconnected(ComponentName componentName) {

        }
    };

这里的onServiceConnected(ComponentName componentName, IBinder iBinder)方法返回的并不是Server的MyService中创建的MyBinder对象本身,而是一个代理对象BinderProxy。(如果没有跨进程,则该方法返回的就是MyService中创建的MyBinder对象)。

iAdd是什么对象呢,看下IAdd.Stub.asInterface()方法:

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

最终执行的是

return new com.binder.aidl.IAdd.Stub.Proxy(obj);

所以iAdd其实是一个Proxy对象:

 private static class Proxy implements com.binder.aidl.IAdd {
            private android.os.IBinder mRemote;

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

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

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

            @Override
            public int add(int a, int b) throws android.os.RemoteException {
                android.os.Parcel _data = android.os.Parcel.obtain();
                android.os.Parcel _reply = android.os.Parcel.obtain();
                int _result;
                try {
                    _data.writeInterfaceToken(DESCRIPTOR);
                    _data.writeInt(a);
                    _data.writeInt(b);
                    mRemote.transact(Stub.TRANSACTION_add, _data, _reply, 0);
                    _reply.readException();
                    _result = _reply.readInt();
                } finally {
                    _reply.recycle();
                    _data.recycle();
                }
                return _result;
            }
        }

所以当点击按钮,执行 result = iAdd.add(1, 2); 这句代码时,调用的是上面Proxy对象的add()方法:

  @Override
            public int add(int a, int b) throws android.os.RemoteException {
                android.os.Parcel _data = android.os.Parcel.obtain();
                android.os.Parcel _reply = android.os.Parcel.obtain();
                int _result;
                try {
                    _data.writeInterfaceToken(DESCRIPTOR);
                    _data.writeInt(a);
                    _data.writeInt(b);
                    mRemote.transact(Stub.TRANSACTION_add, _data, _reply, 0);
                    _reply.readException();
                    _result = _reply.readInt();
                } finally {
                    _reply.recycle();
                    _data.recycle();
                }
                return _result;
            }

关键的代码是这句:

 mRemote.transact(Stub.TRANSACTION_add, _data, _reply, 0);

而这个mRemote对象就是上面onServiceConnected()方法返回的BinderProxy对象,BinderProxy类在Binder.java文件中,看下该类的transact()方法:

    public boolean transact(int code, Parcel data, Parcel reply, int flags) throws RemoteException {
        Binder.checkParcel(this, code, data, "Unreasonably large binder buffer");

        if (mWarnOnBlocking && ((flags & FLAG_ONEWAY) == 0)) {
            // For now, avoid spamming the log by disabling after we've logged
            // about this interface at least once
            mWarnOnBlocking = false;
            Log.w(Binder.TAG, "Outgoing transactions from this process must be FLAG_ONEWAY",
                    new Throwable());
        }

        final boolean tracingEnabled = Binder.isTracingEnabled();
        if (tracingEnabled) {
            final Throwable tr = new Throwable();
            Binder.getTransactionTracker().addTrace(tr);
            StackTraceElement stackTraceElement = tr.getStackTrace()[1];
            Trace.traceBegin(Trace.TRACE_TAG_ALWAYS,
                    stackTraceElement.getClassName() + "." + stackTraceElement.getMethodName());
        }
        try {
            return transactNative(code, data, reply, flags);
        } finally {
            if (tracingEnabled) {
                Trace.traceEnd(Trace.TRACE_TAG_ALWAYS);
            }
        }
    }

这里关键的就是调用了transactNative()方法,看下该方法

    public native boolean transactNative(int code, Parcel data, Parcel reply,
            int flags) throws RemoteException;

可以看到,这个方法是native方法,这个方法其实是进行底层Binder驱动(C++层代码)发送消息的相关过程。
底层Binder驱动(C++层代码)最终会调用Binder的execTransact()方法

    // Entry point from android_util_Binder.cpp's onTransact
    private boolean execTransact(int code, long dataObj, long replyObj,
            int flags) {
        Parcel data = Parcel.obtain(dataObj);
        Parcel reply = Parcel.obtain(replyObj);
        // theoretically, we should call transact, which will call onTransact,
        // but all that does is rewind it, and we just got these from an IPC,
        // so we'll just call it directly.
        boolean res;
        // Log any exceptions as warnings, don't silently suppress them.
        // If the call was FLAG_ONEWAY then these exceptions disappear into the ether.
        final boolean tracingEnabled = Binder.isTracingEnabled();
        try {
            if (tracingEnabled) {
                Trace.traceBegin(Trace.TRACE_TAG_ALWAYS, getClass().getName() + ":" + code);
            }
            res = onTransact(code, data, reply, flags);
        } catch (RemoteException|RuntimeException e) {
            if (LOG_RUNTIME_EXCEPTION) {
                Log.w(TAG, "Caught a RuntimeException from the binder stub implementation.", e);
            }
            if ((flags & FLAG_ONEWAY) != 0) {
                if (e instanceof RemoteException) {
                    Log.w(TAG, "Binder call failed.", e);
                } else {
                    Log.w(TAG, "Caught a RuntimeException from the binder stub implementation.", e);
                }
            } else {
                reply.setDataPosition(0);
                reply.writeException(e);
            }
            res = true;
        } catch (OutOfMemoryError e) {
            // Unconditionally log this, since this is generally unrecoverable.
            Log.e(TAG, "Caught an OutOfMemoryError from the binder stub implementation.", e);
            RuntimeException re = new RuntimeException("Out of memory", e);
            reply.setDataPosition(0);
            reply.writeException(re);
            res = true;
        } finally {
            if (tracingEnabled) {
                Trace.traceEnd(Trace.TRACE_TAG_ALWAYS);
            }
        }
        checkParcel(this, code, reply, "Unreasonably large binder reply buffer");
        reply.recycle();
        data.recycle();

        // Just in case -- we are done with the IPC, so there should be no more strict
        // mode violations that have gathered for this thread.  Either they have been
        // parceled and are now in transport off to the caller, or we are returning back
        // to the main transaction loop to wait for another incoming transaction.  Either
        // way, strict mode begone!
        StrictMode.clearGatheredViolations();

        return res;
    }

上面最关键的是调用了Binder的onTransact()方法,而Stub类重写了onTransact()方法,看下Stub类的onTransact()方法:

        @Override
        public boolean onTransact(int code, android.os.Parcel data, android.os.Parcel reply, int flags) throws android.os.RemoteException {
            switch (code) {
                case INTERFACE_TRANSACTION: {
                    reply.writeString(DESCRIPTOR);
                    return true;
                }
                case TRANSACTION_add: {
                    data.enforceInterface(DESCRIPTOR);
                    int _arg0;
                    _arg0 = data.readInt();
                    int _arg1;
                    _arg1 = data.readInt();
                    int _result = this.add(_arg0, _arg1);
                    reply.writeNoException();
                    reply.writeInt(_result);
                    return true;
                }
            }
            return super.onTransact(code, data, reply, flags);
        }

可以看到调用了Stub类的add()方法,而MyBinder重写了Stub类的add()方法:

    class MyBinder extends IAdd.Stub {

        @Override
        public int add(int a, int b) throws RemoteException {
            int result =  addFunction(a, b);
            return result;
        } 
    }

add()方法里调用了addFunction()方法,到这里就完成了Server端的addFunction()方法的完整调用过程。

上述过程时序图:

在这里插入图片描述
总结:
Proxy是client端创建的用于向server端发送消息的代理(Proxy对象实现了IAdd接口,并且维护着一个Server端返回的BinderProxy对象),而Stub对象(也实现了IAdd接口)是server端用于接收消息的。client端通过BinderProxy对象的transact()方法将消息发送给底层Binder驱动,底层Binder驱动最终会将消息传递给Server端的Stub对象的onTransact()方法。

调用了 bindService() 后,onServiceConnected()方法的iBinder对象是如何返回的

执行 bindService(intent, serviceConnection, BIND_AUTO_CREATE);
调用的是ContextWrapper的bindService()方法:

    @Override
    public boolean bindService(Intent service, ServiceConnection conn,
            int flags) {
        return mBase.bindService(service, conn, flags);
    }

mBase是一个ContextImpl对象,看下ContextImpl的bindService()方法:

    @Override
    public boolean bindService(Intent service, ServiceConnection conn,
            int flags) {
        warnIfCallingFromSystemProcess();
        return bindServiceCommon(service, conn, flags, mMainThread.getHandler(), getUser());
    }

会调用bindServiceCommon()方法,看下该方法:

private boolean bindServiceCommon(Intent service, ServiceConnection conn, int flags, Handler
            handler, UserHandle user) {
        // Keep this in sync with DevicePolicyManager.bindDeviceAdminServiceAsUser.
        IServiceConnection sd;
        if (conn == null) {
            throw new IllegalArgumentException("connection is null");
        }
        if (mPackageInfo != null) {
            sd = mPackageInfo.getServiceDispatcher(conn, getOuterContext(), handler, flags);
        } else {
            throw new RuntimeException("Not supported in system context");
        }
        validateServiceIntent(service);
        try {
            IBinder token = getActivityToken();
            if (token == null && (flags&BIND_AUTO_CREATE) == 0 && mPackageInfo != null
                    && mPackageInfo.getApplicationInfo().targetSdkVersion
                    < android.os.Build.VERSION_CODES.ICE_CREAM_SANDWICH) {
                flags |= BIND_WAIVE_PRIORITY;
            }
            service.prepareToLeaveProcess(this);
            int res = ActivityManager.getService().bindService(
                mMainThread.getApplicationThread(), getActivityToken(), service,
                service.resolveTypeIfNeeded(getContentResolver()),
                sd, flags, getOpPackageName(), user.getIdentifier());
            if (res < 0) {
                throw new SecurityException(
                        "Not allowed to bind to service " + service);
            }
            return res != 0;
        } catch (RemoteException e) {
            throw e.rethrowFromSystemServer();
        }
    }

这里会用ServiceDispatcher对象维护着ServiceConnection对象conn,ServiceDispatcher同时还维护着一个ServiceDispatcher.InnerConnection对象,ServiceDispatcher.InnerConnection对象是一个Binder,代表着Client端传递给AMS的binder。

1.bindService()的过程,我们要关心的binder有两个:

  • 一个是远端service的binder,有了它客户端进程才能跨进程调用service中的方法;
  • 另一个是binder是客户端传递给AMS的,有了这个binder,AMS才会在逻辑连接建立之后与client进程跨进程通信,客户端进而调用ServiceConnection接口的onServiceConnected()和onServiceDisconnected()。


2.client进程与AMS跨进程通信相关的类有IServiceConnection,IServiceConnection.Stub,IServiceConnection.Stub.Proxy,ServiceDispatcher.InnerConnection(继承自IServiceConnection.Stub)。
ServiceDispatcher.InnerConnection是client进程传给AMS的binder,IServiceConnection.Stub.Proxy是AMS向client进程发送数据用的。

bindServiceCommon()方法里最关键的是调用ActivityManager.getService().bindService()进行服务绑定,看下ActivityManager.getService()方法:

    public static IActivityManager getService() {
        return IActivityManagerSingleton.get();
    }

    private static final Singleton<IActivityManager> IActivityManagerSingleton =
            new Singleton<IActivityManager>() {
                @Override
                protected IActivityManager create() {
                    final IBinder b = ServiceManager.getService(Context.ACTIVITY_SERVICE);
                    final IActivityManager am = IActivityManager.Stub.asInterface(b);
                    return am;
                }
            };

可以看到ActivityManager.getService()通过ServiceManager返回的是一个IActivityManager对象,这个对象其实就是ActivityManagerService对象,看下ActivityManagerService的bindService()方法(调用ActivityManagerService的bindService()方法就是client进程与AMS所在进程的一次跨进程通信过程):

 public int bindService(IApplicationThread caller, IBinder token, Intent service,
            String resolvedType, IServiceConnection connection, int flags, String callingPackage,
            int userId) throws TransactionTooLargeException {
        enforceNotIsolatedCaller("bindService");

        // Refuse possible leaked file descriptors
        if (service != null && service.hasFileDescriptors() == true) {
            throw new IllegalArgumentException("File descriptors passed in Intent");
        }

        if (callingPackage == null) {
            throw new IllegalArgumentException("callingPackage cannot be null");
        }

        synchronized(this) {
            return mServices.bindServiceLocked(caller, token, service,
                    resolvedType, connection, flags, callingPackage, userId);
        }
    }

方法里面最关键的是调用了mServices.bindServiceLocked(),mServices是一个ActiveServices对象,看下ActiveServices的bindServiceLocked():

    int bindServiceLocked(IApplicationThread caller, IBinder token, Intent service,
            String resolvedType, final IServiceConnection connection, int flags,
            String callingPackage, final int userId) throws TransactionTooLargeException {
		
	...
	
	requestServiceBindingLocked(s, b.intent, callerFg, false);        

	...
	
	
    return 1;
}

看下requestServiceBindingLocked()方法:

    private final boolean requestServiceBindingLocked(ServiceRecord r, IntentBindRecord i,
            boolean execInFg, boolean rebind) throws TransactionTooLargeException {
        if (r.app == null || r.app.thread == null) {
            // If service is not currently running, can't yet bind.
            return false;
        }
  
  	...

    r.app.thread.scheduleBindService(r, i.intent.getIntent(), rebind,
                        r.app.repProcState);

	...

        return true;
    }

方法里面最关键的是调用 r.app.thread.scheduleBindService(r, i.intent.getIntent(), rebind,
r.app.repProcState); 这个r.app.thread是IApplicationThread对象,具体的实现类是ApplicationThreadNative,看下ApplicationThreadNative的scheduleBindService()方法:

    public final void scheduleBindService(IBinder token, Intent intent, boolean rebind,
            int processState) throws RemoteException {
        Parcel data = Parcel.obtain();
        data.writeInterfaceToken(IApplicationThread.descriptor);
        data.writeStrongBinder(token);
        intent.writeToParcel(data, 0);
        data.writeInt(rebind ? 1 : 0);
        data.writeInt(processState);
        mRemote.transact(SCHEDULE_BIND_SERVICE_TRANSACTION, data, null,
                IBinder.FLAG_ONEWAY);
        data.recycle();
    }

mRemote.transact()会将消息发送到底层Binder驱动,最终发给Server端,然后会调用Server端进程的ApplicationThread(ApplicationThread是ActivityThread的内部类)的scheduleBindService()方法:

private class ApplicationThread extends IApplicationThread.Stub {
       
       	...

        public final void scheduleCreateService(IBinder token,
                ServiceInfo info, CompatibilityInfo compatInfo, int processState) {
            updateProcessState(processState, false);
            CreateServiceData s = new CreateServiceData();
            s.token = token;
            s.info = info;
            s.compatInfo = compatInfo;

            sendMessage(H.CREATE_SERVICE, s);
        }

        public final void scheduleBindService(IBinder token, Intent intent,
                boolean rebind, int processState) {
            updateProcessState(processState, false);
            BindServiceData s = new BindServiceData();
            s.token = token;
            s.intent = intent;
            s.rebind = rebind;

            if (DEBUG_SERVICE)
                Slog.v(TAG, "scheduleBindService token=" + token + " intent=" + intent + " uid="
                        + Binder.getCallingUid() + " pid=" + Binder.getCallingPid());
            sendMessage(H.BIND_SERVICE, s);
        }

	...
	

最终会调用ActivityThread类的handleBindService()方法:

    private void handleBindService(BindServiceData data) {
        Service s = mServices.get(data.token);
      
      ...

       IBinder binder = s.onBind(data.intent);
       ActivityManager.getService().publishService(data.token, data.intent, binder);

	  ...

                                
    }

主要做两个步骤,先调用自定义Service的onBind()方法得到一个IBinder对象,然后调用ActivityManager.getService().publishService(),即获取了ActivityManagerService,然后调用ActivityManagerService的publishService()方法:

    public void publishService(IBinder token, Intent intent, IBinder service) {
        // Refuse possible leaked file descriptors
        if (intent != null && intent.hasFileDescriptors() == true) {
            throw new IllegalArgumentException("File descriptors passed in Intent");
        }

        synchronized(this) {
            if (!(token instanceof ServiceRecord)) {
                throw new IllegalArgumentException("Invalid service token");
            }
            mServices.publishServiceLocked((ServiceRecord)token, intent, service);
        }
    }

关键调用了ActiveServices的publishServiceLocked()方法:

    void publishServiceLocked(ServiceRecord r, Intent intent, IBinder service) {
      
        ...


       c.conn.connected(r.name, service, false);
 
  		...


    }

调用了c.conn.connected()方法(c.conn是一个IServiceConnection对象,实现类是IServiceConnection.Stub.Proxy),把数据发给Binder驱动,最终Binder驱动会把数据发给Client进程的ServiceDispatcher.InnerConnection的connected()方法。
(ServiceDispatcher是LoadedApk的内部类),

    static final class ServiceDispatcher {
        private final ServiceDispatcher.InnerConnection mIServiceConnection;
        private final ServiceConnection mConnection;
        private final Context mContext;
        private final Handler mActivityThread;
        private final ServiceConnectionLeaked mLocation;
        private final int mFlags;

        private RuntimeException mUnbindLocation;

        private boolean mForgotten;

        private static class ConnectionInfo {
            IBinder binder;
            IBinder.DeathRecipient deathMonitor;
        }

        private static class InnerConnection extends IServiceConnection.Stub {
            final WeakReference<LoadedApk.ServiceDispatcher> mDispatcher;

            InnerConnection(LoadedApk.ServiceDispatcher sd) {
                mDispatcher = new WeakReference<LoadedApk.ServiceDispatcher>(sd);
            }

            public void connected(ComponentName name, IBinder service, boolean dead)
                    throws RemoteException {
                LoadedApk.ServiceDispatcher sd = mDispatcher.get();
                if (sd != null) {
                    sd.connected(name, service, dead);
                }
            }
        }


		...
	

}

最终会调用ServiceDispatcher的doConnected()方法

public void doConnected(ComponentName name, IBinder service, boolean dead) {
           
           	...
           
            // If there is a new viable service, it is now connected.
            if (service != null) {
                mConnection.onServiceConnected(name, service);
            } else {
                // The binding machinery worked, but the remote returned null from onBind().
                mConnection.onNullBinding(name);
            }
        }

这里调用了mConnection的onServiceConnected()方法,把Server端的IBinder对象传给了Client端。
到此,client进程与server进程建立连接完成,client进程可以通过server返回的binder调用server的方法进行跨进程通信。

总结:
上述整个过程的关键方法调用的流程图:
在这里插入图片描述
bindService()方法执行完总共进行了6次跨进程调用。
1.client进程调用ServiceManager.getService(“activity”)方法获取到AMS
2.client进程调用AMS的bindService()方法
3.AMS调用了ApplicationThread的scheduleBindService()方法
4.server进程调用ServiceManager.getService(“activity”)方法获取到AMS
5.server进程调用AMS的publishService()方法
6.AMS调用 IServiceConnection.Stub.Proxy的connected()方法(即调用 c.conn.connected(r.name, service, false) )

参考:
Android AIDL与proxy,stub
简单理解Binder机制的原理
Android跨进程通信IPC之10——Binder之Framework层Java篇
Android Framework:Binder(6)-Java层Service的注册及跨进程调用
binderService()方法的调用过程
Android跨进程通信IPC之21–binderService(6.0)
腾讯面试题——谈一谈Binder的原理和实现一次拷贝的流程

https://www.androidos.net.cn/android/9.0.0_r8/xref/frameworks/base/core/java/android/app/ContextImpl.java
https://www.androidos.net.cn/android/9.0.0_r8/xref/frameworks/base/core/java/android/app/ActivityManager.java
https://www.androidos.net.cn/android/7.1.1_r28/xref/frameworks/base/core/java/android/app/IActivityManager.java
https://www.androidos.net.cn/android/9.0.0_r8/xref/frameworks/base/services/core/java/com/android/server/am/ActivityManagerService.java
https://www.androidos.net.cn/android/9.0.0_r8/xref/frameworks/base/services/core/java/com/android/server/am/ActiveServices.java
https://www.androidos.net.cn/android/9.0.0_r8/xref/frameworks/base/core/java/android/os/ServiceManager.java

https://www.androidos.net.cn/android/7.1.1_r28/xref/frameworks/base/core/java/android/app/IApplicationThread.java
https://www.androidos.net.cn/android/7.1.1_r28/xref/frameworks/base/core/java/android/app/ApplicationThreadNative.java
https://www.androidos.net.cn/android/9.0.0_r8/xref/frameworks/base/core/java/android/app/ActivityThread.java

https://www.androidos.net.cn/android/9.0.0_r8/xref/frameworks/base/core/java/android/os/Binder.java
https://www.androidos.net.cn/android/9.0.0_r8/xref/frameworks/base/core/jni/AndroidRuntime.cpp
https://www.androidos.net.cn/android/9.0.0_r8/xref/frameworks/base/core/jni/android_util_Binder.cpp

发布了535 篇原创文章 · 获赞 94 · 访问量 74万+

猜你喜欢

转载自blog.csdn.net/yzpbright/article/details/104872024