Android 13 AOSP 自定义 Service 创建与开机调用实现指南

一、需求分析

1.1 功能需求

基于提供的 patch 文件,本次需求是在 Android 13 的 AOSP 源代码中创建一个自定义的 MyService,并实现以下功能:

需求点 描述 实现位置
创建自定义 Service 实现 IMyService AIDL 接口 MyService.java
开机启动注册 SystemServer 中注册服务 SystemServer.java
开机动画开始调用 开机动画开始时调用 doSomething() WindowManagerService.java
开机动画结束调用 开机动画结束时调用 doSomething() WindowManagerService.java
SELinux 权限配置 配置服务注册所需的 SELinux 权限 service.te / system_server.te / service_contexts

1.2 技术架构

┌─────────────────────────────────────────────────────────────────┐
│                        SystemServer                             │
│  ┌──────────────────────────────────────────────────────────┐   │
│  │  startOtherServices()                                    │   │
│  │      └── ServiceManager.addService("myservice", myService) │   │
│  └──────────────────────────────────────────────────────────┘   │
└─────────────────────────────┬───────────────────────────────────┘
                              │ Binder IPC
                              ▼
┌─────────────────────────────────────────────────────────────────┐
│                     WindowManagerService                        │
│  ┌──────────────────────────────────────────────────────────┐   │
│  │  performEnableScreen()                                   │   │
│  │      ├── 开机动画开始 → getMyService().doSomething()     │   │
│  │      └── 开机动画结束 → getMyService().doSomething()     │   │
│  └──────────────────────────────────────────────────────────┘   │
└─────────────────────────────┬───────────────────────────────────┘
                              │ Binder IPC
                              ▼
┌─────────────────────────────────────────────────────────────────┐
│                         MyService                              │
│  ┌──────────────────────────────────────────────────────────┐   │
│  │  implements IMyService.Stub                              │   │
│  │      └── doSomething() → Log.v(TAG, "duxiwei22")        │   │
│  └──────────────────────────────────────────────────────────┘   │
└─────────────────────────────────────────────────────────────────┘

二、实现方案

2.1 整体流程

开机启动
    │
    ▼
SystemServer.startOtherServices()
    │
    ├── 创建 MyService 实例
    │
    └── ServiceManager.addService("myservice", myService)
            │
            ▼
WindowManagerService.performEnableScreen()
    │
    ├── 设置 service.bootanim.exit=1
    │       │
    │       ▼
    │   开机动画开始
    │       │
    │       └── getMyService().doSomething()
    │
    └── 开机动画完成
            │
            └── getMyService().doSomething()

三、代码修改详解

3.1 Framework 修改 (fwk.txt)

3.1.1 Android.bp 构建配置

文件: frameworks/base/services/core/Android.bp

修改目的: 将自定义的 AIDL 文件添加到编译系统中。

filegroup {
    name: "services.core-sources-ms-aidls",
    srcs: [
        "java/com/android/server/ms/*.aidl",
    ],
    path: "java",
    visibility: ["//frameworks/base/services"],
}

java_library_static {
    name: "services.core.unboosted",
    srcs: [
        ":services.core-sources-ms-aidls",  // 添加 AIDL 文件组
        // ... 其他源文件
    ],
}

说明:

  • filegroup 定义了 AIDL 文件集合
  • path: "java" 指定相对路径
  • services.core.unboosted 模块中引用该文件组

3.1.2 MyService 实现类

文件: frameworks/base/services/core/java/com/android/server/ms/MyService.java

修改目的: 实现自定义服务的业务逻辑。

package com.android.server.ms;

import android.util.Log;

public class MyService extends IMyService.Stub {
    String TAG = "MyService";
    private int mValue;

    @Override
    public void doSomething() {
        // 实现自定义功能
        Log.v(TAG, "duxiwei22");
    }
}

说明:

  • 继承 IMyService.Stub 实现 AIDL 接口
  • doSomething() 方法是对外暴露的服务方法
  • 实现简单的日志输出功能

3.1.3 WindowManagerService 集成

文件: frameworks/base/services/core/java/com/android/server/wm/WindowManagerService.java

修改目的: 在开机动画开始和结束时调用 MyService.doSomething()

关键代码:

// 1. 添加导入
import com.android.server.ms.IMyService;

// 2. 添加成员变量
boolean mBootAnimationStartNotified = false;

// 3. 添加服务获取方法
private IMyService getMyService() {
    IBinder binder = ServiceManager.getService("myservice");
    if (binder != null) {
        return IMyService.Stub.asInterface(binder);
    }
    return null;
}

// 4. 开机动画开始时调用
if (!mBootAnimationStartNotified) {
    IMyService myService = getMyService();
    if (myService != null) {
        try {
            myService.doSomething();
        } catch (RemoteException e) {
            Slog.e(TAG_WM, "Failed to call doSomething on boot animation start", e);
        }
    }
    mBootAnimationStartNotified = true;
}

// 5. 开机动画结束时调用
EventLogTags.writeWmBootAnimationDone(SystemClock.uptimeMillis());
IMyService myService = getMyService();
if (myService != null) {
    try {
        myService.doSomething();
    } catch (RemoteException e) {
        Slog.e(TAG_WM, "Failed to call doSomething on boot animation end", e);
    }
}

说明:

  • getMyService() 通过 ServiceManager 获取服务引用
  • 开机动画开始时机:设置 service.bootanim.exit=1 之前
  • 开机动画结束时机:调用 writeWmBootAnimationDone() 之后

3.1.4 SystemServer 注册服务

文件: frameworks/base/services/java/com/android/server/SystemServer.java

修改目的: 在系统启动时注册 MyService

// 1. 添加导入
import com.android.server.ms.MyService;

