一步步告诉你 Android 应用层是如何调用系统服务的

2 篇文章 0 订阅
1 篇文章 0 订阅

在 Android 系统中,framework 向应用层提供了很多系统服务,我们可以通过 ActivityManager 和 WindowManager 等类使用这些服务,方便地实现软件需求的开发。

一般而言,我们通过调用 Context 类的 getSystemService(String name) 方法获取对应的系统服务管理者,该方法的实现是在 ContextImpl 类中,对此不熟悉的朋友可以查看郭霖大神的博客: Android Context完全解析,你所不知道的Context的各种细节,通过查看 ContextImpl 的源码,发现对应的实现如下:

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

SystemServiceRegistry 的 getSystemService(ContextImpl ctx, String name) 方法如下,它从 以 String 为 Key, 以 ServiceFetcher 为 Value 的 HashMap :SYSTEM_SERVICE_FETCHERS 中获取对应名称的系统服务管理者提取器,然后从中得到对应的服务器管理者。


    ......

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

    ......

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

    ......

    static abstract interface ServiceFetcher<T> {
        T getService(ContextImpl ctx);
    }

而 SYSTEM_SERVICE_FETCHERS 的内容是如何填充的呢?通过跟踪源码可知,在 SystemServiceRegistry 的 registerService 方法中会将对应服务管理者的名称作为 Key, 存储对应服务管理者 Class 类的 CachedServiceFetcher 作为 Value 存储到 SYSTEM_SERVICE_FETCHERS 中。而该方法在静态块中被大量调用,因此 SYSTEM_SERVICE_FETCHERS 在 SystemServiceRegistry 初始化时就已经被填充完成了。
需要注意一下 CachedServiceFetcher 这个类,查看下面代码可知,这个类实现了 ServiceFetcher 的 getService(ContextImpl ctx) 方法,同时有一个抽象方法 createService(ContextImpl ctx) 需要被实现,在这个方法中需要完成对应服务管理者的创建。

    ......
    static {
        registerService(Context.ACCESSIBILITY_SERVICE, AccessibilityManager.class,
                new CachedServiceFetcher<AccessibilityManager>() {
            @Override
            public AccessibilityManager createService(ContextImpl ctx) {
                return AccessibilityManager.getInstance(ctx);
            }});

        registerService(Context.CAPTIONING_SERVICE, CaptioningManager.class,
                new CachedServiceFetcher<CaptioningManager>() {
            @Override
            public CaptioningManager createService(ContextImpl ctx) {
                return new CaptioningManager(ctx);
            }}); 

        ...... 

        registerService(Context.ACTIVITY_SERVICE, ActivityManager.class,
                new CachedServiceFetcher<ActivityManager>() {
            @Override
            public ActivityManager createService(ContextImpl ctx) {
                return new ActivityManager(ctx.getOuterContext(), ctx.mMainThread.getHandler());
            }});        

        ...... 

        registerService(Context.WINDOW_SERVICE, WindowManager.class,
                new CachedServiceFetcher<WindowManager>() {
            @Override
            public WindowManager createService(ContextImpl ctx) {
                return new WindowManagerImpl(ctx);
            }});
    } 

    ......

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

    ......

    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;
    }

ActivityManager 对应的 CachedServiceFetcher 的 createService(ContextImpl ctx) 方法很简单,仅仅是 new 了一个 ActivityManager 对象并将其返回。

return new ActivityManager(ctx.getOuterContext(), ctx.mMainThread.getHandler());

就这样,我们通过 ContextImpl 一步一步的获取到了 ActivityManager 对象。但是这仅仅是调用系统服务的第一步,目前我们的所有调用仍然是在应用层的进程中,而系统服务是运行在其他进程中的,因此想要调用系统服务,Binder 机制就不得不粉墨登场了。实质上 ActivityManager 在很多情况下都是充当了代理的作用,在我们调用 ActivityManager 的方法的时候,其内部通过 Binder 机制获取了系统服务进程的 BinderProxy 对象并进行跨进程通信。对 Binder 机制不了解的朋友可以查看鸿洋大神的博客:Android aidl Binder框架浅析

通过查看 ActivityManager 的源码,我们可以发现很多方法的实际逻辑都是通过 getService() 方法获取了 IActivityManager 对象,并调用其同名方法。返回值 IActivityManager 是一个通过 Aidl 机制生成的 java 接口,声明了应用层可跨进程调用的方法。Aidl 也是基于 Binder 机制的,它对 Binder 进行了封装,让我们更加方便地跨进程通信。

