相关文章链接:

1. Android Framework - 学习启动篇
2. Android Binder 驱动 - Media 服务的添加过程
3. Android Binder 驱动 - 启动 ServiceManager 进程
4. Android Binder 驱动 - 内核驱动层源码分析
5. Android Binder 驱动 - 从驱动层来分析服务的添加过程
6. Android Binder 驱动 - 从 Java 层来跟踪服务的查找过程
7. Android 四大组件 - 进程的 fork 创建过程

相关源码文件:

/frameworks/base/core/java/android/app/ContextImpl.java/frameworks/base/core/java/android/app/ActivityManagerNative.java/frameworks/base/core/jni/android_util_Binder.cpp/frameworks/base/core/jni/android_os_Parcel.cpp/frameworks/native/libs/binder/Parcel.cpp/drivers/staging/android/binder.c/frameworks/base/services/core/java/com/android/server/am/ActivityManagerService.java/frameworks/base/core/java/android/app/ActivityThread.java

1. 代码示例

本文主要从 bindService 的跨进程通信与数据交互来入手分析,关于其具体的创建和绑定流程,大家可以看看之前的内容。aidl 一直都是一个晦涩难懂的内容,笔者在几年前也曾反复尝试去了解其原理,其过程至今想想仍然是心有余悸,因此建议大家如果是刚入手 Android ,只需要了解开发套路就可以了。但还是倡导大家,等有了一定技术沉淀之后,要尝试着去理解其内部实现原理。我们先来看一个简单的示例代码

// 客户端public class MainActivity extends AppCompatActivity {    // 客户端一定要获取aidl的实例    private UserAidl mUserAidl;    private ServiceConnection mServiceConn = new ServiceConnection() {        @Override        public void onServiceConnected(ComponentName name, IBinder service) {            // 链接好了  service就是服务端给我们的 IBinder            mUserAidl = UserAidl.Stub.asInterface(service);        }        @Override        public void onServiceDisconnected(ComponentName name) {            // 断开链接        }    };    @Override    protected void onCreate(Bundle savedInstanceState) {        super.onCreate(savedInstanceState);        setContentView(R.layout.activity_main);        Intent intent = new Intent(this,MessageService.class);        bindService(intent, mServiceConn, Context.BIND_AUTO_CREATE);    }    public void testClick(View view) {        try {            Log.e("TAG","userName = "+mUserAidl.getUserName());        } catch (RemoteException e) {            e.printStackTrace();        }    }}// 服务端public class MessageService extends Service {    @Override    public IBinder onBind(Intent intent) {        // 绑定        return mBinder;    }        private final UserAidl.Stub mBinder = new UserAidl.Stub()    {        @Override        public String getUserName() throws RemoteException {            return "Darren@163.com";        }        @Override        public String getUserPassword() throws RemoteException {            return "19940223";        }    };}

2. Binder 对象初始化

