How are Android system services obtained

  • 2021-12-11 19:11:33
  • OfStack

Directory's conjecture about obtaining system services Obtain the source code implementation of system service A true system service provider

Conjecture on obtaining system services

Android Acquisition System Service 1 generally requires getSystemService Specification System Service Name Acquisition:


val wm = getSystemService(Context.WINDOW_SERVICE) as WindowManager

In real-world development, when we need to write an Manager that provides some 1 business process processing, it is usually implemented as a singleton. So what happened behind the above line of code, why doesn't Android use singleton mode? Let's look at how Android is designed to acquire system services and how it reaches the system side from the application side.

Think about 1. The reason why singletons are not used separately in each service is probably because Android provides many system services, and using getSystemService method is equivalent to providing the entrance of Unified 1. At the same time, because of the service name string in the method parameter, one Map can be provided to store various service instances in Uniform 1, which is close to the singleton mode 10, which is equivalent to the variant of Uniform 1 managing various singletons. So is this the case? (The source code below only retains the key code, API 30)

Obtain the source code implementation of system service

getSystemService methods of various components that inherit or hold Context call ContextImpl's method of the same name:


//ContextImpl.java
  public Object getSystemService(String name) {
    return SystemServiceRegistry.getSystemService(this, name);
  }

SystemServiceRegistry1 is the place where the unified 1 registration system serves:


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

We did find Map here, but not Map from String to system service, SYSTEM_SERVICE_FETCHERS of type Map < String, ServiceFetcher < ? > > .


//SystemServiceRegistry.java  
  static abstract interface ServiceFetcher<T> {
    T getService(ContextImpl ctx);
  }

The internal interface in SystemServiceRegistry, ServiceFetcher, looks like a factory interface for various system services. Let's look at its implementation class:


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

The getService method simplifies a lot of synchronization measures to ensure thread safety, and only retains the core logic. You can see another array of type Object [], ctx. mServiceCache, from which getService gets the system service with the subscript mCacheIndex, and if the service is empty, it is created using the createService method and placed in the array. It can be said that this ctx. mServiceCache array plays the role of storing all system services from String to Map of system services. This mapping becomes:


 Illusion mapping (from String To system services)  <=> SYSTEM_SERVICE_FETCHERS Mapping from String To ServiceFetcher ) 
                    + ctx.mServiceCache Array ( ServiceFetcher In mCacheIndex Subscript to system service) 

This SYSTEM_SERVICE_FETCHERS map is populated by System 1 in the static initialization fast of SystemServiceRegistry, and provides createService which is not implemented above:


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

When the SystemServiceRegistry class is initialized, the ctx. mServiceCache system service array is still empty. When a 1 system service is needed, getService in the above CachedServiceFetcher will call createService to create a service and store it in a specific mCacheIndex subscript.

In summary 1, in the process of obtaining system services by Android, the factory mode is used to create system services, Map is used to manage factories, and arrays are used to manage system service instances. There is at most one service in an array in each ContextImpl, and it is not created in advance before use, which is 1% due to the lazy style of singleton.

A true system service provider

We know that the system service in Android Framework runs in the system process and needs to communicate with the application process through Binder mechanism. If we don't consider the implementation on the system side, is the class obtained above really the Binder class on the application side? Not all of them, but still look at the factory methods in the factory class:

Some of the service classes obtained above are indeed system services on the system side corresponding to Binder classes on the application side, such as 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);
      }});
Some are direct encapsulations of these Binder classes, such as 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());
      }});

A large number of these methods delegate using getService and 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 and getTaskService are singleton methods, and ServiceManager is used to get the real Binder class.

There are also some system services that are encapsulated more complex for ease of use, such as WindowManager:

//ContextImpl.java
  public Object getSystemService(String name) {
    return SystemServiceRegistry.getSystemService(this, name);
  }
0

WindowManagerImpl of different Context will call WindowManagerGlobal as a whole, while WindowManagerGlobal will create ViewRootImpl when addView, and pass Binder class WindowSession to ViewRootImpl, and ViewRootImpl will complete the communication with WMS.

The above realizes the process from the application side to the system side when obtaining system services.

The above is the Android system service is how to obtain the details, more about the Android system service to obtain information please pay attention to other related articles on this site!


Related articles: