首页 > 其他分享 >Android系统服务的注册方式-1

Android系统服务的注册方式-1

时间:2023-08-15 14:16:09浏览次数:40  
标签:服务 service final ServiceManager 注册 addService Android public

一、概述

启动过程有采用过两种不同的方式来注册系统服务:

(1) ServiceManager 的 addService()
(2) SystemServiceManager 的 startService()

其核心都是向 ServiceManager 进程注册 binder 服务,但功能略有不同,下面从源码角度详加说明。


二、SM.addService 方式

这里以 InputManagerService 服务为例, 说明这类服务的启动方式:

inputManager = new InputManagerService(context, null); //先创建服务对象
ServiceManager.addService(Context.INPUT_SERVICE, inputManager); //[见小节2.1]

 

2.1 SM.addService

[-> ServiceManager.java]

public static void addService(String name, IBinder service) {
    try {
        //[见小节2.2 和 2.3]
        getIServiceManager().addService(name, service, false);
    } catch (RemoteException e) {
        Log.e(TAG, "error in addService", e);
    }
}

 

2.2 SM.getIServiceManager

[-> ServiceManager.java]

private static IServiceManager getIServiceManager() {
    if (sServiceManager != null) {
        return sServiceManager;
    }
    //【见2.2.1】
    sServiceManager = ServiceManagerNative.asInterface(BinderInternal.getContextObject());
    return sServiceManager;
}

采用了单例模式获取 ServiceManager getIServiceManager() 返回的是 ServiceManagerProxy(简称SMP)对象.

其中 BinderInternal.getContextObject(), 等价于 new BpBinder(0), handle=0 意味着指向的是远程进程 /system/bin/servicemanager中的 ServiceManager 服务.

2.2.1 asInterface

[-> ServiceManagerNative.java]

public abstract class ServiceManagerNative extends Binder implements IServiceManager {

    static public IServiceManager asInterface(IBinder obj) {
        if (obj == null) {
            return null;
        }
        IServiceManager in =
            (IServiceManager)obj.queryLocalInterface(descriptor);
        if (in != null) {
            return in;
        }
        //创建ServiceManagerProxy对象[见小节2.2.2]
        return new ServiceManagerProxy(obj);
    }
}


2.2.2 ServiceManagerProxy 创建

[-> ServiceManagerNative.java ::ServiceManagerProxy]

class ServiceManagerProxy implements IServiceManager {
    private IBinder mRemote;
    
    public ServiceManagerProxy(IBinder remote) {
        mRemote = remote;
    }
    ...
}

可见, getIServiceManager() 过程是获取一个用于跟远程 ServiceManager 服务(这个用于管理所有binder服务的大管家)进行通信的binder代理端.


2.3 SMP.addService

[-> ServiceManagerNative.java ::ServiceManagerProxy]

public void addService(String name, IBinder service, boolean allowIsolated) throws RemoteException {
    Parcel data = Parcel.obtain();
    Parcel reply = Parcel.obtain();
    data.writeInterfaceToken(IServiceManager.descriptor);
    data.writeString(name);
    data.writeStrongBinder(service);
    data.writeInt(allowIsolated ? 1 : 0);
    mRemote.transact(ADD_SERVICE_TRANSACTION, data, reply, 0);
    reply.recycle();
    data.recycle();
}

通过 mRemote 向将 ADD_SERVICE_TRANSACTION 的事件发送给 ServiceManager. 接下来的内容见《Binder系列5—注册服务(addService)》.


三. SSM.startService 方式

通过这种方式启动的服务,有一个特点都必须是继承于 SystemService 对象,  这里以 PowerManagerService 为例来说明:

//[见小节3.1]
mSystemServiceManager = new SystemServiceManager(mSystemContext); 
//[见小节3.2]
mPowerManagerService = mSystemServiceManager.startService(PowerManagerService.class);

 

3.1 SSM初始化

[-> SystemServiceManager.java]

public class SystemServiceManager {
    private final Context mContext;
    
    //接收lifecycle事件的服务
    private final ArrayList<SystemService> mServices = new ArrayList<SystemService>();
    
    public SystemServiceManager(Context context) {
        mContext = context;
    }
    
}

mSystemServiceManager 只会创建一次,后续其他服务通过该方式启动,直接调用其 startService() 方法即可。


3.2 SSM.startService

[-> SystemServiceManager.java]

