前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >ServiceManager是如何管理java层service的

ServiceManager是如何管理java层service的

原创
作者头像
好好学习吧
发布2023-06-12 14:25:48
4350
发布2023-06-12 14:25:48
举报
文章被收录于专栏:今天学习了吗

前言

ServiceManager是Binder机制的大管家,管理着android系统的各种Service。service向servicemanager注册,当client需要调用service时,先通过servicemanager查询到该service,client接着再与service通信。这些service有java层的,也有native层的。native层通过BpServiceManager/BnServiceManager实现的service与servicemanager的交互。这次打算聊一聊servicemanager管理java层service是如何实现的。

正文

IServiceManager接口

同native层类似,java层,aidl脚本依据IServiceManager.aidl生成IServiceManager接口类,包含子类IServiceManager.Stub和IServiceManager.Stub.Proxy,两者都实现了IServiceManager接口,前者代表server端,后者代表client端。

代码语言:txt
复制
    public interface IServiceManager extends android.os.IInterface 
    {
        public static abstract class Stub extends android.os.Binder implements android.os.IServiceManager
        {
            public static android.os.IServiceManager asInterface(android.os.IBinder obj)
            {
                if (obj == null){
                    return null;
                }
                android.os.IInterface iin = obj.queryLocalInterface(DESCRIPTOR);
                if (iin != null && iin instanceof IServiceManager){
                    return (IServiceManager)iin;
                }
                return new IServiceManager.Stub.Proxy(obj);
            }
            
            public boolean onTransact(int code, Parcel data, Parcel reply, int flags) throws RemoteException
            {
                String descriptor = DESCRIPTOR;
                ...
                switch (code){
                    case TRANSACTION_getService:
                    {
                        String _arg0;
                        _arg0 = data.readString();
                        data.enforceNoDataAvail();
                        IBinder _result = getService(_agr0);
                        reply.writeNoException();
                        reply.writeStrongBinder(_result);
                        break;
                    }
                    ...
                }
            }
        }
        
        private static class Proxy implements IServiceManager
        {
            private IBinder mRemote;
            Proxy(IBinder remote){
                mRemote = remote;
            }
            
            @Override
            public IBinder getService(String name) throws RemoteException
            {
                Parcel _data = Parcel.obtain();
                Parcel _reply = Parcel.obtain();
                IBinder _result;
                try {
                    _data.writeInterfaceToken(DESCRIPTOR);
                    _data.writeString(name);
                    boolean _status = mRemote.transact(Stub.TRANSACTION_getService, _data, _reply, 0);
                    _reply.readException();
                    _result = _reply.readStrongBinder();
                }finally{
                    _reply.recycle();
                    _data.recycle();
                }
                return _result;
            }
            
            @Override
            public IBinder checkService(String name) throws RemoteException
            {
                Parcel _data = Parcel.obtain();
                Parcel _reply = Parcel.obtain();
                IBinder _result;
                try {
                    _data.writeInterfaceToken(DESCRIPTOR);
                    _data.writeString(name);
                    boolean _status = mRemote.transact(Stub.TRANSACTION_checkService, _data, _reply, 0);
                    _reply.readException();
                    _result = _reply.readStrongBinder();
                }finally{
                    _reply.recycle();
                    _data.recycle();
                }
                return _result;
            }
        }
    }

client端->servicemanager的方式

java层使用ServiceManager类实现servicemanager的client端,通过getIServiceManager()获取servicemanager的代理类,其中BinderInternal.getContextObject()通过jni创建一个BinderProxy对象。

这里BinderProxy本来就是java类,为什么要通过jni创建呢?目的是创建BinderPrxoy对象的同时,也创建一个BpBinder对象,BinderProxy和BpBinder是一一对应的关系;同理,创建java层Binder对象时,也会通过jni创建一个BBinder对象。我们可以理解为BinderProxy/Binder封装了BpBinder/BBinder,实际工作的是后者。

代码语言:java
复制
public final class ServiceManager {
    private static IServiceManager sServiceManager;
    
    private static IServiceManager getIServiceManager(){
        if (SServiceManager != null){
            return sServiceManager;
        }
        sServiceManager = ServiceManagerNative
                .asInterface(Binder.allowBlocing(BinderInternal.getContextObject()));
        return sServiceManager;
    }
    
    public static IBinder getService(String name){
        try {
            IBinder service = sCache.get(name);
            if (service != null){
                return service;
            } else {
                return Binder.allowBlocking(rawGetServices(name));
            }
        } catch (RemoteException e){
            ...
        }
        return null;
    }
    
    private static IBinder rawGetService(String name) throws RemoteException  {
        final IBinder binder = getIServiceManager().getService(name);
        ...
        return binder;
    }
}

此时,获取到的servicemanager的代理类IServiceManagerProxy(BinderProxy)。

代码语言:java
复制
public final class ServiceManagerNative {
    private ServiceManagerNative(){}
    
    public static IServiceManager asInterface(IBinder obj){
        if (obj == null){
            return null;
        }
        return new ServiceManagerProxy(obj);
    }
    
    class ServiceManagerProxy implements IServiceManager {
        public ServiceManagerProxy(IBinder remote){
            mRemote = remote;
            //servicemanager实际的代理类
            mServiceManager = IServiceManager.Stub.asInterface(remote);
        }
        
        public IBinder getService(String name) throws RemoteException {
            return mServiceManager.checkService(name);
        }
        ...
        private IBinder mRemote;
        private IServiceManager mServiceManager;
    }
}

这样,我们使用ServiceManager.addService()/getService()等等方法时,会走到BinderProxy的transact()->transactNative()

代码语言:java
复制
public boolean transact(int code, Parcel data, Parcel reply, int flags) throws RemoteException {
    ...
    try {
        return transactNative(code, data, reply, flags);
    }finally{
        ...
    }
}

public native boolean transactNative(int code, Parcel data, Parecl reply, int flags) throws RemoteException;

最终通过jni进入native层,通过BpBinder.transact()->IPCThreadState.transact()->writeTransactionData()->waitForResponse()进入binder驱动层,与servicemanager进程通信,等待返回结果。

注意,这里的servicemanager的服务端,使用的是native层的BnServiceManager,并没有使用到java层的IServiceManager.Stub

servicemanager->client端的方式

servicemanager接收到请求后,执行相应的操作IPCThreadState::executeCommand()->BBinder::transact()->BnServiceManager::onTransact(), 具体的实现方法在ServiceManager.cpp中,这里不详细开展了。

代码语言:text
复制
::android::status_t BnServiceManager::onTransact(uint32_t _aidl_code, const ::android::Parcel& _aidl_data, ::android::Parcel* _aidl_reply, uint32_t _aidl_flags){
    ::android::status_t _aidl_ret_status = ::android::OK;
    switch(_aidl_code){
    case BnServiceManager::TRANSACTION_getService:
        ::std::string in_name;
        ::android::sp<::android::IBinder> _aidl_return;
        ...
        _aidl_ret_status = _aidl_data.readUtf8FromUtf16(&in_name);
        ...
        ::android::binder::Status _aidl_status(getService(in_name, &_aidl_return));
        ...
        _aidl_ret_status = _aidl_reply->writeStrongBinder(_aidl_return);
        break;
     case BnServiceManager::TRANSACTION_checkService:
     ...
    }
}

数据组装完毕后,回到IPCThreadState::executeCommand(),执行sendReply()

代码语言:text
复制
status_t IPCThreadState::sendReply(const Parcel& reply, uint32_t flags){
    status_t err;
    status_t statusBuffer;
    err = writeTransactionData(BC_REPLY, flags, -1, 0, reply, &statusBuffer);
    if (err < NO_ERROR) return err;
    
    return waitForResponse(nullptr, nullptr);
}

通过binder驱动,将请求的结果返回给client端,如下所示,返回的结果写入了Parcel中。

代码语言:text
复制
status_t IPCThreadState::waitForResponse(Parcel *reply, status_t *acquireResult){
    ...
    while(1){
        if ((err=talkWithDriver()) < NO_ERROR) break;
        ...
        cmd = (uint32_t)mIn.readInt32();
        switch(cmd){
        ...
        case BR_REPLY:
            binder_transaction_data tr;
            err = mIn.read(&tr, sizeof(tr));
            ...
            if(reply){
                if((tr.flags & TF_STATUS_CODE) == 0){
                    reply->ipcSetDataReference(reinterpret_cast<const uint8_t*>(tr.data.ptr.buffer), tr.data_size, reinterpret_cast<const binder_size_t*>(tr.data.ptr.offsets), tr.offsets_size/sizeof(binder_size_t), freeBuffer, this);
                }else{
                    ...
                }
            }else{
                ...
            }
            goto finish;
        }
    }
  finish:
      if (err != NO_ERROR){
          ...
      }
      return err;
}

接着进入IServiceManager.Stub.Proxy类的方法中,通过Parcel.readStrongBinder()获取到与servicemanager通信的结果。

结论

servicemanager在管理java层service时,目前只使用了IServiceManager.Stub.Proxy作为代理类,并没有使用IServiceManager.Stub作为服务类,服务类使用的依然是native层的BnServiceManager。

原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。

如有侵权,请联系 cloudcommunity@tencent.com 删除。

原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。

如有侵权,请联系 cloudcommunity@tencent.com 删除。

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 前言
  • 正文
    • IServiceManager接口
      • client端->servicemanager的方式
        • servicemanager->client端的方式
        • 结论
        领券
        问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档