写点什么

插件化框架解读之 android 系统服务实现原理(五),毕业工作 5 年被裁

用户头像
Android架构
关注
发布于: 2 小时前

3、WifiManager 如何的创建

既然 SYSTEM_SERVICE_FETCHERS 是一个 Map 我们不妨找找他是在什么地方被添加数据的:


源码路径:xxx/framework/base/core/java/android/app/SystemServiceRegistry.java


/**


  • Statically registers a system service with the context.

  • This method must be called during static initialization only.*/private static <T> void registerService(String serviceName, Class<T> serviceClass,ServiceFetcher<T> serviceFetcher) {SYSTEM_SERVICE_NAMES.put(serviceClass, serviceName);SYSTEM_SERVICE_FETCHERS.put(serviceName, serviceFetcher);}


我们发现 SYSTEM_SERVICE_FETCHERS 中的数据是通过 registerService()方法添加的,继续查看 SystemServiceRegistry.java 文件你会发现好多类似下面的方法在静态代码块中被调用:


registerService(Context.WIFI_SERVICE, WifiManager.class,new CachedServiceFetcher<WifiManager>() {@Overridepublic WifiManager createService(ContextImpl ctx) {IBinder b = ServiceManager.getService(Context.WIFI_SERVICE);IWifiManager service = IWifiManager.Stub.asInterface(b);return new WifiManager(ctx.getOuterContext(), service);}});


在这段代码中,我们看到 createService()这个抽象方法被实现,到目前为止,我们已经明确了系统是如何一步步的给我们提供 WifiManager 这个对象的了,至于 WifiManager 到底做了什么,我们继续往后看!

二、系统服务的创建以及管理

1、WifiManager

既然我们拿到手的最后是 WifiManager,那么我们先看看 WifiManager 什么东西,他又是如何工作的,就以我们刚开始的时候调用的 disconnect()方法为例:


public boolean disconnect() {try {mService.disconnect();return true;} catch (RemoteException e) {throw e.rethrowFromSystemServer();}}


在代码中我们看到,程序最终是走了 mService.disconnect();的,那么 mService 又是什么呢?


public WifiManager(Context context, IWifiManager service, Looper looper) {mContext = context;mService = service;mLooper = looper;mTargetSdkVersion = context.getApplicationInfo().targetSdkVersion;}


到此我们看到其实 mService 是 IWifiManager,搜索源代码发现,其实它是一个 IWifiManager.aidl 文件,既然是 aidl 那么就肯定有具体的实现,至于它的具体实现是什么我们现在肯定是不知道的,我们需要一步步分析 mService 的来源,最终确定其具体的实现类是什么,我们继续往下走。。。源码路径:xxx/frameworks/base/wifi/java/android/net/wifi/IWifiManager.aidl

2、IWifiManager service = IWifiManager.Stub.asInterface(b)

既然 IWifiManager 是通过 IWifiManager.Stub.asInterface(b)返回的,那么我们不妨分析分析这段代码;看到这句代码的时候,相信很多朋友都觉得很熟悉吧,根据 AIDL 的特殊性,正常情况下编译后会根据 IWifiManager.aidl 这个文件生成一个 IWifiManager.java 的接口,而这个接口中维护了 Stub 怎么一个内部类,我们在 AS 上创建一个 AIDL 编译生成一个 Stub 分析分析:


