当前位置:   article > 正文

android系统服务实现原理详解_android活动和服务实列怎么做

android活动和服务实列怎么做

        惭愧,入行android两年时间,才接触到android系统开发,确切的说是framework层的开发,随着android原生app原来越少,传统的android开发人员已经过剩,导致现在很多朋友换工作的过程中都不尽如人意,没办法,行情就是这样,甚至有些android开发都在考虑转行的事情了,在历史的大潮中,有无数的技术都经历了崛起到没落的过程,但是那些相关的开发者并没有谁会因此而活不下去,总会有新的地方需要到他们,所以没必要杞人忧天!安安心心工作学习就好!正所谓"生与死,冷眼一瞥,行者,且赶路!",好了废话有点多,接下来总结下近段时间自己对系统服务的一些学习心得,并且看看android是如何实现以及管理自己的系统服务的。

        这里要注意,我们一说系统服务,有些朋友可能就想到onCreate()、onCommand()、onBind(),onStart()d等等生命周期方法,其实我们这里说的系统服务跟我们做app开发时候的Service是不一样的,我们平时开发使用使用的服务必须是Service的子类,而系统服务并没有明确的定义,只要能向上层提供具体的功能(api),并且被纳入到ServiceManager中管理,运行在SystemServer进程,我们都可以称之为系统服务!

一、系统服务提供方式

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

  1. WifiManager wifimanager = (WifiManager) getSystemService(Context.WIFI_SERVICE);
  2. 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

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

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

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

  1. /**
  2.  * Gets a system service from a given context.
  3. */
  4. public static Object getSystemService(ContextImpl ctx, String name) {
  5. ServiceFetcher<?> fetcher = SYSTEM_SERVICE_FETCHERS.get(name);
  6. return fetcher != null ? fetcher.getService(ctx) : null;
  7. }
这里我们看到,通过我们传入的标识Context.WIFI_SERVICE从SYSTEM_SERVICE_FETCHERS中获取了ServiceFetcher对象,并通过ServiceFetcher的getService()方法返回我们所需WifiManager对象,那么SYSTEM_SERVICE_FETCHERS是什么? ServiceFetcher又是什么,我们看下下面的代码:

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

  1. private static final HashMap<String, ServiceFetcher<?>> SYSTEM_SERVICE_FETCHERS = new HashMap<String, ServiceFetcher<?>>();
  2. /**
  3. * Base interface for classes that fetch services.
  4. * These objects must only be created during static initialization.
  5. */
  6. static abstract interface ServiceFetcher<T> {
  7. T getService(ContextImpl ctx);
  8. }
  9. /**
  10. * Override this class when the system service constructor needs a
  11. * ContextImpl and should be cached and retained by that context.
  12. */
  13. static abstract class CachedServiceFetcher<T> implements ServiceFetcher<T> {
  14. private final int mCacheIndex;
  15. public CachedServiceFetcher() {
  16. mCacheIndex = sServiceCacheSize++;
  17. }
  18. @Override
  19. @SuppressWarnings("unchecked")
  20. public final T getService(ContextImpl ctx) {
  21. final Object[] cache = ctx.mServiceCache;
  22. synchronized (cache) {
  23. // Fetch or create the service.
  24. Object service = cache[mCacheIndex];
  25. if (service == null) {
  26. service = createService(ctx);
  27. cache[mCacheIndex] = service;
  28. }
  29. return (T)service;
  30. }
  31. }
  32. public abstract T createService(ContextImpl ctx);
  33. }

看到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

  1. /**
  2. * Statically registers a system service with the context.
  3. * This method must be called during static initialization only.
  4. */
  5. private static <T> void registerService(String serviceName, Class<T> serviceClass,
  6. ServiceFetcher<T> serviceFetcher) {
  7. SYSTEM_SERVICE_NAMES.put(serviceClass, serviceName);
  8. SYSTEM_SERVICE_FETCHERS.put(serviceName, serviceFetcher);
  9. }

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

  1. registerService(Context.WIFI_SERVICE, WifiManager.class,
  2. new CachedServiceFetcher<WifiManager>() {
  3. @Override
  4. public WifiManager createService(ContextImpl ctx) {
  5. IBinder b = ServiceManager.getService(Context.WIFI_SERVICE);
  6. IWifiManager service = IWifiManager.Stub.asInterface(b);
  7. return new WifiManager(ctx.getOuterContext(), service);
  8. }});

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

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

1、WifiManager

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

  1. public boolean disconnect() {
  2. try {
  3. mService.disconnect();
  4. return true;
  5. } catch (RemoteException e) {
  6. throw e.rethrowFromSystemServer();
  7. }
  8. }

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

  1. public WifiManager(Context context, IWifiManager service, Looper looper) {
  2. mContext = context;
  3. mService = service;
  4. mLooper = looper;
  5. mTargetSdkVersion = context.getApplicationInfo().targetSdkVersion;
  6. }
