返回介绍

5.2 Context.getSystemService() 源码分析

发布于 2024-12-23 21:29:02 字数 6013 浏览 0 评论 0 收藏 0

追踪 ContextImpl getSystemService() 源代码

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

继续追踪 SystemServiceRegistry 源代码

  /**
   * Gets a system service from a given context.
   */
  public static Object getSystemService(ContextImpl ctx, String name) {
    ServiceFetcher<?> fetcher = SYSTEM_SERVICE_FETCHERS.get(name);
    return fetcher != null ? fetcher.getService(ctx) : null;
  }

追踪 SYSTEM_SERVICE_FETCHERS 可以发现在 SystemServiceRegistry 静态区中注册了几乎所有的系统服务

  registerService(Context.LAYOUT_INFLATER_SERVICE, LayoutInflater.class,
      new CachedServiceFetcher<LayoutInflater>() {
    @Override
    public LayoutInflater createService(ContextImpl ctx) {
      return new PhoneLayoutInflater(ctx.getOuterContext());
    }});

  registerService(Context.LOCATION_SERVICE, LocationManager.class,
      new CachedServiceFetcher<LocationManager>() {
    @Override
    public LocationManager createService(ContextImpl ctx) {
      IBinder b = ServiceManager.getService(Context.LOCATION_SERVICE);
      return new LocationManager(ctx, ILocationManager.Stub.asInterface(b));
    }});

上面代码片断中, PhoneLayoutInflater 最终回到了 LayoutInflater 。而 LocationManager 则是对 ILocationManager 的封装。可以发现,在 frameworks/base/location/java/android/location 包下含有大量的 AIDL 文件。

继续追踪 ServiceManager.getService(Context.LOCATION_SERVICE)

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

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

  /**
   * Returns a reference to a service with the given name.
   * 
   * @param name the name of the service to get
   * @return a reference to the service, or <code>null</code> if the service doesn't exist
   */
  public static IBinder getService(String name) {
    try {
      IBinder service = sCache.get(name);
      if (service != null) {
        return service;
      } else {
        return getIServiceManager().getService(name);
      }
    } catch (RemoteException e) {
      Log.e(TAG, "error in getService", e);
    }
    return null;
  }

从上面代码片断可以看出, ServiceManager 会从 sCache 缓存或 IServiceManager 中查找服务并返回一个 IBinder 对象。这个 IBinder 就是一个远程对象,可以通过它与其他进程交互。

继续深入 getIServiceManager().getService(name) , 进入 ServiceManagerNative

  /**
   * 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);
  }
  
  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;
    }
    
    private IBinder mRemote;
  }

从上边代码片断可以看到, ServiceManager.getIServiceManager() 返回的是一个 ServiceManagerProxy , 而 ServiceManager.getService() 则是在 ServiceManagerProxy 中通过 ServiceManager 的远程 Binder 对象 mRemote ,操作 Parcel 数据,调用 IBinder.transact(int code, Parcel data, Parcel reply, int flags) 方法来发送请求,并通过 reply.readStrongBinder() 返回了要查找的服务的远程对象。

可以看到,系统服务的获取方式也是通过 AIDL 的方式实现的。

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。
列表为空,暂无数据
    我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
    原文