阿里P7移动互联网架构师进阶视频(每日更新中)免费学习请点击:https://space.bilibili.com/474380680

一、系统服务提供方式

1、我们平时最常见的系统服务使用方式

 WifiManager wifimanager = (WifiManager) getSystemService(Context.WIFI_SERVICE);
wifimanager.disconnect();

这里我们通过Context的getSystemService(String name)方法,根据Context.WIFI_SERVICE标识获取到了WifiManager,然后调用disconnerct()这个api实现了下发wifi断开指令的功能,这里就是一个很经典的系统服务使用的例子了,getSystemService()通过我们传入的字符串标识返回我们需要的具体WifiManager实例,那么我们不妨从getSystemService()入手,看看google的工程师是如何做的。

2、getSystemService()方法

源码路径:xxx/framework/base/core/java/android/content/Context.java

 public abstract Object getSystemService(@ServiceName @NonNull String name);

Context中的getSystemService()方法是一个抽象方法,意料之中,他的具体实现是在ContextImpl中:
源码路径:xxx/framework/base/core/java/android/app/ContextImpl.java

@Override
public Object getSystemService(String name) {
return SystemServiceRegistry.getSystemService(this, name);
}

这里要注意,在5.0之前是在ContextImpl中实现的,而5.0之后就去调SystemServiceRegistry中的getSystemService()方法:

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

/**
* Gets a system service from a given context.
*/
public static Object getSystemService(ContextImpl ctx, String name) {
ServiceFetcher<?> fetcher = SYSTEM_SERVICE_FETCHERS.get(name);
return fetcher != null ? fetcher.getService(ctx) : null;
}

这里我们看到,通过我们传入的标识Context.WIFI_SERVICE从SYSTEM_SERVICE_FETCHERS中获取了ServiceFetcher对象,并通过ServiceFetcher的getService()方法返回我们所需WifiManager对象,那么SYSTEM_SERVICE_FETCHERS是什么? ServiceFetcher又是什么,我们看下下面的代码:
源码路径:xxx/framework/base/core/java/android/app/SystemServiceRegistry.java

 private static final HashMap<String, ServiceFetcher<?>> SYSTEM_SERVICE_FETCHERS = new HashMap<String, ServiceFetcher<?>>();

    /**
* Base interface for classes that fetch services.
* These objects must only be created during static initialization.
*/
static abstract interface ServiceFetcher<T> {
T getService(ContextImpl ctx);
} /**
* Override this class when the system service constructor needs a
* ContextImpl and should be cached and retained by that context.
*/
static abstract class CachedServiceFetcher<T> implements ServiceFetcher<T> {
private final int mCacheIndex; public CachedServiceFetcher() {
mCacheIndex = sServiceCacheSize++;
} @Override
@SuppressWarnings("unchecked")
public final T getService(ContextImpl ctx) {
final Object[] cache = ctx.mServiceCache;
synchronized (cache) {
// Fetch or create the service.
Object service = cache[mCacheIndex];
if (service == null) {
service = createService(ctx);
cache[mCacheIndex] = service;
}
return (T)service;
}
}
public abstract T createService(ContextImpl ctx);
}

