进程间的通信-IPC(机制)Binder的原理和源码阅读

版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/qq_24675479/article/details/80838654

IPC进程通信的小案例

MessageService

public class MessageService extends Service {
    @Nullable
    @Override
    public IBinder onBind(Intent intent) {
        //绑定
        return mBinder;
    }
   private final UserAidl.Stub mBinder=new UserAidl.Stub() {
       @Override
       public String getUserName() throws RemoteException {
           return "[email protected]";
       }

       @Override
       public String getUserPwd() throws RemoteException {
           return "19931005";
       }
   };
}

userAild

interface UserAidl {
   String getUserName();
   String getUserPwd();
}

MainActivity

//启动一个服务,等待A应用连接 B
        startService(new Intent(this, MessageService.class));
        //A应用的代码
        Intent intent = new Intent(this, MessageService.class);
        bindService(intent, mServiceConn, Context.BIND_AUTO_CREATE);

两个按钮点击事件

  public void getUserName(View view) {
        try {
            Log.e("TAG","用户名"+mUserAidl.getUserName());
        } catch (RemoteException e) {
            e.printStackTrace();
        }
    }

    public void getPassword(View view) {
        try {
            Log.e("TAG","密码"+mUserAidl.getUserPwd());
        } catch (RemoteException e) {
            e.printStackTrace();
        }
    }

IPC进程通信应用层的走向

bindService->service的onBind方法->自己定义的Aidl文件->Proxy->getUserName()

                    _data.writeInterfaceToken(DESCRIPTOR);
                   //mRemote.transact这个方法最后会走向new 自己的aidl文件时的onTransact方法
                    mRemote.transact(Stub.TRANSACTION_getUserName, _data, _reply, 0);
                    _reply.readException();
                    _result = _reply.readString();
   @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_getUserName: {
                    data.enforceInterface(DESCRIPTOR);
                    java.lang.String _result = this.getUserName();
                    reply.writeNoException();
                    reply.writeString(_result);
                    return true;
                }
                case TRANSACTION_getUserPwd: {
                    data.enforceInterface(DESCRIPTOR);
                   //获得自己重写的getUserPwd方法返回值
                    java.lang.String _result = this.getUserPwd();
                    reply.writeNoException();
                    reply.writeString(_result);
                    return true;
                }
            }

->自己new的ServiceConnection中的onServiceConnected和onServiceDisconnected方法

源码分析

bindService(intent, mServiceConn, Context.BIND_AUTO_CREATE);源码分析

 @Override
    public boolean bindService(Intent service, ServiceConnection conn,
            int flags) {
          //这个方法是个context的抽象方法
        return mBase.bindService(service, conn, flags);
    }

最终走向ContextImpl的bindService方法

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

bindServiceCommon方法主要看这个方法

  int res = ActivityManagerNative.getDefault().bindService(
                mMainThread.getApplicationThread(), getActivityToken(), service,
                service.resolveTypeIfNeeded(getContentResolver()),
                sd, flags, getOpPackageName(), user.getIdentifier());

ActivityManagerNative.getDefault()实际返回的IActivityManager

 static public IActivityManager getDefault() {
        return gDefault.get();
    }

我们看下gDefault源码

private static final Singleton<IActivityManager> gDefault = new Singleton<IActivityManager>() {
        protected IActivityManager create() {
            IBinder b = ServiceManager.getService("activity");
            if (false) {
                Log.v("ActivityManager", "default service binder = " + b);
            }
            IActivityManager am = asInterface(b);
            if (false) {
                Log.v("ActivityManager", "default service = " + am);
            }
            return am;
        }
    };

提下:activity的启动流程也会走向这里,这里我们可以知道,activity启动activity实际也是跨进程

继续分析ActivityManagerNative.getDefault().bindService我们会发现这个实际是个抽象的方法,我们看下它的实现类ActivityManagerService中的bindService源码主要看最后一行

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

直接看bindServiceLocked中的requestServiceBindingLocked这个方法

requestServiceBindingLocked(s, b.intent, callerFg, false);

直接看上面的这行代码

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

r.app.thread实际是IApplicationThread,我们直接看IApplicationThread的实现类ActivityThread中的scheduleBindService的源码

  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());
               //最终实际是走向Handler的
            sendMessage(H.BIND_SERVICE, s);
        }
 case BIND_SERVICE:
                    Trace.traceBegin(Trace.TRACE_TAG_ACTIVITY_MANAGER, "serviceBind");
                    handleBindService((BindServiceData)msg.obj);
                    Trace.traceEnd(Trace.TRACE_TAG_ACTIVITY_MANAGER);
                    break;

handleBindService源码分析

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 binder = s.onBind(data.intent);
                      //随后将自己的IBinder传下去
                        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);
                }
            }
        }
    }

我们会发现publishService实际又是走到IActivityManager中的抽象方法,回到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);
        }
    }

publishServiceLocked中主要看这个方法

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

这时候我们会发现c.conn实际是 final IServiceConnection conn,这时候我们看不下去了只能回去看ContextImpl中的unbindService

 @Override
    public void unbindService(ServiceConnection conn) {
        if (conn == null) {
            throw new IllegalArgumentException("connection is null");
        }
        if (mPackageInfo != null) {
              //看到就这里了
            IServiceConnection sd = mPackageInfo.forgetServiceDispatcher(
                    getOuterContext(), conn);
            try {
                ActivityManagerNative.getDefault().unbindService(sd);
            } catch (RemoteException e) {
            }
        } else {
            throw new RuntimeException("Not supported in system context");
        }
    }

forgetServiceDispatcher->sd.getIServiceConnection()

 IServiceConnection getIServiceConnection() {
            return mIServiceConnection;
        }

private final ServiceDispatcher.InnerConnection mIServiceConnection;
 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) throws RemoteException {
                LoadedApk.ServiceDispatcher sd = mDispatcher.get();
                if (sd != null) {
                    sd.connected(name, service);
                }
            }
        }

sd.connected源码分析

 public void connected(ComponentName name, IBinder service) {
            if (mActivityThread != null) {
                mActivityThread.post(new RunConnection(name, service, 0));
            } else {
                doConnected(name, service);
            }
        }
    public void doConnected(ComponentName name, IBinder service) {
       if (service != null) {
                //自己new时必须写的onServiceConnected方法
                mConnection.onServiceConnected(name, service);
            }
}

IPC机制-binder的原理和源码分析.png

猜你喜欢

转载自blog.csdn.net/qq_24675479/article/details/80838654