ServiceManage分析

我们注册系统初始化的时候,会注册service到ServiceManager,那么我们从源码的角度分析addService和getService到底发生了什么?ServiceManager 本身的方法并不多,代码行数也简单。

/** @hide */
public final class ServiceManager {
    private static final String TAG = "ServiceManager";

    private static IServiceManager sServiceManager;
    //缓存的String到IBinder(远程服务)的Map队列。
    private static HashMap<String, IBinder> sCache = new HashMap<String, IBinder>();

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

        // Find the service manager
        //获取远端的ServiceManager。注意是跨进程的。现在拿到的只是本进程的代理对象而已。因为你是没法直接操作到远程的ServiceManager的,获取这个远程ServiceManager的代理比较简单,这个是最原始的。实际返回的是
// ServiceManagerProxy,关键是构造这个ServiceManagerProxy需要用到一个Ibinder对象。这里我们直接用了本地方法。  public static final native IBinder getContextObject();我简单分析下为啥这个方法能够直接拿到ServiceManager的Ibiner对象。此方法的本地实现在android_util_Binder.cpp中。

//*static jobject android_os_BinderInternal_getContextObject(JNIEnv* env, jobject clazz)
//{
    //实际调用的是getContextObject(null)。
    //sp<IBinder> ProcessState::getContextObject(const sp<IBinder>& /*caller*/)
    //getStrongProxyForHandle(0) 此方法对于Binder 为0会直接实例化一个方法,而不会寻址。
//{
//    return getStrongProxyForHandle(0);
//}
    
//    sp<IBinder> b = ProcessState::self()->getContextObject(NULL);
//    return javaObjectForIBinder(env, b);
//}*


//好了可以理解为BinderInternal.getContextObject()直接拿到0号Binder了。
        
        sServiceManager = ServiceManagerNative.asInterface(BinderInternal.getContextObject());
        return sServiceManager;
    }

     // 根据name去获取这个IBinder。(可以理解IBinder通过他的transact接口具备远程交互能力的java对象,实际的实现还是在native方法里面。)
    public static IBinder getService(String name) {
        try {
        //从缓存获取,看是否存在。
            IBinder service = sCache.get(name);
            if (service != null) {
                return service;
            } else {
            //从ServiceManagerProxy获取。我们分析下ServiceManagerProxy的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;
    //}

                return getIServiceManager().getService(name);
            }
        } catch (RemoteException e) {
            Log.e(TAG, "error in getService", e);
        }
        return null;
    }

    /**
     * Place a new @a service called @a name into the service
     * manager.
     * 
     * @param name the name of the new service
     * @param service the service object
     */
    public static void addService(String name, IBinder service) {
        try {
            getIServiceManager().addService(name, service, false);
        } catch (RemoteException e) {
            Log.e(TAG, "error in addService", e);
        }
    }

    /**
     * Place a new @a service called @a name into the service
     * manager.
     * 
     * @param name the name of the new service
     * @param service the service object
     * @param allowIsolated set to true to allow isolated sandboxed processes
     * to access this service
     */
    public static void addService(String name, IBinder service, boolean allowIsolated) {
        try {
            getIServiceManager().addService(name, service, allowIsolated);
        } catch (RemoteException e) {
            Log.e(TAG, "error in addService", e);
        }
    }
    
    /**
     * Retrieve an existing service called @a name from the
     * service manager.  Non-blocking.
     */
    public static IBinder checkService(String name) {
        try {
            IBinder service = sCache.get(name);
            if (service != null) {
                return service;
            } else {
                return getIServiceManager().checkService(name);
            }
        } catch (RemoteException e) {
            Log.e(TAG, "error in checkService", e);
            return null;
        }
    }

    /**
     * Return a list of all currently running services.
     */
    public static String[] listServices() throws RemoteException {
        try {
            return getIServiceManager().listServices();
        } catch (RemoteException e) {
            Log.e(TAG, "error in listServices", e);
            return null;
        }
    }

    /**
     * This is only intended to be called when the process is first being brought
     * up and bound by the activity manager. There is only one thread in the process
     * at that time, so no locking is done.
     * 
     * @param cache the cache of service references
     * @hide
     */
    public static void initServiceCache(Map<String, IBinder> cache) {
        if (sCache.size() != 0) {
            throw new IllegalStateException("setServiceCache may only be called once");
        }
        sCache.putAll(cache);
    }
}

在这里我分析了如果获取getService方法,总结一下,就是先拿到ServiceManger的客户端java代理,通过他就能够直接获取各种Service。

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值