到此我们看到其实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分析分析:

  1. public interface IWifiManager extends android.os.IInterface {
  2. /**
  3. * Local-side IPC implementation stub class.
  4. */
  5. public static abstract class Stub extends android.os.Binder implements android.discovery
  6. .light.IWifiManager {
  7. private static final java.lang.String DESCRIPTOR = "android.discovery.light.IWifiManager";
  8. /**
  9. * Construct the stub at attach it to the interface.
  10. */
  11. public Stub() {
  12. this.attachInterface(this, DESCRIPTOR);
  13. }
  14. /**
  15. * Cast an IBinder object into an android.discovery.light.IWifiManager interface,
  16. * generating a proxy if needed.
  17. */
  18. public static android.discovery.light.IWifiManager asInterface(android.os.IBinder obj) {
  19. if ((obj == null)) {
  20. return null;
  21. }
  22. android.os.IInterface iin = obj.queryLocalInterface(DESCRIPTOR);
  23. if (((iin != null) && (iin instanceof android.discovery.light.IWifiManager))) {
  24. return ((android.discovery.light.IWifiManager) iin);
  25. }
  26. return new android.discovery.light.IWifiManager.Stub.Proxy(obj);
  27. }
  28. //此处省略N行代码============================================
  29. }

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

  1. public IInterface queryLocalInterface(String descriptor) {
  2. if (mDescriptor.equals(descriptor)) {
  3. return mOwner;
  4. }
  5. return null;
  6. }

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

  1. private IInterface mOwner;
  2. private String mDescriptor;
  3. public void attachInterface(IInterface owner, String descriptor) {
  4. mOwner = owner;
  5. mDescriptor = descriptor;
  6. }

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

  1. private static final java.lang.String DESCRIPTOR = "android.discovery.light.IMyAidlInterface";
  2. public Stub() {
  3. this.attachInterface(this, DESCRIPTOR);
  4. }

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

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

  1. registerService(Context.WIFI_SERVICE, WifiManager.class,
  2. new CachedServiceFetcher<WifiManager>() {
  3. @Override
  4. public WifiManager createService(ContextImpl ctx) {
  5. IBinder b = ServiceManager.getService(Context.WIFI_SERVICE);
  6. IWifiManager service = IWifiManager.Stub.asInterface(b);
  7. return new WifiManager(ctx.getOuterContext(), service);
  8. }});

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

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

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

  1. /**
  2. * Returns a reference to a service with the given name.
  3. *
  4. * @param name the name of the service to get
  5. * @return a reference to the service, or <code>null</code> if the service doesn't exist
  6. */
  7. public static IBinder getService(String name) {
  8. try {
  9. IBinder service = sCache.get(name);
  10. if (service != null) {
  11. return service;
  12. } else {
  13. return getIServiceManager().getService(name);
  14. }
  15. } catch (RemoteException e) {
  16. Log.e(TAG, "error in getService", e);
  17. }
  18. return null;
  19. }
我们看到程序首先通过sCache这个HasMap中去取,如果不存在就通过getIServiceManager().getService(name)去取,而getIServiceManager()返回的是一个IServiceManager接口,他的具体实现是在ServiceManagerNative#ServiceManagerProxy这个内部类中的,看下源码:

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

  1. public IBinder getService(String name) throws RemoteException {
  2. Parcel data = Parcel.obtain();
  3. Parcel reply = Parcel.obtain();
  4. data.writeInterfaceToken(IServiceManager.descriptor);
  5. data.writeString(name);
  6. mRemote.transact(GET_SERVICE_TRANSACTION, data, reply, 0);
  7. IBinder binder = reply.readStrongBinder();
  8. reply.recycle();
  9. data.recycle();
  10. return binder;
  11. }

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

4、ServiceManager.addService()

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

  1. private static final String WIFI_SERVICE_CLASS = "com.android.server.wifi.WifiService";
  2. /**
  3. * Starts a miscellaneous grab bag of stuff that has yet to be refactored
  4. * and organized.
  5. */
  6. private void startOtherServices() {
  7. //省略很多。。。
  8. mSystemServiceManager.startService(WIFI_SERVICE_CLASS);
  9. //省略很多。。。
  10. }
这里我们看到 mSystemServiceManager.startService(WIFI_SERVICE_CLASS)怎么一句代码,查看其定义发现mSystemServiceManager是SystemServiceManager:

源码路径: xxx/frameworks/base/services/core/java/com/android/server/SystemServiceManager.java

  1. * Starts a service by class name.
  2. *
  3. * @return The service instance.
  4. */
  5. @SuppressWarnings("unchecked")
  6. public SystemService startService(String className) {
  7. final Class<SystemService> serviceClass;
  8. try {
  9. serviceClass = (Class<SystemService>)Class.forName(className);
  10. } catch (ClassNotFoundException ex) {
  11. Slog.i(TAG, "Starting " + className);
  12. throw new RuntimeException("Failed to create service " + className
  13. + ": service class not found, usually indicates that the caller should "
  14. + "have called PackageManager.hasSystemFeature() to check whether the "
  15. + "feature is available on this device before trying to start the "
  16. + "services that implement it", ex);
  17. }
  18. return startService(serviceClass);
  19. }

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

  1. /**
  2. * Creates and starts a system service. The class must be a subclass of
  3. * {@link com.android.server.SystemService}.
  4. *
  5. * @param serviceClass A Java class that implements the SystemService interface.
  6. * @return The service instance, never null.
  7. * @throws RuntimeException if the service fails to start.
  8. */
  9. @SuppressWarnings("unchecked")
  10. public <T extends SystemService> T startService(Class<T> serviceClass) {
  11. final String name = serviceClass.getName();
  12. Slog.i(TAG, "Starting " + name);
  13. // Create the service.
  14. if (!SystemService.class.isAssignableFrom(serviceClass)) {
  15. throw new RuntimeException("Failed to create " + name
  16. + ": service must extend " + SystemService.class.getName());
  17. }
  18. final T service;
  19. try {
  20. Constructor<T> constructor = serviceClass.getConstructor(Context.class);
  21. service = constructor.newInstance(mContext);
  22. } catch (InstantiationException ex) {
  23. throw new RuntimeException("Failed to create service " + name
  24. + ": service could not be instantiated", ex);
  25. } catch (IllegalAccessException ex) {
  26. throw new RuntimeException("Failed to create service " + name
  27. + ": service must have a public constructor with a Context argument", ex);
  28. } catch (NoSuchMethodException ex) {
  29. throw new RuntimeException("Failed to create service " + name
  30. + ": service must have a public constructor with a Context argument", ex);
  31. } catch (InvocationTargetException ex) {
  32. throw new RuntimeException("Failed to create service " + name
  33. + ": service constructor threw an exception", ex);
  34. }
  35. // Register it.
  36. mServices.add(service);
  37. // Start it.
  38. try {
  39. service.onStart();
  40. } catch (RuntimeException ex) {
  41. throw new RuntimeException("Failed to start service " + name
  42. + ": onStart threw an exception", ex);
  43. }
  44. return service;
  45. }

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

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

  1. package com.android.server.wifi;
  2. import android.content.Context;
  3. import android.net.wifi.ScanResult;
  4. import android.net.wifi.WifiScanner;
  5. import android.util.Log;
  6. import com.android.server.SystemService;
  7. import java.util.List;
  8. public final class WifiService extends SystemService {
  9. private static final String TAG = "WifiService";
  10. final WifiServiceImpl mImpl;
  11. public WifiService(Context context) {
  12. super(context);
  13. mImpl = new WifiServiceImpl(context);
  14. }
  15. @Override
  16. public void onStart() {
  17. Log.i(TAG, "Registering " + Context.WIFI_SERVICE);
  18. publishBinderService(Context.WIFI_SERVICE, mImpl);
  19. }
  20. @Override
  21. public void onBootPhase(int phase) {
  22. if (phase == SystemService.PHASE_SYSTEM_SERVICES_READY) {
  23. mImpl.checkAndStartWifi();
  24. }
  25. }
  26. }

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

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

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

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

  1. public void addService(String name, IBinder service, boolean allowIsolated)
  2. throws RemoteException {
  3. Parcel data = Parcel.obtain();
  4. Parcel reply = Parcel.obtain();
  5. data.writeInterfaceToken(IServiceManager.descriptor);
  6. data.writeString(name);
  7. data.writeStrongBinder(service);
  8. data.writeInt(allowIsolated ? 1 : 0);
  9. mRemote.transact(ADD_SERVICE_TRANSACTION, data, reply, 0);
  10. reply.recycle();
  11. data.recycle();
  12. }

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

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

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

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

  1. /**
  2. * see {@link android.net.wifi.WifiManager#disconnect()}
  3. */
  4. public void disconnect() {
  5. enforceChangePermission();
  6. mWifiStateMachine.disconnectCommand();
  7. }

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中。


好了,这次就到这里,后面会在这篇文章的基础上给大家分享下,如何一步步的添加一个自己自定义的服务!



声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/你好赵伟/article/detail/311029
推荐阅读
相关标签
  

闽ICP备14008679号