AIDL中 Binder 的具体流转过程(源码讲解)

前言

本篇文章承接上篇 Binder对象的流转(系统服务的调用过程、AIDL的使用过程)
上一篇简单笼统地说明了流转的大致方向与手段,此篇文章我们将深入代码层面,看看 Binder 到底是怎么实现的。

一、一个简单的AIDL示例

客户端:

bindService(serviceIntent, new ServiceConnection() {
    @Override
    public void onServiceConnected(ComponentName name, IBinder service) {
        Log.i(TAG, "onServiceConnected() service=" + service);
        iShopAidlInterface = IShopAidlInterface.Stub.asInterface(service);
        try {
            iShopAidlInterface.buyProduct1(9988, "大连市甘井子区");
        } catch (RemoteException e) {
            e.printStackTrace();
        }
    }

    @Override
    public void onServiceDisconnected(ComponentName name) {

    }
}, BIND_AUTO_CREATE);

服务端:

public class ShopService extends Service {
    private String TAG = "ShopService";
    public ShopService() {
    }

    private IShopAidlInterface.Stub mBinder = new IShopAidlInterface.Stub() {
        @Override
        public void buyProduct1(int productNo, String address) throws RemoteException {
            Log.i(TAG, "SERVER: receive productNo: " + productNo + ", address: " +address);
            Log.i(TAG, "YOU buy succeed!");
        }
    }
    @Override
    public IBinder onBind(Intent intent) {
        return mBinder;
    }
}

客户端调用 bindService 方法,绑定服务,在 ServiceConnection 的 onServiceConnected() 回调中得到了服务端返回的 Binder 对象。然后调用了 buyProduct1() 实现了 IPC 跨进程的业务调用。
今天要探究的问题就是,这中间发生了什么,怎么实现的?

二、Binder对象是怎么回传到 onServiceConnected(ComponentName name, IBinder service) 里的?

调用流程

ContextWrapper.java - bindService()
	ContextImpl.java - bindService() - bindServiceCommon() { getServiceDispatcher(); ActivityManager.bindService();}
ContextImpl.java
private boolean bindServiceCommon(Intent service, ServiceConnection conn, int flags, Handler
            handler, UserHandle user) {
        // Keep this in sync with DevicePolicyManager.bindDeviceAdminServiceAsUser.
        IServiceConnection sd;
        ******** 关键点一 ********
        sd = mPackageInfo.getServiceDispatcher(conn, getOuterContext(), handler, flags);
        service.prepareToLeaveProcess(this);
        ******* 关键点二 ********
        int res = ActivityManager.getService().bindService(
            mMainThread.getApplicationThread(), getActivityToken(), service,
            service.resolveTypeIfNeeded(getContentResolver()),
            sd, flags, getOpPackageName(), user.getIdentifier());
        return res;
}  

关键点一

LoadedApk.java
public final IServiceConnection getServiceDispatcher(ServiceConnection c,
            Context context, Handler handler, int flags) {
     sd = new ServiceDispatcher(c, context, handler, flags);
     return sd.getIServiceConnection();
}

static final class ServiceDispatcher {
    private final ServiceDispatcher.InnerConnection mIServiceConnection;
    private final ServiceConnection mConnection;
}

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);
        }
    }
}

private final ArrayMap<Context, ArrayMap<ServiceConnection, LoadedApk.ServiceDispatcher>> mServices 
        = new ArrayMap<>();

getServiceDispatcher() new出一个ServiceDispatcher,这个 ServiceDispatcher 的作用就是将绑定服务后得到的 Binder 对象上发到 ServiceConnection 中,使得客户端可以在回调中获取 Binder 对象。
ServiceDispatcher 维护在 mServices 成员变量中,这里的 Context 其实就是 bindService 所在的Activity,就是说一个Activity对应一个 ArrayMap,ArrayMap中 一个 ServiceConnection 对应 一个 ServiceDispatcher。

InnerConnection extends IServiceConnection.Stub很明显,InnerConnection 是一个 IPC 的服务端,AMS 使用 InnerConnection的proxy对象,连接上 InnerConnection 时,调用 InnerConnection 的 connected(ComponentName name, IBinder service, boolean dead) 方法,将 Binder 对象传上来。

