1. init進(jìn)程啟動(dòng)
initshiAndroid系統(tǒng)用戶空間的第1個(gè)進(jìn)程锌畸,被賦予了很多重要職責(zé)毅整,比如創(chuàng)建孵化器Zygote嗦枢,屬性服務(wù)等阅悍。由多個(gè)源文件組成
1.1 引入init進(jìn)程
簡單說明init進(jìn)程的前幾步
啟動(dòng)電源以及系統(tǒng)啟動(dòng)
電源按下時(shí)引導(dǎo)芯片代碼從預(yù)定義處開始執(zhí)行朗伶。加載引導(dǎo)程序BootLoader到RAM中弦撩,然后執(zhí)行
引導(dǎo)程序BootLoader
是Android操作系統(tǒng)運(yùn)行前的一個(gè)小程序,主要用于拉起系統(tǒng)OS并運(yùn)行
Linux內(nèi)核啟動(dòng)
此時(shí)設(shè)置緩存论皆、被保護(hù)存儲(chǔ)器益楼、計(jì)劃列表、加載驅(qū)動(dòng)点晴。內(nèi)核完成系統(tǒng)設(shè)置后首先在系統(tǒng)文件中尋找init.rc文件感凤,并啟動(dòng)init進(jìn)程
init進(jìn)程啟動(dòng)
主要用于初始化啟動(dòng)屬性服務(wù),也用來啟動(dòng)Zygote進(jìn)程
1.2 init進(jìn)程的入口函數(shù)
init進(jìn)程的入口函數(shù)main粒督,抽取部分代碼陪竿,如下
main(第1部分)
int main(int argc, char** argv) {
if (!strcmp(basename(argv[0]), "ueventd")) {
return ueventd_main(argc, argv);
}
if (!strcmp(basename(argv[0]), "watchdogd")) {
return watchdogd_main(argc, argv);
}
if (argc > 1 && !strcmp(argv[1], "subcontext")) {
InitKernelLogging(argv);
const BuiltinFunctionMap function_map;
return SubcontextMain(argc, argv, &function_map);
}
if (REBOOT_BOOTLOADER_ON_PANIC) {
InstallRebootSignalHandlers();
}
bool is_first_stage = (getenv("INIT_SECOND_STAGE") == nullptr);
if (is_first_stage) {
boot_clock::time_point start_time = boot_clock::now();
// Clear the umask.
umask(0);
clearenv();
setenv("PATH", _PATH_DEFPATH, 1);
// Get the basic filesystem setup we need put together in the initramdisk
// on / and then we'll let the rc file figure out the rest.
mount("tmpfs", "/dev", "tmpfs", MS_NOSUID, "mode=0755");
mkdir("/dev/pts", 0755);
mkdir("/dev/socket", 0755);
mount("devpts", "/dev/pts", "devpts", 0, NULL);
#define MAKE_STR(x) __STRING(x)
mount("proc", "/proc", "proc", 0, "hidepid=2,gid=" MAKE_STR(AID_READPROC));
// Don't expose the raw commandline to unprivileged processes.
chmod("/proc/cmdline", 0440);
gid_t groups[] = { AID_READPROC };
setgroups(arraysize(groups), groups);
mount("sysfs", "/sys", "sysfs", 0, NULL);
mount("selinuxfs", "/sys/fs/selinux", "selinuxfs", 0, NULL);
mknod("/dev/kmsg", S_IFCHR | 0600, makedev(1, 11));
if constexpr (WORLD_WRITABLE_KMSG) {
mknod("/dev/kmsg_debug", S_IFCHR | 0622, makedev(1, 11));
}
mknod("/dev/random", S_IFCHR | 0666, makedev(1, 8));
mknod("/dev/urandom", S_IFCHR | 0666, makedev(1, 9));
// Mount staging areas for devices managed by vold
// See storage config details at http://source.android.com/devices/storage/
mount("tmpfs", "/mnt", "tmpfs", MS_NOEXEC | MS_NOSUID | MS_NODEV,
"mode=0755,uid=0,gid=1000");
// /mnt/vendor is used to mount vendor-specific partitions that can not be
// part of the vendor partition, e.g. because they are mounted read-write.
mkdir("/mnt/vendor", 0755);
// Now that tmpfs is mounted on /dev and we have /dev/kmsg, we can actually
// talk to the outside world...
InitKernelLogging(argv);
···
上面多段if處都是函數(shù)調(diào)用,在變量is_first_stage為真時(shí)屠橄,會(huì)創(chuàng)建和掛載tmpfs族跛、devpts捐康、proc、sysfs和selinuxfs共5種文件系統(tǒng)庸蔼,這些都是系統(tǒng)運(yùn)行時(shí)目錄解总,系統(tǒng)停止時(shí)會(huì)消失
main(第2部分)
···
property_init();
···
epoll_fd = epoll_create1(EPOLL_CLOEXEC);
if (epoll_fd == -1) {
PLOG(FATAL) << "epoll_create1 failed";
}
sigchld_handler_init();
if (!IsRebootCapable()) {
// If init does not have the CAP_SYS_BOOT capability, it is running in a container.
// In that case, receiving SIGTERM will cause the system to shut down.
InstallSigtermHandler();
}
property_load_boot_defaults();
export_oem_lock_status();
start_property_service();
set_usb_controller();
const BuiltinFunctionMap function_map;
Action::set_function_map(&function_map);
subcontexts = InitializeSubcontexts();
ActionManager& am = ActionManager::GetInstance();
ServiceList& sm = ServiceList::GetInstance();
LoadBootScripts(am, sm);
···
開頭property_init函數(shù)對(duì)屬性進(jìn)行了初始化
末尾處start_property_service函數(shù)啟動(dòng)屬性服務(wù)
中間sigchld_handler_init函數(shù)用于設(shè)置子進(jìn)程信號(hào)處理函數(shù),主要用于防止init進(jìn)程的子進(jìn)程成為僵尸進(jìn)程姐仅。為了防止僵尸進(jìn)程的出現(xiàn)花枫,系統(tǒng)會(huì)在子進(jìn)程暫停和終止的時(shí)候發(fā)出SIGCHLD信號(hào),這個(gè)函數(shù)就是用來接收信號(hào)的
結(jié)尾處LoadBootScripts解析init.rc文件掏膏,講完main函數(shù)再分析
延申:僵尸進(jìn)程
進(jìn)程在OS中使用fork函數(shù)創(chuàng)建劳翰。父進(jìn)程fork子進(jìn)程,在子進(jìn)程終止后馒疹,如果父進(jìn)程不知道子進(jìn)程已經(jīng)終止佳簸,這時(shí)雖然子進(jìn)程已經(jīng)退出,到那時(shí)系統(tǒng)進(jìn)程仍然保留了它的信息颖变,這個(gè)子進(jìn)程就被稱作僵尸進(jìn)程生均。由于系統(tǒng)進(jìn)程表是有限的,如果被耗盡腥刹,則無法創(chuàng)建新進(jìn)程
main(第3部分)
···
while (true) {
// By default, sleep until something happens.
int epoll_timeout_ms = -1;
if (do_shutdown && !shutting_down) {
do_shutdown = false;
if (HandlePowerctlMessage(shutdown_command)) {
shutting_down = true;
}
}
if (!(waiting_for_prop || Service::is_exec_service_running())) {
am.ExecuteOneCommand();
}
if (!(waiting_for_prop || Service::is_exec_service_running())) {
if (!shutting_down) {
auto next_process_restart_time = RestartProcesses();
// If there's a process that needs restarting, wake up in time for that.
if (next_process_restart_time) {
epoll_timeout_ms = std::chrono::ceil<std::chrono::milliseconds>(
*next_process_restart_time - boot_clock::now())
.count();
if (epoll_timeout_ms < 0) epoll_timeout_ms = 0;
}
}
// If there's more work to do, wake up again immediately.
if (am.HasMoreCommands()) epoll_timeout_ms = 0;
}
epoll_event ev;
int nr = TEMP_FAILURE_RETRY(epoll_wait(epoll_fd, &ev, 1, epoll_timeout_ms));
if (nr == -1) {
PLOG(ERROR) << "epoll_wait failed";
} else if (nr == 1) {
((void (*)()) ev.data.ptr)();
}
}
return 0;
}
中間處的RestartProcess函數(shù)就是用來重啟Zygote的马胧。因?yàn)榧偃鏸nit進(jìn)程的子進(jìn)程Zygote終止了,sigchld_handler_init函數(shù)內(nèi)部經(jīng)過層層調(diào)用最終會(huì)找到Zygote進(jìn)程并移除所有的Zygote進(jìn)程的信息衔峰,再重啟Zygote服務(wù)的腳本佩脊,其他init進(jìn)程子進(jìn)程的原理也是類似的
1.3 解析init.rc
這是一個(gè)非常重要的配置文件,是由Android初始化語言編寫的垫卤,主要包含5種類型的語句:Action威彰、Command、Service穴肘、Option和Import歇盼,配置代碼如下
init.rc
···
on init
sysclktz 0
# Mix device-specific information into the entropy pool
copy /proc/cmdline /dev/urandom
copy /default.prop /dev/urandom
···
on boot
# basic network init
ifup lo
hostname localhost
domainname localdomain
···
這里截取一部分,on init和on bool是Action類型的語句梢褐,格式如下
on <trigger> [&&<trigger>]* //設(shè)置觸發(fā)器
<command>
<command> //動(dòng)作觸發(fā)之后的命令
為了分析如何創(chuàng)建Zygote旺遮,我們主要查看Service類型語句赵讯,格式如下
service <name> <pathname> [<argument>]* //<service的名字> <執(zhí)行路徑> <傳遞參數(shù)>
<option>
<option> //是service的修飾詞盈咳,影響何時(shí),怎樣啟動(dòng)Service
我們分析Zygote啟動(dòng)腳本則在init.zygoteXX.rc中定義边翼,以64位處理器為例鱼响,分析zygote64.rc
zygote64.rc
service zygote /system/bin/app_process64 -Xzygote /system/bin --zygote --start-system-server
class main
priority -20
user root
group root readproc reserved_disk
socket zygote stream 660 root system
onrestart write /sys/android_power/request_state wake
onrestart write /sys/power/state on
onrestart restart audioserver
onrestart restart cameraserver
onrestart restart media
onrestart restart netd
onrestart restart wificond
writepid /dev/cpuset/foreground/tasks
大概分析,Service用于通知组底,init進(jìn)程創(chuàng)建名為zygote的進(jìn)程丈积,這個(gè)進(jìn)程執(zhí)行程序的路徑為 /system/bin/app_process64筐骇,后面的代碼是要傳給app_process64的參數(shù)。class main指的是Zygote的classname為main
1.4 解析Service類型語句
init.rc中Action類型語句和Service類型語句都有相應(yīng)的類來解析江滨,Action類型采用ActionParser解析铛纬,Service類型采用ServiceParser解析,這里主要分析Zygote唬滑,所以只介紹ServiceParser告唆。其實(shí)現(xiàn)代碼在service.cpp中,解析Service用到兩個(gè)函數(shù):一個(gè)是ParseSection晶密,會(huì)解析Service的rc文件擒悬,搭建Service的架子。另一個(gè)是ParselineSection稻艰,解析子項(xiàng)懂牧,代碼如下
service
Result<Success> ServiceParser::ParseSection(std::vector<std::string>&& args,
const std::string& filename, int line) {
if (args.size() < 3) {
return Error() << "services must have a name and a program";
}
const std::string& name = args[1];
if (!IsValidName(name)) {
return Error() << "invalid service name '" << name << "'";
}
Subcontext* restart_action_subcontext = nullptr;
if (subcontexts_) {
for (auto& subcontext : *subcontexts_) {
if (StartsWith(filename, subcontext.path_prefix())) {
restart_action_subcontext = &subcontext;
break;
}
}
}
std::vector<std::string> str_args(args.begin() + 2, args.end());
service_ = std::make_unique<Service>(name, restart_action_subcontext, str_args);
return Success();
}
Result<Success> ServiceParser::ParseLineSection(std::vector<std::string>&& args, int line) {
return service_ ? service_->ParseLine(std::move(args)) : Success();
}
Result<Success> ServiceParser::EndSection() {
if (service_) {
Service* old_service = service_list_->FindService(service_->name());
if (old_service) {
if (!service_->is_override()) {
return Error() << "ignored duplicate definition of service '" << service_->name()
<< "'";
}
service_list_->RemoveService(*old_service);
old_service = nullptr;
}
service_list_->AddService(std::move(service_));
}
return Success();
}
第1個(gè)if處,判斷Service是否有name與可執(zhí)行程序
第2個(gè)if處尊勿,檢查Service的name是否有效
中間處std::make_unique<Service>函數(shù)構(gòu)建一個(gè)Service對(duì)象
解析完數(shù)據(jù)后僧凤,最后調(diào)用EndSection函數(shù),函數(shù)里又有AddService函數(shù)
service的AddService
void ServiceList::AddService(std::unique_ptr<Service> service) {
services_.emplace_back(std::move(service));
}
此函數(shù)將Service對(duì)象添加進(jìn)鏈表
1.5 init啟動(dòng)Zygote
接下來說說init如何啟動(dòng)Service元扔,主要講解啟動(dòng)Zygote這個(gè)Service拼弃,在init.rc中有如下配置代碼
init.rc
···
on nonencrypted
class_start main
class_start late_start
···
其中class_start是一個(gè)是一個(gè)Command,對(duì)應(yīng)的函數(shù)為do_class_start摇展,啟動(dòng)了那些classname為main的Service吻氧,我們?cè)谏衔闹繸ygote的classname就是main,所以這里就是用來啟動(dòng)Zygote的咏连。do_class_start函數(shù)在builtins.cpp中定義,如下
builtins的do_class_start
static Result<Success> do_class_start(const BuiltinArguments& args) {
// Starting a class does not start services which are explicitly disabled.
// They must be started individually.
for (const auto& service : ServiceList::GetInstance()) {
if (service->classnames().count(args[1])) {
if (auto result = service->StartIfNotDisabled(); !result) {
LOG(ERROR) << "Could not start service '" << service->name()
<< "' as part of class '" << args[1] << "': " << result.error();
}
}
}
return Success();
}
for循環(huán)會(huì)遍歷ServiceList鏈表祟滴,找到classname為main的Zygote振惰,并執(zhí)行service.cpp里的StartIfNotDisabled函數(shù),如下
service的StartIfNotDisabled
Result<Success> Service::StartIfNotDisabled() {
if (!(flags_ & SVC_DISABLED)) {
return Start();
} else {
flags_ |= SVC_DISABLED_START;
}
return Success();
}
第一個(gè)if處垄懂,如果Service沒有在其對(duì)應(yīng)的rc文件中設(shè)置disabled選項(xiàng)骑晶,則會(huì)調(diào)用Start函數(shù)啟動(dòng)Service,Zygote對(duì)應(yīng)的init.zygote64.rc中并沒有設(shè)置disabled選項(xiàng)草慧,因此我們來查看Start函數(shù)
service的Start
Result<Success> Service::Start() {
bool disabled = (flags_ & (SVC_DISABLED | SVC_RESET));
// Starting a service removes it from the disabled or reset state and
// immediately takes it out of the restarting state if it was in there.
flags_ &= (~(SVC_DISABLED|SVC_RESTARTING|SVC_RESET|SVC_RESTART|SVC_DISABLED_START));
// Running processes require no additional work --- if they're in the
// process of exiting, we've ensured that they will immediately restart
// on exit, unless they are ONESHOT. For ONESHOT service, if it's in
// stopping status, we just set SVC_RESTART flag so it will get restarted
// in Reap().
if (flags_ & SVC_RUNNING) {
if ((flags_ & SVC_ONESHOT) && disabled) {
flags_ |= SVC_RESTART;
}
// It is not an error to try to start a service that is already running.
return Success();
}
bool needs_console = (flags_ & SVC_CONSOLE);
if (needs_console) {
if (console_.empty()) {
console_ = default_console;
}
// Make sure that open call succeeds to ensure a console driver is
// properly registered for the device node
int console_fd = open(console_.c_str(), O_RDWR | O_CLOEXEC);
if (console_fd < 0) {
flags_ |= SVC_DISABLED;
return ErrnoError() << "Couldn't open console '" << console_ << "'";
}
close(console_fd);
}
struct stat sb;
if (stat(args_[0].c_str(), &sb) == -1) {
flags_ |= SVC_DISABLED;
return ErrnoError() << "Cannot find '" << args_[0] << "'";
}
···
pid_t pid = -1;
if (namespace_flags_) {
pid = clone(nullptr, nullptr, namespace_flags_ | SIGCHLD, nullptr);
} else {
pid = fork();
}
if (pid == 0) {
umask(077);
···
if (!ExpandArgsAndExecv(args_)) {
PLOG(ERROR) << "cannot execve('" << args_[0] << "')";
}
_exit(127);
}
···
return Success();
}
第一個(gè)if處判斷Service是否已經(jīng)運(yùn)行桶蛔,如果運(yùn)行則不再啟動(dòng)
如果上面程序一直都沒有啟動(dòng)子進(jìn)程,末尾處pid = fork()時(shí)就會(huì)創(chuàng)建子進(jìn)程并返回pid值漫谷,如果pid值為0仔雷,說明當(dāng)前代碼邏輯在子進(jìn)程運(yùn)行
最后一個(gè)if處,調(diào)用ExpandArgsExecv函數(shù),為真時(shí)則啟動(dòng)子進(jìn)程碟婆,并進(jìn)入該Service的main函數(shù)电抚,如果該Service是Zygote,上文我們知道Zygote的執(zhí)行路徑為 /system/bin/app_process64竖共,對(duì)應(yīng)的文件為app_main.cpp蝙叛,這樣就會(huì)進(jìn)入app_main.cpp的main函數(shù),也就是Zygote的main函數(shù)公给,如下
app_main
int main(int argc, char* const argv[])
{
···
if (zygote){
runtime.start("com.android.internal.os.ZygoteInit", args, zygote);
} else if (className) {
runtime.start("com.android.internal.os.RuntimeInit", args, zygote);
} else {
fprintf(stderr, "Error: no class name or --zygote supplied.\n");
app_usage();
LOG_ALWAYS_FATAL("app_process: no class name or --zygote supplied.");
}
}
可以看到runtime的start函數(shù)啟動(dòng)Zygote甥温,由此,Zygote正式啟動(dòng)
1.6 屬性服務(wù)
Windows的注冊(cè)表管理器中采用鍵值對(duì)形式記錄用戶軟件的一些信息妓布,即使系統(tǒng)重啟姻蚓,也可以根據(jù)記錄進(jìn)行初始化。Android的屬性服務(wù)即是類似的機(jī)制
init進(jìn)程啟動(dòng)時(shí)會(huì)啟動(dòng)屬性服務(wù)匣沼,并為其分配內(nèi)存狰挡,用來存儲(chǔ)屬性,需要時(shí)則直接讀取释涛。在上文中我們提到init.cpp的main函數(shù)中與屬性服務(wù)相關(guān)的代碼如下
init的main
property_init();
start_property_service();
用于初始化屬性服務(wù)和啟動(dòng)屬性服務(wù)加叁,首先我們來看屬性服務(wù)配置的初始化和啟動(dòng)
屬性服務(wù)配置的初始化和啟動(dòng)
property_init函數(shù)的具體實(shí)現(xiàn)如下,在property_service.cpp文件中
property_service的property_init
void property_init() {
mkdir("/dev/__properties__", S_IRWXU | S_IXGRP | S_IXOTH);
CreateSerializedPropertyInfo();
if (__system_property_area_init()) {
LOG(FATAL) << "Failed to initialize property area";
}
if (!property_info_area.LoadDefaultPath()) {
LOG(FATAL) << "Failed to load serialized property info file";
}
}
__system_property_area_init用來初始化屬性內(nèi)存區(qū)域唇撬,接下來查看start_property_service函數(shù)的具體代碼
property_service的start_property_service
void start_property_service() {
selinux_callback cb;
cb.func_audit = SelinuxAuditCallback;
selinux_set_callback(SELINUX_CB_AUDIT, cb);
property_set("ro.property_service.version", "2");
property_set_fd = CreateSocket(PROP_SERVICE_NAME, SOCK_STREAM | SOCK_CLOEXEC | SOCK_NONBLOCK,
false, 0666, 0, 0, nullptr);
if (property_set_fd == -1) {
PLOG(FATAL) << "start_property_service socket creation failed";
}
listen(property_set_fd, 8);
register_epoll_handler(property_set_fd, handle_property_set_fd);
}
CreateSocket函數(shù)創(chuàng)建了非阻塞的Socket它匕,下面調(diào)用listen方法對(duì)參數(shù)property_set_fd進(jìn)行監(jiān)聽,這樣Socket就成為server窖认,也就是屬性服務(wù)
listen方法的第二個(gè)參數(shù)8意味著屬性服務(wù)最多可以同時(shí)為8個(gè)試圖設(shè)置屬性服務(wù)的用戶提供服務(wù)
最后一行用epoll監(jiān)聽property_set_fd豫柬,當(dāng)有數(shù)據(jù)到來時(shí),init進(jìn)程將調(diào)用handle_property_set_fd來進(jìn)行處理
在Linux新內(nèi)核中扑浸,epoll用來替換select烧给,是為了處理大量文件描述符而做了改進(jìn)的poll,底層為紅黑樹喝噪,查找效率高础嫡,顯著增強(qiáng)CPU利用率,只有當(dāng)少量數(shù)據(jù)時(shí)酝惧,epoll效率才和select差不多
服務(wù)處理客戶端請(qǐng)求
上面我們了解了榴鼎,屬性服務(wù)接收到客戶端請(qǐng)求時(shí),會(huì)調(diào)用handle_property_set_fd函數(shù)進(jìn)行處理
property_service的handle_property_set_fd
static void handle_property_set_fd() {
···
switch (cmd) {
case PROP_MSG_SETPROP: {
char prop_name[PROP_NAME_MAX];
char prop_value[PROP_VALUE_MAX];
if (!socket.RecvChars(prop_name, PROP_NAME_MAX, &timeout_ms) ||
!socket.RecvChars(prop_value, PROP_VALUE_MAX, &timeout_ms)) {
PLOG(ERROR) << "sys_prop(PROP_MSG_SETPROP): error while reading name/value from the socket";
return;
}
prop_name[PROP_NAME_MAX-1] = 0;
prop_value[PROP_VALUE_MAX-1] = 0;
const auto& cr = socket.cred();
std::string error;
uint32_t result =
HandlePropertySet(prop_name, prop_value, socket.source_context(), cr, &error);
if (result != PROP_SUCCESS) {
LOG(ERROR) << "Unable to set property '" << prop_name << "' to '" << prop_value
<< "' from uid:" << cr.uid << " gid:" << cr.gid << " pid:" << cr.pid << ": "
<< error;
}
break;
}
···
最后一個(gè)if處的上一句晚唇,HandlePropertySet函數(shù)做了封裝巫财,如下
property_service的HandlePropertySet
uint32_t HandlePropertySet(const std::string& name, const std::string& value,
const std::string& source_context, const ucred& cr, std::string* error) {
···
if (StartsWith(name, "ctl.")) {
if (!CheckControlPropertyPerms(name, value, source_context, cr)) {
*error = StringPrintf("Invalid permissions to perform '%s' on '%s'", name.c_str() + 4,
value.c_str());
return PROP_ERROR_HANDLE_CONTROL_MESSAGE;
}
HandleControlMessage(name.c_str() + 4, value, cr.pid);
return PROP_SUCCESS;
}
const char* target_context = nullptr;
const char* type = nullptr;
property_info_area->GetPropertyInfo(name.c_str(), &target_context, &type);
if (!CheckMacPerms(name, target_context, source_context.c_str(), cr)) {
*error = "SELinux permission check failed";
return PROP_ERROR_PERMISSION_DENIED;
}
if (type == nullptr || !CheckType(type, value)) {
*error = StringPrintf("Property type check failed, value doesn't match expected type '%s'",
(type ?: "(null)"));
return PROP_ERROR_INVALID_VALUE;
}
···
if (name == "selinux.restorecon_recursive") {
return PropertySetAsync(name, value, RestoreconRecursiveAsync, error);
}
return PropertySet(name, value, error);
}
系統(tǒng)屬性分為控制屬性和普通屬性∪绷粒控制屬性用來執(zhí)行一些命令翁涤,比如開機(jī)動(dòng)畫。上面代碼第1個(gè)if和第2個(gè)if處萌踱,檢查是否以ctl.開頭葵礼,說明是控制屬性,緊接著HandleControlMessage設(shè)置控制屬性
第3個(gè)if處檢查是否是普通屬性并鸵,是的話最后會(huì)調(diào)用PropertySet函數(shù)對(duì)普通屬性進(jìn)行修改鸳粉。這里分析如何修改普通屬性
property_service的PropertySet
static uint32_t PropertySet(const std::string& name, const std::string& value, std::string* error) {
size_t valuelen = value.size();
if (!IsLegalPropertyName(name)) {
*error = "Illegal property name";
return PROP_ERROR_INVALID_NAME;
}
···
prop_info* pi = (prop_info*) __system_property_find(name.c_str());
if (pi != nullptr) {
// ro.* properties are actually "write-once".
if (StartsWith(name, "ro.")) {
*error = "Read-only property was already set";
return PROP_ERROR_READ_ONLY_PROPERTY;
}
__system_property_update(pi, value.c_str(), valuelen);
} else {
int rc = __system_property_add(name.c_str(), name.size(), value.c_str(), valuelen);
if (rc < 0) {
*error = "__system_property_add failed";
return PROP_ERROR_SET_FAILED;
}
}
// Don't write properties to disk until after we have read all default
// properties to prevent them from being overwritten by default values.
if (persistent_properties_loaded && StartsWith(name, "persist.")) {
WritePersistentProperty(name, value);
}
property_changed(name, value);
return PROP_SUCCESS;
}
第1個(gè)if處,判斷屬性是否合法园担,下面的(prop_info*) __system_property_find函數(shù)用于從屬性存儲(chǔ)空間查找該屬性
第2個(gè)if處届谈,為真代表屬性存在,以ro.開頭表示只讀不能修改弯汰,直接返回
第3個(gè)if下面__system_property_update()表示如果屬性存在就更新屬性值艰山,緊接著else塊里的邏輯表示如果不存在則添加該屬性
最后一個(gè)if處,是對(duì)以persist.開頭的屬性進(jìn)行了處理
1.7 init進(jìn)程啟動(dòng)總結(jié)
總的來說做了下面三件事
創(chuàng)建和掛載啟動(dòng)所需的文件目錄
初始化和啟動(dòng)屬性服務(wù)
解析init.rc配置文件并啟動(dòng)Zygote進(jìn)程
2. Zygote進(jìn)程啟動(dòng)過程
了解其啟動(dòng)過程咏闪,先了解Zygote是什么
2.1 Zygote概述
Zygote曙搬,亦稱孵化器。DVM鸽嫂、ART纵装、應(yīng)用程序進(jìn)程以及運(yùn)行系統(tǒng)的關(guān)鍵服務(wù)的SystemServer都是他創(chuàng)建的。它通過fork形式創(chuàng)建這些進(jìn)程据某。由于Zygote啟動(dòng)時(shí)會(huì)創(chuàng)建DVM或ART橡娄,因此通過fork創(chuàng)建的應(yīng)用程序進(jìn)程和SystemServer進(jìn)程可以在內(nèi)部獲取一個(gè)DVM或ART的實(shí)例副本
從上文我們知道Zygote是在init進(jìn)程啟動(dòng)時(shí)創(chuàng)建的,原名就是app_process癣籽,在Android.mk中定義挽唉。Zygote進(jìn)程啟動(dòng)后,Linux系統(tǒng)下的pctrl系統(tǒng)會(huì)調(diào)用app_process筷狼,將其名稱替換為Zygote
2.2 Zygote啟動(dòng)腳本
在init.rc文件中采用Import語句來引入Zygote啟動(dòng)腳本橱夭,這些啟動(dòng)腳本都是由Android初始化語言來編寫的:
import /init.${ro.zygote}.rc
所以init.rc并不會(huì)直接引入一個(gè)固定文件,而是根據(jù)ro.zygote的內(nèi)容來引入不同文件的桑逝。由32位和64位程序的不同棘劣,ro.zygote的屬性取值有以下四種
init.zygote32.rc
init.zygote32_64.rc
init.zygote64.rc
init.zygote64_32.rc
為了更好理解這些啟動(dòng)腳本,我們回顧一下上文提到的Service類型語句的格式
service <name> <pathname> [<argument>]* //<service的名字> <執(zhí)行路徑> <傳遞參數(shù)>
<option>
<option> //是service的修飾詞楞遏,影響何時(shí)茬暇,怎樣啟動(dòng)Service
接下來分別了解這些啟動(dòng)腳本
init.zygote32.rc
只支持32位,內(nèi)容如下
service zygote /system/bin/app_process -Xzygote /system/bin --zygote --start-system-server
class main
priority -20
user root
group root readproc reserved_disk
socket zygote stream 660 root system
onrestart write /sys/android_power/request_state wake
onrestart write /sys/power/state on
onrestart restart audioserver
onrestart restart cameraserver
onrestart restart media
onrestart restart netd
onrestart restart wificond
writepid /dev/cpuset/foreground/tasks
進(jìn)程名稱為zygote寡喝,執(zhí)行程序?yàn)閍pp_process糙俗,classname為main,如果audioserver预鬓、cameraserver巧骚、media等進(jìn)程終止了,就需要進(jìn)行重啟
init.zygote32_64.rc
service zygote /system/bin/app_process32 -Xzygote /system/bin --zygote --start-system-server --socket-name=zygote
class main
priority -20
user root
group root readproc reserved_disk
socket zygote stream 660 root system
onrestart write /sys/android_power/request_state wake
onrestart write /sys/power/state on
onrestart restart audioserver
onrestart restart cameraserver
onrestart restart media
onrestart restart netd
onrestart restart wificond
writepid /dev/cpuset/foreground/tasks
service zygote_secondary /system/bin/app_process64 -Xzygote /system/bin --zygote --socket-name=zygote_secondary
class main
priority -20
user root
group root readproc reserved_disk
socket zygote_secondary stream 660 root system
onrestart restart zygote
writepid /dev/cpuset/foreground/tasks
兩個(gè)Service語句,說明啟動(dòng)兩個(gè)Zygote進(jìn)程劈彪,一個(gè)名為zygote竣蹦,啟動(dòng)程序?yàn)閍pp_process32,作為主模式沧奴。另一個(gè)名稱為zygote_secondary痘括,執(zhí)行程序?yàn)閍pp_process64,作為輔模式
另外64位處理與上面兩種類似滔吠,這里不贅述了
2.3 Zygote進(jìn)程啟動(dòng)過程介紹
由上面可知init啟動(dòng)Zygote時(shí)主要調(diào)用app_main.cpp的main函數(shù)中的runtime的start方法來啟動(dòng)Zygote進(jìn)程的纲菌。時(shí)序圖如下,我們就從app_main.cpp的main函數(shù)開始分析
app_main的main
int main(int argc, char* const argv[])
{
···
while (i < argc) {
const char* arg = argv[i++];
if (strcmp(arg, "--zygote") == 0) {
zygote = true;
niceName = ZYGOTE_NICE_NAME;
} else if (strcmp(arg, "--start-system-server") == 0) {
startSystemServer = true;
} else if (strcmp(arg, "--application") == 0) {
application = true;
} else if (strncmp(arg, "--nice-name=", 12) == 0) {
niceName.setTo(arg + 12);
} else if (strncmp(arg, "--", 2) != 0) {
className.setTo(arg);
break;
} else {
--i;
break;
}
}
···
if (!niceName.isEmpty()) {
runtime.setArgv0(niceName.string(), true /* setProcName */);
}
if (zygote) {
runtime.start("com.android.internal.os.ZygoteInit", args, zygote);
} else if (className) {
runtime.start("com.android.internal.os.RuntimeInit", args, zygote);
} else {
fprintf(stderr, "Error: no class name or --zygote supplied.\n");
app_usage();
LOG_ALWAYS_FATAL("app_process: no class name or --zygote supplied.");
}
}
Zygote進(jìn)程都是通過fork自身來創(chuàng)建子進(jìn)程的疮绷,這樣Zygote進(jìn)程和其子進(jìn)程都可以進(jìn)入app_main.cpp的main函數(shù)翰舌,因此main函數(shù)中為了區(qū)分當(dāng)前運(yùn)行在哪個(gè)進(jìn)程,在第1個(gè)if處判斷參數(shù)是否包含--zygote冬骚,若包含則說明main函數(shù)運(yùn)行在Zygote進(jìn)程中灶芝,將其設(shè)置為true。同理下面都是參數(shù)的判斷唉韭,為真則同樣為它們?cè)O(shè)置參數(shù)
最后一個(gè)if處上文已經(jīng)分析過夜涕,如果為true,就調(diào)用runtime的start函數(shù)属愤,在AndroidRuntime.cpp文件中
AndroidRuntime的start
void AndroidRuntime::start(const char* className, const Vector<String8>& options, bool zygote)
{
···
/* start the virtual machine */
JniInvocation jni_invocation;
jni_invocation.Init(NULL);
JNIEnv* env;
if (startVm(&mJavaVM, &env, zygote, primary_zygote) != 0) {
return;
}
onVmCreated(env);
/*
* Register android functions.
*/
if (startReg(env) < 0) {
ALOGE("Unable to register all android natives\n");
return;
}
/*
* We want to call main() with a String array with arguments in it.
* At present we have two arguments, the class name and an option string.
* Create an array to hold them.
*/
jclass stringClass;
jobjectArray strArray;
jstring classNameStr;
stringClass = env->FindClass("java/lang/String");
assert(stringClass != NULL);
strArray = env->NewObjectArray(options.size() + 1, stringClass, NULL);
assert(strArray != NULL);
classNameStr = env->NewStringUTF(className);
assert(classNameStr != NULL);
env->SetObjectArrayElement(strArray, 0, classNameStr);
for (size_t i = 0; i < options.size(); ++i) {
jstring optionsStr = env->NewStringUTF(options.itemAt(i).string());
assert(optionsStr != NULL);
env->SetObjectArrayElement(strArray, i + 1, optionsStr);
}
/*
* Start VM. This thread becomes the main thread of the VM, and will
* not return until the VM exits.
*/
char* slashClassName = toSlashClassName(className != NULL ? className : "");
jclass startClass = env->FindClass(slashClassName);
if (startClass == NULL) {
ALOGE("JavaVM unable to locate class '%s'\n", slashClassName);
/* keep going */
} else {
jmethodID startMeth = env->GetStaticMethodID(startClass, "main",
"([Ljava/lang/String;)V");
if (startMeth == NULL) {
ALOGE("JavaVM unable to find main() in '%s'\n", className);
/* keep going */
} else {
env->CallStaticVoidMethod(startClass, startMeth, strArray);
#if 0
if (env->ExceptionCheck())
threadExitUncaughtException(env);
#endif
}
}
···
}
可以看到開頭調(diào)用startVm函數(shù)來創(chuàng)建Java虛擬機(jī)女器,第2個(gè)if處的startReg函數(shù)為Java虛擬機(jī)注冊(cè)JNI方法
第1個(gè)for循環(huán)上面的classNameStr的值是com.android.internal.os.ZygoteInit,并緊接著在for循環(huán)下面賦值給slashClassName
之后又以slashClassName為參數(shù)調(diào)用FindClass方法找到ZygoteInit住诸,又在第1個(gè)else塊中找到main方法驾胆。最終會(huì)在第2個(gè)else塊中通過JNI調(diào)用main方法
使用JNI是因?yàn)閆ygoteInit的main方法是用Java寫的,當(dāng)前邏輯在Native中贱呐,需要通過JNI調(diào)用Java丧诺,這樣就從Native進(jìn)入了Java框架層,即Zygote開創(chuàng)了Java框架層奄薇,該main方法如下
ZygoteInit的main
public static void main(String argv[]) {
ZygoteServer zygoteServer = new ZygoteServer();
···
zygoteServer.registerServerSocketFromEnv(socketName);
// In some configurations, we avoid preloading resources and classes eagerly.
// In such cases, we will preload things prior to our first fork.
if (!enableLazyPreload) {
bootTimingsTraceLog.traceBegin("ZygotePreload");
EventLog.writeEvent(LOG_BOOT_PROGRESS_PRELOAD_START,
SystemClock.uptimeMillis());
preload(bootTimingsTraceLog);
EventLog.writeEvent(LOG_BOOT_PROGRESS_PRELOAD_END,
SystemClock.uptimeMillis());
bootTimingsTraceLog.traceEnd(); // ZygotePreload
} else {
Zygote.resetNicePriority();
}
···
if (startSystemServer) {
Runnable r = forkSystemServer(abiList, socketName, zygoteServer);
// {@code r == null} in the parent (zygote) process, and {@code r != null} in the
// child (system_server) process.
if (r != null) {
r.run();
return;
}
}
Log.i(TAG, "Accepting command socket connections");
// The select loop returns early in the child process after a fork and
// loops forever in the zygote.
caller = zygoteServer.runSelectLoop(abiList);
} catch (Throwable ex) {
Log.e(TAG, "System zygote died with exception", ex);
throw ex;
} finally {
zygoteServer.closeServerSocket();
}
// We're in the child process and have exited the select loop. Proceed to execute the
// command.
if (caller != null) {
caller.run();
}
}
開頭處驳阎,zygoteServer調(diào)用registerServerSocketFromEnv創(chuàng)建一個(gè)Server端的Socket
第1個(gè)if處,preload方法預(yù)加載類和資源
第2個(gè)if處馁蒂,forkSystemServer創(chuàng)建SystemServer進(jìn)程镜廉,這樣系統(tǒng)的服務(wù)也會(huì)由SystemServer啟動(dòng)
第1個(gè)catch語句上調(diào)用runSelectLoop方法等待AMS請(qǐng)求創(chuàng)建新的應(yīng)用程序進(jìn)程
由此吧凉,我們可知ZygoteInit的main方法主要做了4件事
創(chuàng)建一個(gè)Server端的Socket
預(yù)加載類資源
啟動(dòng)SystemServer進(jìn)程
等待AMS請(qǐng)求創(chuàng)建新的應(yīng)用程序進(jìn)程
這里我們主要分析第1赞咙,3俱饿,4步
第1步 創(chuàng)建一個(gè)Server端的Socket
看看registerServerSocketFromEnv做了什么
ZygoteServer的registerServerSocketFromEnv
void registerServerSocketFromEnv(String socketName) {
if (mServerSocket == null) {
int fileDesc;
final String fullSocketName = ANDROID_SOCKET_PREFIX + socketName;
try {
String env = System.getenv(fullSocketName);
fileDesc = Integer.parseInt(env);
} catch (RuntimeException ex) {
throw new RuntimeException(fullSocketName + " unset or invalid", ex);
}
try {
FileDescriptor fd = new FileDescriptor();
fd.setInt$(fileDesc);
mServerSocket = new LocalServerSocket(fd);
mCloseSocketFd = true;
} catch (IOException ex) {
throw new RuntimeException(
"Error binding to local socket '" + fileDesc + "'", ex);
}
}
}
開頭處拼接SOCKET名稱,其中ANDROID_SOCKET_PREFIX的值為ANDROID_SOCKET_沮脖,socketName為zygote金矛,因此fullSocketName的值為ANDROID_SOCKET_zygote
第1個(gè)if處芯急,將fullSocketName轉(zhuǎn)為環(huán)境變量值,并緊接著parseInt轉(zhuǎn)換為文件描述符參數(shù)
第2個(gè)try處驶俊,創(chuàng)建文件操作符娶耍,傳入上述文件描述符參數(shù)。緊接著創(chuàng)建LocalServerSocket废睦,也就是服務(wù)端Socket伺绽,將文件操作符作為參數(shù)傳入
在Zygote進(jìn)程將SystemServer進(jìn)程啟動(dòng)后养泡,就會(huì)在這個(gè)服務(wù)器端的Socket上等待AMS請(qǐng)求Zygote進(jìn)程來創(chuàng)建新的應(yīng)用程序進(jìn)程
第3步 啟動(dòng)SystemServer進(jìn)程
看看forkSystemServer做了什么
ZygoteInit的forkSystemServer
private static Runnable forkSystemServer(String abiList, String socketName,
ZygoteServer zygoteServer) {
···
/* Hardcoded command line to start the system server */
String[] args = {
"--setuid=1000",
"--setgid=1000",
"--setgroups=1001,1002,1003,1004,1005,1006,1007,1008,1009,1010,1018,1021,1023,"
+ "1024,1032,1065,3001,3002,3003,3006,3007,3009,3010,3011",
"--capabilities=" + capabilities + "," + capabilities,
"--nice-name=system_server",
"--runtime-args",
"--target-sdk-version=" + VMRuntime.SDK_VERSION_CUR_DEVELOPMENT,
"com.android.server.SystemServer",
};
ZygoteArguments parsedArgs;
int pid;
try {
ZygoteCommandBuffer commandBuffer = new ZygoteCommandBuffer(args);
try {
parsedArgs = ZygoteArguments.getInstance(commandBuffer);
} catch (EOFException e) {
throw new AssertionError("Unexpected argument error for forking system server", e);
}
···
/* Request to fork the system server process */
pid = Zygote.forkSystemServer(
parsedArgs.mUid, parsedArgs.mGid,
parsedArgs.mGids,
parsedArgs.mRuntimeFlags,
null,
parsedArgs.mPermittedCapabilities,
parsedArgs.mEffectiveCapabilities);
} catch (IllegalArgumentException ex) {
throw new RuntimeException(ex);
}
/* For child process */
if (pid == 0) {
if (hasSecondZygote(abiList)) {
waitForSecondaryZygote(socketName);
}
zygoteServer.closeServerSocket();
return handleSystemServerProcess(parsedArgs);
}
return null;
}
最開始有個(gè)args數(shù)組嗜湃,保存啟動(dòng)SystemServer的參數(shù)
第2個(gè)try處,用parsedArgs將args數(shù)組封裝并供給下面的Zygote調(diào)用forkSystemServer方法澜掩,其內(nèi)部最終會(huì)通過fork函數(shù)在當(dāng)前進(jìn)程里創(chuàng)建一個(gè)子進(jìn)程购披,也就是SystemServer進(jìn)程
如果其返回的pid為0,則代表當(dāng)前代碼運(yùn)行在新創(chuàng)建的子進(jìn)程中肩榕,通過return的handleSystemServerProcess來處理SystemServer進(jìn)程
第4步 等待AMS請(qǐng)求創(chuàng)建新的應(yīng)用程序進(jìn)程
ZygoteServer的runSelectLoop
啟動(dòng)SystemServer進(jìn)程后刚陡,會(huì)執(zhí)行runSelectLoop方法,如下
Runnable runSelectLoop(String abiList) {
ArrayList<FileDescriptor> fds = new ArrayList<FileDescriptor>();
ArrayList<ZygoteConnection> peers = new ArrayList<ZygoteConnection>();
fds.add(mServerSocket.getFileDescriptor());
peers.add(null);
while (true) {
StructPollfd[] pollFds = new StructPollfd[fds.size()];
for (int i = 0; i < pollFds.length; ++i) {
pollFds[i] = new StructPollfd();
pollFds[i].fd = fds.get(i);
pollFds[i].events = (short) POLLIN;
}
try {
Os.poll(pollFds, -1);
} catch (ErrnoException ex) {
throw new RuntimeException("poll failed", ex);
}
for (int i = pollFds.length - 1; i >= 0; --i) {
if ((pollFds[i].revents & POLLIN) == 0) {
continue;
}
if (i == 0) {
ZygoteConnection newPeer = acceptCommandPeer(abiList);
peers.add(newPeer);
fds.add(newPeer.getFileDesciptor());
} else {
try {
ZygoteConnection connection = peers.get(i);
final Runnable command = connection.processOneCommand(this);
if (mIsForkChild) {
// We're in the child. We should always have a command to run at this
// stage if processOneCommand hasn't called "exec".
if (command == null) {
throw new IllegalStateException("command == null");
}
return command;
} else {
// We're in the server - we should never have any commands to run.
if (command != null) {
throw new IllegalStateException("command != null");
}
// We don't know whether the remote side of the socket was closed or
// not until we attempt to read from it from processOneCommand. This shows up as
// a regular POLLIN event in our regular processing loop.
if (connection.isClosedByPeer()) {
connection.closeSocket();
peers.remove(i);
fds.remove(i);
}
}
} catch (Exception e) {
if (!mIsForkChild) {
// We're in the server so any exception here is one that has taken place
// pre-fork while processing commands or reading / writing from the
// control socket. Make a loud noise about any such exceptions so that
// we know exactly what failed and why.
Slog.e(TAG, "Exception executing zygote command: ", e);
// Make sure the socket is closed so that the other end knows immediately
// that something has gone wrong and doesn't time out waiting for a
// response.
ZygoteConnection conn = peers.remove(i);
conn.closeSocket();
fds.remove(i);
} else {
// We're in the child so any exception caught here has happened post
// fork and before we execute ActivityThread.main (or any other main()
// method). Log the details of the exception and bring down the process.
Log.e(TAG, "Caught post-fork exception in child process.", e);
throw e;
}
} finally {
// Reset the child flag, in the event that the child process is a child-
// zygote. The flag will not be consulted this loop pass after the Runnable
// is returned.
mIsForkChild = false;
}
}
}
}
}
開頭創(chuàng)建了兩個(gè)集合株汉,緊接著添加進(jìn)一個(gè)mServerSocket筐乳,就是我們上面第一步創(chuàng)建的服務(wù)端Socket,進(jìn)入while循環(huán)無限等待AMS的請(qǐng)求
第1個(gè)for循環(huán)處乔妈,通過遍歷fds存儲(chǔ)的信息轉(zhuǎn)移到pollFds數(shù)組中
第2個(gè)for循環(huán)處蝙云,又遍歷pollFds數(shù)組,如果i為0路召,說明服務(wù)器和Socket鏈接上了勃刨,即AMS與Zygote進(jìn)程建立了鏈接
第2個(gè)for循環(huán)的第2個(gè)if處,通過acceptCommandPeer方法得到ZygoteConnection類并添加到Socket鏈接列表peers中股淡,接著將ZygoteConnection的fd添加到fds列表中身隐,以便接收AMS發(fā)送的請(qǐng)求
如果i不為0,下面則分別進(jìn)行了在子線程或服務(wù)端的異常處理
2.4 Zygote進(jìn)程啟動(dòng)總結(jié)
Zygote進(jìn)程啟動(dòng)共做了如下幾件事
創(chuàng)建AppRuntime并調(diào)用其start方法唯灵,啟動(dòng)Zygote進(jìn)程
創(chuàng)建Java虛擬機(jī)并為Java虛擬機(jī)注冊(cè)JNI方法
通過JNI調(diào)用ZygoteInit的main函數(shù)進(jìn)入Zygote的Java框架層
通過registerZygoteSocket方法創(chuàng)建服務(wù)器端Socket贾铝,并通過runSelectLoop方法等待AMS的請(qǐng)求來創(chuàng)建新的應(yīng)用程序進(jìn)程
啟動(dòng)SystemServer進(jìn)程
3. SystemServer處理過程
SystemServer進(jìn)程主要用于創(chuàng)建系統(tǒng)服務(wù),我們熟知的AMS埠帕、WMS和PMS都是由它創(chuàng)建的
3.1 Zygote處理SystemServer進(jìn)程
上文講解了Zygote啟動(dòng)SystemServer的進(jìn)程忌傻,接下來學(xué)習(xí)Zygote是如何處理SystemServer進(jìn)程的,先看看時(shí)序圖
上文提到過搞监,在ZygoteInit的forkSystemServer方法中水孩,啟動(dòng)了SystemServer進(jìn)程
ZygoteInit的forkSystemServer
private static Runnable forkSystemServer(String abiList, String socketName,
ZygoteServer zygoteServer) {
···
if (pid == 0) {
if (hasSecondZygote(abiList)) {
waitForSecondaryZygote(socketName);
}
zygoteServer.closeServerSocket();
return handleSystemServerProcess(parsedArgs);
}
return null;
}
SystemServer進(jìn)程復(fù)制了Zygote進(jìn)程的地址空間,因此也會(huì)用到Zygote進(jìn)程創(chuàng)建的Socket琐驴,但是由于Socket對(duì)SystemServer沒有用處俘种,所以需要調(diào)用closeServerSocket關(guān)閉該Socket秤标,緊接著調(diào)用handleSystemServerProcess方法
ZygoteInit的handleSystemServerProcess
private static Runnable handleSystemServerProcess(ZygoteConnection.Arguments parsedArgs) {
···
if (parsedArgs.invokeWith != null) {
···
} else {
ClassLoader cl = null;
if (systemServerClasspath != null) {
cl = createPathClassLoader(systemServerClasspath, parsedArgs.targetSdkVersion);
Thread.currentThread().setContextClassLoader(cl);
}
/*
* Pass the remaining arguments to SystemServer.
*/
return ZygoteInit.zygoteInit(parsedArgs.targetSdkVersion, parsedArgs.remainingArgs, cl);
}
/* should never reach here */
}
在else塊中調(diào)用createPathClassLoader方法創(chuàng)建PathClassLoader,最后返回了zygoteInit方法宙刘,代碼如下
ZygoteInit的zygoteInit
public static final Runnable zygoteInit(int targetSdkVersion, String[] argv, ClassLoader classLoader) {
if (RuntimeInit.DEBUG) {
Slog.d(RuntimeInit.TAG, "RuntimeInit: Starting application from zygote");
}
Trace.traceBegin(Trace.TRACE_TAG_ACTIVITY_MANAGER, "ZygoteInit");
RuntimeInit.redirectLogStreams();
RuntimeInit.commonInit();
ZygoteInit.nativeZygoteInit();
return RuntimeInit.applicationInit(targetSdkVersion, argv, classLoader);
}
return的上一句調(diào)用nativeZygoteInit方法苍姜,用于啟動(dòng)Binder線程池,這樣悬包,SystemServer進(jìn)程就可以使用Binder與其他進(jìn)程進(jìn)行通信
return語句調(diào)用的方法用于進(jìn)入SystemServer的main方法
下面展開介紹這兩部分
啟動(dòng)Binder線程池
nativeZygoteInit是一個(gè)Native方法衙猪,因此我們先了解其對(duì)應(yīng)的JNI文件,即AndroidRuntime.cpp布近,如下
AndroidRuntime的ZygoteInit
int register_com_android_internal_os_ZygoteInit_nativeZygoteInit(JNIEnv* env)
{
const JNINativeMethod methods[] = {
{ "nativeZygoteInit", "()V",
(void*) com_android_internal_os_ZygoteInit_nativeZygoteInit },
};
return jniRegisterNativeMethods(env, "com/android/internal/os/ZygoteInit",
methods, NELEM(methods));
}
通過JNI的gMethods數(shù)組垫释,可以看出nativeZygoteInit方法對(duì)應(yīng)的是JNI文件AndroidRuntime.cpp的com_android_internal_os_ZygoteInit_nativeZygoteInit函數(shù),如下
AndroidRuntime的nativeZygoteInit
static void com_android_internal_os_ZygoteInit_nativeZygoteInit(JNIEnv* env, jobject clazz)
{
gCurRuntime->onZygoteInit();
}
這里gCurRuntime是AndroidRuntime類型的指針撑瞧,具體指向AndroidRuntime的子類AppRuntime棵譬,它在app_main.cpp中定義,我們來看AppRuntime的onZygoteInit方法预伺,如下
app_main的onZygoteInit
virtual void onZygoteInit()
{
sp<ProcessState> proc = ProcessState::self();
ALOGV("App process: starting thread pool.\n");
proc->startThreadPool();
}
startThreadPool用于啟動(dòng)一個(gè)Binder線程池订咸,這樣SystemServer進(jìn)程就可以使用Binder與其他進(jìn)程進(jìn)行通信
所以我們知道ZygoteInit的nativeZygoteInit函數(shù)主要用于啟動(dòng)Binder線程池
進(jìn)入SystemServer的main方法
回到ZygoteInit的zygoteInit函數(shù)的代碼,最后return的是RuntimeInit的
applicationInit函數(shù)酬诀,代碼如下
RuntimeInit的applicationInit
protected static Runnable applicationInit(int targetSdkVersion, long[] disabledCompatChanges,
String[] argv, ClassLoader classLoader) {
// If the application calls System.exit(), terminate the process
// immediately without running any shutdown hooks. It is not possible to
// shutdown an Android application gracefully. Among other things, the
// Android runtime shutdown hooks close the Binder driver, which can cause
// leftover running threads to crash before the process actually exits.
nativeSetExitWithoutCleanup(true);
VMRuntime.getRuntime().setTargetSdkVersion(targetSdkVersion);
VMRuntime.getRuntime().setDisabledCompatChanges(disabledCompatChanges);
final Arguments args = new Arguments(argv);
// The end of of the RuntimeInit event (see #zygoteInit).
Trace.traceEnd(Trace.TRACE_TAG_ACTIVITY_MANAGER);
// Remaining arguments are passed to the start class's static main
return findStaticMain(args.startClass, args.startArgs, classLoader);
}
注釋的大意就是在應(yīng)用程序調(diào)用System.exit()時(shí)應(yīng)立即終止程序脏嚷,不然會(huì)出現(xiàn)問題,最后返回的是findStaticMain函數(shù)瞒御,我們查看一下
RuntimeInit的findStaticMain
protected static Runnable findStaticMain(String className, String[] argv,
ClassLoader classLoader) {
Class<?> cl;
try {
cl = Class.forName(className, true, classLoader);
} catch (ClassNotFoundException ex) {
throw new RuntimeException(
"Missing class when invoking static main " + className,
ex);
}
Method m;
try {
m = cl.getMethod("main", new Class[] { String[].class });
} catch (NoSuchMethodException ex) {
throw new RuntimeException(
"Missing static main on " + className, ex);
} catch (SecurityException ex) {
throw new RuntimeException(
"Problem getting static main on " + className, ex);
}
int modifiers = m.getModifiers();
if (! (Modifier.isStatic(modifiers) && Modifier.isPublic(modifiers))) {
throw new RuntimeException(
"Main method is not public and static on " + className);
}
/*
* This throw gets caught in ZygoteInit.main(), which responds
* by invoking the exception's run() method. This arrangement
* clears up all the stack frames that were required in setting
* up the process.
*/
return new MethodAndArgsCaller(m, argv);
}
第1個(gè)try語句中父叙,反射forName得到的className是com.android.server.SystemServer,返回的cl為SystemServer中的main方法
第2個(gè)try語句中葵腹,cl.getMethod找到的是SystemServer里的main方法高每,賦值給m
最后return處又根據(jù)m調(diào)用MethodAndArgsCaller方法
RuntimeInit的MethodAndArgsCaller
static class MethodAndArgsCaller implements Runnable {
/** method to call */
private final Method mMethod;
/** argument array */
private final String[] mArgs;
public MethodAndArgsCaller(Method method, String[] args) {
mMethod = method;
mArgs = args;
}
public void run() {
try {
mMethod.invoke(null, new Object[] { mArgs });
} catch (IllegalAccessException ex) {
throw new RuntimeException(ex);
} catch (InvocationTargetException ex) {
Throwable cause = ex.getCause();
if (cause instanceof RuntimeException) {
throw (RuntimeException) cause;
} else if (cause instanceof Error) {
throw (Error) cause;
}
throw new RuntimeException(ex);
}
}
}
這里是一個(gè)靜態(tài)內(nèi)部類,構(gòu)造器中的mMethd就是SystemServer的main方法践宴,在run方法中調(diào)用invoke后鲸匿,SystemServer的main方法就會(huì)被動(dòng)態(tài)調(diào)用,SystemServer進(jìn)程就進(jìn)入了SystemServer的main方法
3.2 解析SystemServer進(jìn)程
下面查看SystemServer的main方法
SystemServer的main
public static void main(String[] args) {
new SystemServer().run();
}
跟進(jìn)run方法
SystemServer的run
private void run() {
TimingsTraceAndSlog t = new TimingsTraceAndSlog();
try {
···
Looper.prepareMainLooper();
Looper.getMainLooper().setSlowLogThresholdMs(
SLOW_DISPATCH_THRESHOLD_MS, SLOW_DELIVERY_THRESHOLD_MS);
SystemServiceRegistry.sEnableServiceNotFoundWtf = true;
// Initialize native services.
System.loadLibrary("android_servers");
// Allow heap / perf profiling.
initZygoteChildHeapProfiling();
···
// Create the system service manager.
mSystemServiceManager = new SystemServiceManager(mSystemContext);
mSystemServiceManager.setStartInfo(mRuntimeRestart,
mRuntimeStartElapsedTime, mRuntimeStartUptime);
LocalServices.addService(SystemServiceManager.class, mSystemServiceManager);
// Prepare the thread pool for init tasks that can be parallelized
SystemServerInitThreadPool.start();
// Attach JVMTI agent if this is a debuggable build and the system property is set.
···
} finally {
t.traceEnd(); // InitBeforeStartServices
}
// Setup the default WTF handler
RuntimeInit.setDefaultApplicationWtfHandler(SystemServer::handleEarlySystemWtf);
// Start services.
try {
t.traceBegin("StartServices");
startBootstrapServices(t);
startCoreServices(t);
startOtherServices(t);
} catch (Throwable ex) {
Slog.e("System", "******************************************");
Slog.e("System", "************ Failure starting system services", ex);
throw ex;
} finally {
t.traceEnd(); // StartServices
}
···
// Loop forever.
Looper.loop();
throw new RuntimeException("Main thread loop unexpectedly exited");
}
開頭調(diào)用prepareMainLooper創(chuàng)建Looper阻肩,緊接著loadLibary加載動(dòng)態(tài)庫libandroid_service.so
下面創(chuàng)建的SystemServiceManager會(huì)對(duì)系統(tǒng)服務(wù)進(jìn)行創(chuàng)建带欢、啟動(dòng)和生命周期管理
第2個(gè)try語句中,startBootstrapServices方法用SystemServiceManager啟動(dòng)了ActivityManagerService烤惊,PackageManagerService乔煞、PowerManagerService等服務(wù)
startCoreServices方法中則啟動(dòng)了DropBoxManagerService、BatteryServices柒室、UsageStatsServices和WebViewUpdateServices
startOtherServices方法中則啟動(dòng)了CameraServices渡贾、AlarmManagerServices、VrManagerServices等服務(wù)
上述服務(wù)的父類均為SystemService雄右。由方法名可以看出官方把系統(tǒng)服務(wù)分為了三種類型:引導(dǎo)服務(wù)空骚、核心服務(wù)和其他服務(wù)
這些啟動(dòng)服務(wù)的邏輯是類似的纺讲,這里舉例PowerManagerService,代碼如下
PowerManagerService
mPowerManagerService = mSystemServiceManager.startService(PowerManagerService.class);
可以看出SystemServiceManager的startService方法啟動(dòng)了PowerManagerService囤屹,startService方法如下
public void startService(@NonNull final SystemService service) {
// Register it.
mServices.add(service);
// Start it.
long time = SystemClock.elapsedRealtime();
try {
service.onStart();
} catch (RuntimeException ex) {
throw new RuntimeException("Failed to start service " + service.getClass().getName()
+ ": onStart threw an exception", ex);
}
warnIfTooLong(SystemClock.elapsedRealtime() - time, service, "onStart");
}
開頭處調(diào)用add方法將PowerManagerService添加到mServices中熬甚,完成注冊(cè)工作
try語句中調(diào)用onStart函數(shù)完成啟動(dòng)PowerManagerService
3.3 SystemServer進(jìn)程總結(jié)
SystemServer進(jìn)程創(chuàng)建后,主要做了3件事
啟動(dòng)Binder線程池肋坚,與其他進(jìn)程通信
創(chuàng)建SystemServiceManager乡括,用于對(duì)系統(tǒng)的服務(wù)進(jìn)行創(chuàng)建、啟動(dòng)和生命周期管理
啟動(dòng)各種系統(tǒng)服務(wù)
4. Launcher啟動(dòng)過程
到了最后一步智厌,來學(xué)習(xí)Launcher的啟動(dòng)流程
4.1 Launcher概述
系統(tǒng)啟動(dòng)的最后一步是啟動(dòng)一個(gè)應(yīng)用程序用來顯示系統(tǒng)中已經(jīng)安裝的應(yīng)用诲泌,這個(gè)應(yīng)用程序就叫做Launcher。啟動(dòng)過程中會(huì)請(qǐng)求PackageManagerService返回系統(tǒng)中已經(jīng)安裝應(yīng)用的信息峦剔,并將這些信息封裝成一個(gè)快捷圖標(biāo)列表顯示在系統(tǒng)屏幕上档礁,這樣用戶就可以通過點(diǎn)擊快捷圖標(biāo)來啟動(dòng)相應(yīng)的應(yīng)用程序
所以通俗來說角钩,Launcher就是Android系統(tǒng)的桌面吝沫,它的作用主要有以下兩點(diǎn)
作為Android系統(tǒng)啟動(dòng)器,啟動(dòng)應(yīng)用程序
作為Android系統(tǒng)桌面递礼,用于顯示和管理應(yīng)用程序的快捷圖標(biāo)或者其他桌面組件
4.2 Launcher啟動(dòng)過程介紹
SystemServer啟動(dòng)過程中會(huì)啟動(dòng)PackageManagerService惨险,PackageManagerService啟動(dòng)后會(huì)將系統(tǒng)中的應(yīng)用程序安裝完成。在此之前已經(jīng)啟動(dòng)的AMS會(huì)將Launcher啟動(dòng)起來脊髓,時(shí)序圖如下
啟動(dòng)Launcher的入口為AMS的systemReady方法辫愉,在SystemServer的startOtherServices方法中被調(diào)用
SystemServer的startOtherServices
private void startOtherServices(@NonNull TimingsTraceAndSlog t) {
···
mActivityManagerService.systemReady(() -> {
Slog.i(TAG, "Making services ready");
t.traceBegin("StartActivityManagerReadyPhase");
mSystemServiceManager.startBootPhase(t, SystemService.PHASE_ACTIVITY_MANAGER_READY);
···
下面查看AMS的systemReady方法做了什么
ActivityManagerService的systemReady
public void systemReady(final Runnable goingCallback, TimingsTraceLog traceLog) {
···
mStackSupervisor.resumeFocusedStackTopActivityLocked();
mUserController.sendUserSwitchBroadcasts(-1, currentUserId);
···
}
調(diào)用了ActivityStackSupervisor的resumeFocusedStackTopActivityLocked方法
ActivityStackSupervisor的resumeFocusedStackTopActivityLocked
boolean resumeFocusedStackTopActivityLocked(
ActivityStack targetStack, ActivityRecord target, ActivityOptions targetOptions) {
···
if (r == null || !r.isState(RESUMED)) {
mFocusedStack.resumeTopActivityUncheckedLocked(null, null);
}
···
return false;
}
調(diào)用ActivityStack的resumeTopActivityUncheckedLocked方法,ActivityStack是用來描述堆棧的将硝,方法如下
ActivityStack的resumeTopActivityUncheckedLocked
boolean resumeTopActivityUncheckedLocked(ActivityRecord prev, ActivityOptions options) {
if (mStackSupervisor.inResumeTopActivity) {
// Don't even start recursing.
return false;
}
boolean result = false;
try {
// Protect against recursion.
mStackSupervisor.inResumeTopActivity = true;
result = resumeTopActivityInnerLocked(prev, options);
// When resuming the top activity, it may be necessary to pause the top activity (for
// example, returning to the lock screen. We suppress the normal pause logic in
// {@link #resumeTopActivityUncheckedLocked}, since the top activity is resumed at the
// end. We call the {@link ActivityStackSupervisor#checkReadyForSleepLocked} again here
// to ensure any necessary pause logic occurs. In the case where the Activity will be
// shown regardless of the lock screen, the call to
// {@link ActivityStackSupervisor#checkReadyForSleepLocked} is skipped.
final ActivityRecord next = topRunningActivityLocked(true /* focusableOnly */);
if (next == null || !next.canTurnScreenOn()) {
checkReadyForSleep();
}
} finally {
mStackSupervisor.inResumeTopActivity = false;
}
return result;
}
try語句中把resumeTopActivityInnerLocked方法的值給了result
ActivityStack的resumeTopActivityInnerLocked
private boolean resumeTopActivityInnerLocked(ActivityRecord prev, ActivityOptions options) {
···
return isOnHomeDisplay() &&
mStackSupervisor.resumeHomeStackTask(prev, reason);
}
···
調(diào)用ActivityStackSupervisor的resumeHomeStackTask方法
ActivityStackSupervisor的resumeHomeStackTask
boolean resumeHomeStackTask(ActivityRecord prev, String reason) {
···
if (r != null && !r.finishing) {
moveFocusableActivityStackToFrontLocked(r, myReason);
return resumeFocusedStackTopActivityLocked(mHomeStack, prev, null);
}
return mService.startHomeActivityLocked(mCurrentUser, myReason);
}
調(diào)用了AMS的startHomeActivityLocked方法恭朗,如下
ActivityManagerService的startHomeActivityLocked
boolean startHomeActivityLocked(int userId, String reason) {
if (mFactoryTest == FactoryTest.FACTORY_TEST_LOW_LEVEL
&& mTopAction == null) {
// We are running in factory test mode, but unable to find
// the factory test app, so just sit around displaying the
// error message and don't try to start anything.
return false;
}
Intent intent = getHomeIntent();
ActivityInfo aInfo = resolveActivityInfo(intent, STOCK_PM_FLAGS, userId);
if (aInfo != null) {
intent.setComponent(new ComponentName(aInfo.applicationInfo.packageName, aInfo.name));
// Don't do this if the home app is currently being
// instrumented.
aInfo = new ActivityInfo(aInfo);
aInfo.applicationInfo = getAppInfoForUser(aInfo.applicationInfo, userId);
ProcessRecord app = getProcessRecordLocked(aInfo.processName,
aInfo.applicationInfo.uid, true);
if (app == null || app.instr == null) {
intent.setFlags(intent.getFlags() | FLAG_ACTIVITY_NEW_TASK);
final int resolvedUserId = UserHandle.getUserId(aInfo.applicationInfo.uid);
// For ANR debugging to verify if the user activity is the one that actually
// launched.
final String myReason = reason + ":" + userId + ":" + resolvedUserId;
mActivityStartController.startHomeActivity(intent, aInfo, myReason);
}
} else {
Slog.wtf(TAG, "No home screen found for " + intent, new Throwable());
}
return true;
}
第一個(gè)if處的mFactoryTest代表系統(tǒng)的運(yùn)行模式,系統(tǒng)運(yùn)行模式分為三種:工廠模式依疼、低級(jí)工廠模式痰腮、高級(jí)工廠模式。mTopAction用來描述第一個(gè)被啟動(dòng)Activiy組件的Action律罢,默認(rèn)值為Intent.ACTION_MAIN膀值。因此if的條件含義為當(dāng)mFactoryTest的模式為低級(jí)工廠模式,且mTopAction為空時(shí)误辑,返回false
下面的Intent調(diào)用了getHomeIntent方法沧踏,代碼如下
ActivityManagerService的getHomeIntent
Intent getHomeIntent() {
Intent intent = new Intent(mTopAction, mTopData != null ? Uri.parse(mTopData) : null);
intent.setComponent(mTopComponent);
intent.addFlags(Intent.FLAG_DEBUG_TRIAGED_MISSING);
if (mFactoryTest != FactoryTest.FACTORY_TEST_LOW_LEVEL) {
intent.addCategory(Intent.CATEGORY_HOME);
}
return intent;
}
這里創(chuàng)建intent,并將mTopAction和mTopData傳入巾钉。mTopAction的值為Intent.ACTION_MAIN翘狱,并且如果系統(tǒng)運(yùn)行模式不是低級(jí)工廠模式,則將intent的Category設(shè)置為Intent.CATEGORY_HOME砰苍,最后返回該Intent
回到ActivityManagerService的startHomeActivityLocked方法潦匈,我們假設(shè)系統(tǒng)運(yùn)行模式不是低級(jí)工廠模式踏烙,在第3個(gè)if處判斷符合Action為Intent.ACTION_MAIN、Category為Intent.CATEGORY_HOME的應(yīng)用程序是否已經(jīng)啟動(dòng)历等,如果沒啟動(dòng)則調(diào)用下面的startHomeActivity啟動(dòng)該應(yīng)用程序讨惩。這個(gè)被啟動(dòng)的應(yīng)用程序就是Launcher,不信我們可以查看Launcher的AndroidMenifest文件
Launcher的AndroidManifest
<manifest
xmlns:android="http://schemas.android.com/apk/res/android"
package="com.android.launcher"
android:sharedUserId="android.uid.shared"
android:sharedUserLabel="@string/uid_name">
···
<activity
android:name="Launcher"
android:launchMode="singleTask"
android:clearTaskOnLaunch="true"
android:stateNotNeeded="true"
android:theme="@style/Theme"
android:screenOrientation="nosensor"
android:windowSoftInputMode="stateUnspecified|adjustPan">
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.HOME"/>
<category android:name="android.intent.category.DEFAULT" />
<category android:name="android.intent.category.MONKEY" />
</intent-filter>
</activity>
···
</application>
</manifest>
我們看到<intent-filter>標(biāo)簽里設(shè)置了android.intent.category.HOME屬性寒屯,這樣他就成了主Activity
再次回到上面ActivityManagerService的startHomeActivityLocked荐捻,我們知道如果Launcher未啟動(dòng)則調(diào)用startHomeActivity啟動(dòng)Launcher,代碼如下
ActivityStartController的startHomeActivity
void startHomeActivity(Intent intent, ActivityInfo aInfo, String reason) {
mSupervisor.moveHomeStackTaskToTop(reason);
mLastHomeActivityStartResult = obtainStarter(intent, "startHomeActivity: " + reason)
.setOutActivity(tmpOutRecord)
.setCallingUid(0)
.setActivityInfo(aInfo)
.execute();
···
}
}
這里將Launcher放入HomeStack中寡夹,HomeStack是在ActivityStackSupervisor中定義的用于存儲(chǔ)Launcher的變量处面,接著調(diào)用obtainStarter來啟動(dòng)Launcher,后面的過程與Activity的啟動(dòng)類似菩掏,最后進(jìn)入Launcher的onCreate方法魂角,到這里L(fēng)auncher完成了啟動(dòng)
4.3 Launcher中應(yīng)用圖標(biāo)顯示過程
Launcher啟動(dòng)后會(huì)做很多工作,作為桌面它會(huì)顯示應(yīng)用程序圖標(biāo)智绸,與應(yīng)用程序開發(fā)有所關(guān)聯(lián)野揪,圖標(biāo)作為應(yīng)用程序的入口,我們有必要接著來學(xué)習(xí)
先看Launcher的onCreate方法
Launcher的onCreate
protected void onCreate(Bundle savedInstanceState) {
···
LauncherAppState app = LauncherAppState.getInstance(this);
mOldConfig = new Configuration(getResources().getConfiguration());
mModel = app.setLauncher(this);
initDeviceProfile(app.getInvariantDeviceProfile());
···
if (!mModel.startLoader(currentScreen)) {
if (!internalStateHandled) {
// If we are not binding synchronously, show a fade in animation when
// the first page bind completes.
mDragLayer.getAlphaProperty(ALPHA_INDEX_LAUNCHER_LOAD).setValue(0);
}
}
···
}
開頭處獲取LauncherAppState的實(shí)例瞧栗,并調(diào)用setLauncher傳給mModel斯稳,setLauncher方法如下
LauncherAppState的setLauncher
LauncherModel setLauncher(Launcher launcher) {
getLocalProvider(mContext).setLauncherProviderChangeListener(launcher);
mModel.initialize(launcher);
return mModel;
}
mModel會(huì)調(diào)用initialize方法,如下
LauncherModel的initialize
public void initialize(Callbacks callbacks) {
synchronized (mLock) {
Preconditions.assertUIThread();
mCallbacks = new WeakReference<>(callbacks);
}
}
這里會(huì)將Callbacks迹恐,也就是傳入的Launcher封裝成弱引用
回到Launcher的onCreate方法挣惰,末尾的if語句中調(diào)用了startLoader方法,如下
LauncherModel的startLoader
public boolean startLoader(int synchronousBindPage) {
// Enable queue before starting loader. It will get disabled in Launcher#finishBindingItems
InstallShortcutReceiver.enableInstallQueue(InstallShortcutReceiver.FLAG_LOADER_RUNNING);
synchronized (mLock) {
// Don't bother to start the thread if we know it's not going to do anything
if (mCallbacks != null && mCallbacks.get() != null) {
final Callbacks oldCallbacks = mCallbacks.get();
// Clear any pending bind-runnables from the synchronized load process.
mUiExecutor.execute(oldCallbacks::clearPendingBinds);
// If there is already one running, tell it to stop.
stopLoader();
LoaderResults loaderResults = new LoaderResults(mApp, sBgDataModel,
mBgAllAppsList, synchronousBindPage, mCallbacks);
if (mModelLoaded && !mIsLoaderTaskRunning) {
// Divide the set of loaded items into those that we are binding synchronously,
// and everything else that is to be bound normally (asynchronously).
loaderResults.bindWorkspace();
// For now, continue posting the binding of AllApps as there are other
// issues that arise from that.
loaderResults.bindAllApps();
loaderResults.bindDeepShortcuts();
loaderResults.bindWidgets();
return true;
} else {
startLoaderForResults(loaderResults);
}
}
}
return false;
}
開頭創(chuàng)建了一個(gè)隊(duì)列殴边,接著在同步塊中進(jìn)行操作憎茂,調(diào)用execute方法從同步加載過程中清除所有掛起的綁定可運(yùn)行對(duì)象
第2個(gè)if處,會(huì)根據(jù)當(dāng)前是否已經(jīng)加載過數(shù)據(jù)锤岸,而決定是直接綁定UI竖幔,還是去加載數(shù)據(jù)。如果已經(jīng)加載過數(shù)據(jù)能耻,則調(diào)用bindWorkspace赏枚、bindAllApps、bindDeepShortcuts晓猛、bindWidgets四個(gè)重要方法饿幅,分別加載Workspace(即桌面啟動(dòng)后看到的主界面)、AllApps(即當(dāng)前安裝的所有app)戒职、DeepShortcuts(即長按圖標(biāo)后懸浮的界面)栗恩、Widgets(天氣溫度等小部件)。我們來看看沒有加載過數(shù)據(jù)時(shí)對(duì)應(yīng)的最后一個(gè)else語句里的startLoaderForResults方法做了什么
LauncherModel的startLoaderForResults
public void startLoaderForResults(LoaderResults results) {
synchronized (mLock) {
stopLoader();
mLoaderTask = new LoaderTask(mApp, mBgAllAppsList, sBgDataModel, results);
runOnWorkerThread(mLoaderTask);
}
}
這個(gè)LoaderTask是個(gè)Runnable方法洪燥,我們看看這個(gè)類
LoaderTask的run
public void run() {
···
TraceHelper.beginSection(TAG);
try (LauncherModel.LoaderTransaction transaction = mApp.getModel().beginLoader(this)) {
TraceHelper.partitionSection(TAG, "step 1.1: loading workspace");
loadWorkspace();
verifyNotStopped();
TraceHelper.partitionSection(TAG, "step 1.2: bind workspace workspace");
mResults.bindWorkspace();
// Notify the installer packages of packages with active installs on the first screen.
TraceHelper.partitionSection(TAG, "step 1.3: send first screen broadcast");
sendFirstScreenActiveInstallsBroadcast();
// Take a break
TraceHelper.partitionSection(TAG, "step 1 completed, wait for idle");
waitForIdle();
verifyNotStopped();
// second step
TraceHelper.partitionSection(TAG, "step 2.1: loading all apps");
loadAllApps();
TraceHelper.partitionSection(TAG, "step 2.2: Binding all apps");
verifyNotStopped();
mResults.bindAllApps();
verifyNotStopped();
TraceHelper.partitionSection(TAG, "step 2.3: Update icon cache");
updateIconCache();
// Take a break
TraceHelper.partitionSection(TAG, "step 2 completed, wait for idle");
waitForIdle();
verifyNotStopped();
// third step
TraceHelper.partitionSection(TAG, "step 3.1: loading deep shortcuts");
loadDeepShortcuts();
verifyNotStopped();
TraceHelper.partitionSection(TAG, "step 3.2: bind deep shortcuts");
mResults.bindDeepShortcuts();
// Take a break
TraceHelper.partitionSection(TAG, "step 3 completed, wait for idle");
waitForIdle();
verifyNotStopped();
// fourth step
TraceHelper.partitionSection(TAG, "step 4.1: loading widgets");
mBgDataModel.widgetsModel.update(mApp, null);
verifyNotStopped();
TraceHelper.partitionSection(TAG, "step 4.2: Binding widgets");
mResults.bindWidgets();
transaction.commit();
} catch (CancellationException e) {
// Loader stopped, ignore
TraceHelper.partitionSection(TAG, "Cancelled");
}
TraceHelper.endSection(TAG);
}
我們可以看到每一個(gè)partitionSection方法里都標(biāo)明了步驟磕秤,這里不贅述乳乌,觀察一下還可以發(fā)現(xiàn)步驟和步驟之間基本都有waitForIdle方法和verifyNotStopped方法
waitForIdle方法用于等待上個(gè)步驟的UI線程加載完畢,即上個(gè)步驟UI沒展示前市咆,不進(jìn)行下一步的數(shù)據(jù)準(zhǔn)備
verifyNotStopped用于檢查該加載過程是否已經(jīng)被取消汉操,這意味著這個(gè)加載過程是可以中途取消的
最后調(diào)用commit方法提交,然后endSection結(jié)束
由于我們介紹的是App應(yīng)用圖標(biāo)的顯示蒙兰,所以我們?cè)俅芜M(jìn)入LoaderTask類的loadAllApps方法查看
LoaderTask的loadAllApps
private void loadAllApps() {
final List<UserHandle> profiles = mUserManager.getUserProfiles();
// Clear the list of apps
mBgAllAppsList.clear();
for (UserHandle user : profiles) {
// Query for the set of apps
final List<LauncherActivityInfo> apps = mLauncherApps.getActivityList(null, user);
// Fail if we don't have any apps
// TODO: Fix this. Only fail for the current user.
if (apps == null || apps.isEmpty()) {
return;
}
boolean quietMode = mUserManager.isQuietModeEnabled(user);
// Create the ApplicationInfos
for (int i = 0; i < apps.size(); i++) {
LauncherActivityInfo app = apps.get(i);
// This builds the icon bitmaps.
mBgAllAppsList.add(new AppInfo(app, user, quietMode), app);
}
}
if (FeatureFlags.LAUNCHER3_PROMISE_APPS_IN_ALL_APPS) {
// get all active sessions and add them to the all apps list
for (PackageInstaller.SessionInfo info :
mPackageInstaller.getAllVerifiedSessions()) {
mBgAllAppsList.addPromiseApp(mApp.getContext(),
PackageInstallerCompat.PackageInstallInfo.fromInstallingState(info));
}
}
mBgAllAppsList.added = new ArrayList<>();
}
開頭for循環(huán)查找app集合磷瘤,對(duì)于無app的特殊情況進(jìn)行了處理,接著就是把圖標(biāo)bitmaps放入集合中
最后一個(gè)if就是獲取所有活動(dòng)的會(huì)話放入集合
我們回到上面看看LauncherModel的startLoader中的bindAllApps方法做了什么
LoaderResults的bindAllApps
public void bindAllApps() {
// shallow copy
@SuppressWarnings("unchecked")
final ArrayList<AppInfo> list = (ArrayList<AppInfo>) mBgAllAppsList.data.clone();
Runnable r = new Runnable() {
public void run() {
Callbacks callbacks = mCallbacks.get();
if (callbacks != null) {
callbacks.bindAllApplications(list);
}
}
};
mUiExecutor.execute(r);
}
run方法里如果callbacks不為空則調(diào)用bindAllApplications方法綁定搜变,其中的參數(shù)list就是開始創(chuàng)建的ArrayList采缚,集合的泛型恰好就是AppInfo,和LoaderTask的loadAllApps中的集合泛型一致挠他,我們回顧上文可知callback指向的是Launcher扳抽,我們查看Launcher的bindAllApplications方法
Launcher的bindAllApplications
public void bindAllApplications(ArrayList<AppInfo> apps) {
mAppsView.getAppsStore().setApps(apps);
if (mLauncherCallbacks != null) {
mLauncherCallbacks.bindAllApplications(apps);
}
}
mAppsView是AllAppsContainerView的對(duì)象,調(diào)用了getAppsStore方法殖侵,我們來看看這個(gè)方法做了什么
AllAppsContainerView的getAppsStore
public AllAppsStore getAppsStore() {
return mAllAppsStore;
}
返回了一個(gè)mAllAppsStore對(duì)象贸呢,是AllAppsStore類的實(shí)例,所以上面的setApps方法就在這個(gè)類中愉耙,跟進(jìn)
AllAppsStore的setApps
public void setApps(List<AppInfo> apps) {
mComponentToAppMap.clear();
addOrUpdateApps(apps);
}
點(diǎn)進(jìn)addOrUpdateApps方法
AllAppsStore的addOrUpdateApps
public void addOrUpdateApps(List<AppInfo> apps) {
for (AppInfo app : apps) {
mComponentToAppMap.put(app.toComponentKey(), app);
}
notifyUpdate();
}
最后調(diào)用addOrUpdateApps把包含應(yīng)用信息的列表放入一個(gè)Map中
回到AllAppsContainerView類中贮尉,還有一個(gè)適配器Adpater拌滋,里面還有一個(gè)setup方法朴沿,我們看看這個(gè)方法的內(nèi)容
AllAppsContainerView的setup
void setup(@NonNull View rv, @Nullable ItemInfoMatcher matcher) {
appsList.updateItemFilter(matcher);
recyclerView = (AllAppsRecyclerView) rv;
recyclerView.setEdgeEffectFactory(createEdgeEffectFactory());
recyclerView.setApps(appsList, mUsingTabs);
recyclerView.setLayoutManager(layoutManager);
recyclerView.setAdapter(adapter);
recyclerView.setHasFixedSize(true);
// No animations will occur when changes occur to the items in this RecyclerView.
recyclerView.setItemAnimator(null);
FocusedItemDecorator focusedItemDecorator = new FocusedItemDecorator(recyclerView);
recyclerView.addItemDecoration(focusedItemDecorator);
adapter.setIconFocusListener(focusedItemDecorator.getFocusListener());
applyVerticalFadingEdgeEnabled(verticalFadingEdge);
applyPadding();
}
可以看出其實(shí)我們的界面也是recyclerView,顯示app列表败砂,調(diào)用setApps方法顯示應(yīng)用程序快捷圖標(biāo)的列表就會(huì)顯示在屏幕上
到這里赌渣,Launcher的啟動(dòng)流程就結(jié)束了
5. Android系統(tǒng)啟動(dòng)流程
結(jié)合前面四點(diǎn),簡單總結(jié)流程如下
啟動(dòng)電源以及系統(tǒng)啟動(dòng)
電源按下時(shí)引導(dǎo)芯片代碼從預(yù)定義處開始執(zhí)行昌犹。加載引導(dǎo)程序BootLoader到RAM中坚芜,然后執(zhí)行
引導(dǎo)程序BootLoader
是Android操作系統(tǒng)運(yùn)行前的一個(gè)小程序,主要用于拉起系統(tǒng)OS并運(yùn)行
Linux內(nèi)核啟動(dòng)
此時(shí)設(shè)置緩存斜姥、被保護(hù)存儲(chǔ)器鸿竖、計(jì)劃列表、加載驅(qū)動(dòng)铸敏。內(nèi)核完成系統(tǒng)設(shè)置后首先在系統(tǒng)文件中尋找init.rc文件缚忧,并啟動(dòng)init進(jìn)程
init進(jìn)程啟動(dòng)
主要用于初始化啟動(dòng)屬性服務(wù),也用來啟動(dòng)Zygote進(jìn)程
Zygote進(jìn)程啟動(dòng)
創(chuàng)建Java虛擬機(jī)并為Java虛擬機(jī)注冊(cè)JNI方法杈笔,創(chuàng)建服務(wù)器端Socket闪水,啟動(dòng)SystemServer進(jìn)程
SystemServer進(jìn)程啟動(dòng)
啟動(dòng)Binder線程池和SystemServiceManager,并且啟動(dòng)各種系統(tǒng)服務(wù)
Launcher啟動(dòng)
被SystemServer進(jìn)程啟動(dòng)的AMS會(huì)啟動(dòng)Launcher蒙具,Launcher啟動(dòng)后會(huì)將已經(jīng)安裝的應(yīng)用的快捷圖標(biāo)顯示到桌面
流程圖
歡迎指正球榆。