服务端返回的是 Aidl.Stub 服务对象,这个对象是我们自定义 aidl 后,编译器帮我们自动生成的一个对象,该对象继承自 Binder.java 对象,子类在构建对象时默认会执行父类的构造函数,也就是说会执行 Binder.java 的构造函数:

    public Binder() {        // 调用初始化方法        init();    }    // 调用 native 方法    private native final void init();    static void android_os_Binder_init(JNIEnv* env, jobject obj)    {      JavaBBinderHolder* jbh = new JavaBBinderHolder();      ...      env->SetLongField(obj, gBinderOffsets.mObject, (jlong)jbh);    }

由上面的源码可以看出,Stub 对象在构建的时候,会对应绑定 native 层的一个 JavaBBinderHolder 对象,至于为什么要创建 native 层对象,是因为跨进程通信的核心是要基于 binder 驱动。

3. Stub 对象传递

    @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;        ...        if (mPackageInfo != null) {            sd = mPackageInfo.getServiceDispatcher(conn, getOuterContext(),                    mMainThread.getHandler(), 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();            // 像 AMS 发起 bind 请求            int res = ActivityManagerNative.getDefault().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 new RuntimeException("Failure from system", e);        }    }

由于 ServiceConnection 是一个普通对象,并不能用来做跨进程传递,所以在 bindService 的源码底层,系统帮我包装了一个可以跨进程传递的 IServiceConnection 对象,该对象是一个 Stub 对象。

    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);        // asBinder 返回的是 connection 自身        data.writeStrongBinder(connection.asBinder());        data.writeInt(flags);        data.writeString(callingPackage);        data.writeInt(userId);        mRemote.transact(BIND_SERVICE_TRANSACTION, data, reply, 0);        reply.readException();        int res = reply.readInt();        data.recycle();        reply.recycle();        return res;    }    static void android_os_Parcel_writeStrongBinder(JNIEnv* env, jclass clazz, jlong nativePtr, jobject object)    {      Parcel* parcel = reinterpret_cast(nativePtr);      if (parcel != NULL) {          const status_t err = parcel->writeStrongBinder(ibinderForJavaObject(env, object));          if (err != NO_ERROR) {              signalExceptionForError(env, clazz, err);          }      }    }    sp ibinderForJavaObject(JNIEnv* env, jobject obj)    {      if (obj == NULL) return NULL;      // 返回的其实是一个 JavaBBinder      if (env->IsInstanceOf(obj, gBinderOffsets.mClass)) {          JavaBBinderHolder* jbh = (JavaBBinderHolder*) env->GetLongField(obj, gBinderOffsets.mObject);          return jbh != NULL ? jbh->get(env, obj) : NULL;      }      ...      return NULL;    }    // 这个之前的文章有讲就不再贴代码了    status_t Parcel::writeStrongBinder(const sp& val)    {      return flatten_binder(ProcessState::self(), val, this);    }

上面会调用 writeStrongBinder 方法将 IServiceConnection 对象写入到 Parcel 内存中,其实也就是将 native 层的 JavaBBinder 对象写入到 native 层的 Parcel 中,关于 flatten_binder 方法的实现原理大家可以参考之前的文章。

4. 客户端驱动层处理过程

我们向 ServiceManager 查询到的 AMS 对象,其实是一个 BindProxy.java 对象,对应 native 层的 BpBinder 对象,也就是说 mRemote.transact 最后会调用 BpBinder.cpp 的 transact 方法。

static void binder_transaction(struct binder_proc *proc,       struct binder_thread *thread,       struct binder_transaction_data *tr, int reply){if (reply) {...} else {if (tr->target.handle) {struct binder_ref *ref;            // 找到 AMS 目标进程的 binder_node 和 binder_procref = binder_get_ref(proc, tr->target.handle);target_node = ref->node;} else {...}                ...}...off_end = (void *)offp + tr->offsets_size;for (; offp < off_end; offp++) {struct flat_binder_object *fp;        ...fp = (struct flat_binder_object *)(t->buffer->data + *offp);switch (fp->type) {case BINDER_TYPE_BINDER:case BINDER_TYPE_WEAK_BINDER: {struct binder_ref *ref;            // 先通过 fp->binder 从自己进程找 binder_node struct binder_node *node = binder_get_node(proc, fp->binder);            // 刚开始第一次是找不到的if (node == NULL) {                // 把他添加到当前进程node = binder_new_node(proc, fp->binder, fp->cookie);...}// 添加到目标进程ref = binder_get_ref_for_node(target_proc, node);if (ref == NULL) {return_error = BR_FAILED_REPLY;goto err_binder_get_ref_for_node_failed;}            // 替换 type 和 handle 值 if (fp->type == BINDER_TYPE_BINDER)fp->type = BINDER_TYPE_HANDLE;elsefp->type = BINDER_TYPE_WEAK_HANDLE;fp->handle = ref->desc;} break;...}}t->work.type = BINDER_WORK_TRANSACTION;list_add_tail(&t->work.entry, target_list);tcomplete->type = BINDER_WORK_TRANSACTION_COMPLETE;list_add_tail(&tcomplete->entry, &thread->todo);        // 唤醒目标进程的等待队列if (target_wait)wake_up_interruptible(target_wait);return;}

5. AMS 服务端处理 bind 过程

AMS 接收到 bindService 请求后会去读取 IServiceConnection 对象,注意这里读取到的 IServiceConnection 其实已经是本地的一个 BpBinder 了,只不过我们可以通过 BpBinder 对象回调到客户端的 onServiceConnected 绑定方法。

case BIND_SERVICE_TRANSACTION: {  data.enforceInterface(IActivityManager.descriptor);  IBinder b = data.readStrongBinder();  IApplicationThread app = ApplicationThreadNative.asInterface(b);  IBinder token = data.readStrongBinder();  Intent service = Intent.CREATOR.createFromParcel(data);  String resolvedType = data.readString();  b = data.readStrongBinder();  int fl = data.readInt();  String callingPackage = data.readString();  int userId = data.readInt();  IServiceConnection conn = IServiceConnection.Stub.asInterface(b);  int res = bindService(app, token, service, resolvedType, conn, fl, callingPackage, userId);  reply.writeNoException();  reply.writeInt(res);  return true;}static jobject android_os_Parcel_readStrongBinder(JNIEnv* env, jclass clazz, jlong nativePtr){    Parcel* parcel = reinterpret_cast(nativePtr);    if (parcel != NULL) {        return javaObjectForIBinder(env, parcel->readStrongBinder());    }    return NULL;}sp Parcel::readStrongBinder() const{    sp val;    unflatten_binder(ProcessState::self(), *this, &val);    return val;}status_t unflatten_binder(const sp& proc,    const Parcel& in, sp* out){    const flat_binder_object* flat = in.readObject(false);    if (flat) {        switch (flat->type) {            case BINDER_TYPE_BINDER:                *out = reinterpret_cast(flat->cookie);                return finish_unflatten_binder(NULL, *flat, in);            case BINDER_TYPE_HANDLE:                *out = proc->getStrongProxyForHandle(flat->handle);                return finish_unflatten_binder(                    static_cast(out->get()), *flat, in);        }    }    return BAD_TYPE;}

6. 进程循环等待处理请求

服务端处理客户端的请求,肯定会有一个等待执行处理的过程,但整个交互逻辑流程分析下来,并没有发现服务端有等待的过程。那服务端到底是怎样进入等待的呢?这个得追溯到 Zygote 创建进程的流程去。

    public static final void zygoteInit(int targetSdkVersion, String[] argv, ClassLoader classLoader)            throws ZygoteInit.MethodAndArgsCaller {        if (DEBUG) Slog.d(TAG, "RuntimeInit: Starting application from zygote");        Trace.traceBegin(Trace.TRACE_TAG_ACTIVITY_MANAGER, "RuntimeInit");        redirectLogStreams();        commonInit();        nativeZygoteInit();        applicationInit(targetSdkVersion, argv, classLoader);    }    private static final native void nativeZygoteInit();    static void com_android_internal_os_RuntimeInit_nativeZygoteInit(JNIEnv* env, jobject clazz)    {      gCurRuntime->onZygoteInit();    }    virtual void onZygoteInit()    {        // 初始化 binder 驱动        sp proc = ProcessState::self();        ALOGV("App process: starting thread pool.\n");        // 启动一个线程进入循环处理客户端 binder 请求        proc->startThreadPool();    }        void ProcessState::spawnPooledThread(bool isMain)    {      if (mThreadPoolStarted) {          String8 name = makeBinderThreadName();          ALOGV("Spawning new pooled thread, name=%s\n", name.string());          sp t = new PoolThread(isMain);          t->run(name.string());      }    }    class PoolThread : public Thread    {    public:        PoolThread(bool isMain)            : mIsMain(isMain)        {        }        protected:        virtual bool threadLoop()        {            IPCThreadState::self()->joinThreadPool(mIsMain);            return false;        }            const bool mIsMain;    };    void IPCThreadState::joinThreadPool(bool isMain)    {      ...      status_t result;      do {          ...          // 进入 binder 驱动的 wait 队列上进行等待          result = getAndExecuteCommand();          ...      } while (result != -ECONNREFUSED && result != -EBADF);      ...    }

视频地址:https://pan.baidu.com/s/1qd2UafSGELpKwBsT30IuHw
视频密码:0tgv

更多相关文章

  1. Android(安卓)关闭整个应用程序
  2. android kill process 杀死进程的方法
  3. 谈谈Binder
  4. AIDL进程间通信
  5. android4.0.3多点触摸屏设备设置
  6. Android(安卓)Application详解
  7. 使用AIDL实现进程间的通信
  8. android深度搜索学习笔记三( 蜂鸣器驱动)
  9. Android开发之多线程处理、Handler详解

随机推荐

  1. android之Buffer类及子类学习
  2. Android(安卓)layout_alignBottom 注意事
  3. Android(安卓)获取联系人
  4. Android(安卓)View And Activity
  5. Android
  6. 多个控件跑马灯效果
  7. Android(安卓)studio 多渠道打包以及自定
  8. Android(安卓)总结 Android(安卓)系统架
  9. android网络访问兼容
  10. android Activity 半透明效果