添加 Java 系统服务

1. 编写 AIDL

Binder 程序示例之 java 篇我们写了一个 Binder java 服务,不过需要我们手动去执行 Java 程序。今天我们就来看一下怎么添加一个在开机就自启动的 Java 系统服务。

frameworks/base/core/java 目录下创建如下的文件与文件夹:

bash 复制代码
com/yuandaima
└── IJavaHelloService.aidl

其中 IJavaHelloService.aidl 的内容如下:

java 复制代码
package com.yuandaima;

interface IJavaHelloService
{
	void sayhello();
	int sayhello_to(String name);
}

AIDL 在我们自定义的 com/yuandaima 包结构下。

2. 将 AIDL 加入 Android.bp

接着修改 frameworks/base/Android.bp,在 framework-defaults 模块的 srcs 节点中添加 "core/java/android/rice14/com/yuandaima/IJavaHelloService.aidl"

java 复制代码
java_defaults {
    name: "framework-defaults",
    installable: true,

    srcs: [
        //......
        "core/java/com/yuandaima/IJavaHelloService.aidl"
    ]
    //......
}

接着我们可以执行:

bash 复制代码
source build/envsetup.sh
# 自定义 Product rice14-eng
lunch rice14-eng
make update-api

然后查看 Frameworks/base/api/current.txt中查看是否存在对应 IJavaHelloService 接口。

3. 定义 Binder 服务端类

frameworks/base/services/core/java/com 目录下新建如下的目录与文件:

bash 复制代码
yuandaima
└── JavaHelloService.java

其中 JavaHelloService.java:

java 复制代码
package com.yuandaima;

import android.util.Log;

public class JavaHelloService extends IJavaHelloService.Stub {
    private static final String TAG = "JavaHelloService";
    private int cnt1 = 0;
    private int cnt2 = 0;

    public void sayhello() throws android.os.RemoteException {
        cnt1++;
        Log.i(TAG, "sayhello : cnt = "+cnt1);
    }
    
    public int sayhello_to(java.lang.String name) throws android.os.RemoteException {
        cnt2++;
        Log.i(TAG, "sayhello_to "+name+" : cnt = "+cnt2);
        return cnt2;
    }
}

4. 开机启动服务

修改 frameworks/base/services/java/com/android/server/SystemServer.java 文件,在 startOtherServices 方法的最后增加以下代码:

java 复制代码
//import 不要忘了
import com.yuandaima.JavaHelloService;


// add hello service
traceBeginAndSlog("JavaHelloService");
ServiceManager.addService("JavaHelloService", new JavaHelloService());
traceEnd();

5. selinux 配置

接着添加 selinux 配置:

同时修改 system/sepolicy/private 和 system/sepolicy/prebuilts/api/29.0/private 目录下的:

service.te:

bash 复制代码
type JavaHelloServiceType,          system_server_service, service_manager_type;

service_contexts:

bash 复制代码
JavaHelloService                          u:object_r:JavaHelloServiceType:s0

platform_app.te

bash 复制代码
allow platform_app JavaHelloServiceType:service_manager find;

6. 添加 Java 接口白名单

我们新添加了 com/yuandaima Java 软件包,这些包需要在白名单中声明才能被上层 App 访问到:

build/make/core/tasks/check_boot_jars/package_whitelist.txt 中添加如下内容:

bash 复制代码
com\.yuandaima
com\.yuandaima\..*

7. 系统 App 使用系统服务

接着我们就可以在我们的系统 App 中使用我们的自定义的系统服务了:

修改我们在玩转 AOSP 之系统 App 源码添加中添加的系统 App Demo:

Android.bp:

json 复制代码
android_app {
    name: "FirstSystemApp",
    srcs: ["src/**/*.java"],
    resource_dirs: ["res"],
    manifest: "AndroidManifest.xml",
    platform_apis: true,
    sdk_version: "",
    certificate: "platform",
    //去掉 product_specific
    // product_specific: true,
    static_libs: ["androidx.appcompat_appcompat",
                 "com.google.android.material_material",
                 "androidx-constraintlayout_constraintlayout",
                 "lib-lottie"],
}

接着修改自定义 Product 配置文件 device/jelly/rice14/rice14.mk

Makefile 复制代码
PRODUCT_PACKAGES += \
    # ......
    FirstSystemApp
 
PRODUCT_ARTIFACT_PATH_REQUIREMENT_WHITELIST += \
    # ......
    /system/app/FirstSystemApp/FirstSystemApp.apk

修改 device/jelly/rice14/FirstSystemApp/src/com/yuandaima/firstsystemapp/MainActivity.java 源码:

java 复制代码
public class MainActivity extends AppCompatActivity {

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        try {
            IJavaHelloService service = IJavaHelloService.Stub.asInterface(ServiceManager.getService("JavaHelloService"));
            service.sayhello();
        } catch (Exception e) {
           e.printStackTrace();
        }
       
    }
}

接着我们就可以重新编译系统,启动虚拟机了:

bash 复制代码
source build/envsetup.sh
# 自定义 Product rice14
lunch rice14-eng
make -j32
emulator

接着我们就可以打开我们的 FirstSystemApp 了,然后查看 log:

关于

我叫阿豪,2015 年本科毕业于国防科学技术大学指挥信息系统专业,毕业后从事信息化装备的研发工作,主要研究方向是 Android Framework 与 Linux Kernel。

如果你对 Android Framework 感兴趣或者正在学习 Android Framework,可以关注我的微信公众号,我会持续分享我的学习经验,帮助正在学习的你少走一些弯路。学习过程中如果你有疑问或者你的经验想要分享给大家可以添加我的微信,我拉你进技术交流群。

如果你想系统学习 Anroid Framework 也可以关注我的抖音账号,在主页店铺即可购买付费课程。

相关推荐
锋风Fengfeng19 分钟前
安卓15预置第三方apk时签名报错问题解决
android
User_undefined1 小时前
uniapp Native.js原生arr插件服务发送广播到uniapp页面中
android·javascript·uni-app
程序员厉飞雨2 小时前
Android R8 耗时优化
android·java·前端
丘狸尾3 小时前
[cisco 模拟器] ftp服务器配置
android·运维·服务器
van叶~5 小时前
探索未来编程:仓颉语言的优雅设计与无限可能
android·java·数据库·仓颉
Crossoads9 小时前
【汇编语言】端口 —— 「从端口到时间:一文了解CMOS RAM与汇编指令的交汇」
android·java·汇编·深度学习·网络协议·机器学习·汇编语言
li_liuliu10 小时前
Android4.4 在系统中添加自己的System Service
android
C4rpeDime12 小时前
自建MD5解密平台-续
android
鲤籽鲲14 小时前
C# Random 随机数 全面解析
android·java·c#
m0_5485147718 小时前
2024.12.10——攻防世界Web_php_include
android·前端·php