public <T extends SystemService> T startService(Class<T> serviceClass) {
    final String name = serviceClass.getName();

    //保证要启动的服务是继承于SystemService,否则抛出异常
    if (!SystemService.class.isAssignableFrom(serviceClass)) {
        throw new RuntimeException(...);
    }
    
    final T service;
    try {
        Constructor<T> constructor = serviceClass.getConstructor(Context.class);
        //通过反射创建目标服务类的对象
        service = constructor.newInstance(mContext);
    } catch (Exception ex) {
        ...
    }
    //将该服务添加到mServices
    mServices.add(service);

    try {
        //执行服务的onStart过程
        service.onStart();
    } catch (RuntimeException ex) {
        ...
    }
    return service;
}

mSystemServiceManager.startService(xxx.class) 功能主要:

(1) 创建xxx类的对象,执行该对象的构造函数;
(2) 将该对象添加到 mSystemServiceManager 的成员变量 mServices;
(3) 调用该对象的 onStart(); 只有通过SSM这种方式注册的才才会执行这个回调。

看到这并没有看到服务是如何注册到 ServiceManager, 这里继续以 PowerManagerService 为例,其实是在 onStart() 完成.

3.2.1 onStart

[-> PowerManagerService.java]

public void onStart() {
    //[见小节3.2.2]
    publishBinderService(Context.POWER_SERVICE, new BinderService());
    publishLocalService(PowerManagerInternal.class, new LocalService());

    Watchdog.getInstance().addMonitor(this);
    Watchdog.getInstance().addThread(mHandler);
}

PowerManagerService 定义了一个内部类 BinderService, 继承于 IPowerManager.Stub 服务. 再调用 publishBinderService 来注册服务.

3.2.2 publishBinderService

[-> SystemService.java]

public abstract class SystemService {
    protected final void publishBinderService(String name, IBinder service) {
        publishBinderService(name, service, false);
    }

    protected final void publishBinderService(String name, IBinder service, boolean allowIsolated) {
        ServiceManager.addService(name, service, allowIsolated);
    }
}

到此可见, 采用该方式真正注册服务的过程,同样也是采用 ServiceManager.addService 方式.

通过这种方式启动的服务, 都是继承于 SystemService 类, 那么这种方式启动的服务有什么特殊之处吗? 答应就是 startBootPhase 的过程:


3.3 SSM.startBootPhase

[–>SystemServiceManager.java]

public void startBootPhase(final int phase) {
    mCurrentPhase = phase;
    final int serviceLen = mServices.size();
    for (int i = 0; i < serviceLen; i++) {
        final SystemService service = mServices.get(i);
        try {
            service.onBootPhase(mCurrentPhase);
        } catch (Exception ex) {
            ...
    }
}

所有通过该方式注册的继承于 SystemService 的服务,都会被添加到 mServices. 该方法会根据当前系统启动到不同的阶段, 则回调所有服务 onBootPhase() 方法

3.3.1 BootPhase

系统开机启动过程, 当执行到 system_server 进程时, 将启动过程划分了几个阶段, 定义在 SystemService.java 文件

public static final int PHASE_WAIT_FOR_DEFAULT_DISPLAY = 100; 
public static final int PHASE_LOCK_SETTINGS_READY = 480;
public static final int PHASE_SYSTEM_SERVICES_READY = 500;
public static final int PHASE_ACTIVITY_MANAGER_READY = 550;
public static final int PHASE_THIRD_PARTY_APPS_CAN_START = 600;
public static final int PHASE_BOOT_COMPLETED = 1000;

这些阶段跟系统服务大致的顺序图,如下:

PHASE_BOOT_COMPLETED=1000,该阶段是发生在 Boot完成 和 home应用启动完毕,对于系统服务更倾向于监听该阶段,而非监听广播 ACTION_BOOT_COMPLETED


四、总结

4.1 两种方式的区别

方式1. ServiceManager.addService():

功能:向 ServiceManager 注册该服务.
特点:服务往往直接或间接继承于 Binder 服务;
举例:input, window, package;

方式2. SystemServiceManager.startService:

功能:
(1) 创建服务对象;
(2) 执行该服务的 onStart() 方法;该方法会执行上面的 SM.addService();
(3) 根据启动到不同的阶段会回调 onBootPhase() 方法;
(4) 另外,还有多用户模式下用户状态的改变也会有回调方法;例如 onStartUser();
特点:服务自身或内部类继承于 SystemService;
举例:power, activity;

两种方式真正注册服务的过程都会调用到 ServiceManager.addService() 方法. 对于方式2多了一个服务对象创建以及 根据不同启动阶段采用不同的动作的过程。可以理解为方式2比方式1的功能更丰富。

 

 

参考:
Android系统服务的注册方式:http://gityuan.com/2016/10/01/system_service_common/
Binder系列4—获取ServiceManager: http://gityuan.com/2015/11/08/binder-get-sm/
Binder系列5—注册服务(addService):http://gityuan.com/2015/11/14/binder-add-service/#addservice

 

标签:服务,service,final,ServiceManager,注册,addService,Android,public
From: https://www.cnblogs.com/hellokitty2/p/17631124.html

相关文章

  • ttyd工具,实现web 界面登陆服务器
    1、安装方案一-:yum-yinstallopenssl-develwgetcd/rootwgethttps://github.com/tsl0922/ttyd/releases/download/1.6.3/ttyd.x86_64--no-check-certificatemvttyd.x86_64ttydchmod+xttydmvttyd/usr/sbin/安装方案二:官网地址或者直接yum安装https://github......
  • Android 怎么就不卡了呢之Choreographer
    前言针对AndroidUI不流畅的问题,Google提出了ProjectButter对Android的显示系统进行了重构。这次重构的三个关键点VSynch垂直同步TripleBuffer三重缓存Choreographer编舞者这篇文章我们主要聊一聊Choregrapher,后续的我们写关于其他。choreographer界面的显示大体会经过CPU的......
  • 项目发布部署:如何发布.NETCore项目到IIS服务器?
    前言:本文将详细介绍如何发布.NETCore项目到IIS服务器。首先,第一步需要安装IIS,介绍了在本地电脑和服务器中进行安装。然后需要安装SDK和运行时才能发布.NETCore项目。其次介绍了如何发布.NETCore项目和Vue项目,并配置IIS。最后介绍了如何将项目部署到Service服务中。一、安装IIS教程......
  • 短信和注册前端
    1. 注册页面   941.1 添加路由   94index.js{path:'/page/user/register',name:'RegisterView',component:()=>import('../views/ProductDetail.vue')}1.2 添加按钮  94Header.vue<divclass="public-head-right"&g......
  • linux环境下监控docker进程运行情况,使用钉钉群机器人报警异常服务
    背景:在linux环境下,很多服务我们都使用docker来跑,很是方便,容器服务独立,配置独立,数据独立等等,但是有个问题,就是如果某个服务异常了,暂停了,停止了,一直重启中,我们要怎么及时的知道是哪个服务,并进行处理,保证业务正常运行。本文主要介绍使用docker服务自带的一些命令来实现一个基本的监......
  • iTOP-RK3588开发板单独编译Android固件-打包update.img
    在ubootkernelandroid都编译完成的情况下,才可以打包update.img,所以一般在完整编译的时候用。输入以下命令:./build.sh-u打包完成会在rockdev/Image-rk3588_s目录下生成update.img镜像。更多内容:B站搜索迅为RK3588开发板......
  • 浅谈统一权限管理服务的设计与开发
    作者| 天地练心导读本文详细探讨了统一权限管理服务(MPS)的设计与开发,针对企业内部多平台权限管理混乱的问题,提出了一套综合RBAC、ACL、DAC权限模型的解决方案。文章从需求分析、技术选型、功能设计等方面全面介绍了MPS的构建过程。在平台&节点管理方面,MPS支持多种业务平台接入方式......
  • 分布式、微服务、集群、SOA之间的关系及区别
    概念介绍分布式、微服务、集群和SOA(面向服务的架构)是现代软件架构中的一些重要概念,它们之间有一些联系和关系,但又有一些区别。下面是它们之间的关系解释:分布式官方解释分布式是一种计算资源或任务在多个节点之间分散的方式。它旨在提高系统的性能、可靠性和可扩展性。类比来说,可以......
  • 基于微信小程序的居民疫情服务系统-计算机毕业设计源码+LW文档
    摘 要新冠病毒传播迅速,已经严重影响了人类生命安全,防控手段成为大众关注的重点。另外,随着目前信息化手段的进步,使用技术手段可以有效的对新冠疫情进行防控管理。在社区,人员多,出入流动性大,如果单靠人工进行管理,很难进行有效的统计。为此提出开发基于微信小程序的居民疫情服务系统......
  • Docker-compose容器服务异常重启脚本
    前言:有些企业可能并没有足够的能力或者没必要搭建(云上租用)一个K8S集群,会考虑使用Docker。公司今年有个项目,一部分服务就是使用原来的,改改配置就能用,然后再配合实际的场景再新上1、2个服务。在云上再租用一个K8S集群或者自己搭建一个K8S集群就显得尤为浪费。但是有几个都是之前的服......