Android Frameworks 启动过程--以 Radio Frameworks 为例
Radio Frameworks
- 收音机服务进程在 Android 中在
frameworks/base/services/java/com/android/server/SystemServer.java/startOtherServices
中被调用启动
一、加载 Radio 权限配置文件
- SystemConfig 在构造函数中加载权限配置文件时,会在多个文件目录下找权限配置文件,比如环境变量中设置的目录,如 /system/etc/permissions/,还允许自定义设置环境变量目录,比如 /vendor/etc/permissions/
- 但是这些配置文件都是由
frameworks/native/data/etc/
目录下拷贝过去的,比如收音机的权限配置文件是名为android.hardware.broadcastradio.xml
- 拷贝命令一般都位于编译的 mk 文件中,使用系统变量
PRODUCT_COPY_FILES
,- 如想要移动收音机的配置权限从目录
frameworks/native/data/etc/
移动到/vendor/etc/permissions
, PRODUCT_COPY_FILES += frameworks/native/data/etc/android.hardware.broadcastradio.xml:$(TARGET_COPY_OUT_VENDOR)/etc/permissions/android.hardware.broadcastradio.xml
- 如想要移动收音机的配置权限从目录
二、启动 Radio frameworks 进程
// frameworks/base/core/java/android/content/pm/PackageManager.java
// 就是收音机权限配置文件中的 feature name
public static final String FEATURE_BROADCAST_RADIO = "android.hardware.broadcastradio";
// frameworks/base/services/java/com/android/server/SystemServer.java
private void startOtherServices() {
...
// 判断收音机是否需要加载
if (mPackageManager.hasSystemFeature(PackageManager.FEATURE_BROADCAST_RADIO)) {
traceBeginAndSlog("StartBroadcastRadioService");
mSystemServiceManager.startService(BroadcastRadioService.class); // 启动 RadioHalService
traceEnd();
}
...
}
// frameworks/base/services/core/java/com/android/server/broadcastradio/BroadcastRadioService.java
public class BroadcastRadioService extends SystemService {
public void onStart() {
publishBinderService(Context.RADIO_SERVICE, mServiceImpl); // 注册 Radio 的服务
}
}
三、Radio App 启动过程
- Radio 的服务是由 App 的进程调用,如以 Android 原生 APP 的调用
- APP 的启动是由 Launcher 服务启动的
packages/apps/Car/Radio/src/com/android/car/radio
文件夹是原始的 Radio APP 代码,主要是 Android 界面上 HMI 的代码packages/apps/Car/Radio/src/com/android/car/radio/platform/
是 RadioService 也就是访问 Frameworks 接口的代码。- 一个是 HMI 专注于用户交互,一个负责接收上层业务调用,并且调用 Android 原生的内核接口传递请求到内层。个人理解是前后依赖后者即可,但是在前者的原始 APP 代码中,即 RadioService.java 文件中还引入了
import android.hardware.radio.RadioManager;
。该设计不知道目的是什么?
至此就完成了 RadioHalService 的启动,注册,上层应用进程获取,使用的整个启动过程。
四、RadioService 使用 Frameworks 接口步骤
- 获取 RadioManager 的实例化
public RadioManagerExt(@NonNull Context ctx) {
mRadioManager = (RadioManager)ctx.getSystemService(Context.RADIO_SERVICE);
...
}
- 初始化 Modules,每个连接 RadioManager 的服务都有一个 ModuleId,用来支持多进程访问 Radio 服务的
private void initModules() {}
- 打开一个 RadioTuner 实例,用来控制 Radio 设备的类,里面提供了 Radio 操作的功能,如 tune,scan,mute 等功能
RadioTuner tuner = mRadioManager.openTuner( module.getId(), null, true, cbExt, hwHandler);
- 使用 Tuner 的功能,如 tune,scan
mRadioTuner.tune(ProgramSelectorExt.createAmFmSelector(lastChannel));
mRadioTuner.scan(RadioTuner.DIRECTION_UP, true);
---- END ----