查看以下源码可知,ActivityManager 的 getService() 方法返回的 IActivityManager 是由 ServiceManager.getService(Context.ACTIVITY_SERVICE) 方法返回的 IBinder 对象构成的,IActivityManager 的实现类对 IBinder 对象进行了封装。这个 Binder 对象是通过底层 IBinder 驱动传递过来的,也就是我们上面说的 BinderProxy ,应用层可以通过调用它的 transact 方法调用对应系统服务的方法。不过调用 transact 方法会比较繁琐,因此这里是通过 Aidl 机制调用 IActivityManager.Stub.asInterface 方法将这个 IBinder 对象封装到实现了 IActivityManager 接口的 IActivityManager.Proxy 代理类,简化我们跨进程通信的步骤。
Aidl 与 Binder 的关系可以参考我另外一篇博客:通过一个简单的音乐播放器探讨 Android Aidl 的实现原理

    public static IActivityManager getService() {
        return IActivityManagerSingleton.get();
    }

    ......

    private static final Singleton<IActivityManager> IActivityManagerSingleton =
            new Singleton<IActivityManager>() {
                @Override
                protected IActivityManager create() {
                    final IBinder b = ServiceManager.getService(Context.ACTIVITY_SERVICE);
                    final IActivityManager am = IActivityManager.Stub.asInterface(b);
                    return am;
                }
            };

跨进程之后应用层实质上调用的 ActivityManagerService 类的方法,我们稍微查看一下源码就能发现 ActivityManagerService 是继承自 IActivityManager.Stub 的:

public class ActivityManagerService extends IActivityManager.Stub
        implements Watchdog.Monitor, BatteryStatsImpl.BatteryCallback {

就这样,ActivityManager 通过 aidl 机制跨进程与 ActivityManagerService 系统服务进行了通信。

既然从 getService 方法中可以得到对应的服务,那么就肯定有地方是通过 add 操作添加系统服务才对。查看 ServiceManager 类可知有一个 addService 方法,由于添加的是系统的基础服务,因此 addService 方法理所应当的在系统开机初始化的时候就进行调用,同时系统服务也应该在这个时候进行创建。我们查看 SystemServer 类,可以发现在这个类当中 ServiceManager 大量调用 addService 方法,将一个个初始化了的系统服务添加了进去。

以 ActivityManagerService 为例, 在 SystemServer 中它通过以下代码进行初始化:

        mActivityManagerService = mSystemServiceManager.startService(
                ActivityManagerService.Lifecycle.class).getService();

限于篇幅就不仔细分析初始化的代码实现了,里面的逻辑并不难,有兴趣的朋友可以自己去查看。

初始化之后,mActivityManagerService 在 SystemServer 中调用自身的 setSystemProcess 方法,将自己添加到 ServerManager 里。setSystemProcess 代码如下:


public class ActivityManagerService extends IActivityManager.Stub
        implements Watchdog.Monitor, BatteryStatsImpl.BatteryCallback {

    ......

    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));

            ApplicationInfo info = mContext.getPackageManager().getApplicationInfo(
                    "android", STOCK_PM_FLAGS | MATCH_SYSTEM_ONLY);
            mSystemThread.installSystemApplicationInfo(info, getClass().getClassLoader());

            synchronized (this) {
                ProcessRecord app = newProcessRecordLocked(info, info.processName, false, 0);
                app.persistent = true;
                app.pid = MY_PID;
                app.maxAdj = ProcessList.SYSTEM_ADJ;
                app.makeActive(mSystemThread.getApplicationThread(), mProcessStats);
                synchronized (mPidsSelfLocked) {
                    mPidsSelfLocked.put(app.pid, app);
                }
                updateLruProcessLocked(app, false, null);
                updateOomAdjLocked();
            }
        } catch (PackageManager.NameNotFoundException e) {
            throw new RuntimeException(
                    "Unable to find android system package", e);
        }
    }

就这样,我们把与 ActivityManagerService 系统服务通信的流程大致分析了一遍。但是我们上面的分析忽略了一个关键类 ServiceManager,在上文中我们知道,ActivityManager 能跨进程通信是因为 ServiceManager.getService(Context.ACTIVITY_SERVICE) 方法返回了一个 BinderProxy,因此可以通过 Binder 机制实现跨进程,那 ServiceManager.getService(Context.ACTIVITY_SERVICE) 方法内部逻辑是怎样的呢?

带着疑问,我们从 ServiceManager 的 getService 方法作为入口分析,部分源码如下:


    private static IServiceManager getIServiceManager() {
        if (sServiceManager != null) {
            return sServiceManager;
        }

        // Find the service manager
        sServiceManager = ServiceManagerNative
                .asInterface(Binder.allowBlocking(BinderInternal.getContextObject()));
        return sServiceManager;
    }

    ......

    public static IBinder getService(String name) {
        try {
            IBinder service = sCache.get(name);
            if (service != null) {
                return service;
            } else {
                return Binder.allowBlocking(getIServiceManager().getService(name));
            }
        } catch (RemoteException e) {
            Log.e(TAG, "error in getService", e);
        }
        return null;
    }

