添加 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 也可以关注我的抖音账号,在主页店铺即可购买付费课程。

相关推荐
西瓜本瓜@2 小时前
在Android中如何使用Protobuf上传协议
android·java·开发语言·git·学习·android-studio
似霰6 小时前
安卓adb shell串口基础指令
android·adb
fatiaozhang95278 小时前
中兴云电脑W102D_晶晨S905X2_2+16G_mt7661无线_安卓9.0_线刷固件包
android·adb·电视盒子·魔百盒刷机·魔百盒固件
CYRUS_STUDIO9 小时前
Android APP 热修复原理
android·app·hotfix
鸿蒙布道师9 小时前
鸿蒙NEXT开发通知工具类(ArkTs)
android·ios·华为·harmonyos·arkts·鸿蒙系统·huawei
鸿蒙布道师9 小时前
鸿蒙NEXT开发网络相关工具类(ArkTs)
android·ios·华为·harmonyos·arkts·鸿蒙系统·huawei
大耳猫10 小时前
【解决】Android Gradle Sync 报错 Could not read workspace metadata
android·gradle·android studio
ta叫我小白10 小时前
实现 Android 图片信息获取和 EXIF 坐标解析
android·exif·经纬度
dpxiaolong11 小时前
RK3588平台用v4l工具调试USB摄像头实践(亮度,饱和度,对比度,色相等)
android·windows
tangweiguo0305198712 小时前
Android 混合开发实战:统一 View 与 Compose 的浅色/深色主题方案
android