Android系统服务调用分析

276 阅读3分钟

一起养成写作习惯!这是我参与「掘金日新计划 · 4 月更文挑战」的第21天,点击查看活动详情

在Android系统中,framework向应用层提供了很多系统服务,例如InputManager、ActivityManager、WindowManager等,方便的实现软件需求的开发。

一.系统服务使用

      一般而言,在使用时,通过以下方式来获取对应的系统服务管理者:

WindowManager mWindowManager;
mWindowManager = (WindowManager) mService.getSystemService(Context.WINDOW_SERVICE);
mWindowManager.addView();

      即:调用 Context 类的 getSystemService(String name) 方法,通过一步一步调用,该方法的最终实现是在 ContextImpl 类中,通过查看 ContextImpl 的源码,发现对应的实现如下:

public Object getSystemService(String name) {
    return SystemServiceRegistry.getSystemService(this, name);
}

      从ContextImpl里面的实现来看,会调用到SystemServiceRegistry类里面的getSystemService方法,再进去看一下SystemServiceRegistry.java的内部实现:

public static Object getSystemService(ContextImpl ctx, String name) {
    SystemServiceRegistry.ServiceFetcher<?> fetcher = (SystemServiceRegistry.ServiceFetcher)SYSTEM_SERVICE_FETCHERS.get(name);
    return fetcher != null ? fetcher.getService(ctx) : null;
}

      从以上方法可以看到:从SYSTEM_SERVICE_FETCHERS 中获取对应名称的系统服务管理者提取器,然后从中得到对应的服务器管理者。看一下SYSTEM_SERVICE_FETCHERS:

private static final HashMap<String, SystemServiceRegistry.ServiceFetcher<?>> SYSTEM_SERVICE_FETCHERS = new HashMap();

      SYSTEM_SERVICE_FETCHERS是一个HashMap,存放着String为key,ServiceFetcher为value的键值对:

private static <T> void registerService(String serviceName, Class<T> serviceClass, SystemServiceRegistry.ServiceFetcher<T> serviceFetcher) {
    SYSTEM_SERVICE_NAMES.put(serviceClass, serviceName);
    SYSTEM_SERVICE_FETCHERS.put(serviceName, serviceFetcher);
}

      在执行registerService方法时,将serviceName对应的serviceFetcher存入HashMap,接着看一下ServiceFetcher的实现:

abstract static class CachedServiceFetcher<T> implements SystemServiceRegistry.ServiceFetcher<T> {
    private final int mCacheIndex;

    public CachedServiceFetcher() {
        mCacheIndex = SystemServiceRegistry.sServiceCacheSize++;
    }

    public final T getService(ContextImpl ctx) {
        final Object[] cache = ctx.mServiceCache;
        synchronized(cache) {
            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;
}
interface ServiceFetcher<T> {
    T getService(ContextImpl var1);
}

      从以上可以看到,ServiceFetcher是一个接口,通过CachedServiceFetcher来实现,里面有一个抽象方法createService()需要实现,在getService()方法里面有调用到createService(),接下来看一下系统服务是如何注册的:

二.系统服务注册

      要想使用系统服务,肯定是需要系统服务先注册后使用,看一下系统服务是什么时候注册的:

static {
    ....
    registerService("rttmanager", RttManager.class, new SystemServiceRegistry.CachedServiceFetcher<RttManager>() {
        public RttManager createService(ContextImpl ctx) throws ServiceNotFoundException {
            IBinder b = ServiceManager.getServiceOrThrow("rttmanager");
            IRttManager service = android.net.wifi.IRttManager.Stub.asInterface(b);
            return new RttManager(ctx.getOuterContext(), service, ConnectivityThread.getInstanceLooper());
        }
    });

    registerService("ethernet", EthernetManager.class, new SystemServiceRegistry.CachedServiceFetcher<EthernetManager>() {
        public EthernetManager createService(ContextImpl ctx) throws ServiceNotFoundException {
            IBinder b = ServiceManager.getServiceOrThrow("ethernet");
            IEthernetManager service = android.net.IEthernetManager.Stub.asInterface(b);
            return new EthernetManager(ctx.getOuterContext(), service);
        }
    });

    registerService("window", WindowManager.class, new SystemServiceRegistry.CachedServiceFetcher<WindowManager>() {
        public WindowManager createService(ContextImpl ctx) {
            return new WindowManagerImpl(ctx);
        }
    });
}
....

      registerService()是在static代码块里面,createService()会返回对应的Manager,那么在getSystemService()内部执行fetcher.getService(ctx)就获取到了manager,在返回前有以下逻辑:

IBinder b = ServiceManager.getServiceOrThrow("ethernet");
IEthernetManager service = android.net.IEthernetManager.Stub.asInterface(b);

      先通过ServiceManager获取了“ethernet”对应的IBinder,然后获取到service,最后把service作为参数传递给EthernetManager。看一下EthernetManager的实现:

public class EthernetManager {
    private final IEthernetManager mService;
    public EthernetManager(Context context, IEthernetManager service) {
        mContext = context;
        mService = service;
    }

    public IpConfiguration getConfiguration() {
        try {
            return mService.getConfiguration();
        }
        .....
    }

    public void setConfiguration(IpConfiguration config) {
        try {
            mService.setConfiguration(config);
        } 
        .....
    }

    public boolean isAvailable() {
        try {
            return mService.isAvailable();
        }
        ......
    }

    public void addListener(Listener listener) {
        mListeners.add(listener);
        if (mListeners.size() == 1) {
            try {
                mService.addListener(mServiceListener);
            }
            ......
        }
    }

    public void removeListener(Listener listener) {
        mListeners.remove(listener);
        if (mListeners.isEmpty()) {
            try {
                mService.removeListener(mServiceListener);
            }
            ......
        }
    }

      通过以上看到,通过EthernetManager来调用framework接口,其实是通过IEthernetManager来执行的,IEthernetManager是aidl接口,而前面看到,IEthernetManager是通过Stub.asInterface()来获取的,肯定有对应Binder实现,接下来看一下该Binder的实现及Binder是如何暴露出来的: