android servicemanager与binder源码分析二 ------ servicemanager服务提供者

承接上篇,serviceManager是怎么被调用的呢?如何为app提供服务支持?怎么衔接的?。这次我打算从最上层开始逐步把脉络屡清楚。
首先,我们在写app的时候需要使用AudioManager这类东西的时候,都要调用context.getSystemService(Context.AUDIO_SERVICE);获取服务。逐层看下代码:

a.activity的getSystemService:

@Override    public Object getSystemService(String name) {        if (getBaseContext() == null) {            throw new IllegalStateException(                    "System services not available to Activities before onCreate()");        }        if (WINDOW_SERVICE.equals(name)) {            return mWindowManager;        } else if (SEARCH_SERVICE.equals(name)) {            ensureSearchManager();            return mSearchManager;        }        return super.getSystemService(name);    }

如果是WINDOW_SERVICE或者SEARCH_SERVICE,直接在activity这里就做了处理返回了,否则调用super的同名方法。
b.ContextThemeWrapper的getSystemService:

@Override public Object getSystemService(String name) {        if (LAYOUT_INFLATER_SERVICE.equals(name)) {            if (mInflater == null) {                mInflater = LayoutInflater.from(mBase).cloneInContext(this);            }            return mInflater;        }        return mBase.getSystemService(name);    }

如果是LAYOUT_INFLATER_SERVICE,在这里直接返回,否则调用mBase的同名方法。
mBase是Context类型,那么其实就是ContextImpl。看下:

1363    @Override1364    public Object getSystemService(String name) {1365        return SystemServiceRegistry.getSystemService(this, name);1366    }

SystemServiceRegistry.java:

716    / 717     * Gets a system service from a given context.718     */719    public static Object getSystemService(ContextImpl ctx, String name) {720        ServiceFetcher fetcher = SYSTEM_SERVICE_FETCHERS.get(name);721        return fetcher != null ? fetcher.getService(ctx) : null;722    }
133    private static final HashMap> SYSTEM_SERVICE_FETCHERS =134            new HashMap>();

这么逐层看来,你请求的内容在每层都分别回应自己所关心的,如果不关心,交给父类处理,最后会走到SystemServiceRegistry类中,看定义就明白,使用一个hashmap来存储名字和ServiceFetcher的对应关系。那么看到这里大体应该有个了解了,SystemServiceRegistry来维护注册进去的所有服务,当然是其他层级上不关心的。
也同时可以看到责任链的应用,一个请求从上到下会经过很多层,每层都只处理和自己相关的部分,如果没有则交由下层继续传递,如果有直接返回。这种模式的使用其实已经在很多年前就非常广泛了,比如tcp/ip的封包和解包过程,比如windows下的层级调用,再比如android的ui event相应等都采用了类似的思想。不要较真儿说这里是继承那边是调用链什么的,我觉得还是看整体思想为好,不需要拘泥于具体什么什么模式,什么什么规则。
再继续看SystemServiceRegistry这个类,静态类一个,连构造都隐藏了,但不是单例,直接在static中进行了很多服务的注册:

140    static {141        registerService(Context.ACCESSIBILITY_SERVICE, AccessibilityManager.class,142                new CachedServiceFetcher() {143            @Override144            public AccessibilityManager createService(ContextImpl ctx) {145                return AccessibilityManager.getInstance(ctx);146            }});147148        registerService(Context.CAPTIONING_SERVICE, CaptioningManager.class,149                new CachedServiceFetcher() {150            @Override151            public CaptioningManager createService(ContextImpl ctx) {152                return new CaptioningManager(ctx);153            }});154        ......707    }

这里使用了静态代码块static,在类被加载的时候必然会走这里。
往下看registerService:

732     * Statically registers a system service with the context.733     * This method must be called during static initialization only.734     */735    private static  void registerService(String serviceName, Class serviceClass,736            ServiceFetcher serviceFetcher) {737        SYSTEM_SERVICE_NAMES.put(serviceClass, serviceName);738        SYSTEM_SERVICE_FETCHERS.put(serviceName, serviceFetcher);739    }

只是向两个hashmap中填充了名字和class而已。在这里已经实例化了。
简单看下ServiceFetcher:

741    / 742     * Base interface for classes that fetch services.743     * These objects must only be created during static initialization.744     */745    static abstract interface ServiceFetcher {746        T getService(ContextImpl ctx);747    }

只是个包装interface,根据类型不同提供了3种子类供各个服务使用:

