Android7.1 [Camera] CameraService启动源代码分析

源码平台:rk3399

摘要:

1.拷贝cameraserver.rc编译拷贝到system/etc/init目录

2.启动cameraserver服务

摘要1:cameraserver.rc编译拷贝到system/etc/init目录

android 系统启动完bootloader后,会启动内核,内核启动完后,会启动文件系统,很多服务也是在这时候启动起来,CameraService的启动在frameworks/av/camera/cameraserver/cameraserver.rc文件

service cameraserver /system/bin/cameraserver
    class main
    user cameraserver
    group audio camera input drmrpc readproc
    ioprio rt 4
    writepid /dev/cpuset/camera-daemon/tasks /dev/stune/top-app/tasks

这个文件会在Android.mk文件里面编译到指定位置:

LOCAL_PATH:= $(call my-dir)

include $(CLEAR_VARS)

LOCAL_SRC_FILES:= \
    main_cameraserver.cpp

LOCAL_SHARED_LIBRARIES := \
    libcameraservice \
    libcutils \
    libutils \
    libbinder \
    libcamera_client

LOCAL_MODULE:= cameraserver
LOCAL_32_BIT_ONLY := true

LOCAL_CFLAGS += -Wall -Wextra -Werror -Wno-unused-parameter

LOCAL_INIT_RC := cameraserver.rc #这里指定编译为LOCAL_INIT_RC

include $(BUILD_EXECUTABLE)

其中LOCAL_INIT_RC := cameraserver.rc这个LOCAL_INIT_RC在编译的时候,build/core/base_rules.mk会将这个文件直接拷贝到/system/etc/init目录下,

# Rule to install the module's companion init.rc.
my_init_rc := $(LOCAL_INIT_RC_$(my_32_64_bit_suffix))
my_init_rc_src :=
my_init_rc_installed :=
ifndef my_init_rc
my_init_rc := $(LOCAL_INIT_RC)
# Make sure we don't define the rule twice in multilib module.
LOCAL_INIT_RC :=
endif  
ifdef my_init_rc
my_init_rc_src := $(LOCAL_PATH)/$(my_init_rc)
my_init_rc_installed := $(TARGET_OUT$(partition_tag)_ETC)/init/$(notdir 
$(my_init_rc_src)) #这里指定的install路径就是/system/etc/init/目录
$(my_init_rc_installed) : $(my_init_rc_src) | $(ACP)
    @echo "Install: $@"       
    $(copy-file-to-new-target)

$(my_register_name) : $(my_init_rc_installed)
endif # my_init_rc
endif # !LOCAL_UNINSTALLABLE_MODULE

摘要2.启动cameraserver服务

       system/core/init/init.cpp根据/init.rc启动一个无限循环的进程,也就是init进程,init进程会等待一些命令抛进来执行.加载到fstab.rk30board后,这个文件会挂载各个分区,挂载分区的后,会扫描执行分区下的指定目录,在system/core/init/builtins.cpp,do_mount_all函数会根据fstab.rk30board文件挂载各个分区,具体怎么挂载这里不描述,最终会导入并解析rc文件

/* mount_all <fstab> [ <path> ]* [--<options>]*
 *
 * This function might request a reboot, in which case it will
 * not return.
 */    
static int do_mount_all(const std::vector<std::string>& args) {
    std::size_t na = 0; 
    bool import_rc = true;    
    bool queue_event = true;  
    int mount_mode = MOUNT_MODE_DEFAULT; 
    const char* fstabfile = args[1].c_str();
    std::size_t path_arg_end = args.size();

    for (na = args.size() - 1; na > 1; --na) {
        if (args[na] == "--early") {        
             path_arg_end = na;             
             queue_event = false;           
             mount_mode = MOUNT_MODE_EARLY;
        } else if (args[na] == "--late") { 
            path_arg_end = na;
            import_rc = false;
            mount_mode = MOUNT_MODE_LATE;
        }
    }  

    /* 这里会先读取根目录的fstab.rk30board 文件
       这个文件指定了要挂载的各个分区,包括system分区 */
    int ret =  mount_fstab(fstabfile, mount_mode);

    /* 分区挂载出来后,开始搜索导入rc文件 */
    if (import_rc) {
        /* Paths of .rc files are specified at the 2nd argument and beyond */
        import_late(args, 2, path_arg_end);
    }  

    if (queue_event) {
        /* queue_fs_event will queue event based on mount_fstab return code
         * and return processed return code*/
        ret = queue_fs_event(ret); 
    }  

    return ret;
}

/* Imports .rc files from the specified paths. Default ones are applied if none is given.
 *
 * start_index: index of the first path in the args list
 */
