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: [email protected]"
$(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的服務就啟動起來了