摘要:也同时可以看到责任链的应用,一个请求从上到下会经过很多层,每层都只处理和自己相关的部分,如果没有则交由下层继续传递,如果有直接返回。因此虽然看着费劲点,但是在此还是要对搞操作系统的以及研究操作系统的人们给予敬意。
承接上篇,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 @Override 1364 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 @Override 144 public AccessibilityManager createService(ContextImpl ctx) { 145 return AccessibilityManager.getInstance(ctx); 146 }}); 147 148 registerService(Context.CAPTIONING_SERVICE, CaptioningManager.class, 149 new CachedServiceFetcher () { 150 @Override 151 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 staticvoid 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 a 751 * ContextImpl and should be cached and retained by that context. 752 */ 753 static abstract class CachedServiceFetcherimplements ServiceFetcher { 754 private final int mCacheIndex; 755 756 public CachedServiceFetcher() { 757 mCacheIndex = sServiceCacheSize++; 758 } 759 760 @Override 761 @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 } 774 775 public abstract T createService(ContextImpl ctx); 776 } 777 778 /** 779 * Override this class when the system service does not need a ContextImpl 780 * and should be cached and retained process-wide. 781 */ 782 static abstract class StaticServiceFetcher implements ServiceFetcher { 783 private T mCachedInstance; 784 785 @Override 786 public final T getService(ContextImpl unused) { 787 synchronized (StaticServiceFetcher.this) { 788 if (mCachedInstance == null) { 789 mCachedInstance = createService(); 790 } 791 return mCachedInstance; 792 } 793 } 794 795 public abstract T createService(); 796 } 797 798 /** 799 * Like StaticServiceFetcher, creates only one instance of the service per process, but when 800 * creating the service for the first time, passes it the outer context of the creating 801 * 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 the 805 * case where multiple application components each have their own ConnectivityManager object. 806 */ 807 static abstract class StaticOuterContextServiceFetcher implements ServiceFetcher { 808 private T mCachedInstance; 809 810 @Override 811 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 } 819 820 public abstract T createService(Context applicationContext); 821 } 822 823}
暂时不深究到底这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 get
47 * @return a reference to the service, or null
if the service doesn"t exist
48 */
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 } 37 38 // Find the service manager 39 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 } 43 44 return new ServiceManagerProxy(obj); 45 }
通过IBinder对象去查询本地接口,如果没查到需要帮助,就建立一个ServiceManagerProxy。这个代理对象是这样的:
109class ServiceManagerProxy implements IServiceManager { 110 public ServiceManagerProxy(IBinder remote) { 111 mRemote = remote; 112 } 113 114 public IBinder asBinder() { 115 return mRemote; 116 } 117 118 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 } 129 130 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 } 141 142 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 } 154 155 public String[] listServices() throws RemoteException { 156 ArrayListservices = 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 can 171 // cause the call to throw an exception back instead of 172 // 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 } 183 184 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 } 194 195 private IBinder mRemote; 196}
至此,已经开始进入binder的跨进程部分,可以看到其中的getService函数是怎么运作的:
1.建立2个Parcel数据data和reply,一个是入口数据,一个是出口数据;
2.data中写入要获取的service的name;
3.关键:走mRemote的transact函数;
4.读取出口数据;
5.回收资源,返回读取到的binder对象;
够晕吧,这一通调用,但是这部分没办法,实在不好层级总结,只能是一口气跟着调用走下来,然后回过头再看。上面那么多步骤的调用都是为了这最后一步做准备,那么为什么要分为这么多层次呢?任何一个操作系统都是非常复杂的,每个地方都要考虑到很多的扩展性及健壮性,随时可以在某个版本或补丁上去除或扩展出一些内容来。也为了利于多人协作,那么分层的调用能够保证在每一个层级上都有可扩展的余地,再进行修改的时候不至于要动很多代码,动的越少就越不容易出错。因此虽然看着费劲点,但是在此还是要对搞操作系统的以及研究操作系统的人们给予敬意。
最后总结一下,这篇主要说的是从应用层开始与servicemanager衔接的过程,是怎么将servicemanager应用起来的。写这篇的原因也是发现网上这部分的衔接的资料较少,我觉得梳理一下还是有助于理解系统的机制的,难点并不多,只是帮助理解系统的机制,作为参考吧。顺便再说下,如果你的兴趣在于底层,那么不看此文也罢,不过我的建议是不仅要了解各个环节的运作机制,还要在一个更高的角度去看待每个环节的衔接过程,否则可能你费劲心血在底层做了各种优化后发现效率还是上不来,那么往往问题出在衔接过程。当然这么庞大复杂的系统不可能是一个人写的,每个人的能力也各有差别,瓶颈总会有的,但是如果你站的够高,那么架构的角度去理解每个细节及衔接,就能够找出问题所在。不是吗?总之都是个人愚见而已,各位海涵。
下面该说binder的远程通讯机制内部的内容了,下一篇文我会继续的。
文章版权归作者所有,未经允许请勿转载,若此文章存在违规行为,您可以联系管理员删除。
转载请注明本文地址:https://www.ucloud.cn/yun/65001.html
摘要:抱歉,此文暂时作废,不会使用的删除功能。我会在后面重新整理后再继续写下去。是内部的一个机制,通过设备驱动的协助能够起到进程间通讯的的作用。这个应该是个全局表,统计所有结构。实际上是保存在打开的设备文件的结构中。目前还未涉及到其他操作,只是。 抱歉,此文暂时作废,不会使用segmentfault的删除功能。我会在后面重新整理后再继续写下去。 继续上篇的文,这篇打算进入到android的内...
摘要:以版本源码为例。源码位于下打开驱动设备,将自己作为的管理者,进入循环,作为等待的请求位于首先,建立一个结构体,然后剩下的就是给这个结构体的成员赋值。同属于这一层,因此我们看看具体内容刚才从驱动设备读取的的前位取出来作为进行判断处理。 前一阵子在忙项目,没什么更新,这次开始写点android源码内部的东西分析下。以6.0.1_r10版本android源码为例。servicemanager...
摘要:的构造传递进入的就是。如果状态是,直接返回。到底是否正确呢看代码先创建一个对象,这个对象是个存储读写内容的对象。然后终于进入了内核驱动的部分。 承接上文,从getService开始,要开始走binder的通讯机制了。首先是上文的java层 /frameworks/base/core/java/android/os/ServiceManagerNative.java: 118 pu...
阅读 1126·2021-11-25 09:43
阅读 2945·2019-08-30 15:54
阅读 3268·2019-08-30 15:54
阅读 2962·2019-08-30 15:44
阅读 1609·2019-08-26 12:18
阅读 2240·2019-08-26 11:42
阅读 858·2019-08-26 11:35
阅读 3280·2019-08-23 18:22