看到SYSTEM_SERVICE_FETCHERS的定义我们发现它其实是一个HashMap,而ServiceFetcher是一个接口,而CachedServiceFetcher就是它的其中一个实现,我们看到当调用个getService()方法的时候,先去mServiceCache这个数组中查找,如果取不到再调用createService()这个抽象方法创建,至于createService()的具体实现,请往下看。。。

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>() {
@Override
public 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>() {
@Override
public 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/android/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

package com.android.server.wifi;
import android.content.Context;
import android.net.wifi.ScanResult;
import android.net.wifi.WifiScanner;
import android.util.Log;
import com.android.server.SystemService;
import java.util.List; public final class WifiService extends SystemService {
private static final String TAG = "WifiService";
final WifiServiceImpl mImpl; public WifiService(Context context) {
super(context);
mImpl = new WifiServiceImpl(context);
} @Override
public void onStart() {
Log.i(TAG, "Registering " + Context.WIFI_SERVICE);
publishBinderService(Context.WIFI_SERVICE, mImpl);
} @Override
public void onBootPhase(int phase) {
if (phase == SystemService.PHASE_SYSTEM_SERVICES_READY) {
mImpl.checkAndStartWifi();
}
}
}

这里,我们看到了在WifiService的构造方法中创建了WifiServiceImpl实例,并且通过onStart()方法,将WifiServiceImpl实例mImpl传入到 publishBinderService(Context.WIFI_SERVICE, mImpl)中,我们继续到SystemService看看:
源码路径:xxx/frameworks/base/services/core/java/com/android/server/SystemService.java

/**
* Publish the service so it is accessible to other services and apps.
*/
protected final void publishBinderService(String name, IBinder service,
boolean allowIsolated) {
ServiceManager.addService(name, service, allowIsolated);
}

历尽千辛万苦,终于看到我们想要找的东西了,原来publishBinderService()方法通过ServiceManager.addService(name, service, allowIsolated)将WifiServiceImpl注册到了ServiceManager中,我们看下注册的方式:

源码路径:xxx/frameworks/base/core/java/android/os/ServiceManagerNative#ServiceManagerProxy

public void addService(String name, IBinder service, boolean allowIsolated)
throws RemoteException {
Parcel data = Parcel.obtain();
Parcel reply = Parcel.obtain();
data.writeInterfaceToken(IServiceManager.descriptor);
data.writeString(name);
data.writeStrongBinder(service);
data.writeInt(allowIsolated ? 1 : 0);
mRemote.transact(ADD_SERVICE_TRANSACTION, data, reply, 0);
reply.recycle();
data.recycle();
}

这个保存方式跟我们getService()的方式是一致的!

至此,我们算是找到总算找到了IWifiManager.aidl的具体实现了,就是WifiServiceImpl,那么也就意味着我们的这整个WIfi的系统服务的接口定义、实现、注册、访问等流程都有两个一个大致的了解!

5、抱着怀疑的态度,我们看下WifiServiceImpl中是否真的实现了disconnect()方法:

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

    /**
* see {@link android.net.wifi.WifiManager#disconnect()}
*/
public void disconnect() {
enforceChangePermission();
mWifiStateMachine.disconnectCommand();
}

ok,验证通过!

三、总结

这整个Wifi服务是如何被创建以及注册到系统管理,然后如何向上层提供接口进行调用的过程看起来比较复杂,但是其实系统服务里面多数的实现方式都差不多是这样,只要理解了其中一个,其它的就相差不是很大,更重要的是我们去了解怎么一个过程,对我们以后进行framework层的开发还是有非常大的帮助的,比如说我们如何添加一个自己的系统服务。那么接下来我们队这整个流程进行简单的总结。

1、创建相关的AIDL文件IWifiManager.aidl,并定义相关功能方法。

2、创建WifiServiceImpl.java并实现IWifiManager.Stub,并在Contex中定义服务的唯一标识字符串。

3、创建创建WifiManager.java内部维护了通过ServiceManager获取到的WifiServiceImpl实例。

4、在SystemServiceRegistry.java的静态太代码块中通过registerService()方法创建WifiManager实例,并保存到SYSTEM_SERVICE_FETCHERS这个map中,这里要强调一点的是,由于WifiManager是在静态代码块中被创建,所以是单例的。

5、在SystemServer.java中通过SystemServiceManager创建WifiService实例,并调用其onStart()方法。

6、在WifiService的构造方法中创建WifiServiceImpl实例。

7、最终通过SystemService的publishBinderService()方法调用 ServiceManager.addService(name, service, allowIsolated);将WifiServiceImpl注册到ServiceManager中。
原文链接https://blog.csdn.net/monalisatearr/article/details/80801926

阿里P7移动互联网架构师进阶视频(每日更新中)免费学习请点击:https://space.bilibili.com/474380680

插件化框架解读之android系统服务实现原理(五)的更多相关文章

  1. 插件化框架解读之四大组件调用原理-Service(三)下篇

    阿里P7移动互联网架构师进阶视频(每日更新中)免费学习请点击:https://space.bilibili.com/474380680 本文将继续通过Service调用原理来解读Replugin插件化 ...

  2. 插件化框架解读之四大组件调用原理-Activity(三)上篇

    阿里P7移动互联网架构师进阶视频(每日更新中)免费学习请点击:https://space.bilibili.com/474380680 本文通过Activity调用原理来解读Replugin插件化技术 ...

  3. 插件化框架解读之Android 资源加载机制详解(二)

    阿里P7移动互联网架构师进阶视频(每日更新中)免费学习请点击:https://space.bilibili.com/474380680Android提供了一种非常灵活的资源系统,可以根据不同的条件提供 ...

  4. Android Small插件化框架解读——Activity注册和生命周期

    通过对嵌入式企鹅圈原创团队成员degao之前发表的<Android Small插件化框架源码分析>的学习,对Android使用的插件化技术有了初步的了解,但还是有很多需要认真学习的地方,特 ...

  5. 插件化框架解读之so 文件加载机制(四)

    阿里P7移动互联网架构师进阶视频(每日更新中)免费学习请点击:https://space.bilibili.com/474380680 提问 本文的结论是跟着 System.loadlibrary() ...

  6. 插件化框架解读之Class文件与Dex文件的结构(一)

    阿里P7移动互联网架构师进阶视频(每日更新中)免费学习请点击:https://space.bilibili.com/474380680 Class文件 Class文件是Java虚拟机定义并被其所识别的 ...

  7. Android Small插件化框架源码分析

    Android Small插件化框架源码分析 目录 概述 Small如何使用 插件加载流程 待改进的地方 一.概述 Small是一个写得非常简洁的插件化框架,工程源码位置:https://github ...

  8. 自己动手写Android插件化框架,让老板对你刮目相看

    欢迎大家前往腾讯云+社区,获取更多腾讯海量技术实践干货哦~ 本文由达文西发表于云+社区专栏 最近在工作中接触到了Android插件内的开发,发现自己这种技术还缺乏最基本的了解,以至于在一些基本问题上浪 ...

  9. Android插件化框架

    1.   dynamic-load-apk/DL动态加载框架 是基于代理的方式实现插件框架,对 App 的表层做了处理,通过在 Manifest 中注册代理组件,当启动插件组件时,首先启动一个代理组件 ...

随机推荐

  1. 1233: [Usaco2009Open]干草堆tower

    传送门 感觉正着做不太好搞,考虑倒过来搞 容易想到贪心,每一层都贪心地选最小的宽度,然后发现 $WA$ 了... 因为一开始多选一点有时可以让下一层宽度更小 然后有一个神奇的结论,最高的方案一定有一种 ...

  2. spring 配置属性细节

    版权声明:本文为博主原创文章.未经博主同意不得转载. https://blog.csdn.net/qilixiang012/article/details/28233811 概要(红色为上一篇所讲,蓝 ...

  3. Yii2 错误 'Headers already sent.'

    错误日志如下: __source__: __topic__: web category: yii\web\HeadersAlreadySentException ip: level: message: ...

  4. 【Vue 2.X】基于input[type='number']封装parseFloat、parseInt-自定义指令系列(一)

    一.parseFloat 效果:限制负值输入,且输入值不为空时自动保留两位小数,等同于js的parseFloat(value).toFixed(2) 使用:与v-model配合使用,v-parseFl ...

  5. UIGestureRecognizer 手势

    - (void)viewDidLoad { [super viewDidLoad]; // Do any additional setup after loading the view. self.v ...

  6. 2019-1-5-Windows-的-Pen-协议

    title author date CreateTime categories Windows 的 Pen 协议 lindexi 2019-01-05 11:14:49 +0800 2019-01-0 ...

  7. 295-Xilinx Kintex-7 X7K325T的半高PCIe x4双路万兆光纤收发卡

    Xilinx Kintex-7 X7K325T的半高PCIe x4双路万兆光纤收发卡 一.板卡概述       本板卡系我公司自主研发,采用Xilinx公司的XC7K325T-2FFG676I芯片作为 ...

  8. Python 无法安装PyAudio问题

    一.错误与原因 在Windows上没有用于Python 3.7的轮子(预构建包)(有一个用于Python 2.7和3.4到3.6),因此需要在PC上准备构建环境以使用此包.因为有些软件包很难在Wind ...

  9. Navicat Premium 12 如何连接阿里云虚拟主机SQL Server 数据库

    这个是一台 阿里云购买云虚拟主机!密码已经重置完毕,现在我们 需要知道 数据连接的地址,数据库名,帐号以及密码. 根据不同的运营商 选择 这里我们选择阿里云 云数据库 SQL Server版本 填写 ...

  10. python使用bs4爬取boss静态页面

    思路: 1.将需要查询城市列表,通过城市接口转换成相应的code码 2.遍历城市.职位生成url 3.通过url获取列表页面信息,遍历列表页面信息 4.再根据列表页面信息的job_link获取详情页面 ...