進程間的通信-IPC(機制)Binder的原理和源碼閱讀

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

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章