新板子car版本android系统收不到m4发送的资源释放消息,屏不亮,先分析一下逻辑关系。
上图就是car版本AP核和M41核之间的倒车逻辑。
阶段1 系统启动完毕
mek_8q.mk 63: $(IMX_DEVICE_PATH)/init_car_m4.rc:$(TARGET_COPY_OUT_VENDOR)/etc/init/hw/init.car_additional.rc 68: $(IMX_DEVICE_PATH)/init_car_no_m4.rc:$(TARGET_COPY_OUT_VENDOR)/etc/init/hw/init.car_additional.rc
也就是说vendor.all.system_server.ready代表系统启动完成。
frameworks/base/packages/SystemUI/src/com/android/systemui/SystemUIApplication.java 159:
SystemProperties.set("vendor.all.system_server.ready", "1");
阶段2
(1)注册vehicle_rpmsg_m4驱动
init_car_m4.rc将被触发:
on property:vendor.all.system_server.ready=1 # register the vehicle_rpmsg_m4 on raw android. write /sys/devices/platform/vehicle_rpmsg_m4/register 1 # register the vehicle_rpmsg_m4 on android running in xen. write /sys/devices/platform/passthrough/passthrough\:vehicle_rpmsg_m4/register 1
write /sys/devices/platform/vehicle_rpmsg_m4/register 1 注册vehicle_rpmsg_driver内核驱动。
vendor/nxp-opensource/kernel_imx/drivers/mxc/vehicle/vehicle_rpmsg_m4.c:
static struct rpmsg_driver vehicle_rpmsg_driver = {
.drv.name = "vehicle_rpmsg",
.drv.owner = THIS_MODULE,
.id_table = vehicle_rpmsg_id_table,
.probe = vehicle_rpmsg_probe,
.callback = vehicle_rpmsg_cb,
};
/*register ap to M4 once echo 1 > /sys/devices/platform/vehicle_rpmsg/register*/
static ssize_t register_store(struct device *dev,
'''省略'''
unsigned long state_set = simple_strtoul(buf, NULL, 10);
if (state_set == 1 && state_set != state) {
err = register_rpmsg_driver(&vehicle_rpmsg_driver);
'''省略'''
return size;
}
其中vehicle_rpmsg_cb为接收m4消息的callback函数,注册驱动成功后执行probe函数,vehicle_init_handler将VEHICLE_RPMSG_REGISTER消息发送给m4
static int vehicle_rpmsg_probe(struct rpmsg_device *rpdev)
{
'''省略'''
init_completion(&vehicle_rpmsg->cmd_complete);
INIT_DELAYED_WORK(&vehicle_rpmsg->vehicle_register_work,
vehicle_init_handler); 重要
schedule_delayed_work(&vehicle_rpmsg->vehicle_register_work, 0);
return 0;
}
/* send register event to M4 core
* M4 will release camera/display once register successfully.
将regster事件发送到M4核心,M4将在成功注册后释放摄像头/显示器。
*/
static void vehicle_init_handler(struct work_struct *work)
{
msg.header.cmd = VEHICLE_RPMSG_REGISTER;
err = sc_rm_get_partition(ipc_handle, &os_part); 获取Android系统分区号
if (err != SC_ERR_NONE) {
pr_err("sc_rm_get_partition failed!\n");
msg.partition_id = 0xff;
} else {
msg.partition_id = os_part;
}
/* need check whether ap have been unregistered before register the ap*/
if (!vehicle_rpmsg->vehicle_client_registered) {
while (vehicle_send_message(&msg, vehicle_rpmsg, true)) { 将VEHICLE_RPMSG_REGISTER消息发送给m4
msleep(REGISTER_PERIOD);
}
}
}
阶段3
m4接收到VEHICLE_RPMSG_REGISTER消息,释放资源,进入Android界面。
m4逻辑如下:
(1)Auto_register服务注册过程,主要用于监听Android的VEHICLE_RPMSG_REGISTER消息:
main(...)
APP_SRTM_Init();
-->xTaskCreate(SRTM_MonitorTask, "SRTM monitor", 256U, NULL, APP_SRTM_MONITOR_TASK_PRIO, NULL);
-->APP_SRTM_InitAutoService(void)
-->SRTM_AutoService_Create(&autoAdapter); /* Create and register service */
static struct _srtm_auto_adapter autoAdapter = {.registerEvent = APP_SRTM_Auto_RegisterEvent,
.unregisterEvent = APP_SRTM_Auto_UnregisterEvent,
.control = APP_SRTM_Auto_Control,
.powerReport = APP_SRTM_Auto_PowerReport,
.getInfo = APP_SRTM_Auto_GetInfo};
--> APP_SRTM_Auto_RegisterEvent(...) 跟踪注册成功的registerEvent服务
-->stateMsg.reg.enroll = 0x01; 表示m4接收到了 VEHICLE_RPMSG_REGISTER消息,准备进入接下来的释放资源
以上表示m4接收到了 VEHICLE_RPMSG_REGISTER消息,准备进入接下来的释放资源。
(2)资源释放过程,主要是根据stateMsg.reg.enroll的数值,android注册成功后,置位标志位AUTO_UI_EVENT_BIT_STOP:
main(...)
xTaskCreate(vehicle_state_monitor_task, "VehicleMonitor"...)
-->vehicle_state_monitor_task(void *pvParameters)
case STATE_TYPE_ANDROID:
android_registered_flag = stateMsg.reg.enroll;/* 1:registered, 0:unregistered */
if (android_registered_flag)
{
if (!shared_resource_free)
/* camera resource is not occupied, stop display and release it*/
xEventGroupSetBits(g_xAutoUiEvent, AUTO_UI_EVENT_BIT_STOP);
}
该线程监听到AUTO_UI_EVENT_BIT_STOP位置高,则释放资源。
xTaskCreate(rear_view_camera_task, "RearViewCamera",...)
-->rear_view_camera_task(void *pvParameters)
if (eventBits & AUTO_UI_EVENT_BIT_STOP)
{
APP_StopCamera();
APP_DeinitDisplay();
APP_AutoPassResource(); //释放资源
--> SOC_AssignDisplayCamera(android_pt);
}
阶段4、5
(1)驱动回调函数接收到m4的释放信息,通过netlink将从m4接收的cmd指令信息以广播的方式传给evs服务,对应阶段6的uevent_kernel_multicast_recv函数,通知上层加载显示/摄像头驱动。
register_ready味着AP已经注册为客户机,并且已经准备好加载摄像头/显示模块。当它第一次得到驱动信号并且寄存器就绪为真时,它将加载相关的模块。
kernel_imx/drivers/mxc/vehicle/vehicle_rpmsg_m4.c
/*vehicle_rpmsg_cb is called once get rpmsg from M4*/
vehicle_rpmsg_cb(struct rpmsg_device *rpdev)
{
if (msg->header.cmd == VEHICLE_RPMSG_REGISTER)
{
vehicle_rpmsg->register_ready = true;
}
if (vehicle_rpmsg->register_ready)
{
notice_evs_released(rpdev);
vehicle_rpmsg->register_ready = false;
}
此函数是通过netlink将从m4接收的cmd指令信息以广播的方式传给evs服务,对应阶段6的uevent_kernel_multicast_recv函数,
阶段6就是讲的上层完成解析过程及后续步骤。
vehicle_hal_set_property(msg->statetype, msg->index, msg->statevalue);
-->send_usrmsg(buffer, stream.bytes_written);
-->netlink_unicast(nlsk, nl_skb, user_pid, MSG_DONTWAIT);
}
阶段6
(1)设置系统属性 vendor.vehicle.register
vendor/nxp-opensource/imx/evs_service/evs_service.c
#define RPMSG_CAN_REGISTER "vendor.vehicle.register"
static void
handle_events(int uevent_fd)
{
char msg[UEVENT_MSG_LEN+2];
n = uevent_kernel_multicast_recv(uevent_fd, msg, UEVENT_MSG_LEN);
cp = msg;
...省略...
while (*cp) {
if (!strncmp(cp, "STATE=VEHICLE_RPMSG_EVENT=0", strlen("STATE=VEHICLE_RPMSG_EVENT=0")))
{
if (property_set(RPMSG_CAN_EVENT, "0") < 0)
ALOGE("%s: could not set property RPMSG_CAN_EVENT", __FUNCTION__);
}
else if (!strncmp(cp, "STATE=VEHICLE_RPMSG_EVENT=1", strlen("STATE=VEHICLE_RPMSG_EVENT=1"))) {
if (property_set(RPMSG_CAN_EVENT, "1") < 0)
ALOGE("%s: could not set property RPMSG_CAN_EVENT", __FUNCTION__);
}
else if (!strncmp(cp, "STATE=VEHICLE_RPMSG_REGISTER=0", strlen("STATE=VEHICLE_RPMSG_REGISTER=0"))) {
if (property_set(RPMSG_CAN_REGISTER, "0") < 0)
ALOGE("%s: could not set property RPMSG_CAN_REGISTER", __FUNCTION__);
}
else if (!strncmp(cp, "STATE=VEHICLE_RPMSG_REGISTER=1", strlen("STATE=VEHICLERPMSG_REGISTER=1"))) {
if (property_set(RPMSG_CAN_REGISTER, "1") < 0)
ALOGE("%s: could not set property RPMSG_CAN_REGISTER", __FUNCTION__);
}
...省略...
(2)启动boot_completed_core_sh(setup.core.cfg驱动)
/device/fsl/imx8q/mek_8q/init_car_m4.rc
on property:vendor.vehicle.register=1 start boot_completed_core_sh
init_car.rc
service boot_completed_core_sh /vendor/bin/init.insmod.sh /vendor/etc/setup.core.cfg vendor.all.setup_core.ready
class main
user root
group root system
disabled
oneshot
on property:vendor.all.setup_core.ready=1
start boot_completed_main_sh
start selinuxswitch
service boot_completed_main_sh /vendor/bin/init.insmod.sh /vendor/etc/setup.main.cfg vendor.all.setup_main.ready
class main
user root
group root system
disabled
oneshot
on property:vendor.all.setup_main.ready=1
# Trigger start adbd service
start usbd
start zygote_late
以上的意思是用init.insmod.sh脚本安装setup.core.cfg里面的模块,然后将vendor.all.setup_core.ready置为1,然后insmod setup.main.cfg中的模块,最后开启adbd服务。