// 2. 在 startOtherServices() 中注册服务
t.traceBegin("myservice");
MyService myService = new MyService();
ServiceManager.addService("myservice", (IBinder) myService);
t.traceEnd();

说明:

  • WindowManagerService 启动之前注册服务
  • 使用 ServiceManager.addService() 将服务添加到全局服务管理器

3.2 SELinux 权限配置 (selinux.txt)

3.2.1 服务类型定义

文件: system/sepolicy/private/service.te

type myservice, system_server_service, service_manager_type;

说明:

  • system_server_service 属性表示此服务由 system_server 管理
  • service_manager_type 属性表示这是一个服务管理器类型

3.2.2 服务上下文映射

文件: system/sepolicy/private/service_contexts

myservice                                   u:object_r:myservice:s0

说明:

  • 将服务名称 myservice 映射到安全上下文 u:object_r:myservice:s0
  • 格式:<服务名> <安全上下文>

3.2.3 服务注册权限

文件: system/sepolicy/private/system_server.te

add_service(system_server, myservice)

说明:

  • add_service() 宏展开后会生成:
    • allow system_server myservice:service_manager { add find };
    • neverallow { domain -system_server } myservice:service_manager add;
  • 允许 system_server 注册和查找 myservice
  • 禁止其他域注册 myservice

3.2.4 预构建文件同步

说明: 所有修改需要同步到 prebuilts/api/33.0/private/ 目录,保持公共 API 版本一致。


四、编译与测试

4.1 编译步骤

# 1. 初始化编译环境
source build/envsetup.sh
lunch coral-userdebug  # 选择目标设备

# 2. 编译 SELinux 策略
m sepolicy

# 3. 编译 Framework 服务
m services.core

# 4. 完整编译(可选)
make -j$(nproc)

4.2 推送文件

# 1. 推送 SELinux 策略文件
adb root
adb remount
adb push out/target/product/coral/system/etc/selinux  /system/etc/


# 2. 推送 Framework 服务
adb push out/target/product/coral/system/framework/services.jar /system/framework/services.jar

# 3. 重启设备
adb reboot

4.3 验证方法

# 1. 查看服务是否注册成功
adb shell service list | grep myservice

# 2. 查看日志输出
adb logcat | grep MyService

# 期望输出:
# V/MyService: duxiwei22  (开机动画开始时)
# V/MyService: duxiwei22  (开机动画结束时)

五、关键技术要点

5.1 AIDL 通信机制

  • 接口定义: IMyService.aidl 定义了服务接口
  • Stub 实现: MyService 继承 IMyService.Stub 实现服务端逻辑
  • 客户端调用: 通过 IMyService.Stub.asInterface(binder) 获取代理对象

5.2 ServiceManager 工作原理

ServiceManager 作为 Binder 上下文管理器:
1. SystemServer 调用 addService() 注册服务
2. WindowManagerService 调用 getService() 获取服务引用
3. 基于 Binder IPC 机制进行进程间通信

5.3 SELinux 安全机制

  • 类型强制: 每个服务都有独立的安全类型
  • 权限检查: 注册服务需要 add 权限
  • 上下文映射: service_contexts 文件定义服务名称到安全上下文的映射

5.4 开机动画流程

BootAnimation 进程启动
    │
    ▼
SurfaceFlinger 显示开机动画
    │
    ▼
WindowManagerService.performEnableScreen()
    │
    ├── SystemProperties.set("service.bootanim.exit", "1")
    │       │
    │       ▼
    │   BootAnimation 收到退出信号
    │
    └── EventLogTags.writeWmBootAnimationDone()
            │
            ▼
        屏幕点亮,显示 Launcher

六、文件清单

文件路径 修改类型 说明
frameworks/base/services/core/Android.bp 修改 添加 AIDL 文件组
frameworks/base/services/core/java/com/android/server/ms/MyService.java 修改 服务实现类
frameworks/base/services/core/java/com/android/server/ms/IMyService.aidl 新增 AIDL 接口定义
frameworks/base/services/core/java/com/android/server/wm/WindowManagerService.java 修改 开机动画回调
frameworks/base/services/java/com/android/server/SystemServer.java 修改 服务注册
system/sepolicy/private/service.te 修改 服务类型定义
system/sepolicy/private/service_contexts 修改 服务上下文映射
system/sepolicy/private/system_server.te 修改 服务注册权限
system/sepolicy/prebuilts/api/33.0/private/service.te 修改 预构建同步
system/sepolicy/prebuilts/api/33.0/private/service_contexts 修改 预构建同步
system/sepolicy/prebuilts/api/33.0/private/system_server.te 修改 预构建同步

七、注意事项

  1. SELinux 策略必须完整: 缺少任何一个 SELinux 文件修改都会导致服务注册失败
  2. 预构建文件必须同步: API 版本目录下的文件也需要同步修改
  3. 服务名称一致性: Java 代码中的服务名称必须与 service_contexts 中的名称一致
  4. 编译顺序: 先编译 SELinux 策略,再编译 Framework
  5. 设备分区权限: 需要 root 权限和 remount 系统分区才能推送文件

八、总结

本方案完整实现了在 Android 13 AOSP 中创建自定义 MyService 并在开机动画阶段调用其方法的功能。核心步骤包括:

  1. 创建 AIDL 接口和服务实现
  2. 在 SystemServer 中注册服务
  3. 在 WindowManagerService 中调用服务方法
  4. 配置 SELinux 安全策略

通过以上步骤,可以实现自定义服务的开机启动和开机动画阶段的回调功能,为系统级功能扩展提供了完整的实现路径。

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
【社区内容提示】社区部分内容疑似由AI辅助生成,浏览时请结合常识与多方信息审慎甄别。
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。

相关阅读更多精彩内容

友情链接更多精彩内容