Service_Manager获取系统服务源码分析

引子

在分析activity的启动过程时,一定会看到如下代码:

../framewoks/base/core/java/android/app/Instrumentation.java

    public ActivityResult execStartActivity(
            Context who, IBinder contextThread, IBinder token, Activity target,
            Intent intent, int requestCode, Bundle options) {
        IApplicationThread whoThread = (IApplicationThread) contextThread;
        Uri referrer = target != null ? target.onProvideReferrer() : null;

        ...

        try {
            intent.migrateExtraStreamToClipData();
            intent.prepareToLeaveProcess(who);
                // 这里分析的重点
            int result = ActivityTaskManager.getService()
                .startActivity(whoThread, who.getBasePackageName(), intent,
                        intent.resolveTypeIfNeeded(who.getContentResolver()),
                        token, target != null ? target.mEmbeddedID : null,
                        requestCode, 0, null, options);
            checkStartActivityResult(result, intent);
        } catch (RemoteException e) {
            throw new RuntimeException("Failure from system", e);
        }
        return null;
    }

直接来到ActivityTaskManager.getService(),这是我们今天要分析的主角。

../framewoks/base/core/java/android/app/ActivityTaskManager.java:

    public static IActivityTaskManager getService() {
        return IActivityTaskManagerSingleton.get();
    }

    private static final Singleton<IActivityTaskManager> IActivityTaskManagerSingleton =
            new Singleton<IActivityTaskManager>() {
                @Override
                protected IActivityTaskManager create() {

            

                //  获取ATMS      
              final IBinder b = ServiceManager.getService(Context.ACTIVITY_TASK_SERVICE);
                    return IActivityTaskManager.Stub.asInterface(b);
                }
            };

从上面的代码可以看出,ATMS是确实是通过ServiceManager获取的。不过这里的ATMS是一个实现了IBinder接口的对象,然后通过asInterface转化成了一个Proxy对象(后面用于跨进程调用)。

IBinder b??

这里的b对象到底是什么东西呢?(不得不说面向对象的多态特性有时会让我们在阅读代码时不能直接看到对象的本质)

那就继续跟进ServiceManager.getService吧:

../framewoks/base/core/java/android/os/ServiceManager.java

    public static IBinder getService(String name) {
        try {
            IBinder service = sCache.get(name);
            if (service != null) {
                return service;
            } else {

                // 这里
                return Binder.allowBlocking(rawGetService(name));
            }
        } catch (RemoteException e) {
            Log.e(TAG, "error in getService", e);
        }
        return null;
    }

    private static IBinder rawGetService(String name) throws RemoteException {
        final long start = sStatLogger.getTime();

        final IBinder binder = getIServiceManager().getService(name);

        ...
        return binder;
    }

getIServiceManager().getService(name)分成两步:

1.getIServiceManager()

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

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

        再分两步:

        1.1 ServiceManagerNative.asInterface

        ServiceManagerNative.java:

         static public IServiceManager asInterface(IBinder obj)
            {
               ...

                return new ServiceManagerProxy(obj);
            }

        class ServiceManagerProxy implements IServiceManager {
            public ServiceManagerProxy(IBinder remote) {
                mRemote = remote;
            }

            public IBinder asBinder() {
                return mRemote;
            }            
            ...
        }

    这里跟aidl文件生成的Stub类的方式如出一辙,同样通过asInterface方法构造了一个ServiceManagerProxy代理对象,而内部的mRemote对象是通过下面1.2方法得到的。还可以发现一点:这个mRemote对象和我们最终要分析的"b"对象类型应该是一致的,只不过一个对应的是servicemanager,一个对应的是atms。

继续往下分析:

        1.2 BinderInternal.getContextObject()

        public static final native IBinder getContextObject();

        这是个native方法,源码见:

../framewoks/base/core/jni/android_util_Binder.cpp

这里是jni方法的注册,传入函数指针指向下面的方法

里面有个javaObjectForIBinder方法:

 ​​​​​这个方法的作用就是将C层binder的对象转化成java对象, 这个c层的binder对象其实是一个Bpbinder,那么它将被转化成java层的什么类型的对象呢?

继续往下看:

答案一目了然,没错也是 BinderProxy对象,直接调用了getInstance方法构造。

 到这里其实分析还没有结束,我们知道这里获取到的binder对象是servicemanger的,那怎么看出是servicemanager的呢?

 还记得javaObjectForIBinder上面还有个方法吧:

 ../framewoks/native/libs/binder/ProcessState.cpp

 getStrongProxyForHandle的参数直接传了0,说明service_manger作为Android系统服务的”大总管“,它的标识是固定的,并且是0,也正因如此它对任何进程都是”可见的“。

2.getService(name)

最后我们来看看这个atms的binder对象是否也是BinderProxy对象。

直接对应上面的源码:

        class ServiceManagerProxy implements IServiceManager {

             ...

            @UnsupportedAppUsage
            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;
            }         
            ...
        }

 

reply.readStrongBinder()

最终也会调用一个native方法,源码如下:

../base/core/jni/android_os_Parcel.cpp

 

可以看到,最后还是调用了javaObjectForIBiner方法,得到了一个atms的BinderProxy对象。

ps:至于为什么是atms的,可以深入了解一下binder机制,本文不再赘述。

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值