ServiceManager 的 getService 方法通过第 21 行代码 Binder.allowBlocking(getIServiceManager().getService(name)) 将 IBinder 返回 。Binder.allowBlocking 方法仅仅是设置一个标志位,然后将 getIServiceManager().getService(name) 返回,因此我们主要来分析 getIServiceManager().getService(name) 的逻辑。

我们先分析 getIServiceManager() 方法。该方法的返回值是一个 IServiceManager 接口,IServiceManager 定义了添加系统服务、获取系统服务、获取系统服务列表等方法。getIServiceManager() 方法通过调用 ServiceManagerNative 类的 asInterface 方法将 BinderInternal.getContextObject() 进行封装转换。

要分析这里面的流程,我们不可避免的来需要大致阅读一下 ServiceManagerNative 的源码,如下:

public abstract class ServiceManagerNative extends Binder implements IServiceManager
{
    /**
     * Cast a Binder object into a service manager interface, generating
     * a proxy if needed.
     */
    static public IServiceManager asInterface(IBinder obj)
    {
        if (obj == null) {
            return null;
        }
        IServiceManager in =
            (IServiceManager)obj.queryLocalInterface(descriptor);
        if (in != null) {
            return in;
        }

        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;
            }

            case IServiceManager.CHECK_SERVICE_TRANSACTION: {
                data.enforceInterface(IServiceManager.descriptor);
                String name = data.readString();
                IBinder service = checkService(name);
                reply.writeStrongBinder(service);
                return true;
            }

            case IServiceManager.ADD_SERVICE_TRANSACTION: {
                data.enforceInterface(IServiceManager.descriptor);
                String name = data.readString();
                IBinder service = data.readStrongBinder();
                boolean allowIsolated = data.readInt() != 0;
                addService(name, service, allowIsolated);
                return true;
            }

            case IServiceManager.LIST_SERVICES_TRANSACTION: {
                data.enforceInterface(IServiceManager.descriptor);
                String[] list = listServices();
                reply.writeStringArray(list);
                return true;
            }

            case IServiceManager.SET_PERMISSION_CONTROLLER_TRANSACTION: {
                data.enforceInterface(IServiceManager.descriptor);
                IPermissionController controller
                        = IPermissionController.Stub.asInterface(
                                data.readStrongBinder());
                setPermissionController(controller);
                return true;
            }
            }
        } catch (RemoteException e) {
        }

        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;
    }

    public IBinder checkService(String name) throws RemoteException {
        Parcel data = Parcel.obtain();
        Parcel reply = Parcel.obtain();
        data.writeInterfaceToken(IServiceManager.descriptor);
        data.writeString(name);
        mRemote.transact(CHECK_SERVICE_TRANSACTION, data, reply, 0);
        IBinder binder = reply.readStrongBinder();
        reply.recycle();
        data.recycle();
        return binder;
    }

    public void addService(String name, IBinder service, boolean allowIsolated)
            throws RemoteException {
        Parcel data = Parcel.obtain();
        Parcel reply = Parcel.obtain();
        data.writeInterfaceToken(IServiceManager.descriptor);
        data.writeString(name);
        data.writeStrongBinder(service);
        data.writeInt(allowIsolated ? 1 : 0);
        mRemote.transact(ADD_SERVICE_TRANSACTION, data, reply, 0);
        reply.recycle();
        data.recycle();
    }

    public String[] listServices() throws RemoteException {
        ArrayList<String> services = new ArrayList<String>();
        int n = 0;
        while (true) {
            Parcel data = Parcel.obtain();
            Parcel reply = Parcel.obtain();
            data.writeInterfaceToken(IServiceManager.descriptor);
            data.writeInt(n);
            n++;
            try {
                boolean res = mRemote.transact(LIST_SERVICES_TRANSACTION, data, reply, 0);
                if (!res) {
                    break;
                }
            } catch (RuntimeException e) {
                // The result code that is returned by the C++ code can
                // cause the call to throw an exception back instead of
                // returning a nice result...  so eat it here and go on.
                break;
            }
            services.add(reply.readString());
            reply.recycle();
            data.recycle();
        }
        String[] array = new String[services.size()];
        services.toArray(array);
        return array;
    }

    public void setPermissionController(IPermissionController controller)
            throws RemoteException {
        Parcel data = Parcel.obtain();
        Parcel reply = Parcel.obtain();
        data.writeInterfaceToken(IServiceManager.descriptor);
        data.writeStrongBinder(controller.asBinder());
        mRemote.transact(SET_PERMISSION_CONTROLLER_TRANSACTION, data, reply, 0);
        reply.recycle();
        data.recycle();
    }

    private IBinder mRemote;
}

