一、守護進程啓動包含的路徑文件
1) 確定daemon進程編譯路徑
代碼路徑:vendor/qcom/proprietary/mm-camera/Android.mk
概述:確定生成mm-qcamera-daemon的路徑
代碼路徑:vendor/qcom/proprietary/mm-camera/mm-camera2/server-imaging/Android.mk
概述:確定生成mm-qcamera-daemon的包含的文件
代碼路徑:device/qcom/msm8909/init.target.rc
概述:啓動mm-qcamera-daemon服務
代碼路徑:device/qcom/common/rootdir/etc/init.qcom.rc
概述:爲域套接字的通信創建文件
二、守護進程具體的內容
1) 初始化模塊
函數分析:
1) 代碼路徑:vendor/qcom/proprietary/mm-camera/mm-camera2/server-imaging/server_process.c
函數:server_process_module_init();
概述:對modules_list數組中的模塊進行初始化
2) 代碼路徑:kernel/drivers/media/platform/msm/camera_v2/camera/camera.c
函數:int camera_init_v4l2(struct device *dev, unsigned int *session);
函數ioctl(hal_fd->fd[0], VIDIOC_SUBSCRIBE_EVENT, &subscribe);打開的文件是dev/video0,所以ioctl調用是這video_register_device註冊的ioctl_ops。
這裏主要關注的兩個函是
函數:static unsigned int camera_v4l2_poll(struct file *filep, struct poll_table_struct *wait)
作用:select函數通過設備文件的poll函數來檢查是否可讀、可寫。(用戶空間的select系統調用對應內核中的poll函數)
參考文章:http://blog.csdn.net/waldmer/article/details/18735517 關於select的調用方法
在函數camera_v4l2_poll()中的v4l2_event_pending()函數返回的是fh->navailable;
函數:static void __v4l2_event_queue_fh(struct v4l2_fh *fh, const struct v4l2_event *ev, const struct timespec *ts)
作用: fh->sequence++;
函數:static int __v4l2_event_dequeue(struct v4l2_fh *fh, struct v4l2_event *event)
作用:fh->sequence--;
例如MSM_CAMERA_NEW_SESSION的過程
HAL層:調用int32_t mm_camera_open(mm_camera_obj_t *my_obj)打開camera
kernel層:static int camera_v4l2_open(struct file *filep) ----> camera_pack_event(filep, MSM_CAMERA_NEW_SESSION, 0, -1, &event);---->
rc = msm_post_event(&event, MSM_POST_EVT_TIMEOUT);----> v4l2_event_queue(vdev, event);----> __v4l2_event_queue_fh(fh, ev, ×tamp);
----> fh->sequence++; ---> static unsigned int camera_v4l2_poll(struct file *filep, struct poll_table_struct *wait) ---> rc |= POLLPRI;(POLLPRI表示可讀)
vendor層:ret = select(select_fds.select_fd + 1, &(select_fds.fds), NULL, NULL, NULL)---> ioctl(fd_info->fd[0], VIDIOC_DQEVENT, &event)--->fh->sequence--;
通過select系統調用獲得kernel的fd的狀態改變,從而進行事件的處理,同時調用VIDIOC_DQEVENT使得fh->sequence--。
3)代碼路徑:vendor/qcom/proprietary/mm-camera/mm-camera2/media-controller/mct/tools/mct_list.c
函數:boolean mct_list_traverse(mct_list_t *mct_list, mct_list_traverse_func traverse, void *user_data);
函數:mct_list_traverse(listen_fd_list, server_reset_select_fd, &select_fds);
作用:Traverse whole list
函數:static boolean server_reset_select_fd(void *data, void *user_data)
作用:
Camera daemon handles the following types of domain socket messages:
域套接字
消息類型:
Buffer mapping –Handled via type RD_DS_FD_HAL 對應於 hal_ds_fd->fd[0]
消息來源:
hal_ds_fd->session = proc_ret.new_session_info.session_idx;
hal_ds_fd->fd[0] = proc_ret.new_session_info.hal_ds_fd;/***域套接字***/
hal_ds_fd->type = RD_DS_FD_HAL;
VIDIOC_SUBSCRIBE_EVENT
消息類型:
Video node updates from kernel –Handled via type RD_FD_HAL 對應於 hal_fd->fd[0]
消息來源:
hal_fd->fd[0] = open(dev_name, O_RDWR | O_NONBLOCK); /****dev_name = dev/video0***/
hal_fd->type = RD_FD_HAL;
ioctl(hal_fd->fd[0], VIDIOC_SUBSCRIBE_EVENT, &subscribe)
管道
消息類型:
Updates from MCT (over Unix pipe) –Handled via type RD_PIPE_FD_MCT 對應於 mct_fds->fd[0]
消息來源:
mct_fds->session = proc_ret.new_session_info.session_idx;
mct_fds->fd[0] = proc_ret.new_session_info.mct_msg_rd_fd;/***管道***/
mct_fds->fd[1] = proc_ret.new_session_info.mct_msg_wt_fd;/***管道***/
mct_fds->type = RD_PIPE_FD_MCT;
通過下面三個函數將三個不同類型的fd全部添加到listen_fd_list這個鏈表中,最後通過mct_list_traverse(listen_fd_list, server_reset_select_fd,
&select_fds);獲取最大的fd作爲select函數的第一個參數。
listen_fd_list = mct_list_append(listen_fd_list,hal_ds_fd, NULL, NULL)
|---> mct_list_t* mct_list_append(mct_list_t *mct_list, void *data, void *appendto, mct_list_find_func list_find)
|---> new_list = mct_list_new(data);
listen_fd_list = mct_list_append(listen_fd_list, mct_fds, NULL, NULL)
|---> mct_list_t* mct_list_append(mct_list_t *mct_list, void *data, void *appendto, mct_list_find_func list_find)
|---> new_list = mct_list_new(data);
listen_fd_list = mct_list_append(listen_fd_list, hal_fd, NULL, NULL)
|---> mct_list_t* mct_list_append(mct_list_t *mct_list, void *data, void *appendto, mct_list_find_func list_find)
|---> new_list = mct_list_new(data);