static void import_late(const std::vector<std::string>& args, size_t start_index, size_t end_index) {
    Parser& parser = Parser::GetInstance();
    if (end_index <= start_index) {
        // Use the default set if no path is given
        static const std::vector<std::string> init_directories = {
            "/system/etc/init",
            "/vendor/etc/init",
            "/odm/etc/init"
        };   

        for (const auto& dir : init_directories) {
            parser.ParseConfig(dir);
        }    
    } else {
        for (size_t i = start_index; i < end_index; ++i) {
            parser.ParseConfig(args[i]);
        }    
    }    
}

        其中也会解析到/system/etc/init/cameraserver.rc文件.具体的解析过程可以看init目录下的源码,这里直接简单讲解下过程

1.init.cpp会实例一个Parser,这个Parser添加了service,on,import三个SectionParser,这三个SectionParser解析出是否是server,还是on的section时,就用对应的解析器解析了

2.上面说的解析器具体有3个,但import实际上导入后,还是调用service或者action的解析器,service和action的解析器都是继承SectionParser的

3.service的解析器会针对每个选项进行解析,比如:

Service::OptionHandlerMap::Map& Service::OptionHandlerMap::map() const {
    constexpr std::size_t kMax = std::numeric_limits<std::size_t>::max();
    static const Map option_handlers = { 
        {"class",       {1,     1,    &Service::HandleClass}},
        {"console",     {0,     0,    &Service::HandleConsole}},
        {"critical",    {0,     0,    &Service::HandleCritical}},
        {"disabled",    {0,     0,    &Service::HandleDisabled}},
        {"group",       {1,     NR_SVC_SUPP_GIDS + 1, &Service::HandleGroup}},
        {"ioprio",      {2,     2,    &Service::HandleIoprio}},
        {"keycodes",    {1,     kMax, &Service::HandleKeycodes}},
        {"oneshot",     {0,     0,    &Service::HandleOneshot}},
        {"onrestart",   {1,     kMax, &Service::HandleOnrestart}},
        {"seclabel",    {1,     1,    &Service::HandleSeclabel}},
        {"setenv",      {2,     2,    &Service::HandleSetenv}},
        {"socket",      {3,     6,    &Service::HandleSocket}},
        {"user",        {1,     1,    &Service::HandleUser}},
        {"writepid",    {1,     kMax, &Service::HandleWritepid}},
    };  
    return option_handlers;
}

所以对于cameraserver

service cameraserver /system/bin/cameraserver
    class main
    user cameraserver
    group audio camera input drmrpc readproc
    ioprio rt 4
    writepid /dev/cpuset/camera-daemon/tasks /dev/stune/top-app/tasks

每一行的都有对于的处理函数../service.cpp 的start函数根据配置启动服务,启动服务时在内核打印

NOTICE("Starting service '%s'...\n", name_.c_str());

rk3399-x24:/ # dmesg | grep "Starting service"
[    3.351255] init: Starting service 'ueventd'...
[    3.900692] init: Starting service 'healthd'...
[    3.902384] init: Starting service 'zygote'...
[    3.903117] init: Starting service 'zygote_secondary'...
[    3.903727] init: Starting service 'lmkd'...
[    3.904320] init: Starting service 'servicemanager'...
[    3.905270] init: Starting service 'surfaceflinger'...
[    3.906341] init: Starting service 'vold'...
[    3.957724] init: Starting service 'debuggerd'...
[    3.958596] init: Starting service 'debuggerd64'...
[    4.259461] init: Starting service 'exec 1 (/system/bin/tzdatacheck)'...
[    4.286239] init: Starting service 'logd'...
[    4.287204] init: Starting service 'logd-reinit'...
[    4.304512] init: Starting service 'console'...
[    4.305094] init: Starting service 'adbd'...
[    4.306347] init: Starting service 'ril-daemon'...
[    4.307179] init: Starting service 'drmservice'...
[    4.308131] init: Starting service 'akmd'...
[    4.317428] init: Starting service 'audioserver'...
[    4.321919] init: Starting service 'cameraserver'...   cameraserver服务
[    4.322659] init: Starting service 'drm'...
[    4.323364] init: Starting service 'installd'...
[    4.324265] init: Starting service 'keystore'...
[    4.327250] init: Starting service 'mediacodec'...
[    4.327986] init: Starting service 'mediadrm'...
[    4.328601] init: Starting service 'mediaextractor'...
[    4.329469] init: Starting service 'media'...
[    4.330048] init: Starting service 'netd'...
[    4.331389] init: Starting service 'gatekeeperd'...
[    4.342622] init: Starting service 'perfprofd'...
[    5.409223] init: Starting service 'bootanim'...
[   11.399632] init: Starting service 'mode_switch'...
[   11.402586] init: Starting service 'exec 3 (/system/bin/bootstat)'...
[   11.421041] init: Starting service 'exec 4 (/system/bin/bootstat)'...
[   11.430231] init: Starting service 'exec 5 (/system/bin/bootstat)'...
[   11.441745] init: Starting service 'exec 6 (/system/bin/bootstat)'...

至此,cameraserver的服务就启动起来了

猜你喜欢

转载自blog.csdn.net/kiazhu/article/details/84643769