美文网首页
Binder机制

Binder机制

作者: 爬行的蚂蚁2725 | 来源:发表于2019-03-02 17:04 被阅读0次

    Binder概念
    1 机制 Binder是一种Android中实现跨进程通信(IPC)的方式
    2 从组成,设备来说,什么是Binder Binder还是一种虚拟的物理设备驱动 /dev/binder
    3 从Android代码来说 BInder 是一个类,实现了IBinder接口

    可以这么理解AIDL和Binder的关系:
    AIDL:是定义的一种通信规范
    BInder:是一种具体的通信媒介

    跨进程通信方式实现:
    服务端
    第一步:
    创建一个服务Service,返回一个IBinder对象

    public class MyService extends Service {
        @Override
        public void onCreate() {super.onCreate();}
        /**
         * 提供给客户端
         */
        @Nullable
        @Override
        public IBinder onBind(Intent intent) {
            //MyApp myApp;
            return new MyAppIml();
        }
    }
    

    第二步:创建一个AIDL文件
    aild文件其实是一个模板类,系统会根据这个模板自动生成别的java代码

    //接口里只能定义基本的数据类型
    interface MyApp {
        String getName();
        String setName(String name);
    }
    

    第三步:build工程,系统会自动生成一些java代码

    客户端
    1.将服务端提供的AIDL文件和aild所在的包,拷贝到客户端工程
    2.build编译

    1. 在需要和服务端通信的地方调用bindService ,重写ServiceConnection对象的onServiceConnected方法,参数中的ibinder即为服务端传递过来的IBinder对象,这样便可以完成跨进程间的通信。
    public void load(View view) {
            Intent intent = new Intent();
            intent.setAction("com.example.baby.binderframwork.MyService");
            intent.setPackage("com.example.baby.binderframwork");
            //进程B 目的   binderServise  ----->  IBinder iBinder
            // c.conn.connected(r.name, service);
            bindService(intent, new ServiceConnection() {
                @Override
                public void onServiceConnected(ComponentName componentName, IBinder iBinder) {
                        //proxy   装煤炭  Proxy 对象  MyApp接口
                   MyApp myApp= MyApp.Stub.asInterface(iBinder);
                    try {
                        myApp.setName("xxx");
                        Toast.makeText(MainActivity.this, "--->  " + myApp.getName(), Toast.LENGTH_SHORT).show();
                    } catch (RemoteException e) {
                        e.printStackTrace();
                    }
                }
                @Override
                public void onServiceDisconnected(ComponentName componentName) {
                }
            }, Context.BIND_AUTO_CREATE);
        }
    

    查看通过aild文件生成的对应的java文件发现该接口继承android.os.IInterface

    public interface MyApp extends android.os.IInterface {
        /**
         * Stub表示接收方
         */
        public static abstract class Stub extends android.os.Binder implements com.example.baby.binderframwork.MyApp {
            private static final java.lang.String DESCRIPTOR = "com.example.baby.binderframwork.MyApp";
    
            /**
             * DESCRIPTOR相当于一个进程的id或tag
             */
            public Stub() {
                this.attachInterface(this, DESCRIPTOR);
            }
    
            public static com.example.baby.binderframwork.MyApp asInterface(android.os.IBinder obj) {
                if ((obj == null)) {
                    return null;
                }
      //根据DESCRIPTOR查询是否在同一个进程
                android.os.IInterface iin = obj.queryLocalInterface(DESCRIPTOR);
                if (((iin != null) && (iin instanceof com.example.baby.binderframwork.MyApp))) {
                    return ((com.example.baby.binderframwork.MyApp) iin);
                }
    //不在同一个进程则返回Proxy对象(Proxy implement MyApp)
                return new com.example.baby.binderframwork.MyApp.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_getName: {
                        data.enforceInterface(DESCRIPTOR);
                        java.lang.String _result = this.getName();
                        reply.writeNoException();
                        reply.writeString(_result);
                        return true;
                    }
                    case TRANSACTION_setName: {
                        data.enforceInterface(DESCRIPTOR);
                        java.lang.String _arg0;
                        _arg0 = data.readString();
                        java.lang.String _result = this.setName(_arg0);
                        reply.writeNoException();
                        reply.writeString(_result);
                        return true;
                    }
                }
                return super.onTransact(code, data, reply, flags);
            }
    
    //Proxy表示发送方
            private static class Proxy implements com.example.baby.binderframwork.MyApp {
                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 java.lang.String getName() throws android.os.RemoteException {
    //Parcel写入另一个进程的参数,类似于一个缓存区,用来保存传递的数据(要访问的类)
                    android.os.Parcel _data = android.os.Parcel.obtain();
                    android.os.Parcel _reply = android.os.Parcel.obtain();
                    java.lang.String _result;
                    try {
                        _data.writeInterfaceToken(DESCRIPTOR);
                        
    //调用另一个进程即Binder进程 会调用Binder中的onTransact方法
    //  TRANSACTION_getName参数为调用哪个方法(int类型)
    mRemote.transact(Stub.TRANSACTION_getName, _data, _reply, 0);
                        _reply.readException();
                        _result = _reply.readString();
                    } finally {
                        _reply.recycle();
                        _data.recycle();
                    }
                    return _result;
                }
    
                @Override
                public java.lang.String setName(java.lang.String name) throws android.os.RemoteException {
                    android.os.Parcel _data = android.os.Parcel.obtain();
                    android.os.Parcel _reply = android.os.Parcel.obtain();
                    java.lang.String _result;
                    try {
                        _data.writeInterfaceToken(DESCRIPTOR);
                        _data.writeString(name);
                        mRemote.transact(Stub.TRANSACTION_setName, _data, _reply, 0);
                        _reply.readException();
                        _result = _reply.readString();
                    } finally {
                        _reply.recycle();
                        _data.recycle();
                    }
                    return _result;
                }
            }
    
            static final int TRANSACTION_getName = (android.os.IBinder.FIRST_CALL_TRANSACTION + 0);
            static final int TRANSACTION_setName = (android.os.IBinder.FIRST_CALL_TRANSACTION + 1);
        }
    
        public java.lang.String getName() throws android.os.RemoteException;
    
        public java.lang.String setName(java.lang.String name) throws android.os.RemoteException;
    }
    

    我们再来看下Binder的transact方法
    Binder.java

     public final boolean transact(int code, Parcel data, Parcel reply,
                int flags) throws RemoteException {
            if (false) Log.v("Binder", "Transact: " + code + " to " + this);
    //将数据写入流
            if (data != null) {
                data.setDataPosition(0);
            }
    //调用onTransact方法 进入系统进程
            boolean r = onTransact(code, data, reply, flags);
            if (reply != null) {
                reply.setDataPosition(0);
            }
            return r;
        }
    

    客户端给服务端发送消息:


    image.png

    再来看下客户端绑定服务(bindService())时的经过:

    bindService()方法的真正实现类为ContextImpl,看源码

    ContextWrapper.java

    @Override
        public boolean bindService(Intent service, ServiceConnection conn,
                int flags) {
            return 
    //mBase为Context 
    //bindService 真的实现为ContextImpl
    mBase.bindService(service, conn, flags);
        }
    

    ContextImpl.java

    @Override
        public boolean bindService(Intent service, ServiceConnection conn,
                int flags) {
            warnIfCallingFromSystemProcess();
            return bindServiceCommon(service, conn, flags, Process.myUserHandle());
        }
    
    private boolean bindServiceCommon(Intent service, ServiceConnection conn, int flags,
                UserHandle user) {
            IServiceConnection sd;
            .......
    //ActivityManagerNative.getDefault()的类型为IActivityManager
    //IActivityManager extends IInterface 类似于AIDL接口
    //ActivityManagerNative extends Binder implements IActivityManager 类似于Stub
    //ActivityManagerProxy implements IActivityManager 类似于Proxy
    //class ActivityManagerService extends ActivityManagerNative
    
    //调用ActivityManagerProxy的bindService
                int res = ActivityManagerNative.getDefault().bindService(
                    mMainThread.getApplicationThread(), getActivityToken(), service,
                    service.resolveTypeIfNeeded(getContentResolver()),
                    sd, flags, getOpPackageName(), user.getIdentifier());
               .....
        }
    

    ActivityManagerProxy.java
    ActivityManagerProxy implements IActivityManager 类似于Proxy

    public int bindService(IApplicationThread caller, IBinder token,
                Intent service, String resolvedType, IServiceConnection connection,
                int flags,  String callingPackage, int userId) throws RemoteException {
            Parcel data = Parcel.obtain();
            Parcel reply = Parcel.obtain();
            data.writeInterfaceToken(IActivityManager.descriptor);
            data.writeStrongBinder(caller != null ? caller.asBinder() : null);
            data.writeStrongBinder(token);
            service.writeToParcel(data, 0);
            data.writeString(resolvedType);
            data.writeStrongBinder(connection.asBinder());
            data.writeInt(flags);
            data.writeString(callingPackage);
            data.writeInt(userId);
    //调用另一个进程即Binder进程 会调用Binder中的onTransact方法
            mRemote.transact(BIND_SERVICE_TRANSACTION, data, reply, 0);
            reply.readException();
            int res = reply.readInt();
            data.recycle();
            reply.recycle();
            return res;
        }
    

    ActivityManagerNative.java
    ActivityManagerNative extends Binder implements IActivityManager 类似于Stub

     @Override
        public boolean onTransact(int code, Parcel data, Parcel reply, int flags)
                throws RemoteException {
    .....
    
            case BIND_SERVICE_TRANSACTION: {
                ...
    //调用ActivityManagerService的bindService
                int res = bindService(app, token, service, resolvedType, conn, fl,
                        callingPackage, userId);
                ...
                return true;
    
    }
    

    ActivityManagerService.java
    ActivityManagerService extends ActivityManagerNative
    ActivityManagerNative extends Binder implements IActivityManager 类似于Stub

    public int bindService(IApplicationThread caller, IBinder token, Intent service,
                String resolvedType, IServiceConnection connection, int flags, String callingPackage,
                int userId) throws TransactionTooLargeException {
            .....
    
            synchronized(this) {
    //调用ActiveServices的bindServiceLocked
                return mServices.bindServiceLocked(caller, token, service,
                        resolvedType, connection, flags, callingPackage, userId);
            }
        }
    

    ActiveServices.java

    int bindServiceLocked(IApplicationThread caller, IBinder token, Intent service,
                String resolvedType, IServiceConnection connection, int flags,
                String callingPackage, int userId) throws TransactionTooLargeException {
    ....
     final ProcessRecord callerApp = mAm.getRecordForAppLocked(caller);
    
    ...//检查调用者是否存在....
    
                AppBindRecord b = s.retrieveAppBindingLocked(service, callerApp);
    //创建ConnectionRecord 
                ConnectionRecord c = new ConnectionRecord(b, activity,
                        connection, flags, clientLabel, clientIntent);
    
    //得到IBinder对象,就是要回调给客户端的IBinder对象
    //并添加到集合保存
                IBinder binder = connection.asBinder();
                ArrayList<ConnectionRecord> clist = s.connections.get(binder);
                if (clist == null) {
                    clist = new ArrayList<ConnectionRecord>();
                    s.connections.put(binder, clist);
                }
                clist.add(c);
                b.connections.add(c);
                if (activity != null) {
                    if (activity.connections == null) {
                        activity.connections = new HashSet<ConnectionRecord>();
                    }
                    activity.connections.add(c);
                }
                b.client.connections.add(c);
                if ((c.flags&Context.BIND_ABOVE_CLIENT) != 0) {
                    b.client.hasAboveClient = true;
                }
                if (s.app != null) {
                    updateServiceClientActivitiesLocked(s.app, c, true);
                }
                clist = mServiceConnections.get(binder);
                if (clist == null) {
                    clist = new ArrayList<ConnectionRecord>();
                    mServiceConnections.put(binder, clist);
                }
                clist.add(c);
    
                ...进行四种情况判断...
    //1.整个进程B没有启动()
    //2.进程有了但Service没有创建(执行ActivityThread的scheduleCreateService)
    //3.进程有了Service创建了但没有被客户端绑定(执行ActivityThread的scheduleBindService)
    //4.进程有了Service创建了已经被其他客户端绑定 (执行onRebind)
    ...
    }
    

    ActivityThread.java

    public final void scheduleCreateService(IBinder token,
                    ServiceInfo info, CompatibilityInfo compatInfo, int processState) {
                ...
    //发送给Hander
                sendMessage(H.CREATE_SERVICE, s);
            }
    
    public final void scheduleBindService(IBinder token, Intent intent,
                    boolean rebind, int processState) {
                .....
    //发送给Hander
                sendMessage(H.BIND_SERVICE, s);
            }
    

    H.java extends Handler

    private void handleCreateService(CreateServiceData data) {
            // If we are getting ready to gc after going to the background, well
            // we are back active so skip it.
            unscheduleGcIdler();
    
            LoadedApk packageInfo = getPackageInfoNoCheck(
                    data.info.applicationInfo, data.compatInfo);
            Service service = null;
            try {
    //重要的地方,可以替换为我们的DexClassLoader干别的
                java.lang.ClassLoader cl = packageInfo.getClassLoader();
    //反射的方式创建Service
                service = (Service) cl.loadClass(data.info.name).newInstance();
            } catch (Exception e) {
                if (!mInstrumentation.onException(service, e)) {
                    throw new RuntimeException(
                        "Unable to instantiate service " + data.info.name
                        + ": " + e.toString(), e);
                }
            }
    
            try {
                if (localLOGV) Slog.v(TAG, "Creating service " + data.info.name);
    
                ContextImpl context = ContextImpl.createAppContext(this, packageInfo);
                context.setOuterContext(service);
    
                Application app = packageInfo.makeApplication(false, mInstrumentation);
    //调用Service生命周期中的attach方法
                service.attach(context, this, data.info.name, data.token, app,
                        ActivityManagerNative.getDefault());
    //调用Service生命周期中的onCreate方法
                service.onCreate();
                mServices.put(data.token, service);
                try {
                    ActivityManagerNative.getDefault().serviceDoneExecuting(
                            data.token, SERVICE_DONE_EXECUTING_ANON, 0, 0);
                } catch (RemoteException e) {
                    // nothing to do.
                }
            } catch (Exception e) {
                if (!mInstrumentation.onException(service, e)) {
                    throw new RuntimeException(
                        "Unable to create service " + data.info.name
                        + ": " + e.toString(), e);
                }
            }
        }
    
        private void handleBindService(BindServiceData data) {
            Service s = mServices.get(data.token);
            if (DEBUG_SERVICE)
                Slog.v(TAG, "handleBindService s=" + s + " rebind=" + data.rebind);
            if (s != null) {
                try {
                    data.intent.setExtrasClassLoader(s.getClassLoader());
                    data.intent.prepareToEnterProcess();
                    try {
                        if (!data.rebind) {
    //重点 调用service的onBind方法返回IBinder对象
                            IBinder binder = s.onBind(data.intent);
    //发送给客户端          
    ActivityManagerNative.getDefault().publishService(
                                    data.token, data.intent, binder);
                        } else {
                            s.onRebind(data.intent);
                            ActivityManagerNative.getDefault().serviceDoneExecuting(
                                    data.token, SERVICE_DONE_EXECUTING_ANON, 0, 0);
                        }
                        ensureJitEnabled();
                    } catch (RemoteException ex) {
                    }
                } catch (Exception e) {
                    if (!mInstrumentation.onException(s, e)) {
                        throw new RuntimeException(
                                "Unable to bind to service " + s
                                + " with " + data.intent + ": " + e.toString(), e);
                    }
                }
            }
        }
    

    Binder核心机制


    Binder核心机制.png

    相关文章

      网友评论

          本文标题:Binder机制

          本文链接:https://www.haomeiwen.com/subject/lteeuqtx.html