public void connected(ComponentName name, IBinder service, boolean dead) {
    mActivityThread.post(new RunConnection(name, service, 0, dead));
}
 private final class RunConnection implements Runnable {
	doConnected(mName, mService, mDead);
}
public void doConnected(ComponentName name, IBinder service, boolean dead) {
    mConnection.onServiceConnected(name, service);
}

这样我们的客户端就可以得到 Binder 对象了,onServiceConnected(ComponentName name, IBinder service)
请添加图片描述
到此为止,红框中的前半部分流程对应的代码就讲完了。

三、服务端是如何生成对象,并返回给 AMS 的?

关键点二

ActivityManager.getService().bindService()

ActivityManagerService.java - bindService()
	ActiveServices.java - bindServiceLocked()
	bringUpServiceLocked() { realStartServiceLocked() } // 先启动目标service
	requestServiceBindingLocked() { // 再bind()
	    r.app.thread.scheduleBindService(r, i.intent.getIntent(), rebind,
                        r.app.repProcState);
	}

IApplicationThread.aidl - scheduleBindService()

注意此处:app.thread.scheduleBindService()ProcessRecord app,IApplicationThread thread,也就是调用了目标进程的 applicationThread 去 bindService()

/**
 * System private API for communicating with the application.  This is given to
 * the activity manager by an application  when it starts up, for the activity
 * manager to tell the application about things it needs to do.
 *
 * {@hide}
 */
oneway interface IApplicationThread {
    void scheduleBindService(IBinder token,
            in Intent intent, boolean rebind, int processState);

我们看一下 IApplicationThread 的解释:这是一个向外公布的与此应用沟通的系统私有的api,当应用启动时,会将此对象给到 AMS,AMS 通过此对象告诉 APP 需要做什么。说白了,就是IApplicationThread.aidl 为AMS 提供了一个 跨进程调用的工具(手段)。AMS通过这种方法,让目标进程 执行一些动作如 createService、bindService等。

这个 IApplicationThread 的实现服务端在:

ActivityThread.java 的内部类 ApplicationThread
private class ApplicationThread extends IApplicationThread.Stub {
	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;
            sendMessage(H.BIND_SERVICE, s);
        }
}

class H extends Handler {
	public void handleMessage(Message msg) {
	    switch (msg.what) {
            case BIND_SERVICE:
                    handleBindService((BindServiceData)msg.obj);
                    break;
}

private void handleBindService(BindServiceData data) {
        Service s = mServices.get(data.token);
        if (s != null) {
            try {
                data.intent.setExtrasClassLoader(s.getClassLoader());
                data.intent.prepareToEnterProcess();
                try {
                    if (!data.rebind) {
                        IBinder binder = s.onBind(data.intent);
                        ActivityManager.getService().publishService(
                                data.token, data.intent, binder);
                    } else {
                        s.onRebind(data.intent);
                        ActivityManager.getService().serviceDoneExecuting(
                                data.token, SERVICE_DONE_EXECUTING_ANON, 0, 0);
                    }
                    ensureJitEnabled();
                } catch (RemoteException ex) {
                    throw ex.rethrowFromSystemServer();
                }
            } 
        }
    }
IBinder binder = s.onBind(data.intent);
ActivityManager.getService().publishService(data.token, data.intent, binder);

调用目标的 onBind 方法,返回 IBinder 对象,再通过 AMS 的 publishService 方法,将 binder 公布出去。

ActivityManagerService.java
public void publishService(IBinder token, Intent intent, IBinder service) {
      mServices.publishServiceLocked((ServiceRecord)token, intent, service);
}

ActiveServices.java
 void publishServiceLocked(ServiceRecord r, Intent intent, IBinder service) {
      try {
          c.conn.connected(r.name, service, false);
      } catch (Exception e) {
          Slog.w(TAG, "Failure sending service " + r.name +
                " to connection " + c.conn.asBinder() +
                " (in " + c.binding.client.processName + ")", e);
      }
}              

到此处,再与第一节最后讲的关键点一的逻辑衔接上。
完成闭环,将服务端返回的对象,通过 AMS 传给了 客户端。也即:
请添加图片描述

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

洛克Lee

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值