public interface IWifiManager extends android.os.IInterface {/**


  • Local-side IPC implementation stub class.*/public static abstract class Stub extends android.os.Binder implements android.discovery.light.IWifiManager {private static final java.lang.String DESCRIPTOR = "android.discovery.light.IWifiManager";


/**


  • Construct the stub at attach it to the interface.*/public Stub() {this.attachInterface(this, DESCRIPTOR);}


/**


  • Cast an IBinder object into an android.discovery.light.IWifiManager interface,

  • generating a proxy if needed.*/public static android.discovery.light.IWifiManager asInterface(android.os.IBinder obj) {if ((obj == null)) {return null;}android.os.IInterface iin = obj.queryLocalInterface(DESCRIPTOR);if (((iin != null) && (iin instanceof android.discovery.light.IWifiManager))) {return ((android.discovery.light.IWifiManager) iin);}return new android.discovery.light.IWifiManager.Stub.Proxy(obj);}//此处省略 N 行代码============================================}


在代码中我们可以看到 asInterface(android.os.IBinder obj)通过 obj.queryLocalInterface(DESCRIPTOR)返回了一个 IInterface,而在 Binder 中 queryLocalInterface()方法的实现如下:


public IInterface queryLocalInterface(String descriptor) {if (mDescriptor.equals(descriptor)) {return mOwner;}return null;}


这里首先对传入的 descriptor 进行判断,然后返回 mOwner 对象,他们在 Binder 中的定义以及赋值如下:


private IInterface mOwner;private String mDescriptor;public void attachInterface(IInterface owner, String descriptor) {mOwner = owner;mDescriptor = descriptor;}


看到 attachInterface()方法朋友们应该想起点什么了吧?没想其没关系,看看下面的代码:


private static final java.lang.String DESCRIPTOR = "android.discovery.light.IMyAidlInterface";


public Stub() {this.attachInterface(this, DESCRIPTOR);}


这里我们看到其实当我们创建 Stub 实例的时候,通过构造方法把 this 以及包名为保存到 mOwner,mDescriptor 两个属性中,当我们调用 asInterface(IBinder obj)方法的时候,根据 mDescriptor 标识进行判断,如果匹配就返回 mOwner,返回的其实就是 obj 本身,这种是最正常的情况了,我们暂时以这种情况为准!


好了,扯远了,回到我们之前的代码:


registerService(Context.WIFI_SERVICE, WifiManager.class,new CachedServiceFetcher<WifiManager>() {@Overridepublic WifiManager createService(ContextImpl ctx) {IBinder b = ServiceManager.getService(Context.WIFI_SERVICE);IWifiManager service = IWifiManager.Stub.asInterface(b);return new WifiManager(ctx.getOuterContext(), service);}});


按照我们上面的分析,正常情况下,其实 IWifiManager.Stub.asInterface(b)返回的其实就是 b 本身,那么接下来我们要确定 b 这个 IBinder 对象是什么即可:

3、那么接下来我们分析 ServiceManager.getService(Context.WIFI_SERVICE)

源码路径:xxx/frameworks/base/core/java/android/os/ServiceManager.java


/**


  • Returns a reference to a service with the given name.

  • @param name the name of the service to get

  • @return a reference to the service, or <code>null</code> if the service doesn't exist*/public static IBinder getService(String name) {try {IBinder service = sCache.get(name);if (service != null) {return service;} else {return getIServiceManager().getService(name);}} catch (RemoteException e) {Log.e(TAG, "error in getService", e);}return null;}


我们看到程序首先通过 sCache 这个 HasMap 中去取,如果不存在就通过 getIServiceManager().getService(name)去取,而 getIServiceManager()返回的是一个 IServiceManager 接口,他的具体实现是在 ServiceManagerNative#ServiceManagerProxy 这个内部类中的,看下源码:源码路径:xxx/frameworks/base/core/java/and


《Android学习笔记总结+最新移动架构视频+大厂安卓面试真题+项目实战源码讲义》
浏览器打开:qq.cn.hn/FTe 免费领取
复制代码


roid/os/ServiceManagerNative#ServiceManagerProxy


public IBinder getService(String name) throws RemoteException {Parcel data = Parcel.obtain();Parcel reply = Parcel.obtain();data.writeInterfaceToken(IServiceManager.descriptor);data.writeString(name);mRemote.transact(GET_SERVICE_TRANSACTION, data, reply, 0);IBinder binder = reply.readStrongBinder();reply.recycle();data.recycle();return binder;}


至此,我们就知道了 ServiceManager.getService(Context.WIFI_SERVICE)中返回的 IBinder 是怎么来的了,这里的 Parcel 大家先不用关心,这个东西只不过是一个容器而已,我们只要知道这里是通过 Context.WIFI_SERVICE 这个字符串标识获取到了对应的 IBinder 对象即可,但是直到此处,我们依然没能知道这个 IBinder 对象到底是什么,这个时候别急,既然是容器,能取出来东西自然也要能存东西,取出来的时候不知道是什么,存进去的时候总该知道吧,继续往下走。。。

4、ServiceManager.addService()

细心的朋友应该已经发现了 ServiceManager 中还有另一个方法 addService(),这个方法就是我们创建服务之后注册到系统去管理的方法,他的调用是在 SystemServer.java 中,那我们去 SystemServer 找找看。。。找了半天是否发现没有在 SystemServer 中找不到哪个是队 Wifi 服务进行注册的?别急,其实他是通过了 WifiService 这个东西进行注册的!


private static final String WIFI_SERVICE_CLASS = "com.android.server.wifi.WifiService";


/**


  • Starts a miscellaneous grab bag of stuff that has yet to be refactored

  • and organized.*/private void startOtherServices() {//省略很多。。。mSystemServiceManager.startService(WIFI_SERVICE_CLASS);//省略很多。。。}


这里我们看到 mSystemServiceManager.startService(WIFI_SERVICE_CLASS)怎么一句代码,查看其定义发现 mSystemServiceManager 是 SystemServiceManager:源码路径: xxx/frameworks/base/services/core/java/com/android/server/SystemServiceManager.java


  • Starts a service by class name.

  • @return The service instance.*/@SuppressWarnings("unchecked")public SystemService startService(String className) {final Class<SystemService> serviceClass;try {serviceClass = (Class<SystemService>)Class.forName(className);} catch (ClassNotFoundException ex) {Slog.i(TAG, "Starting " + className);throw new RuntimeException("Failed to create service " + className


  • ": service class not found, usually indicates that the caller should "

  • "have called PackageManager.hasSystemFeature() to check whether the "

  • "feature is available on this device before trying to start the "

  • "services that implement it", ex);}return startService(serviceClass);}


这里我们看到,通过反射的方式返回了 WifiService 的 Class 对象,然后作为参数传给了 startService(serviceClass):


/**


  • Creates and starts a system service. The class must be a subclass of

  • {@link com.android.server.SystemService}.

  • @param serviceClass A Java class that implements the SystemService interface.

  • @return The service instance, never null.

  • @throws RuntimeException if the service fails to start.*/@SuppressWarnings("unchecked")public <T extends SystemService> T startService(Class<T> serviceClass) {final String name = serviceClass.getName();Slog.i(TAG, "Starting " + name);


// Create the service.if (!SystemService.class.isAssignableFrom(serviceClass)) {throw new RuntimeException("Failed to create " + name


  • ": service must extend " + SystemService.class.getName());}final T service;try {Constructor<T> constructor = serviceClass.getConstructor(Context.class);service = constructor.newInstance(mContext);} catch (InstantiationException ex) {throw new RuntimeException("Failed to create service " + name

  • ": service could not be instantiated", ex);} catch (IllegalAccessException ex) {throw new RuntimeException("Failed to create service " + name

  • ": service must have a public constructor with a Context argument", ex);} catch (NoSuchMethodException ex) {throw new RuntimeException("Failed to create service " + name

  • ": service must have a public constructor with a Context argument", ex);} catch (InvocationTargetException ex) {throw new RuntimeException("Failed to create service " + name

  • ": service constructor threw an exception", ex);}


// Register it.mServices.add(service);


// Start it.try {service.onStart();} catch (RuntimeException ex) {throw new RuntimeException("Failed to start service " + name


  • ": onStart threw an exception", ex);}return service;}


我们发现,代码通过 service = constructor.newInstance(mContext)方法创建了 WifiService 的实例,并且调用了 service.onStart();方法,继续查看 WifiService 的源码:


源码路径:xxx/frameworks/opt/net/wifi/service/java/com/android/server/wifi/WifiService.java

用户头像

Android架构

关注

还未添加个人签名 2021.10.31 加入

还未添加个人简介

评论

发布
暂无评论
插件化框架解读之android系统服务实现原理(五),毕业工作5年被裁