Android Context.getSystemService() 与 ServiceManager 的理解和使用详解手机开发

背景

这几天在天天在写Context.getSystemService()获取系统服务,例如在获取窗口服务的时候都会这样写:

WindowManager manager = (WindowManager) context.getSystemService(Context.WINDOW_SERVICE);

突然有人问我说,就是getSystemService() 每次获取的对应的WindowManager是否是同一个,还是每次生成新的?

直接翻看了下源码,事实上还是比较简单的,以下做一下记录:

分析

直接看一下Context源码:

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

Context只是一个抽象类,具体看下实现类ContextWrapper

@Override 
public Object getSystemService(String name) {
    
    return mBase.getSystemService(name); 
} 

ContextWrapper使用了代理模式,mBase是Context的具体实现。

在Activity启动的时候,ActivityThread的performLaunchActivity中会创建ContextImpl,同时会调用了Activity的attach(),将Context设置给了activity

// ActivityThread 
private Activity performLaunchActivity(ActivityClientRecord r, Intent customIntent) {
    
        // 创建了ContextImpl 
        ContextImpl appContext = createBaseContextForActivity(r); 
        Activity activity = null; 
        // 反射创建了activity 
        java.lang.ClassLoader cl = appContext.getClassLoader(); 
        activity = mInstrumentation.newActivity( 
                    cl, component.getClassName(), r.intent); 
        // 创建applicaiton 
        Application app = r.packageInfo.makeApplication(false, mInstrumentation); 
         
        appContext.setOuterContext(activity); 
        // 将appContext传入 
        activity.attach(appContext, this, getInstrumentation(), r.token, 
                        r.ident, app, r.intent, r.activityInfo, title, r.parent, 
                        r.embeddedID, r.lastNonConfigurationInstances, config, 
                        r.referrer, r.voiceInteractor, window, r.configCallback); 
        return activity; 
    } 

ContextImpl才是Context的真正实现。

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

SystemServiceRegistry是一个负责注册系统服务的类,内部有一个静态的HashMap,静态加载了各种系统服务在里面,其中就包括了window_service。

    // ContextImpl 
    private static final HashMap<Class<?>, String> SYSTEM_SERVICE_NAMES = 
            new HashMap<Class<?>, String>(); 
    private static final HashMap<String, ServiceFetcher<?>> SYSTEM_SERVICE_FETCHERS = 
            new HashMap<String, ServiceFetcher<?>>(); 
    private static int sServiceCacheSize; 
     
    static {
    
        ... 
        registerService(Context.WINDOW_SERVICE, WindowManager.class, 
                new CachedServiceFetcher<WindowManager>() {
    
            @Override 
            public WindowManager createService(ContextImpl ctx) {
    
                return new WindowManagerImpl(ctx); 
            }}); 
        ... 
    } 
 
    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) {
    
                    try {
    
                        service = createService(ctx); 
                        cache[mCacheIndex] = service; 
                    } catch (ServiceNotFoundException e) {
    
                        onServiceNotFound(e); 
                    } 
                } 
                return (T)service; 
            } 
        } 
 
        public abstract T createService(ContextImpl ctx) throws ServiceNotFoundException; 
    } 

可见,我们获取的window_service对应的就是静态hashmap存储的WindowManagerImpl,也就是一个进程只会创建一个WindowManagerImpl。

ServiceManager

WindowManagerImpl比较特别,我们再来看一个:

registerService(Context.POWER_SERVICE, PowerManager.class, 
            new CachedServiceFetcher<PowerManager>() {
    
        @Override 
        public PowerManager createService(ContextImpl ctx) throws ServiceNotFoundException {
    
            IBinder b = ServiceManager.getServiceOrThrow(Context.POWER_SERVICE); 
            IPowerManager service = IPowerManager.Stub.asInterface(b); 
            return new PowerManager(ctx.getOuterContext(), 
                    service, ctx.mMainThread.getHandler()); 
        }}); 

其中,从ServiceManager获取对应的服务的binder

 IBinder b = ServiceManager.getServiceOrThrow(Context.POWER_SERVICE); 

ServiceManager提供获取服务的接口

// ServiceManager 
    public static IBinder getServiceOrThrow(String name) throws ServiceNotFoundException {
    
        final IBinder binder = getService(name); 
        if (binder != null) {
    
            return binder; 
        } else {
    
            throw new ServiceNotFoundException(name); 
        } 
    } 
    // 通过服务名字获取binder 
    public static IBinder getService(String name) {
    
        try {
    
            IBinder service = sCache.get(name); 
            if (service != null) {
    
                return service; 
            } else {
    
                // 重点:获取对应服务的Binder 
                return Binder.allowBlocking(getIServiceManager().getService(name)); 
            } 
        } catch (RemoteException e) {
    
            Log.e(TAG, "error in getService", e); 
        } 
        return null; 
    } 

上面的代码很简单,其中sCache是一个hashMap,缓存了已经加载过的服务的binder,避免二次获取。

private static IServiceManager sServiceManager; 
private static HashMap<String, IBinder> sCache = new HashMap<String, IBinder>(); 

最后我们的关注点就是:

  1. IServiceManager是对应什么?

  2. getIServiceManager().getService(name)如何获取到具体的服务的binder?


先看下IServiceManager接口的定义:

public interface IServiceManager extends IInterface 
{
    
    public IBinder getService(String name) throws RemoteException; 
     
    public IBinder checkService(String name) throws RemoteException; 
 
    public void addService(String name, IBinder service, boolean allowIsolated) 
                throws RemoteException; 
 
    public String[] listServices() throws RemoteException; 
 