我们先来关注 asInterface 方法,这个方法的最后一行 new 了一个 ServiceManagerProxy 对象,并将 BinderInternal.getContextObject() 作为参数传了进去。

ServiceManagerProxy 实现了 IServiceManager 接口,作为客户端代理类,方便客户端向服务端 ServiceManagerNative 发出进程通信信息。而实现的逻辑主要是通过调用内部 IBinder 变量 mRemote 的 transact 方法。通过 Parcel 将数据序列化,并将对应服务端方法的 Code 传入,从而与服务端一一对应。

ServiceManagerProxy 仅仅是一个代理类,实际的跨进程通信的得归功于 mRemote,即 BinderInternal.getContextObject() 返回的 IBinder 对象。我们查看 BinderInternal.getContextObject() 这个方法,可以发现这是一个 native 方法:

public static final native IBinder getContextObject();

这里其实是底层 Binder 机制返回的一个 BinderProxy 对象,该对象作为客户端,可通过调用 transact 方法与服务端进行进程间通信。

综上所述,ServiceManagerNative .asInterface(Binder.allowBlocking(BinderInternal.getContextObject())) 方法返回的其实是一个 ServiceManagerProxy。ServiceManagerProxy 通过调用 BinderProxy 对象的 transact 方法与服务端进行交互。

可能会有朋友觉得上面的流程似曾相识,这是因为 ActivityManager 的调用流程和 ServerManager 的调用都是通过 Binder 跨进程的,只不过 ActivityManager 是使用了 Aidl 机制简化操作,自动生成对应的 Java 类。我们之前分析 ActivityManager 调用流程的时候说过,应用层是通过 Aidl 机制,调用 IActivityManager.Stub.asInterface 方法将 ServerManager.getService 方法返回的 IBinder 对象封装到了 IActivityManager 接口的内部类 IActivityManager.Proxy,然后调用 Proxy 代理类的同名方法与实现了IActivityManager.Stub 的 ActivityManagerService 进程进行通信。这里的 IActivityManager 以及其内部的 IActivityManager.Stub 和 IActivityManager.Proxy 类就是通过 aidl 自动生成的。其中 Stub 作为服务端,实现了具体逻辑,而 Proxy 类作为客户端,调用服务端。

而 ServiceManagerNative.java 的代码结构其实跟 Aidl 生成的代码的结构几乎是一样的,或者应该说,Aidl 自动生成的 Java 类就是参照 ServiceManagerNative 这种结构的,再重新看看上面贴出来的代码,发现是不是确实如此?

getIServiceManager() 方法分析完了,我们来分析 getIServiceManager().getService(name) 的后半部分。getService() 方法最终会调用到如下代码:

    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;
    }

通过 mRemote.transact(GET_SERVICE_TRANSACTION, data, reply, 0); 向服务端发消息,最终 ServiceManagerNative 的 onTransact 方法会被调用,并执行以下代码:

            case IServiceManager.GET_SERVICE_TRANSACTION: {
                data.enforceInterface(IServiceManager.descriptor);
                String name = data.readString();
                IBinder service = getService(name);
                reply.writeStrongBinder(service);
                return true;
            }

其中调用了 getService 方法,该方法是 IServiceManager 接口声明的方法,而 ServiceManagerNative 是一个抽象类,该方法的实现留给了它的子类,子类的实现已经是在底层进行的了,既获取和添加系统服务的操作都是在底层通过 Binder 驱动实现的。

最后稍微总结一下流程:当我们想要与 ActivityManagerService 通信的时候,我们通过 Context 类的 getSystemService 方法获取到 ActivityManager,AcitvityManager 在 getService 方法中调用 ServerManager 的静态方法 getService,然后 ServerManager 的静态方法 getService 通过 BinderInternal.getContextObject() 方法从 Binder 驱动上获取 ServiceManagerNative 的 BinderProxy,并将其封装到客户端类 ServiceManagerProxy 上,然后调用 ServiceManagerProxy 的 getService 方法调用 ServiceManagerNative 的实现类的 getService 方法将 IActivityManager.Proxy 返回,这时候 AcitvityManager 就可以通过 IActivityManager.Proxy 调用 ActivityManagerService 中对应的方法了。

如有错漏,欢迎提出指教,谢谢。

  • 3
    点赞
  • 8
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值