未验证 提交 e6d3a83d 编写于 作者: O openharmony_ci 提交者: Gitee

!1046 开机启动过程投票机制日志分析

Merge pull request !1046 from cheng_jinsong/bootevent
......@@ -17,29 +17,46 @@
#include <string.h>
#include "begetctl.h"
#include "beget_ext.h"
#include "control_fd.h"
#include "securec.h"
#include "init_param.h"
#define DUMP_SERVICE_INFO_CMD_ARGS 2
#define DUMP_SERVICE_BOOTEVENT_CMD_ARGS 3
static int main_cmd(BShellHandle shell, int argc, char **argv)
{
if (argc != DUMP_SERVICE_INFO_CMD_ARGS) {
BShellCmdHelp(shell, argc, argv);
return 0;
}
if (strcmp(argv[0], "dump_service") == 0) {
if (argc == DUMP_SERVICE_INFO_CMD_ARGS) {
printf("dump service info \n");
CmdClientInit(INIT_CONTROL_FD_SOCKET_PATH, ACTION_DUMP, argv[1]);
} else if (argc == DUMP_SERVICE_BOOTEVENT_CMD_ARGS) {
printf("dump service bootevent info \n");
int serviceNameLen = strlen(argv[1]) + strlen(argv[2]) + 2; // 2 is \0 and #
char *serviceBootevent = (char *)calloc(1, serviceNameLen);
BEGET_ERROR_CHECK(sprintf_s(serviceBootevent, serviceNameLen, "%s#%s", argv[1], argv[2]) >= 0,
return 0, "dumpservice arg create failed");
CmdClientInit(INIT_CONTROL_FD_SOCKET_PATH, ACTION_DUMP, serviceBootevent);
free(serviceBootevent);
} else {
BShellCmdHelp(shell, argc, argv);
}
return 0;
}
static int ClearBootEvent(BShellHandle shell, int argc, char **argv)
{
return SystemSetParameter("ohos.servicectrl.clear", "bootevent");
}
MODULE_CONSTRUCTOR(void)
{
const CmdInfo infos[] = {
{"dump_service", main_cmd, "dump one service info by serviceName", "dump_service serviceName", NULL},
{"dump_service", main_cmd, "dump one service bootevent", "dump_service serviceName bootevent", NULL},
{"dump_service", main_cmd, "dump all services info", "dump_service all", NULL},
{"dump_service", main_cmd, "dump all services bootevent", "dump_service all bootevent", NULL},
{"service", ClearBootEvent, "Clear all services bootevent", "service clear bootevent",
"service clear bootevent"},
};
for (size_t i = 0; i < sizeof(infos) / sizeof(infos[0]); i++) {
BShellEnvRegitsterCmd(GetShellHandle(), &infos[i]);
......
......@@ -61,8 +61,8 @@ void ReleaseService(Service *service);
void StartAllServices(int startMode);
void LoadAccessTokenId(void);
Service *AddService(const char *name);
void DumpAllServices(void);
void DumpOneService(const Service *service);
void DumpServiceHookExecute(const char *name, const char *info);
void ProcessControlFd(uint16_t type, const char *serviceCmd, const void *context);
#ifdef __cplusplus
#if __cplusplus
}
......
......@@ -51,122 +51,6 @@ static const int CRITICAL_DEFAULT_CRASH_TIME = 20;
static const int CRITICAL_DEFAULT_CRASH_COUNT = 4;
static const int CRITICAL_CONFIG_ARRAY_LEN = 3;
static void DumpServiceArgs(const char *info, const ServiceArgs *args)
{
printf("\tservice %s count %d \n", info, args->count);
for (int j = 0; j < args->count; j++) {
if (args->argv[j] != NULL) {
printf("\t\tinfo [%d] %s \n", j, args->argv[j]);
}
}
}
static void DumpServiceJobs(const Service *service)
{
printf("\tservice job info \n");
if (service->serviceJobs.jobsName[JOB_ON_BOOT] != NULL) {
printf("\t\tservice boot job %s \n", service->serviceJobs.jobsName[JOB_ON_BOOT]);
}
if (service->serviceJobs.jobsName[JOB_ON_START] != NULL) {
printf("\t\tservice start job %s \n", service->serviceJobs.jobsName[JOB_ON_START]);
}
if (service->serviceJobs.jobsName[JOB_ON_STOP] != NULL) {
printf("\t\tservice stop job %s \n", service->serviceJobs.jobsName[JOB_ON_STOP]);
}
if (service->serviceJobs.jobsName[JOB_ON_RESTART] != NULL) {
printf("\t\tservice restart job %s \n", service->serviceJobs.jobsName[JOB_ON_RESTART]);
}
}
static void DumpServiceSocket(const Service *service)
{
printf("\tservice socket info \n");
ServiceSocket *sockopt = service->socketCfg;
while (sockopt != NULL) {
printf("\t\tsocket name: %s \n", sockopt->name);
printf("\t\tsocket type: %u \n", sockopt->type);
printf("\t\tsocket uid: %u \n", sockopt->uid);
printf("\t\tsocket gid: %u \n", sockopt->gid);
sockopt = sockopt->next;
}
}
#ifndef OHOS_LITE
static void DumpServiceHookExecute(const char *name, const char *info)
{
SERVICE_INFO_CTX context;
context.serviceName = name;
context.reserved = info;
(void)HookMgrExecute(GetBootStageHookMgr(), INIT_SERVICE_DUMP, (void *)(&context), NULL);
}
#endif
void DumpOneService(const Service *service)
{
const InitArgInfo startModeMap[] = {
{"condition", START_MODE_CONDITION},
{"boot", START_MODE_BOOT},
{"normal", START_MODE_NORMAL}
};
const static char *serviceStatusMap[] = {
"created", "starting", "running", "ready",
"stopping", "stopped", "suspended", "freezed", "disabled", "critical"
};
printf("\tservice name: [%s] \n", service->name);
#ifdef WITH_SELINUX
if (service->secon != NULL) {
printf("\tservice secon: [%s] \n", service->secon);
}
#endif
printf("\tservice pid: [%d] \n", service->pid);
printf("\tservice crashCnt: [%d] \n", service->crashCnt);
printf("\tservice attribute: [%u] \n", service->attribute);
printf("\tservice importance: [%d] \n", service->importance);
printf("\tservice startMode: [%s] \n", startModeMap[service->startMode].name);
printf("\tservice status: [%s] \n", serviceStatusMap[service->status]);
printf("\tservice perms uID [%u] \n", service->servPerm.uID);
DumpServiceArgs("path arg", &service->pathArgs);
DumpServiceArgs("writepid file", &service->writePidArgs);
DumpServiceJobs(service);
DumpServiceSocket(service);
printf("\tservice perms groupId %d \n", service->servPerm.gIDCnt);
for (int i = 0; i < service->servPerm.gIDCnt; i++) {
printf("\t\tservice perms groupId %u \n", service->servPerm.gIDArray[i]);
}
printf("\tservice perms capability %u \n", service->servPerm.capsCnt);
for (int i = 0; i < (int)service->servPerm.capsCnt; i++) {
printf("\t\tservice perms capability %u \n", service->servPerm.caps[i]);
}
#ifndef OHOS_LITE
/*
* dump service hooks
*/
DumpServiceHookExecute(service->name, NULL);
#endif
}
void DumpAllServices(void)
{
printf("Ready to dump all services: \n");
printf("total service number: %d \n", g_serviceSpace.serviceCount);
InitGroupNode *node = GetNextGroupNode(NODE_TYPE_SERVICES, NULL);
while (node != NULL) {
if (node->data.service == NULL) {
node = GetNextGroupNode(NODE_TYPE_SERVICES, node);
continue;
}
Service *service = node->data.service;
DumpOneService(service);
node = GetNextGroupNode(NODE_TYPE_SERVICES, node);
}
printf("Dump all services finished \n");
}
static void FreeServiceArg(ServiceArgs *arg)
{
if (arg == NULL) {
......@@ -265,6 +149,12 @@ void ReleaseService(Service *service)
FreeServiceSocket(service->socketCfg);
FreeServiceFile(service->fileCfg);
#ifndef OHOS_LITE
// clear ext data
SERVICE_INFO_CTX ctx = {0};
ctx.serviceName = service->name;
HookMgrExecute(GetBootStageHookMgr(), INIT_SERVICE_CLEAR, (void *)&ctx, NULL);
#endif
g_serviceSpace.serviceCount--;
InitGroupNode *groupNode = GetGroupNode(NODE_TYPE_SERVICES, service->name);
if (groupNode != NULL) {
......
......@@ -24,6 +24,134 @@
#include "init_modulemgr.h"
#include "init_utils.h"
#include "init_log.h"
#include "init_group_manager.h"
#include "hookmgr.h"
#include "bootstage.h"
static void DumpServiceArgs(const char *info, const ServiceArgs *args)
{
printf("\tservice %s count %d \n", info, args->count);
for (int j = 0; j < args->count; j++) {
if (args->argv[j] != NULL) {
printf("\t\tinfo [%d] %s \n", j, args->argv[j]);
}
}
}
static void DumpServiceJobs(const Service *service)
{
printf("\tservice job info \n");
if (service->serviceJobs.jobsName[JOB_ON_BOOT] != NULL) {
printf("\t\tservice boot job %s \n", service->serviceJobs.jobsName[JOB_ON_BOOT]);
}
if (service->serviceJobs.jobsName[JOB_ON_START] != NULL) {
printf("\t\tservice start job %s \n", service->serviceJobs.jobsName[JOB_ON_START]);
}
if (service->serviceJobs.jobsName[JOB_ON_STOP] != NULL) {
printf("\t\tservice stop job %s \n", service->serviceJobs.jobsName[JOB_ON_STOP]);
}
if (service->serviceJobs.jobsName[JOB_ON_RESTART] != NULL) {
printf("\t\tservice restart job %s \n", service->serviceJobs.jobsName[JOB_ON_RESTART]);
}
}
static void DumpServiceSocket(const Service *service)
{
printf("\tservice socket info \n");
ServiceSocket *sockopt = service->socketCfg;
while (sockopt != NULL) {
printf("\t\tsocket name: %s \n", sockopt->name);
printf("\t\tsocket type: %u \n", sockopt->type);
printf("\t\tsocket uid: %u \n", sockopt->uid);
printf("\t\tsocket gid: %u \n", sockopt->gid);
sockopt = sockopt->next;
}
}
void DumpServiceHookExecute(const char *name, const char *info)
{
SERVICE_INFO_CTX context;
context.serviceName = name;
context.reserved = info;
(void)HookMgrExecute(GetBootStageHookMgr(), INIT_SERVICE_DUMP, (void *)(&context), NULL);
}
static void DumpOneService(const Service *service)
{
const InitArgInfo startModeMap[] = {
{"condition", START_MODE_CONDITION},
{"boot", START_MODE_BOOT},
{"normal", START_MODE_NORMAL}
};
const static char *serviceStatusMap[] = {
"created", "starting", "running", "ready",
"stopping", "stopped", "suspended", "freezed", "disabled", "critical"
};
printf("\tservice name: [%s] \n", service->name);
printf("\tservice pid: [%d] \n", service->pid);
printf("\tservice crashCnt: [%d] \n", service->crashCnt);
printf("\tservice attribute: [%u] \n", service->attribute);
printf("\tservice importance: [%d] \n", service->importance);
printf("\tservice startMode: [%s] \n", startModeMap[service->startMode].name);
printf("\tservice status: [%s] \n", serviceStatusMap[service->status]);
printf("\tservice perms uID [%u] \n", service->servPerm.uID);
DumpServiceArgs("path arg", &service->pathArgs);
DumpServiceArgs("writepid file", &service->writePidArgs);
DumpServiceJobs(service);
DumpServiceSocket(service);
printf("\tservice perms groupId %d \n", service->servPerm.gIDCnt);
for (int i = 0; i < service->servPerm.gIDCnt; i++) {
printf("\t\tservice perms groupId %u \n", service->servPerm.gIDArray[i]);
}
printf("\tservice perms capability %u \n", service->servPerm.capsCnt);
for (int i = 0; i < (int)service->servPerm.capsCnt; i++) {
printf("\t\tservice perms capability %u \n", service->servPerm.caps[i]);
}
DumpServiceHookExecute(service->name, NULL);
}
static void PrintBootEventHead(const char *cmd)
{
if (strcmp(cmd, "bootevent") == 0) {
printf("\t%-20.20s\t%-50s\t%-20.20s\t%-20.20s\n",
"service-name", "bootevent-name", "fork", "ready");
}
return;
}
static void DumpAllExtData(const char *cmd)
{
PrintBootEventHead(cmd);
InitGroupNode *node = GetNextGroupNode(NODE_TYPE_SERVICES, NULL);
while (node != NULL) {
if (node->data.service == NULL) {
node = GetNextGroupNode(NODE_TYPE_SERVICES, node);
continue;
}
DumpServiceHookExecute(node->name, cmd);
node = GetNextGroupNode(NODE_TYPE_SERVICES, node);
}
}
static void DumpAllServices(void)
{
printf("Ready to dump all services: \n");
InitGroupNode *node = GetNextGroupNode(NODE_TYPE_SERVICES, NULL);
while (node != NULL) {
if (node->data.service == NULL) {
node = GetNextGroupNode(NODE_TYPE_SERVICES, node);
continue;
}
Service *service = node->data.service;
DumpOneService(service);
node = GetNextGroupNode(NODE_TYPE_SERVICES, node);
}
printf("Dump all services finished \n");
}
static void ProcessSandboxControlFd(uint16_t type, const char *serviceCmd)
{
......@@ -45,12 +173,28 @@ static void ProcessDumpServiceControlFd(uint16_t type, const char *serviceCmd)
if ((type != ACTION_DUMP) || (serviceCmd == NULL)) {
return;
}
Service *service = GetServiceByName(serviceCmd);
char *cmd = strrchr(serviceCmd, '#');
if (cmd != NULL) {
cmd[0] = '\0';
cmd++;
}
if (service == NULL) {
DumpAllServices();
} else {
DumpOneService(service);
if (strcmp(serviceCmd, "all") == 0) {
if (cmd != NULL) {
DumpAllExtData(cmd);
} else {
DumpAllServices();
}
return;
}
Service *service = GetServiceByName(serviceCmd);
if (service != NULL) {
if (cmd != NULL) {
PrintBootEventHead(cmd);
DumpServiceHookExecute(serviceCmd, cmd);
} else {
DumpOneService(service);
}
}
return;
}
......
......@@ -16,9 +16,12 @@ import("//build/ohos.gni")
config("bootevent_static_config") {
include_dirs = [
"//base/startup/init/services/param/linux",
"//base/startup/init/services/init/include",
"//base/startup/init/services/loopevent/include",
"//base/startup/init/services/modules/init_hook",
"//base/startup/init/services/param/include",
"//base/startup/init/services/include/param",
"//third_party/bounds_checking_function/include/",
]
}
......@@ -27,4 +30,12 @@ ohos_source_set("libbootevent_static") {
include_dirs = [ ".." ]
public_configs = [ ":bootevent_static_config" ]
public_configs += [ "//base/startup/init/interfaces/innerkits/init_module_engine:init_module_engine_exported_config" ]
if (build_selinux) {
include_dirs += [
"//third_party/selinux/libselinux/include/",
"//base/security/selinux/interfaces/policycoreutils/include/",
"//base/startup/init/services/include/param",
]
defines = [ "WITH_SELINUX" ]
}
}
......@@ -18,155 +18,213 @@
#include "trigger_manager.h"
#include "init_log.h"
#include "plugin_adapter.h"
#include "init_hook.h"
#include "init_service.h"
#include "bootstage.h"
#include "securec.h"
#define BOOT_EVENT_PARA_PREFIX "bootevent."
#define BOOT_EVENT_PARA_PREFIX_LEN 10
#ifdef BOOTEVENT
#define BOOT_EVENT_TIMESTAMP_MAX_LEN 50
static int bootEventNum = 0;
enum {
BOOTEVENT_FORK,
BOOTEVENT_READY,
BOOTEVENT_MAX
};
typedef struct tagBOOT_EVENT_PARAM_ITEM {
ListNode node;
const char *paramName;
struct timespec timestamp[BOOTEVENT_MAX];
} BOOT_EVENT_PARAM_ITEM;
static ListNode *bootEventList = NULL;
static ListNode bootEventList = {&bootEventList, &bootEventList};
static ListNode *getBootEventParaList(bool autoCreate)
static int BootEventParaListCompareProc(ListNode *node, void *data)
{
if (!autoCreate) {
return bootEventList;
}
if (bootEventList != NULL) {
return bootEventList;
}
// Create list node
bootEventList = (ListNode *)malloc(sizeof(ListNode));
if (bootEventList == NULL) {
return NULL;
BOOT_EVENT_PARAM_ITEM *item = (BOOT_EVENT_PARAM_ITEM *)node;
if (strcmp(item->paramName + BOOT_EVENT_PARA_PREFIX_LEN, (const char *)data) == 0) {
return 0;
}
OH_ListInit(bootEventList);
return bootEventList;
return -1;
}
static void BootEventParaAdd(const char *paramName)
static int AddServiceBootEvent(const char *serviceName, const char *paramName)
{
ListNode *list;
BOOT_EVENT_PARAM_ITEM *item;
if (paramName == NULL) {
return;
}
// Only bootevent. parameters can be added
ServiceExtData *extData = NULL;
ListNode *found = NULL;
if (strncmp(paramName, BOOT_EVENT_PARA_PREFIX, BOOT_EVENT_PARA_PREFIX_LEN) != 0) {
return;
return -1;
}
INIT_LOGI("Add bootevent [%s] ...", paramName);
list = getBootEventParaList(true);
if (list == NULL) {
return;
found = OH_ListFind(&bootEventList, (void *)paramName, BootEventParaListCompareProc);
if (found != NULL) {
return -1;
}
// Create item
item = (BOOT_EVENT_PARAM_ITEM *)malloc(sizeof(BOOT_EVENT_PARAM_ITEM));
if (item == NULL) {
return;
for (int i = HOOK_ID_BOOTEVENT; i < HOOK_ID_BOOTEVENT_MAX; i++) {
extData = AddServiceExtData(serviceName, i, NULL, sizeof(BOOT_EVENT_PARAM_ITEM));
if (extData != NULL) {
break;
}
}
item->paramName = strdup(paramName);
if (item->paramName == NULL) {
free((void *)item);
return;
if (extData == NULL) {
return -1;
}
// Add to list
OH_ListAddTail(list, (ListNode *)item);
}
static int BootEventParaListCompareProc(ListNode *node, void *data)
{
BOOT_EVENT_PARAM_ITEM *item = (BOOT_EVENT_PARAM_ITEM *)node;
if (strcmp(item->paramName, (const char *)data) == 0) {
return 0;
BOOT_EVENT_PARAM_ITEM *item = (BOOT_EVENT_PARAM_ITEM *)extData->data;
OH_ListInit(&item->node);
for (int i = 0; i < BOOTEVENT_MAX; i++) {
item->timestamp[i].tv_nsec = 0;
item->timestamp[i].tv_sec = 0;
}
return -1;
}
static void BootEventParaItemDestroy(BOOT_EVENT_PARAM_ITEM *item)
{
if (item->paramName != NULL) {
free((void *)item->paramName);
item->paramName = strdup(paramName);
if (item->paramName == NULL) {
INIT_LOGI("strdup failed");
return -1;
}
free((void *)item);
OH_ListAddTail(&bootEventList, (ListNode *)&item->node);
return 0;
}
#define BOOT_EVENT_BOOT_COMPLETED "bootevent.boot.completed"
static void BootEventParaFireByName(const char *paramName)
{
ListNode *found;
if (bootEventList == NULL) {
ListNode *found = NULL;
char *bootEventValue = strrchr(paramName, '.');
if (bootEventValue == NULL) {
return;
}
bootEventValue[0] = '\0';
found = OH_ListFind(getBootEventParaList(false), (void *)paramName, BootEventParaListCompareProc);
if (found != NULL) {
// Remove from list
OH_ListRemove(found);
BootEventParaItemDestroy((BOOT_EVENT_PARAM_ITEM *)found);
found = OH_ListFind(&bootEventList, (void *)paramName, BootEventParaListCompareProc);
if (found == NULL) {
return;
}
if (((BOOT_EVENT_PARAM_ITEM *)found)->timestamp[BOOTEVENT_READY].tv_sec != 0) {
return;
}
INIT_CHECK_ONLY_RETURN(clock_gettime(CLOCK_MONOTONIC,
&(((BOOT_EVENT_PARAM_ITEM *)found)->timestamp[BOOTEVENT_READY])) == 0);
bootEventNum--;
// Check if all boot event params are fired
if (OH_ListGetCnt(getBootEventParaList(false)) > 0) {
if (bootEventNum > 0) {
return;
}
// Delete hooks for boot event
free((void *)bootEventList);
bootEventList = NULL;
// All parameters are fired, set boot completed now ...
INIT_LOGI("All bootevents are fired, boot complete now ...");
SystemWriteParam(BOOT_EVENT_BOOT_COMPLETED, "true");
return;
}
#define BOOT_EVENT_FIELD_NAME "bootevents"
#endif
static void ServiceParseBootEventHook(SERVICE_PARSE_CTX *serviceParseCtx)
{
PLUGIN_LOGI("ServiceParseBootEventHook %s", serviceParseCtx->serviceName);
int cnt;
cJSON *bootEvents = cJSON_GetObjectItem(serviceParseCtx->serviceNode, BOOT_EVENT_FIELD_NAME);
// No bootevents in config file
if (bootEvents == NULL) {
return;
}
// Single bootevent in config file
if (!cJSON_IsArray(bootEvents)) {
if (AddServiceBootEvent(serviceParseCtx->serviceName,
cJSON_GetStringValue(bootEvents)) != 0) {
INIT_LOGI("Add service bootevent failed %s", serviceParseCtx->serviceName);
return;
}
bootEventNum++;
return;
}
// Multiple bootevents in config file
cnt = cJSON_GetArraySize(bootEvents);
for (int i = 0; i < cnt; i++) {
cJSON *item = cJSON_GetArrayItem(bootEvents, i);
if (AddServiceBootEvent(serviceParseCtx->serviceName,
cJSON_GetStringValue(item)) != 0) {
INIT_LOGI("Add service bootevent failed %s", serviceParseCtx->serviceName);
return;
}
bootEventNum++;
}
}
static int DoBootEventCmd(int id, const char *name, int argc, const char **argv)
{
PLUGIN_LOGI("DoBootEventCmd argc %d %s", argc, name);
PLUGIN_CHECK(argc >= 1, return -1, "Invalid parameter");
// argv[0] samgr.ready.true
PLUGIN_LOGI("DoBootEventCmd argv %s", argv[0]);
BootEventParaFireByName(argv[0]);
return 0;
}
void ClearServiceBootEventHook(SERVICE_INFO_CTX *serviceCtx)
{
PLUGIN_LOGI("ClearServiceBootEventHook serviceName %s", serviceCtx->serviceName);
}
static int32_t g_executorId = -1;
static int ParamSetBootEventHook(const HOOK_INFO *hookInfo, void *cookie)
{
if (g_executorId == -1) {
g_executorId = AddCmdExecutor("bootevent", DoBootEventCmd);
PLUGIN_LOGI("DoBootEventCmd executorId %d", g_executorId);
}
return 0;
}
static void DumpServiceBootEvent(SERVICE_INFO_CTX *serviceCtx)
{
if (serviceCtx->reserved != NULL && strcmp(serviceCtx->reserved, "bootevent") != 0) {
return;
}
for (int i = HOOK_ID_BOOTEVENT; i < HOOK_ID_BOOTEVENT_MAX; i++) {
ServiceExtData *serviceExtData = GetServiceExtData(serviceCtx->serviceName, i);
if (serviceExtData == NULL) {
return;
}
BOOT_EVENT_PARAM_ITEM *item = (BOOT_EVENT_PARAM_ITEM *)serviceExtData->data;
char booteventForkTimeStamp[BOOT_EVENT_TIMESTAMP_MAX_LEN] = "";
char booteventReadyTimeStamp[BOOT_EVENT_TIMESTAMP_MAX_LEN] = "";
INIT_CHECK_ONLY_RETURN(sprintf_s(booteventForkTimeStamp, BOOT_EVENT_TIMESTAMP_MAX_LEN, "%ld.%ld",
(long)item->timestamp[BOOTEVENT_FORK].tv_sec, (long)item->timestamp[BOOTEVENT_FORK].tv_nsec) >= 0);
INIT_CHECK_ONLY_RETURN(sprintf_s(booteventReadyTimeStamp, BOOT_EVENT_TIMESTAMP_MAX_LEN, "%ld.%ld",
(long)item->timestamp[BOOTEVENT_READY].tv_sec, (long)item->timestamp[BOOTEVENT_READY].tv_nsec) >= 0);
printf("\t%-20.20s\t%-50s\t%-20.20s\t%-20.20s\n", serviceCtx->serviceName, item->paramName,
booteventForkTimeStamp, booteventReadyTimeStamp);
}
return;
}
static void ClearServiceBootEvent(SERVICE_INFO_CTX *serviceCtx)
{
if (serviceCtx->reserved == NULL || strcmp(serviceCtx->reserved, "bootevent") == 0) {
for (int i = HOOK_ID_BOOTEVENT; i < HOOK_ID_BOOTEVENT_MAX; i++) {
ServiceExtData *extData = GetServiceExtData(serviceCtx->serviceName, i);
if (extData == NULL) {
return;
}
OH_ListRemove(&((BOOT_EVENT_PARAM_ITEM *)extData->data)->node);
DelServiceExtData(serviceCtx->serviceName, i);
}
}
return;
}
static void SetServiceBootEventFork(SERVICE_INFO_CTX *serviceCtx)
{
for (int i = HOOK_ID_BOOTEVENT; i < HOOK_ID_BOOTEVENT_MAX; i++) {
ServiceExtData *extData = GetServiceExtData(serviceCtx->serviceName, i);
if (extData == NULL || ((BOOT_EVENT_PARAM_ITEM *)extData->data)->timestamp[BOOTEVENT_FORK].tv_sec != 0) {
return;
}
INIT_CHECK_ONLY_RETURN(clock_gettime(CLOCK_MONOTONIC,
&(((BOOT_EVENT_PARAM_ITEM *)extData->data)->timestamp[BOOTEVENT_FORK])) == 0);
}
return;
}
MODULE_CONSTRUCTOR(void)
{
EnableInitLog(INIT_DEBUG);
InitAddServiceHook(SetServiceBootEventFork, INIT_SERVICE_FORK_BEFORE);
InitAddServiceHook(ClearServiceBootEvent, INIT_SERVICE_CLEAR);
InitAddServiceHook(DumpServiceBootEvent, INIT_SERVICE_DUMP);
InitAddServiceParseHook(ServiceParseBootEventHook);
InitAddGlobalInitHook(0, ParamSetBootEventHook);
InitAddClearServiceHook(ClearServiceBootEventHook);
}
......@@ -89,7 +89,6 @@ static int ServiceClearHookWrapper(const HOOK_INFO *hookInfo, void *executionCon
SERVICE_INFO_CTX *ctx = (SERVICE_INFO_CTX *)executionContext;
ServiceHook realHook = (ServiceHook)hookInfo->hookCookie;
realHook(ctx);
INIT_LOGI("ServiceClearHookWrapper realHook %p", realHook);
return 0;
};
......@@ -100,7 +99,6 @@ int InitAddClearServiceHook(ServiceHook hook)
info.prio = 0;
info.hook = ServiceClearHookWrapper;
info.hookCookie = (void *)hook;
PLUGIN_LOGI("InitAddClearServiceHook hook %p info.stage %d %p", hook, info.stage, GetBootStageHookMgr());
return HookMgrAddEx(GetBootStageHookMgr(), &info);
}
......
......@@ -41,7 +41,7 @@ const ParamCmdInfo *GetOtherSpecial(size_t *size);
typedef struct {
struct ListNode node;
uint32_t dataId;
uint8_t data[];
uint8_t data[0];
} ServiceExtData;
ServiceExtData *AddServiceExtData(const char *serviceName, uint32_t id, void *data, uint32_t dataLen);
......
......@@ -50,5 +50,7 @@
enum HOOK_ID_ {
HOOKID(BOOTCHART),
HOOKID(SELINUX),
HOOKID(BOOTEVENT),
HOOKID(BOOTEVENT_MAX) = HOOK_ID_BOOTEVENT + 10,
};
#endif
......@@ -64,6 +64,7 @@ ohos_unittest("init_unittest") {
"//base/startup/init/services/init/standard/init.c",
"//base/startup/init/services/init/standard/init_cmdexecutor.c",
"//base/startup/init/services/init/standard/init_cmds.c",
"//base/startup/init/services/init/standard/init_control_fd_service.c",
"//base/startup/init/services/init/standard/init_jobs.c",
"//base/startup/init/services/init/standard/init_mount.c",
"//base/startup/init/services/init/standard/init_reboot.c",
......@@ -81,6 +82,7 @@ ohos_unittest("init_unittest") {
"//base/startup/init/services/loopevent/task/le_watchtask.c",
"//base/startup/init/services/loopevent/timer/le_timer.c",
"//base/startup/init/services/loopevent/utils/le_utils.c",
"//base/startup/init/services/modules/bootevent/bootevent.c",
"//base/startup/init/services/modules/init_hook/init_hook.c",
"//base/startup/init/services/modules/init_hook/param_hook.c",
"//base/startup/init/services/param/adapter/param_dac.c",
......
......@@ -23,6 +23,7 @@
#include "le_timer.h"
#include "param_stub.h"
#include "securec.h"
#include "control_fd.h"
using namespace testing::ext;
using namespace std;
......@@ -299,7 +300,8 @@ HWTEST_F(InitGroupManagerUnitTest, TestAddService2, TestSize.Level1)
ASSERT_NE(nullptr, fileRoot);
ParseAllServices(fileRoot);
cJSON_Delete(fileRoot);
DumpAllServices();
char cmdStr[] = "all#bootevent";
ProcessControlFd(ACTION_DUMP, cmdStr, NULL);
Service *service = GetServiceByName("test-service6");
ASSERT_NE(service, nullptr);
workspace->groupMode = GROUP_BOOT;
......
......@@ -26,6 +26,9 @@
#include "securec.h"
#include "init_group_manager.h"
#include "trigger_manager.h"
#include "bootstage.h"
#include "init_hook.h"
#include "plugin_adapter.h"
using namespace testing::ext;
using namespace std;
......@@ -262,6 +265,36 @@ HWTEST_F(ServiceUnitTest, TestServiceManagerGetService, TestSize.Level1)
ret = ParseOneService(serviceItem, service);
EXPECT_NE(ret, 0);
}
HWTEST_F(ServiceUnitTest, TestServiceBootEventHook, TestSize.Level1)
{
Service *service = nullptr;
const char *jsonStr = "{\"services\":{\"name\":\"test_service8\",\"path\":[\"/data/init_ut/test_service\"],"
"\"importance\":-20,\"uid\":\"system\",\"writepid\":[\"/dev/test_service\"],\"console\":1,"
"\"bootevents\" : [\"bootevent1\", \"bootevent2\"],"
"\"gid\":[\"system\"], \"critical\":[1,2]}}";
cJSON* jobItem = cJSON_Parse(jsonStr);
ASSERT_NE(nullptr, jobItem);
cJSON *serviceItem = cJSON_GetObjectItem(jobItem, "services");
ASSERT_NE(nullptr, serviceItem);
service = AddService("test_service2");
ASSERT_NE(nullptr, service);
int ret = ParseOneService(serviceItem, service);
if (ret < 0) {
return;
}
SERVICE_PARSE_CTX context;
context.serviceName = "test_service2";
context.serviceNode = serviceItem;
(void)HookMgrExecute(GetBootStageHookMgr(), INIT_SERVICE_PARSE, (void *)(&context), NULL);
ASSERT_NE(GetServiceExtData("test_service2", HOOK_ID_BOOTEVENT), nullptr);
SERVICE_INFO_CTX serviceInfoContext;
serviceInfoContext.serviceName = "test_service2";
serviceInfoContext.reserved = nullptr;
(void)HookMgrExecute(GetBootStageHookMgr(), INIT_SERVICE_FORK_BEFORE, (void *)(&serviceInfoContext), NULL);
(void)HookMgrExecute(GetBootStageHookMgr(), INIT_SERVICE_DUMP, (void *)(&serviceInfoContext), NULL);
(void)HookMgrExecute(GetBootStageHookMgr(), INIT_SERVICE_CLEAR, (void *)(&serviceInfoContext), NULL);
}
HWTEST_F(ServiceUnitTest, TestServiceExec, TestSize.Level1)
{
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册