系统版本: Ubuntu 22.04 lts
AOSP分支: android-16.0.0_r4
本文将介绍如何在AOSP16中新增一个Java层的系统服务
一 创建功能发布标志
在最新的AOSP开发中,Google推荐使用功能发布标志来进行新功能的开发和迭代,具体可以查看这里:
首先我们先创建一个功能发布标志,由于我们的服务将创建在android.os包下,所以我们使用现有的aconfig文件即可,如果希望使用自定义的aconfig文件,可以在上面的链接中查看如何创建自定义文件并修改Android BP文件使自定义aconfig文件生效。
打开AOSP16/frameworks/base/core/java/android/os/flags.aconfig,声明aconfig标志:
Aconfig
flag {
name: "jyc_battery_service_enabled"
namespace: "jyc_power"
description: "check battery status"
bug: "none"
is_exported: true
}
之后打开AOSP16/build/release/aconfig/trunk_staging/android.os目录,创建新文件jyc_battery_service_enabled_flag_values.textproto,并写入如下内容:
Aconfig
flag_value {
package: "android.os"
name: "jyc_battery_service_enabled"
state: ENABLED
permission: READ_WRITE
}
最后由于我们新增了aconfig,所以需要部分编译一下:
shell
. build/envsetup.sh
lunch aosp_cf_x86_64_phone-trunk_staging-userdebug
m update-api
这时,在Java代码中,就已经可以android.os包下找到对应方法,并且能看到声明的发布标志:
Java
android.os.Flags.jycBatteryServiceEnabled()
android.os.Flags.FLAG_JYC_BATTERY_SERVICE_ENABLED
二 新建AIDL文件
打开/AOSP16/frameworks/base/core/java/android/os,新建文件夹jycservice,并创建文件IJYCBatteryService.aidl:
Java
package android.os.jycservice;
/** @hide **/
interface IJYCBatteryService {
int getBattery();
}
之后进行编译:
Shell
m framework-minus-apex
三 创建Service
打开AOSP16/frameworks/base/core/java/android/content/Context.java,新增:
Java
/**
* @hide
*/
@FlaggedApi(android.os.Flags.FLAG_JYC_BATTERY_SERVICE_ENABLED)
@SystemApi
public static final String JYC_BATTERY_SERVICE = "jyc_battery";
打开AOSP16/frameworks/base/services/core/java/com/android/server,创建文件夹jycservice,并在此文件夹下创建JYCBatteryService.java:
Java
package com.android.server.jycservice;
import android.annotation.FlaggedApi;
import android.content.Context;
import android.os.BatteryManagerInternal;
import android.os.jycservice.IJYCBatteryService;
import com.android.server.LocalServices;
import com.android.server.SystemService;
@FlaggedApi(android.os.Flags.FLAG_JYC_BATTERY_SERVICE_ENABLED)
public class JYCBatteryService extends IJYCBatteryService.Stub {
public static final String SERVICE_TAG = "jyc_battery";
private Context mContext;
public JYCBatteryService(Context context) {
this.mContext = context;
}
public static final class Lifecycle extends SystemService {
private JYCBatteryService mService;
public Lifecycle(Context context) {
super(context);
}
@Override
public void onStart() {
mService = new JYCBatteryService(getContext());
publishBinderService(Context.JYC_BATTERY_SERVICE, mService);
}
}
@Override
public int getBattery() {
BatteryManagerInternal bmi = LocalServices.getService(BatteryManagerInternal.class);
if (bmi != null) {
return bmi.getBatteryLevel();
}
return -1;
}
}
四 注册Service
打开AOSP16/frameworks/base/services/java/com/android/server/SystemServer.java,在startOtherServices方法中,添加:
Java
/* Add JYCBatteryService */
if (android.os.Flags.jycBatteryServiceEnabled()) {
t.traceBegin("StartJYCBatteryService");
mSystemServiceManager.startService(JYCBatteryService.Lifecycle.class);
t.traceEnd();
}
/* End Add JYCBatteryService */
五 创建对应的Manager
如果我们的Service需要开放给系统App或第三方App使用,那么与其他系统服务一样,需要一个Service对应的ServiceManager。 在AOSP16/frameworks/base/core/java/android/os下,创建文件夹jycservice,并新增文件JycBatteryManager.java:
Java
package android.os.jycservice;
import android.annotation.FlaggedApi;
import android.annotation.NonNull;
import android.annotation.SystemService;
import android.content.Context;
import android.os.RemoteException;
import android.util.Log;
@SystemService(Context.JYC_BATTERY_SERVICE)
@FlaggedApi(android.os.Flags.FLAG_JYC_BATTERY_SERVICE_ENABLED)
public class JycBatteryManager {
private static final String TAG = "JYCBatteryManager";
private final Context mContext;
private final IJYCBatteryService mService;
/** @hide **/
@FlaggedApi(android.os.Flags.FLAG_JYC_BATTERY_SERVICE_ENABLED)
public JycBatteryManager(@NonNull Context context, @NonNull IJYCBatteryService service) {
mContext = context;
mService = service;
}
/**
* 获取当前电量
*/
@FlaggedApi(android.os.Flags.FLAG_JYC_BATTERY_SERVICE_ENABLED)
public int getBatteryLevel() {
try {
return mService.getBattery();
} catch (RemoteException e) {
Log.e(TAG, "RemoteException in getBatteryLevel", e);
return -1;
}
}
}
六 注册Manager
打开AOSP16/frameworks/base/core/java/android/app/SystemServiceRegistry.java,在registerServices方法中,新增注册逻辑:
Java
if (android.os.Flags.jycBatteryServiceEnabled()) {
registerService(Context.JYC_BATTERY_SERVICE, JycBatteryManager.class,
new CachedServiceFetcher<JycBatteryManager>() {
@Override
public JycBatteryManager createService(ContextImpl ctx) throws ServiceNotFoundException {
IBinder b = ServiceManager.getServiceOrThrow(Context.JYC_BATTERY_SERVICE);
IJYCBatteryService service = IJYCBatteryService.Stub.asInterface(b);
return new JycBatteryManager(ctx.getOuterContext(), service);
}});
}
由于我们新增了Service并创建了对应的manager,所以我们需要更新:
shell
m update-api
七 配置Selinux
在Android系统中,我们的系统服务必须配置相应的selinux权限,才能生效。 打开AOSP16/system/sepolicy/private/service.te,新增如下代码:
shell
###
### JYC Services
###
type jyc_battery_service, app_api_service, system_api_service, system_server_service, service_manager_type;
接着打开AOSP16/system/sepolicy/private/service_contexts,新增:
bash
# JYC Service
jyc_battery u:object_r:jyc_battery_service:s0
然后打开AOSP16/system/sepolicy/private/system_server.te,新增:
scss
# Add JYC Service
add_service(system_server, jyc_battery_service)
最后打开AOSP16/system/sepolicy/private/untrusted_app_all.te,新增配置允许第三方App访问我们的服务:
ini
# Allow Other App Can Find JYCBatteryService
allow untrusted_app jyc_battery_service:service_manager find;
最后进行编译:
m
八 验证服务
编译成功之后,运行:
Shell
launch_cvd --daemon
等待启动成功之后,运行命令查找服务:
Shell
adb shell service list | grep jyc_battery
之后我们会看到输出:
Shell
190 jyc_battery: [android.os.jycservice.IJYCBatteryService]
然后我们可以尝试调用Service中的方法:
Shell
adb shell service call jyc_battery 1
之后可以看到输出:
Shell
Result: Parcel( 00000000 00000055 '....U...')