浅谈Android(安卓)java层ServiceManager
概述
ServiceManager作为Android进程间通信binder机制中的重要角色,运行在native层,由c++语言实现,任何Service被使用之前,例如播放音乐的MediaService,例如管理activity的ActivityManagerService,均要向SM注册,同时客户端使用某个service时,也需要向ServiceManager查询该Service是否注册过了。
ServiceManager作用
1、负责与Binder driver通信,维护一个死循环,不断地读取内核binder driver。即不断读取看是否有对service的操作请求。 2、维护一个svclist列表来存储service信息。 3、向客户端提供Service的代理,也就是BinderProxy。 延伸:客户端向ServiceManager查找Service并获取BinderProxy,通过BinderProxy实现与Service端的通信。 4、负责提供Service注册服务 其实,ServiceManager就像是一个路由,首先,Service把自己注册在ServiceManager中,调用方(客户端)通过ServiceManager查询服务它的实现是service_manager.c。而java中的ServiceManager.java仅仅是service_manager.c的封装。这里,我们不讨论service_manager.c是如何向下与Binder driver通信的,也不讨论注册、查找service的具体逻辑。而是从java层面,也就是Android FrameWork层面讨论是如何使用ServceManager.java服务的。
ServiceManager.java的源码很简单,如下:
public final class ServiceManager { private static final String TAG = "ServiceManager"; private static IServiceManager sServiceManager; private static HashMap sCache = new HashMap(); private static IServiceManager getIServiceManager() { if (sServiceManager != null) { return sServiceManager; } // Find the service manager sServiceManager = ServiceManagerNative.asInterface(BinderInternal.getContextObject()); return sServiceManager; } /** * 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 null
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; } /** * Place a new @a service called @a name into the service * manager. * * @param name the name of the new service * @param service the service object */ public static void addService(String name, IBinder service) { try { getIServiceManager().addService(name, service, false); } catch (RemoteException e) { Log.e(TAG, "error in addService", e); } } /** * Place a new @a service called @a name into the service * manager. * * @param name the name of the new service * @param service the service object * @param allowIsolated set to true to allow isolated sandboxed processes * to access this service */ public static void addService(String name, IBinder service, boolean allowIsolated) { try { getIServiceManager().addService(name, service, allowIsolated); } catch (RemoteException e) { Log.e(TAG, "error in addService", e); } } /** * Retrieve an existing service called @a name from the * service manager. Non-blocking. */ public static IBinder checkService(String name) { try { IBinder service = sCache.get(name); if (service != null) { return service; } else { return getIServiceManager().checkService(name); } } catch (RemoteException e) { Log.e(TAG, "error in checkService", e); return null; } } /** * Return a list of all currently running services. * @return an array of all currently running services, or null
in * case of an exception */ public static String[] listServices() { try { return getIServiceManager().listServices(); } catch (RemoteException e) { Log.e(TAG, "error in listServices", e); return null; } } /** * This is only intended to be called when the process is first being brought * up and bound by the activity manager. There is only one thread in the process * at that time, so no locking is done. * * @param cache the cache of service references * @hide */ public static void initServiceCache(Map cache) { if (sCache.size() != 0) { throw new IllegalStateException("setServiceCache may only be called once"); } sCache.putAll(cache); }}
有如下功能
1、提供addService()方法,向native层注册服务
2、提供getService()方法,从native层获取服务
3、维护了缓存Map
其实getService()就是从native层获取Binder,获取后通过Stub.asInterface()方法转化为BinderProxy,通过BinderProxy就可以通过其调用远端方法了。这部分知识我们是比较熟悉的,在通过AIDL自定义Service时,用到的就是这部分知识。这里我们先认为native层对我们是不透明的,只要了解到通过addService()和getService()就可以向native注册服务或从native层获取服务。想了解native是如何实现注册和获取服务的同学可以看这两篇文章:
Android Framework学习(十)之向ServiceManager注册Native层服务
Android Framework学习(十一)之从ServiceManager获取Native层服务
我们这里暂时不讨论
App端
从本人总结的的上一篇文章Android SystemServer解析中我们可以了解到,通过getSystemService()获取远端服务代理时,最终是通过ServiceFetcher.createService()方法创建XXManager,XXManager中封装了用于访问远端服务的BinderProxy,那么,这里我们探究下XXManager中的BinderProxy是如何而来的。其实我们猜也能猜到一定是通过ServiceManager.getService()获取的,我们来证实这一过程。
先挑一个最常用的ActivityManager,ActivityManager封装了对远端访问的业务方法,那么在这些方法中必然是通过调用BinderProxy来实现的,我们举两个例子:
@Deprecated public List getRunningTasks(int maxNum) throws SecurityException { try { return ActivityManagerNative.getDefault().getTasks(maxNum, 0); } catch (RemoteException e) { throw e.rethrowFromSystemServer(); } }
可以看到是通过调用ActivityManagerNative.getDefault().getTasks()方法,说明ActivityManagerNative.getDefault()返回的 BinderProxy,我们跟进去看:
ActivityManagerNative.getDefault()
/** * Retrieve the system's default/global activity manager. */ static public IActivityManager getDefault() { return gDefault.get(); }
看看getDefault()是什么:
private static final Singleton gDefault = new Singleton() { protected IActivityManager create() { IBinder b = ServiceManager.getService("activity"); if (false) { Log.v("ActivityManager", "default service binder = " + b); } IActivityManager am = asInterface(b); if (false) { Log.v("ActivityManager", "default service = " + am); } return am; } };
果不其然,是从ServiceManager中获取的IBinder,并转换为BinderProxy。
再看一个XXManager,BluetoothManager,其中有一个逻辑方法getConnectedSevices()如下:
public List getConnectedDevices(int profile) { if (DBG) Log.d(TAG,"getConnectedDevices"); if (profile != BluetoothProfile.GATT && profile != BluetoothProfile.GATT_SERVER) { throw new IllegalArgumentException("Profile not supported: " + profile); } List connectedDevices = new ArrayList(); try { IBluetoothManager managerService = mAdapter.getBluetoothManager(); IBluetoothGatt iGatt = managerService.getBluetoothGatt(); if (iGatt == null) return connectedDevices; connectedDevices = iGatt.getDevicesMatchingConnectionStates( new int[] { BluetoothProfile.STATE_CONNECTED }); } catch (RemoteException e) { Log.e(TAG,"",e); } return connectedDevices; }
可以看到是通过mAdapter获取IBluetoothManager接口,也就是BinderProxy,跟进去BluetoothAdapter:
/*package*/ IBluetoothManager getBluetoothManager() { return mManagerService; }
返回mManagerService,该变量是构造BluetoothAdapter时传入的,发现BluetoothAdapter中包含创建BluetoothAdapter的方法getDefaultAdapter,如下:
public static synchronized BluetoothAdapter getDefaultAdapter() { if (sAdapter == null) { IBinder b = ServiceManager.getService(BLUETOOTH_MANAGER_SERVICE); if (b != null) { IBluetoothManager managerService = IBluetoothManager.Stub.asInterface(b); sAdapter = new BluetoothAdapter(managerService); } else { Log.e(TAG, "Bluetooth binder is null"); } } return sAdapter; }
可以看到,也是通过ServiceManager.getService()获取IBinder,并通过adInterface(b)方法转换为BinderProxy。
当然并不是所有的XXManager都需要远端服务,有些XXManager的业务方法是通过ContentProvider来实现的。
由此,我们验证了一点:XXManager中包含的BinderProxy是从ServiceManager.getService()获取的并通过asInterface()得到的。
SystemServer端
下面,我们再来验证注册服务是通过ServiceManager.addService()实现的,从上一篇文章Android SystemServer解析,我们得知,各中XXManagerService都是通过SystemServer.java的静态代码块创建并调用onStart()方法启动,看起来并没有和ServiceManager.addService()发生联系,不急,我们可以看到SystemServer.startOtherService()方法中存在如下代码:
telephonyRegistry = new TelephonyRegistry(context);ServiceManager.addService("telephony.registry", telephonyRegistry);vibrator = new VibratorService(context);ServiceManager.addService("vibrator", vibrator);
可以发现就是通过ServiceManager.addService()向native注册服务
同时,在AMS中也可以发现注册核心Service的代码:
ServiceManager.addService(Context.ACTIVITY_SERVICE, this, true);ServiceManager.addService(ProcessStats.SERVICE_NAME, mProcessStats);ServiceManager.addService("meminfo", new MemBinder(this));ServiceManager.addService("gfxinfo", new GraphicsBinder(this));ServiceManager.addService("dbinfo", new DbBinder(this));
说是注册Service,其实就是注册一个IBinder,该IBinder标明了自己的身份,我们可以发现addService()的第二个参数的类均是Binder,如VibratorService:
public class VibratorService extends IVibratorService.Stub implements InputManager.InputDeviceListener {....
如TelephonyRegistory:
class TelephonyRegistry extends ITelephonyRegistry.Stub { private static final String TAG = "TelephonyRegistry";.....
另外,XXManagerService的父类SystemService中,也提供了向ServiceManager注册的方法:
protected final void publishBinderService(String name, IBinder service, boolean allowIsolated) { ServiceManager.addService(name, service, allowIsolated); }
更多相关文章
- ANDROID STUDIO&&Eclipse Android项目缺少R文件解决方法(完解)
- android中WebView的Java与JavaScript交互
- 《第一行代码》 6.3 SharedPreferences存储
- Android(java)同步方法synchronized
- Android——RecyclerView入门学习之LayoutManager
- Android(安卓)通用获取Ip的方法(判断手机是否联网的方法)!!!
- Content Provider使用方法以及Android运行时权限申请
- Android心得2.4--四大组件之一--Activity
- Webkit for Android分析