欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页  >  移动技术

Android系统服务是如何获取的

程序员文章站 2022-03-24 10:36:48
关于获取系统服务的猜想android获取系统服务一般都需要用getsystemservice指定系统服务名称获取:val wm = getsystemservice(context.window_se...

关于获取系统服务的猜想

android获取系统服务一般都需要用getsystemservice指定系统服务名称获取:

val wm = getsystemservice(context.window_service) as windowmanager

在实际开发中,当我们需要编写提供某一业务流程处理的manager,通常会实现为单例。那么上面那行代码背后发生了什么,为什么android不使用单例模式呢?下面我们观察android是如何设计获取系统服务的,它如何从应用侧到达系统侧。

可以思考一下,不在每个服务中单独使用单例的原因大概是因为android提供的系统服务众多,都使用getsystemservice方法相当于提供了统一的入口。同时因为方法参数中的服务名称字符串,可以提供一个map来统一存放各种服务实例,这与单例模式十分接近,相当于统一管理各种单例的变种。那么事实是不是这样呢?(下方源码只保留关键代码,api 30)

获取系统服务源码实现

各种继承或者持有context的组件的getsystemservice方法都会调用contextimpl的同名方法:

//contextimpl.java
  public object getsystemservice(string name) {
    return systemserviceregistry.getsystemservice(this, name);
  }

systemserviceregistry一看就是统一注册系统服务的地方:

//systemserviceregistry.java  
  public static object getsystemservice(contextimpl ctx, string name) {
    final servicefetcher<?> fetcher = system_service_fetchers.get(name);
    final object ret = fetcher.getservice(ctx);
    return ret;
  }

这里我们确实发现了map,可却不是从string到系统服务的map,system_service_fetchers的类型为map<string, servicefetcher<?>>。

//systemserviceregistry.java  
  static abstract interface servicefetcher<t> {
    t getservice(contextimpl ctx);
  }

这个systemserviceregistry中的内部接口servicefetcher,看上去像是各种系统服务的工厂接口。我们看它的实现类:

//systemserviceregistry.java  
  static abstract class cachedservicefetcher<t> implements servicefetcher<t> {
    private final int mcacheindex;

    cachedservicefetcher() {
      mcacheindex = sservicecachesize++;
    }

    @override
    public final t getservice(contextimpl ctx) {
      final object[] cache = ctx.mservicecache;
      t ret = null;

      t service = (t) cache[mcacheindex];
      if (service != null) {
        ret = service;
      } else {
        service = createservice(ctx);
        cache[mcacheindex] = service;
        ret = service;
      }
      return ret;
    }

    public abstract t createservice(contextimpl ctx) throws servicenotfoundexception;
  }

getservice方法精简了大量保证线程安全的同步措施,只保留了最核心的逻辑。可以看到另有一个类型为object[]的数组ctx.mservicecache,getservice从中用下标mcacheindex获取系统服务,如果服务为空则使用createservice方法创建服务并放在数组中。可以说,这个ctx.mservicecache数组起到了我们最初设想的从string到系统服务的map的存放所有系统服务的作用。这个映射变为了:

假象的映射(从string到系统服务) <=> system_service_fetchers映射(从string到servicefetcher)
                    + ctx.mservicecache数组(servicefetcher中的mcacheindex下标到系统服务)

这个system_service_fetchers映射在systemserviceregistry的静态初始化快中被统一填充,同时提供了上方没有实现的createservice:

//systemserviceregistry.java
  static {
    registerservice(context.window_service, windowmanager.class,
        new cachedservicefetcher<windowmanager>() {
      @override
      public windowmanager createservice(contextimpl ctx) {
        return new windowmanagerimpl(ctx);
      }}); 
  }
  private static <t> void registerservice(@nonnull string servicename,
      @nonnull class<t> serviceclass, @nonnull servicefetcher<t> servicefetcher) {
    system_service_fetchers.put(servicename, servicefetcher);
  }

systemserviceregistry类初始化时,ctx.mservicecache系统服务数组还是空的,当某一系统服务需要时,上方cachedservicefetcher中getservice会调用createservice创建服务并存放在特定mcacheindex下标中。

总结一下就是:在android获取系统服务的流程中,使用工厂模式创建系统服务,使用map管理工厂,使用数组管理系统服务实例。每种服务在每个contextimpl中的数组中最多只有一个,且使用前不会提前创建,这点和单例的懒汉式是一致的。

真正的系统服务提供者

我们知道android framework中系统服务是运行在系统进程中,需要通过binder机制与应用进程通信,如果我们不考虑系统侧实现,上面拿到的类真的应用侧的binder类么?其实并不全是,依旧查看工厂类中的工厂方法:

  • 上面获取到的服务类,有些类的确是系统侧的系统服务对应到应用侧的binder类,比如alarmmanager:
//systemserviceregistry.java    
	registerservice(context.alarm_service, alarmmanager.class,
        new cachedservicefetcher<alarmmanager>() {
      @override
      public alarmmanager createservice(contextimpl ctx) throws servicenotfoundexception {
        ibinder b = servicemanager.getserviceorthrow(context.alarm_service);
        ialarmmanager service = ialarmmanager.stub.asinterface(b);
        return new alarmmanager(service, ctx);
      }});
  • 有些则是对这些binder类的直接封装,比如activitymanager:
//systemserviceregistry.java    
    registerservice(context.activity_service, activitymanager.class,
        new cachedservicefetcher<activitymanager>() {
      @override
      public activitymanager createservice(contextimpl ctx) {
        return new activitymanager(ctx.getoutercontext(), ctx.mmainthread.gethandler());
      }});

其中大量的方法使用getservice与gettaskservice进行委托:

//activitymanager.java
  public void killuid(int uid, string reason) {
    try {
      getservice().killuid(userhandle.getappid(uid),
          userhandle.getuserid(uid), reason);
    } catch (remoteexception e) {
      throw e.rethrowfromsystemserver();
    }
  }
  
  public list<runningtaskinfo> getrunningtasks(int maxnum)
      throws securityexception {
    try {
      return gettaskservice().gettasks(maxnum);
    } catch (remoteexception e) {
      throw e.rethrowfromsystemserver();
    }
  }
  
  public static iactivitymanager getservice() {
    return iactivitymanagersingleton.get();
  }

  private static iactivitytaskmanager gettaskservice() {
    return activitytaskmanager.getservice();
  }

而getservice与gettaskservice都是单例方法,另外使用servicemanager获取真正的binder类。

  • 另外还有些系统服务为了便于使用,封装得更加复杂,比如windowmanager:
    registerservice(context.window_service, windowmanager.class,
        new cachedservicefetcher<windowmanager>() {
      @override
      public windowmanager createservice(contextimpl ctx) {
        return new windowmanagerimpl(ctx);
      }});

这里的各不同context的windowmanagerimpl会统一调用到windowmanagerglobal,而windowmanagerglobal在addview时会创建viewrootimpl,并将binder类windowsession传递给viewrootimpl,由viewrootimpl完成与wms通信的工作。

以上实现了获取系统服务时从应用侧到达系统侧的过程。

以上就是android系统服务是如何获取的的详细内容,更多关于android系统服务获取的资料请关注其它相关文章!