文章目录

    • 背景
    • 分析
    • ServiceManager
    • 总结
      • ServiceManager作用
      • Context.bindService() 跟ServiceManager获取对应的binder方式
      • 除了bindService(),其他方式获取binder
    • PS:

背景

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

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

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

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

分析

直接看一下Context源码:

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

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

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

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

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

// ActivityThreadprivate 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@Overridepublic 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。

// ServiceManagerNativepublic 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可以参考
https://www.cnblogs.com/lzlltmf/p/5906831.html

除了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是同一个。

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

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

更多相关文章

  1. Android获取View的宽高与View.measure详解
  2. Android端上传文件到Web服务器
  3. android获取周围WIFI热点
  4. Android系统剪贴板(ClipboardManager)的简单使用
  5. 利用power_profile.xml获取Android运行时的能耗
  6. android andbase 线程池
  7. Android原生GPS和网络定位工具类
  8. Android(安卓)开机自动启动服务
  9. android 模拟器上查看shareperference文件内容

随机推荐

  1. 欢迎页,引导页和主页
  2. android动态添加图层
  3. 13. android Context Menu With Icon (英
  4. android经典DEMO
  5. Android中特殊图形的生成例子
  6. android 图片缩放
  7. android之CheckBox
  8. android gridview 九宫格布局
  9. android 获取服务器json数据
  10. Android(安卓)studio 给标题栏加上返回按