framework开发-系统服务的写法

456 阅读4分钟

[toc]

平台对外提供新接口的几种方式:

  • 1、标准写法:同 AMS WMS 一样,在 system_server 中添加一个新的服务
    • 缺点1,代码具有侵入性。同时代码出现问题会把SystemServer带崩,整个系统就崩了
    • 缺点2,只能随系统rom升级
  • 2、写一个AIDL接口的persistent系统App,内部写一个binder服务,加入到ServiceManager。
    • 优点,能跟随系统启动而启动,并且进程死亡后自动重启。
    • 缺点,不能使用app商店升级,只能随系统rom升级。
    • 缺点,连续崩溃次数太多会导致系统上层重启
  • 3、写一个HIDL接口的native进程的HWbinder服务
    • 优点,能提供vendor进程域特有的数据(有些数据系统app不方便拿)
    • 缺点,提供的是bin文件,同样不方便升级
  • 4、写一个普通的系统app,内部写一个普通的 app service
    • 优点,解耦程度最高,能够随时升级
    • 缺点,需要自身维持进程永驻
  • 5、其他:socket、contentprovider等等

以下内容讲述"标准写法"。

步骤简述

  • 1、定义 aidl 接口,比如 ITestManager.aidl

  • 2、创建服务类 比如 TestManagerService.java

    • 继承抽象父类 SystemService 和 aidl接口 ITestManager.aidl

    • 实现服务的相关功能

    • 实现父类的 onStart() 方法

      • onStart中调用 publishBinderService("TestService", mService);
      • publishBinderService 函数为父类 SystemService 的方法。
      • publishBinderService 方法内部会调用 ServiceManager.addService 添加 binder 服务
    • 如有必要实现其他周期函数(这些周期函数会随启动阶段,系统状态而被调用)

  • 3、SystemServer.java 中找个合适的位置,调用 SystemServiceManager.startService 方法:

    • mSystemServiceManager.startService(TestManagerService.class);

      • startService 方法内部会把反射后得到的服务实例添加到数组 mServices ,用于systemserver遍历所有服务,分发生命周期事件。
      • 并会调用TestManagerService服务的 onStart() 方法,最终调用 ServiceManager.addService 添加binder服务
  • 4、创建App进程端的binder服务代理类,比如:TestManager.java

    • TestManager.java 中获取binder服务代理,并实现各种代理接口
    • 然后在 SystemServiceRegistry.java 中,调用registerService方法,把TestManager的实例注册到 SystemServiceRegistry
  • 5、使用

    • App端的代码可以像使用其他系统服务一样使用:
    • TestManager testManager = context.getSystemService(SERVICE_NAME);

其他细节,需要处理隐藏类问题,系统接口问题等等。

按进程来看各部分代码

SystemServer 进程
  • SystemServer 相关函数中插入添加系统服务的代码------添加的系统服务处于 SystemServer 进程中

    • frameworks/base/services/java/com/android/server/SystemServer.java
  • SystemServiceManager SystemServer 中添加服务调用的方法是 SystemServiceManager.startService(TestManagerService.class)

    • SystemServiceManager 统一处理所有 service 的生命周期。SystemServer进程通过SystemServiceManager把系统状态事件分发到各个服务。SystemServiceManager遍历其数组对象mServices的所有的service,调用对应的周期函数。
    • frameworks/base/services/core/java/com/android/server/SystemServiceManager.java
  • SystemService 系统服务继承此类------抽象类---定义了生命周期函数

    • frameworks/base/services/core/java/com/android/server/SystemService.java
App进程
  • SystemServiceRegistry.java

    • framework.jar中的代码。创建binder服务代理实例,并注册到SystemServiceRegistry.java中。
    • 这里是在静态代码中创建的实例,每个app启动时,都会把系统服务的代理实例预先注册到 SystemServiceRegistry。
    • app进程通过 context.getSystemService 获取各种binder服务代理
    • frameworks\base\core\java\android\app\SystemServiceRegistry.java
