插件化框架解读之android系统服务实现原理(五)
阿里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系统服务实现原理(五)的更多相关文章
- 插件化框架解读之四大组件调用原理-Service(三)下篇
阿里P7移动互联网架构师进阶视频(每日更新中)免费学习请点击:https://space.bilibili.com/474380680 本文将继续通过Service调用原理来解读Replugin插件化 ...
- 插件化框架解读之四大组件调用原理-Activity(三)上篇
阿里P7移动互联网架构师进阶视频(每日更新中)免费学习请点击:https://space.bilibili.com/474380680 本文通过Activity调用原理来解读Replugin插件化技术 ...
- 插件化框架解读之Android 资源加载机制详解(二)
阿里P7移动互联网架构师进阶视频(每日更新中)免费学习请点击:https://space.bilibili.com/474380680Android提供了一种非常灵活的资源系统,可以根据不同的条件提供 ...
- Android Small插件化框架解读——Activity注册和生命周期
通过对嵌入式企鹅圈原创团队成员degao之前发表的<Android Small插件化框架源码分析>的学习,对Android使用的插件化技术有了初步的了解,但还是有很多需要认真学习的地方,特 ...
- 插件化框架解读之so 文件加载机制(四)
阿里P7移动互联网架构师进阶视频(每日更新中)免费学习请点击:https://space.bilibili.com/474380680 提问 本文的结论是跟着 System.loadlibrary() ...
- 插件化框架解读之Class文件与Dex文件的结构(一)
阿里P7移动互联网架构师进阶视频(每日更新中)免费学习请点击:https://space.bilibili.com/474380680 Class文件 Class文件是Java虚拟机定义并被其所识别的 ...
- Android Small插件化框架源码分析
Android Small插件化框架源码分析 目录 概述 Small如何使用 插件加载流程 待改进的地方 一.概述 Small是一个写得非常简洁的插件化框架,工程源码位置:https://github ...
- 自己动手写Android插件化框架,让老板对你刮目相看
欢迎大家前往腾讯云+社区,获取更多腾讯海量技术实践干货哦~ 本文由达文西发表于云+社区专栏 最近在工作中接触到了Android插件内的开发,发现自己这种技术还缺乏最基本的了解,以至于在一些基本问题上浪 ...
- Android插件化框架
1. dynamic-load-apk/DL动态加载框架 是基于代理的方式实现插件框架,对 App 的表层做了处理,通过在 Manifest 中注册代理组件,当启动插件组件时,首先启动一个代理组件 ...
随机推荐
- H Kuangyeye and hamburgers
链接:https://ac.nowcoder.com/acm/contest/338/H来源:牛客网 题目描述 Kuangyeye is a dalao of the ACM school team ...
- C# Base64编码解码 ,Md5、Rsa加密解密
using System; using System.IO; using System.Security.Cryptography; using System.Text; namespace Clas ...
- 攻防世界--re2-cpp-is-awesome
测试文件:https://adworld.xctf.org.cn/media/task/attachments/c5802869b8a24033b4a80783a67c858b 1.准备 获取信息 6 ...
- 使用 typeof bar === "object" 来确定 bar 是否是对象的潜在陷阱是什么?
使用typeof首先要明白 typeof 可以检测什么. typeof 主要用于检测基本数据类型.typeof尽量不要用来检测复杂数据类型. typeof 检测null 和 数组 的时候 结果也是ob ...
- swiper轮播图设置每组显示的个数及自定义slide宽度
一.html演示代码: <div class="swiper-container"> <div class="swiper-wrapper"& ...
- ASE "黄金点游戏"
问题定义 黄金点游戏是源于经济学家Richar Thaler构思的在1997年伦敦金融时报进行了一次公开竞猜活动.MSRA-ASE课程的第一次结对编程中,我们写了一个AI Bot来与大家玩儿这个游戏. ...
- shell函数的结束与返回值
- Redis5.0集群搭建实战
安装环境: 6台 centos7.4 在各个节点下载官网release包,可以自己去官网找: wget http://download.redis.io/releases/redis-5.0.5.t ...
- C Primer Plus 学习 第四章
字符串与格式化输入/输出 函数 strlen() 关键字 const 利用#define 和 const创建符号常量 #include <stdio.h> #include <str ...
- Linux 进程通信之:内存共享(Shared Memory)(转,好文章)
https://blog.csdn.net/afei__/article/details/84188548