749    / 750     * Override this class when the system service constructor needs a751     * ContextImpl and should be cached and retained by that context.752     */753    static abstract class CachedServiceFetcher implements ServiceFetcher {754        private final int mCacheIndex;755756        public CachedServiceFetcher() {757            mCacheIndex = sServiceCacheSize++;758        }759760        @Override761        @SuppressWarnings("unchecked")762        public final T getService(ContextImpl ctx) {763            final Object[] cache = ctx.mServiceCache;764            synchronized (cache) {765                // Fetch or create the service.766                Object service = cache[mCacheIndex];767                if (service == null) {768                    service = createService(ctx);769                    cache[mCacheIndex] = service;770                }771                return (T)service;772            }773        }774775        public abstract T createService(ContextImpl ctx);776    }777778    / 779     * Override this class when the system service does not need a ContextImpl780     * and should be cached and retained process-wide.781     */782    static abstract class StaticServiceFetcher implements ServiceFetcher {783        private T mCachedInstance;784785        @Override786        public final T getService(ContextImpl unused) {787            synchronized (StaticServiceFetcher.this) {788                if (mCachedInstance == null) {789                    mCachedInstance = createService();790                }791                return mCachedInstance;792            }793        }794795        public abstract T createService();796    }797798    / 799     * Like StaticServiceFetcher, creates only one instance of the service per process, but when800     * creating the service for the first time, passes it the outer context of the creating801     * component.802     *803     * TODO: Is this safe in the case where multiple applications share the same process?804     * TODO: Delete this once its only user (ConnectivityManager) is known to work well in the805     * case where multiple application components each have their own ConnectivityManager object.806     */807    static abstract class StaticOuterContextServiceFetcher implements ServiceFetcher {808        private T mCachedInstance;809810        @Override811        public final T getService(ContextImpl ctx) {812            synchronized (StaticOuterContextServiceFetcher.this) {813                if (mCachedInstance == null) {814                    mCachedInstance = createService(ctx.getOuterContext());815                }816                return mCachedInstance;817            }818        }819820        public abstract T createService(Context applicationContext);821    }822823}

暂时不深究到底这3种是什么用途,不过都可看到getService内部会走到createService(ctx);中,而这个抽象方法是必须被实现的。然后在static代码块中注册服务的时候都要有选择的去根据这3种类型实现ServiceFetcher,实现createService。那么无论这个服务是单例非单例,或者在创建的时候需要做什么事情,都可以在这个createService中来进行。那么这3类里面又使用了惰性加载,如果缓存有或者单例有就不用走createService,没有的时候就走。
回过头来看,getService最终返回的是一个注册过的服务的实例化对象。
说了这么半天,跟servicemanager有什么关系?其实在于getService的实现上。以AudioManager为例 /frameworks/base/media/java/android/media/AudioManager.java:

655    private static IAudioService getService()656    {657        if (sService != null) {658            return sService;659        }660        IBinder b = ServiceManager.getService(Context.AUDIO_SERVICE);661        sService = IAudioService.Stub.asInterface(b);662        return sService;663    }

看到了吧,这里已经开始对ServiceManager的使用了,并且是通过binder来得到的。那么结合之前的分析,ServiceManager是在一个独立的进程中的,那么其他进程要是想通过它拿到Service等操作,就需要借助Binder这个跨进程的通讯方式。再往下看:
/frameworks/base/core/java/android/os/ServiceManager.java:

43    / 44     * Returns a reference to a service with the given name.45     *46     * @param name the name of the service to get47     * @return a reference to the service, or null if the service doesn't exist48     */49    public static IBinder getService(String name) {50        try {51            IBinder service = sCache.get(name);52            if (service != null) {53                return service;54            } else {55                return getIServiceManager().getService(name);56            }57        } catch (RemoteException e) {58            Log.e(TAG, "error in getService", e);59        }60        return null;61    }

简单说:先从缓存中拿,如果没有通过getIServiceManager()去拿,看getIServiceManager:

33    private static IServiceManager getIServiceManager() {34        if (sServiceManager != null) {35            return sServiceManager;36        }3738        // Find the service manager39        sServiceManager = ServiceManagerNative.asInterface(BinderInternal.getContextObject());40        return sServiceManager;41    }

单例,然后调用到ServiceManagerNative.asInterface,继续看:
/frameworks/base/core/java/android/os/ServiceManagerNative.java:

33    static public IServiceManager asInterface(IBinder obj)34    {35        if (obj == null) {36            return null;37        }38        IServiceManager in =39            (IServiceManager)obj.queryLocalInterface(descriptor);40        if (in != null) {41            return in;42        }4344        return new ServiceManagerProxy(obj);45    }

通过IBinder对象去查询本地接口,如果没查到需要帮助,就建立一个ServiceManagerProxy。这个代理对象是这样的:

109class ServiceManagerProxy implements IServiceManager {110    public ServiceManagerProxy(IBinder remote) {111        mRemote = remote;112    }113114    public IBinder asBinder() {115        return mRemote;116    }117118    public IBinder getService(String name) throws RemoteException {119        Parcel data = Parcel.obtain();120        Parcel reply = Parcel.obtain();121        data.writeInterfaceToken(IServiceManager.descriptor);122        data.writeString(name);123        mRemote.transact(GET_SERVICE_TRANSACTION, data, reply, 0);124        IBinder binder = reply.readStrongBinder();125        reply.recycle();126        data.recycle();127        return binder;128    }129130    public IBinder checkService(String name) throws RemoteException {131        Parcel data = Parcel.obtain();132        Parcel reply = Parcel.obtain();133        data.writeInterfaceToken(IServiceManager.descriptor);134        data.writeString(name);135        mRemote.transact(CHECK_SERVICE_TRANSACTION, data, reply, 0);136        IBinder binder = reply.readStrongBinder();137        reply.recycle();138        data.recycle();139        return binder;140    }141142    public void addService(String name, IBinder service, boolean allowIsolated)143            throws RemoteException {144        Parcel data = Parcel.obtain();145        Parcel reply = Parcel.obtain();146        data.writeInterfaceToken(IServiceManager.descriptor);147        data.writeString(name);148        data.writeStrongBinder(service);149        data.writeInt(allowIsolated ? 1 : 0);150        mRemote.transact(ADD_SERVICE_TRANSACTION, data, reply, 0);151        reply.recycle();152        data.recycle();153    }154155    public String[] listServices() throws RemoteException {156        ArrayList services = new ArrayList();157        int n = 0;158        while (true) {159            Parcel data = Parcel.obtain();160            Parcel reply = Parcel.obtain();161            data.writeInterfaceToken(IServiceManager.descriptor);162            data.writeInt(n);163            n++;164            try {165                boolean res = mRemote.transact(LIST_SERVICES_TRANSACTION, data, reply, 0);166                if (!res) {167                    break;168                }169            } catch (RuntimeException e) {170                // The result code that is returned by the C++ code can171                // cause the call to throw an exception back instead of172                // returning a nice result...  so eat it here and go on.173                break;174            }175            services.add(reply.readString());176            reply.recycle();177            data.recycle();178        }179        String[] array = new String[services.size()];180        services.toArray(array);181        return array;182    }183184    public void setPermissionController(IPermissionController controller)185            throws RemoteException {186        Parcel data = Parcel.obtain();187        Parcel reply = Parcel.obtain();188        data.writeInterfaceToken(IServiceManager.descriptor);189        data.writeStrongBinder(controller.asBinder());190        mRemote.transact(SET_PERMISSION_CONTROLLER_TRANSACTION, data, reply, 0);191        reply.recycle();192        data.recycle();193    }194195    private IBinder mRemote;196}

至此,已经开始进入binder的跨进程部分,可以看到其中的getService函数是怎么运作的:
1.建立2个Parcel数据data和reply,一个是入口数据,一个是出口数据;
2.data中写入要获取的service的name;
3.关键:走mRemote的transact函数;
4.读取出口数据;
5.回收资源,返回读取到的binder对象;

够晕吧,这一通调用,但是这部分没办法,实在不好层级总结,只能是一口气跟着调用走下来,然后回过头再看。上面那么多步骤的调用都是为了这最后一步做准备,那么为什么要分为这么多层次呢?任何一个操作系统都是非常复杂的,每个地方都要考虑到很多的扩展性及健壮性,随时可以在某个版本或补丁上去除或扩展出一些内容来。也为了利于多人协作,那么分层的调用能够保证在每一个层级上都有可扩展的余地,再进行修改的时候不至于要动很多代码,动的越少就越不容易出错。因此虽然看着费劲点,但是在此还是要对搞操作系统的以及研究操作系统的人们给予敬意。

最后总结一下,这篇主要说的是从应用层开始与servicemanager衔接的过程,是怎么将servicemanager应用起来的。写这篇的原因也是发现网上这部分的衔接的资料较少,我觉得梳理一下还是有助于理解系统的机制的,难点并不多,只是帮助理解系统的机制,作为参考吧。顺便再说下,如果你的兴趣在于底层,那么不看此文也罢,不过我的建议是不仅要了解各个环节的运作机制,还要在一个更高的角度去看待每个环节的衔接过程,否则可能你费劲心血在底层做了各种优化后发现效率还是上不来,那么往往问题出在衔接过程。当然这么庞大复杂的系统不可能是一个人写的,每个人的能力也各有差别,瓶颈总会有的,但是如果你站的够高,那么架构的角度去理解每个细节及衔接,就能够找出问题所在。不是吗?总之都是个人愚见而已,各位海涵。

下面该说binder的远程通讯机制内部的内容了,下一篇文我会继续的。

c++# c, java


本文来自互联网用户投稿,文章观点仅代表作者本人,不代表本站立场,不承担相关法律责任。如若转载,请注明出处。 如若内容造成侵权/违法违规/事实不符,请点击【内容举报】进行投诉反馈!

相关文章

立即
投稿

微信公众账号

微信扫一扫加关注

返回
顶部