ServiceManager 进程
  • SystemServer 进程中调用 ServiceManager.addService() 函数,把binder服务添加到 ServiceManager 进程

    • /frameworks/base/core/java/android/os/ServiceManager.java
    • frameworks/native/cmds/servicemanager/ServiceManager.cpp

SystemServer进程中添加系统服务过程

  • SystemServiceManager.startService(TestManagerService.class);
    • SystemServiceManager.mServices.add(service);
    • service.onStart(); // 调用TestManagerService.onStart();
      • SystemService.publishBinderService("TestService", mService);
        • ServiceManager.addService(name, service, allowIsolated, dumpPriority);
//frameworks/base/services/java/com/android/server/SystemServer.java

//SystemServer.java 调用SystemServiceManager启动各种系统服务
mSystemServiceManager.startService(OemInfoManagerService.class);

// 反射获得实例后调用  startService(SystemService service) 方法
///frameworks/base/services/core/java/com/android/server/SystemServiceManager.java
    public void startService(@NonNull final SystemService service) {
        // Register it.
        // 用于统一处理各种service的生命周期函数
        // 比如 SystemServiceManager.startBootPhase 方法中 遍历 mServices 中的服务,调用每个服务的 onBootPhase 方法
        mServices.add(service);  // mServices 是个数组 ArrayList<SystemService> 
        
        
        // Start it.
        long time = SystemClock.elapsedRealtime();
        try {
            service.onStart();//===调用对应服务的onStart方法==========!!!!
        } catch (RuntimeException ex) {
            throw new RuntimeException("Failed to start service " + service.getClass().getName()
                    + ": onStart threw an exception", ex);
        }
        warnIfTooLong(SystemClock.elapsedRealtime() - time, service, "onStart");
    }

//TestManagerService.java
    @Override
    public void onStart() {
        publishBinderService("TestService", mService);
    }
//com.android.server.SystemService
///frameworks/base/services/core/java/com/android/server/SystemService.java
    protected final void publishBinderService(String name, IBinder service,
            boolean allowIsolated, int dumpPriority) {
            //添加到 ServiceManager
        ServiceManager.addService(name, service, allowIsolated, dumpPriority);
    }

context.getSystemService(Context.XXXX) 功能的的实现

以WMS为例:

//frameworks\base\core\java\android\app\SystemServiceRegistry.java
// SystemServiceRegistry 注册管理器
// 在静态代码块中注册管理器,  所以每个App进程都会有一份
static {
	registerService(Context.WINDOW_SERVICE, WindowManager.class,new CachedServiceFetcher<WindowManager>() {
            @Override
            public WindowManager createService(ContextImpl ctx) {
                return new WindowManagerImpl(ctx);
                }
            }
        );
}


// Context 中获取服务管理器
final WindowManager wm = (WindowManager) context.getSystemService(Context.WINDOW_SERVICE);

// frameworks/base/core/java/android/app/ContextImpl.java
    @Override
    public Object getSystemService(String name) {
        if (vmIncorrectContextUseEnabled()) {
            // We may override this API from outer context.
            final boolean isUiContext = isUiContext() || isOuterUiContext();
            // Check incorrect Context usage.
            if (isUiComponent(name) && !isUiContext) {
                final String errorMessage = "Tried to access visual service "
                        + SystemServiceRegistry.getSystemServiceClassName(name)
                        + " from a non-visual Context:" + getOuterContext();
                final String message = "Visual services, such as WindowManager, WallpaperService "
                        + "or LayoutInflater should be accessed from Activity or other visual "
                        + "Context. Use an Activity or a Context created with "
                        + "Context#createWindowContext(int, Bundle), which are adjusted to "
                        + "the configuration and visual bounds of an area on screen.";
                final Exception exception = new IllegalAccessException(errorMessage);
                StrictMode.onIncorrectContextUsed(message, exception);
                Log.e(TAG, errorMessage + " " + message, exception);
            }
        }
        // 调用的 SystemServiceRegistry.getSystemService
        return SystemServiceRegistry.getSystemService(this, name);  
    }

// 最终调用
SystemServiceRegistry.getSystemService(this, name);