diff --git a/interfaces/innerkits/include/service_watcher.h b/interfaces/innerkits/include/service_watcher.h index 7364bc37a28aa14150a8770f63892def73122553..4708e829a36fe874f93a28a99c75f9538a89451a 100644 --- a/interfaces/innerkits/include/service_watcher.h +++ b/interfaces/innerkits/include/service_watcher.h @@ -16,6 +16,7 @@ #ifndef SERVICE_WATCH_API_H #define SERVICE_WATCH_API_H +#include #include "init_param.h" #include "service_control.h" @@ -25,7 +26,14 @@ extern "C" { #endif #endif -typedef void (*ServiceStatusChangePtr)(const char *key, ServiceStatus status); +#define INVALID_PID 0 + +typedef struct serviceInfo { + ServiceStatus status; + pid_t pid; +} ServiceInfo; + +typedef void (*ServiceStatusChangePtr)(const char *key, const ServiceInfo *serviceInfo); int ServiceWatchForStatus(const char *serviceName, ServiceStatusChangePtr changeCallback); #ifdef __cplusplus diff --git a/interfaces/innerkits/service_watcher/service_watcher.c b/interfaces/innerkits/service_watcher/service_watcher.c index 7efc5a8bf100df3857918cdb65b8ceafe48f8b3e..58f18a045f1120e7066abf74a82f75d19fa534c5 100644 --- a/interfaces/innerkits/service_watcher/service_watcher.c +++ b/interfaces/innerkits/service_watcher/service_watcher.c @@ -31,9 +31,17 @@ static void ServiceStateChange(const char *key, const char *value, void *context uint32_t v = 0; int ret = StringToUint(value, &v); BEGET_ERROR_CHECK(ret == 0, return, "Failed to get value from %s", value); - ServiceStatus status = (ServiceStatus)v; + + // get pid + char paramName[PARAM_NAME_LEN_MAX] = { 0 }; + ret = snprintf_s(paramName, sizeof(paramName), sizeof(paramName) - 1, "%s.pid", key); + BEGET_ERROR_CHECK(ret != -1, return, "Failed to get format pid ret %d for %s ", ret, key); + + ServiceInfo info = {0}; + info.status = (ServiceStatus)v; + info.pid = (pid_t)GetUintParameter(paramName, INVALID_PID); if (strlen(key) > strlen(STARTUP_SERVICE_CTL)) { - callback(key + strlen(STARTUP_SERVICE_CTL) + 1, status); + callback(key + strlen(STARTUP_SERVICE_CTL) + 1, &info); } else { BEGET_LOGE("Invalid service name %s %s", key, value); } @@ -41,19 +49,23 @@ static void ServiceStateChange(const char *key, const char *value, void *context int ServiceWatchForStatus(const char *serviceName, ServiceStatusChangePtr changeCallback) { - if (serviceName == NULL) { - BEGET_LOGE("Service wait failed, service is null."); - return -1; - } + BEGET_ERROR_CHECK(serviceName != NULL, return EC_INVALID, "Service watch failed, service is null."); + BEGET_ERROR_CHECK(changeCallback != NULL, return EC_INVALID, "Service watch failed, callback is null."); + char paramName[PARAM_NAME_LEN_MAX] = {0}; + BEGET_LOGI("Watcher service %s status", serviceName); if (snprintf_s(paramName, PARAM_NAME_LEN_MAX, PARAM_NAME_LEN_MAX - 1, "%s.%s", STARTUP_SERVICE_CTL, serviceName) == -1) { BEGET_LOGE("Failed snprintf_s err=%d", errno); - return -1; + return EC_SYSTEM_ERR; } - if (SystemWatchParameter(paramName, ServiceStateChange, (void *)changeCallback) != 0) { - BEGET_LOGE("Wait param for %s failed.", paramName); - return -1; + int ret = SystemWatchParameter(paramName, ServiceStateChange, (void *)changeCallback); + if (ret != 0) { + BEGET_LOGE("Failed to watcher service %s ret %d.", serviceName, ret); + if (ret == DAC_RESULT_FORBIDED) { + return SYSPARAM_PERMISSION_DENIED; + } + return EC_SYSTEM_ERR; } return 0; } diff --git a/services/init/init_common_service.c b/services/init/init_common_service.c index 9c7da05d937627243c25be1ea51665f93a7341a2..79aae2a2daac5f57beca414ac037ae5ffeddc923 100644 --- a/services/init/init_common_service.c +++ b/services/init/init_common_service.c @@ -414,6 +414,7 @@ int ServiceStart(Service *service) int ServiceStop(Service *service) { INIT_ERROR_CHECK(service != NULL, return SERVICE_FAILURE, "stop service failed! null ptr."); + NotifyServiceChange(service, SERVICE_STOPPING); if (service->serviceJobs.jobsName[JOB_ON_STOP] != NULL) { DoJobNow(service->serviceJobs.jobsName[JOB_ON_STOP]); } @@ -435,7 +436,6 @@ int ServiceStop(Service *service) } INIT_ERROR_CHECK(kill(service->pid, GetKillServiceSig(service->name)) == 0, return SERVICE_FAILURE, "stop service %s pid %d failed! err %d.", service->name, service->pid, errno); - NotifyServiceChange(service, SERVICE_STOPPING); INIT_LOGI("stop service %s, pid %d.", service->name, service->pid); service->pid = -1; NotifyServiceChange(service, SERVICE_STOPPED); diff --git a/services/init/standard/init_service.c b/services/init/standard/init_service.c index f164454b16f3427619677b5b877b78ced6a20e7a..2747bf6fe4258ed3db05ea29a27e62d13bfa7221 100644 --- a/services/init/standard/init_service.c +++ b/services/init/standard/init_service.c @@ -46,11 +46,20 @@ void NotifyServiceChange(Service *service, int status) char paramName[PARAM_NAME_LEN_MAX] = { 0 }; int ret = snprintf_s(paramName, sizeof(paramName), sizeof(paramName) - 1, "%s.%s", STARTUP_SERVICE_CTL, service->name); + INIT_ERROR_CHECK(ret > 0, return, "Failed to format service name %s.", service->name); char statusStr[MAX_INT_LEN] = {0}; - int ret1 = snprintf_s(statusStr, sizeof(statusStr), sizeof(statusStr) - 1, "%d", status); - if (ret >= 0 && ret1 > 0) { - SystemWriteParam(paramName, statusStr); - } + ret = snprintf_s(statusStr, sizeof(statusStr), sizeof(statusStr) - 1, "%d", status); + INIT_ERROR_CHECK(ret > 0, return, "Failed to format service status %s.", service->name); + SystemWriteParam(paramName, statusStr); + + // write pid + ret = snprintf_s(paramName, sizeof(paramName), sizeof(paramName) - 1, + "%s.%s.pid", STARTUP_SERVICE_CTL, service->name); + INIT_ERROR_CHECK(ret > 0, return, "Failed to format service pid name %s.", service->name); + ret = snprintf_s(statusStr, sizeof(statusStr), sizeof(statusStr) - 1, + "%u", (service->pid == -1) ? 0 : service->pid); + INIT_ERROR_CHECK(ret > 0, return, "Failed to format service pid %s.", service->name); + SystemWriteParam(paramName, statusStr); } int IsForbidden(const char *fieldStr) diff --git a/services/param/base/param_comm.c b/services/param/base/param_comm.c index c0ae772dfef8dc0e3cb98a6d393b80184096b741..2afae99da50eae66c84e2b0775ac8c2939363799 100644 --- a/services/param/base/param_comm.c +++ b/services/param/base/param_comm.c @@ -35,6 +35,8 @@ INIT_LOCAL_API WorkSpace *GetWorkSpace(uint32_t labelIndex) { ParamWorkSpace *paramSpace = GetParamWorkSpace(); PARAM_CHECK(paramSpace != NULL, return NULL, "Invalid paramSpace"); + PARAM_CHECK(paramSpace->workSpace != NULL, return NULL, "Invalid paramSpace->workSpace"); + PARAM_WORKSPACE_CHECK(paramSpace, return NULL, "Invalid space"); #ifdef PARAM_SUPPORT_SELINUX if (labelIndex == 0) { return paramSpace->workSpace[0]; diff --git a/test/fuzztest/ServiceWatchForStatus_fuzzer/ServiceWatchForStatus_fuzzer.cpp b/test/fuzztest/ServiceWatchForStatus_fuzzer/ServiceWatchForStatus_fuzzer.cpp index 275357ed98c38e359f3f12d885df87a07b6931e6..d92113369170fd3f3afdd5cfaaa97ebd70d087ea 100644 --- a/test/fuzztest/ServiceWatchForStatus_fuzzer/ServiceWatchForStatus_fuzzer.cpp +++ b/test/fuzztest/ServiceWatchForStatus_fuzzer/ServiceWatchForStatus_fuzzer.cpp @@ -18,9 +18,9 @@ #include "service_watcher.h" #include "fuzz_utils.h" -void callback(const char *key, ServiceStatus status) +void callback(const char *key, const ServiceInfo *status) { - printf("key is: %s, ServiceStatus is: %d\n", key, status); + printf("key is: %s, ServiceStatus is: %d\n", key, status->status); } namespace OHOS { diff --git a/test/moduletest/param_test_cmds.c b/test/moduletest/param_test_cmds.c index 9acfd52994e1b03f8859236369cd497211a62925..9c6f7a789ce834f35de68ec099cc0110e7a7c336 100644 --- a/test/moduletest/param_test_cmds.c +++ b/test/moduletest/param_test_cmds.c @@ -246,10 +246,10 @@ static int32_t BShellParamCmdDisplay(BShellHandle shell, int32_t argc, char *arg return 0; } -void ServiceStatusChangeTest(const char *key, ServiceStatus status) +void ServiceStatusChangeTest(const char *key, const ServiceInfo *status) { - PLUGIN_LOGI("group-test-stage3: wait service %s status: %d", key, status); - if (status == SERVICE_READY || status == SERVICE_STARTED) { + PLUGIN_LOGI("group-test-stage3: wait service %s status: %d", key, status->status); + if (status->status == SERVICE_READY || status->status == SERVICE_STARTED) { PLUGIN_LOGI("Service %s start work", key); } } @@ -340,6 +340,33 @@ static int32_t BShellParamCmdMemGet(BShellHandle shell, int32_t argc, char *argv return 0; } +void CmdServiceStatusChange(const char *key, const ServiceInfo *status) +{ + static const char *serviceStatusMap[] = { + "idle", + "starting", + "running", + "ready", + "stopping", + "stopped", + "error", + "suspended", + "freezed", + "disabled", + "critical", + }; + PLUGIN_CHECK(key != NULL && status != NULL, return, "Invalid parameter"); + printf("Service %s status: %s pid %d \n", key, + ((status->status < ARRAY_LENGTH(serviceStatusMap)) ? serviceStatusMap[status->status] : "unknown"), + status->pid); +} + +static int32_t BShellParamCmdWatchService(BShellHandle shell, int32_t argc, char *argv[]) +{ + PLUGIN_CHECK(argc > 1, return -1, "Invalid parameter"); + return ServiceWatchForStatus(argv[1], CmdServiceStatusChange); +} + int32_t BShellCmdRegister(BShellHandle shell, int execMode) { if (execMode == 0) { @@ -354,12 +381,15 @@ int32_t BShellCmdRegister(BShellHandle shell, int execMode) const CmdInfo infos[] = { {"display", BShellParamCmdDisplay, "display system service", "display service", "display service"}, {"read", BShellParamCmdRead, "read system parameter", "read [start | stop]", ""}, - {"watcher", BShellParamCmdWatch, "watcher system parameter", "watcher [name]", ""}, + {"watcher", BShellParamCmdWatch, + "watcher system parameter", "watcher parameter [name]", "watcher parameter"}, {"install", BShellParamCmdInstall, "install plugin", "install [name]", ""}, {"uninstall", BShellParamCmdInstall, "uninstall plugin", "uninstall [name]", ""}, {"group", BShellParamCmdGroupTest, "group test", "group test [stage]", "group test"}, {"display", BShellParamCmdUdidGet, "display udid", "display udid", "display udid"}, {"display", BShellParamCmdMemGet, "display memory pid", "display memory [pid]", "display memory"}, + {"watcher", BShellParamCmdWatchService, + "watcher service status", "watcher service [name]", "watcher service"}, }; for (size_t i = 0; i < sizeof(infos) / sizeof(infos[0]); i++) { BShellEnvRegisterCmd(GetShellHandle(), &infos[i]); diff --git a/test/moduletest/service_watcher_moduleTest.cpp b/test/moduletest/service_watcher_moduleTest.cpp index 2ee0283f9adb98722e0ef72801d25df343b084c4..386ff491f968ff81cb84703fcacfa775dec4b662 100644 --- a/test/moduletest/service_watcher_moduleTest.cpp +++ b/test/moduletest/service_watcher_moduleTest.cpp @@ -16,6 +16,8 @@ #include #include #include + +#include "parameter.h" #include "service_control.h" #include "service_watcher.h" #include "test_utils.h" @@ -31,9 +33,11 @@ public: void TearDown(void) {}; }; -static void ServiceStatusChange(const char *key, ServiceStatus status) +static void ServiceStatusChange(const char *key, const ServiceInfo *status) { - std::cout<<"service Name is: "<status; + std::cout <<", pid is: "<< status->pid << std::endl; } HWTEST_F(ServiceWatcherModuleTest, serviceWatcher_test_001, TestSize.Level0) @@ -65,4 +69,25 @@ HWTEST_F(ServiceWatcherModuleTest, serviceWatcher_test_002, TestSize.Level0) EXPECT_TRUE(status == "stopped"); GTEST_LOG_(INFO) << "serviceWatcher_test_002 end"; } + +HWTEST_F(ServiceWatcherModuleTest, serviceWatcher_test_003, TestSize.Level0) +{ + GTEST_LOG_(INFO) << "serviceWatcher_test_003 start"; + const std::string serviceName = "deviceinfoservice"; + // watcher service status + int ret = ServiceWatchForStatus(serviceName.c_str(), ServiceStatusChange); + EXPECT_EQ(ret, 0); // No matter if service exist or not, ServiceWatchForStatus always success. + // start service + char udid[65] = {}; // 65 udid len + ret = AclGetDevUdid(udid, sizeof(udid)); + EXPECT_EQ(ret, 0); + auto status1 = GetServiceStatus(serviceName); + EXPECT_TRUE(status1 == "running"); + // wait service exit + std::this_thread::sleep_for(std::chrono::seconds(80)); // wait sa died 80s + auto status2 = GetServiceStatus(serviceName); + EXPECT_TRUE(status2 == "stopped"); + + GTEST_LOG_(INFO) << "serviceWatcher_test_003 end"; +} } diff --git a/test/moduletest/syspara_moduleTest.cpp b/test/moduletest/syspara_moduleTest.cpp index e488d90fce94ec176e8268ba8b6159840afb1b18..a99f5a7e3cb4e11d6446d4ebe670ac83a55ec4f7 100644 --- a/test/moduletest/syspara_moduleTest.cpp +++ b/test/moduletest/syspara_moduleTest.cpp @@ -404,4 +404,45 @@ HWTEST_F(SysparaModuleTest, Syspara_GetParameter_test_011, TestSize.Level0) GTEST_LOG_(INFO) << "Syspara_GetParameter_test_011 end"; } + +HWTEST_F(SysparaModuleTest, Syspara_CacheParameter_test_001, TestSize.Level0) +{ + GTEST_LOG_(INFO) << "Syspara_CacheParameter_test_001 start"; + + const char *name = "test.write.1111111.222222"; + CachedHandle cacheHandle = CachedParameterCreate(name, "true"); + EXPECT_NE(cacheHandle, nullptr); + const char *value = CachedParameterGet(cacheHandle); + EXPECT_EQ(strcmp(value, "true"), 0); + int ret = SetParameter(name, "false"); + EXPECT_EQ(ret, 0); + + value = CachedParameterGet(cacheHandle); + EXPECT_EQ(strcmp(value, "false"), 0); + CachedParameterDestroy(cacheHandle); + + GTEST_LOG_(INFO) << "Syspara_CacheParameter_test_001 end"; +} + +HWTEST_F(SysparaModuleTest, Syspara_CacheParameter_test_002, TestSize.Level0) +{ + GTEST_LOG_(INFO) << "Syspara_CacheParameter_test_002 start"; + + const char *name = "test.write.1111111.333333"; + int ret = SetParameter(name, "3333"); + EXPECT_EQ(ret, 0); + CachedHandle cacheHandle3 = CachedParameterCreate(name, "true"); + EXPECT_NE(cacheHandle3, nullptr); + const char *value = CachedParameterGet(cacheHandle3); + EXPECT_EQ(strcmp(value, "3333"), 0); + + ret = SetParameter(name, "2222222"); + EXPECT_EQ(ret, 0); + int valueChange = 0; + value = CachedParameterGetChanged(cacheHandle3, &valueChange); + EXPECT_EQ(strcmp(value, "2222222"), 0); + EXPECT_EQ(valueChange, 1); + CachedParameterDestroy(cacheHandle3); + GTEST_LOG_(INFO) << "Syspara_CacheParameter_test_002 end"; +} } \ No newline at end of file diff --git a/test/unittest/param/watcher_agent_unittest.cpp b/test/unittest/param/watcher_agent_unittest.cpp index d06f2469f37841ed92b3740099cdf7f702372c1f..9a35fa29e9e659df8da1979ac920a5ae35453b51 100644 --- a/test/unittest/param/watcher_agent_unittest.cpp +++ b/test/unittest/param/watcher_agent_unittest.cpp @@ -42,9 +42,9 @@ static void TestParameterChange(const char *key, const char *value, void *contex g_callbackCount++; } -static void TestWatcherCallBack(const char *key, ServiceStatus status) +static void TestWatcherCallBack(const char *key, const ServiceInfo *status) { - printf("TestWatcherCallBack key:%s %d", key, status); + printf("TestWatcherCallBack key:%s %d", key, status->status); } class WatcherAgentUnitTest : public ::testing::Test {