    public void setPermissionController(IPermissionController controller) 
            throws RemoteException;  
} 

IServiceManager接口提供了getServiceaddServicecheckServicelistService接口,对应的就是binder机制里面的ServiceManager,负责跟Binder打交道,注册binder、获取binder等服务。

再看下getIServiceManager(),他也是一个获取binder转化成对应的服务接口的方法

private static IServiceManager getIServiceManager() {
    
    if (sServiceManager != null) {
    
        return sServiceManager; 
    } 
 
    // Find the service manager 
    sServiceManager = ServiceManagerNative 
           .asInterface(Binder.allowBlocking(BinderInternal.getContextObject())); 
    return sServiceManager; 
} 

ServiceManagerNative是一个类似AIDL为我们自动生成的类的方法,他对应了服务端和客户端的实现。在我们客户端的进程中,打交道的就是ServiceManagerProxy,他是一个BpBinder。

// ServiceManagerNative 
public abstract class ServiceManagerNative extends Binder implements IServiceManager 
{
    
    static public IServiceManager asInterface(IBinder obj) 
    {
    
        ... 
        IServiceManager in = 
            (IServiceManager)obj.queryLocalInterface(descriptor); 
        ... 
        return new ServiceManagerProxy(obj); 
    } 
     
    public ServiceManagerNative() 
    {
    
        attachInterface(this, descriptor); 
    } 
     
    public boolean onTransact(int code, Parcel data, Parcel reply, int flags) 
    {
    
        try {
    
            switch (code) {
    
            case IServiceManager.GET_SERVICE_TRANSACTION: {
    
                data.enforceInterface(IServiceManager.descriptor); 
                String name = data.readString(); 
                IBinder service = getService(name); 
                reply.writeStrongBinder(service); 
                return true; 
            } 
            ... 
        }  
        return false; 
    } 
 
    public IBinder asBinder() 
    {
    
        return this; 
    } 
} 
 
class ServiceManagerProxy implements IServiceManager {
    
    public ServiceManagerProxy(IBinder remote) {
    
        mRemote = remote; 
    } 
     
    public IBinder asBinder() {
    
        return mRemote; 
    } 
     
    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; 
    } 
    .... 
} 

很明显,ServiceManagerNative就是对应了binder服务端BBinder的实现,类似aidl帮助自动生成的Stub类。ServiceManagerProxy则对应客户端BpBinder的实现,类似对应aidl帮助自动生成的Stub.Proxy代理类。

最后的问题,BinderInternal.getContextObject()获取的是什么服务的binder?

// BinderInternal 
/** 
 * Return the global "context object" of the system.  This is usually 
 * an implementation of IServiceManager, which you can use to find 
 * other services. 
 */ 
public static final native IBinder getContextObject(); 

getContextObject是一个native方法,根据注释,它是整个系统的Context对象,一般情况下,IServiceManager通过它去获取其他服务。

总结

由上面总结的信息可以得到

ServiceManager作用

  1. 通过BinderInternal.getContextObject()可以得到ServiceManager的binder,获取得到ServiceManager服务接口,借用ServiceManager服务接口可以去注册、获取我们需要的系统服务。

  2. ServiceManager用于系统服务的注册添加和获取,在AMS都可以看到他的身影,通过它来注册系统服务:

     // ActivityManagerService.java 
     public void setSystemProcess() {
          
    	try {
          
        	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)); 
        	if (MONITOR_CPU_USAGE) {
          
         	   ServiceManager.addService("cpuinfo", new CpuBinder(this)); 
        	} 
        	ServiceManager.addService("permission", new PermissionController(this)); 
        	ServiceManager.addService("processinfo", new ProcessInfoService(this)); 
        	... 
     } 
    

Context.bindService() 跟ServiceManager获取对应的binder方式

Context.bindService() 跟ServiceManager获取对应的binder方式是不一样的

  1. A 进程 Context.bindService()会将ServiceConnection封装成可IPC调用的IServiceConnection;

  2. 同时调用了AMS的bindService,AMS分发给了ActiveServices执行真正的任务;

  3. ActiveServices做保存IServiceConnection工作,启动ActivityThread的handleBindService()去反射生成一个新的Service;

  4. ActivityThread调用了Service的onBind()获取到了Service的binder,调用AMS的publishService(),AMS又让ActiveServices执行工作;

  5. ActiveServices将这个binder通过IServiceConnection发给A进程。完成bindService工作,整个工作流程中,并没有去调用ServiceManager加载这个binder。

  6. 至于getContextObject()如何获取到ServiceManager的BpBinder,没有继续深究
    service_manager进程是由是由init进程,通过解析init.rc文件来启动的进程。
    根据底层0号可以获取到ServiceManager的binder

关于ServiceManager可以参考
云图网

除了bindService(),其他方式获取binder

  1. bindService通过ServiceConnection获取对应的binder
  2. 借助binder接口获取binder,比如说通过bindService获取binder A,而binder A提供获取binder B的接口
  3. 通过ServiceManager的addService,但ServiceManager是hide类,这种方式是SystemService注册的方式,适合系统应用的开发

PS:

同一个进程,getSystemService() 每次获取的对应的WindowManager是同一个。

发布文章的时候,系统提示说:该文章不是原创。

才发现原来这部分网上有好多文章分析过了,看来自己不能浅显的只学习这些简单的知识点,还得继续努力,往深度发展

原创文章,作者:奋斗,如若转载,请注明出处:https://blog.ytso.com/tech/app/6258.html

(0)
上一篇 2021年7月17日 00:45
下一篇 2021年7月17日 00:45

相关推荐

发表回复

登录后才能评论