diff --git a/bundle.json b/bundle.json index 281daf0d4c2ad9c16e7385e36715194e17231de1..4801ab70927ad2aeed70a4378cc16f207f7fb0e8 100644 --- a/bundle.json +++ b/bundle.json @@ -27,6 +27,7 @@ "rom": "296KB", "ram": "13125KB", "hisysevent_config": [ + "//base/startup/appspawn/hisysevent.yaml", "//base/startup/appspawn/startup_events.yaml" ], "deps": { diff --git a/hisysevent.yaml b/hisysevent.yaml new file mode 100644 index 0000000000000000000000000000000000000000..10df09ac4c3c8e1f24ba15ab58a54c1045032d8a --- /dev/null +++ b/hisysevent.yaml @@ -0,0 +1,39 @@ +# Copyright (c) 2024 Huawei Device Co., Ltd. +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +domain: APPSPAWN + +SPAWN_CHILD_PROCESS_FAIL: + __BASE: {type: FAULT, level: CRITICAL, desc: Spawn Child Process Fail} + PROCESS_NAME: {type: STRING, desc: Process Name} + ERROR_CODE: {type: INT32, desc: Error Code} + SRC_PATH : {type: STRING, desc: Source Path For Mount Failed} + TARGET_PATH: {type: STRING, desc: Target Path For Mount Failed} + SPAWN_RESULT : {type: INT32, desc: Process Spawn Result} + +SPAWN_KEY_EVENT: + __BASE: {type: BEHAVIOR, level: CRITICAL, desc: Spawn Key Event Finish} + EVENT_NAME: {type: STRING, desc: Event Name} + +SPAWN_PROCESS_DURATION: + __BASE: {type: STATISTIC, level: CRITICAL, desc: Boot Process Duration} + MAXDURATION: {type: INT64, desc: Max Spawn Process Duration} + MINDURATION: {type: INT64, desc: Min Spawn Process Duration} + TOTALDURATION: {type: INT64, desc: Total Spawn Process Duration} + EVENTCOUNT: {type: INT64, desc: Total Spawn Process Count} + STAGE: {type: STRING, desc: Boot Stage Or BootFinished Stage} + +SPAWN_ABNORMAL_DURATION: + __BASE: {type: BEHAVIOR, level: CRITICAL, desc: Scene Duration} + SCENE_NAME: {type: STRING, desc: Scene Name} + DURATION: {type: INT64, desc: Scene Duration} \ No newline at end of file diff --git a/modules/common/BUILD.gn b/modules/common/BUILD.gn index 37655107e465736f5677ccf95dabd0535be7751e..41cb1a3091a677ac3f1d810b6fb75abc1798ce0b 100644 --- a/modules/common/BUILD.gn +++ b/modules/common/BUILD.gn @@ -77,6 +77,12 @@ ohos_shared_library("appspawn_common") { if (defined(appspawn_sandbox_new) && appspawn_sandbox_new) { defines += [ "APPSPAWN_SANDBOX_NEW" ] } + if (appspawn_report_event) { + defines += [ "APPSPAWN_HISYSEVENT" ] + external_deps += [ "hisysevent:libhisysevent" ] + include_dirs += [ "${appspawn_path}/modules/sysevent" ] + sources += [ "${appspawn_path}/modules/sysevent/hisysevent_adapter.cpp" ] + } subsystem_name = "${subsystem_name}" part_name = "${part_name}" diff --git a/modules/sandbox/BUILD.gn b/modules/sandbox/BUILD.gn index 649b3db90ed147ec8f672e0a937cf7043ec38b57..59edc0210165633c0b526b166f840f19fe7fbf94 100644 --- a/modules/sandbox/BUILD.gn +++ b/modules/sandbox/BUILD.gn @@ -102,6 +102,12 @@ if (defined(appspawn_sandbox_new) && appspawn_sandbox_new) { defines += [ "WITH_SELINUX" ] external_deps += [ "selinux_adapter:libhap_restorecon" ] } + if (appspawn_report_event) { + defines += [ "APPSPAWN_HISYSEVENT" ] + external_deps += [ "hisysevent:libhisysevent" ] + include_dirs += [ "${appspawn_path}/modules/sysevent" ] + sources += [ "${appspawn_path}/modules/sysevent/hisysevent_adapter.cpp" ] + } subsystem_name = "${subsystem_name}" part_name = "${part_name}" diff --git a/modules/sandbox/sandbox_utils.cpp b/modules/sandbox/sandbox_utils.cpp index 101bb82084d533cdb067864e692f5b162510be6e..4a91fca22328df6f6ab82b8e1741f208a7765fe2 100644 --- a/modules/sandbox/sandbox_utils.cpp +++ b/modules/sandbox/sandbox_utils.cpp @@ -44,6 +44,9 @@ #include "parameters.h" #include "securec.h" #include "appspawn_trace.h" +#ifdef APPSPAWN_HISYSEVENT +#include "hisysevent_adapter.h" +#endif #ifdef WITH_SELINUX #include "hap_restorecon.h" @@ -216,6 +219,37 @@ static void MakeDirRecursive(const std::string &path, mode_t mode) } while (index < size); } +static void MakeDirRecursiveWithClock(const std::string &path, mode_t mode) +{ + size_t size = path.size(); + if (size == 0) { + return; + } +#ifdef APPSPAWN_HISYSEVENT + struct timespec startClock = {0}; + clock_gettime(CLOCK_MONOTONIC, &startClock); +#endif + size_t index = 0; + do { + size_t pathIndex = path.find_first_of('/', index); + index = pathIndex == std::string::npos ? size : pathIndex + 1; + std::string dir = path.substr(0, index); +#ifndef APPSPAWN_TEST + APPSPAWN_CHECK(!(access(dir.c_str(), F_OK) < 0 && mkdir(dir.c_str(), mode) < 0), + return, "errno is %{public}d, mkdir %{public}s failed", errno, dir.c_str()); +#endif + } while (index < size); + +#ifdef APPSPAWN_HISYSEVENT + struct timespec endClock = {0}; + clock_gettime(CLOCK_MONOTONIC, &endClock); + uint64_t diff = DiffTime(&startClock, &endClock); + + APPSPAWN_CHECK_ONLY_EXPER(diff < FUNC_REPORT_DURATION, + ReportAbnormalDuration("MakeDirRecursive", diff)); +#endif +} + static bool CheckDirRecursive(const std::string &path) { size_t size = path.size(); @@ -279,6 +313,9 @@ int32_t SandboxUtils::DoAppSandboxMountOnce(const char *originPath, const char * clock_gettime(CLOCK_MONOTONIC, &mountEnd); uint64_t diff = DiffTime(&mountStart, &mountEnd); APPSPAWN_CHECK_ONLY_LOG(diff < MAX_MOUNT_TIME, "mount %{public}s time %{public}" PRId64 " us", originPath, diff); +#ifdef APPSPAWN_HISYSEVENT + APPSPAWN_CHECK_ONLY_EXPER(diff < FUNC_REPORT_DURATION, ReportAbnormalDuration("MOUNT", diff)); +#endif if (ret != 0) { APPSPAWN_LOGI("errno is: %{public}d, bind mount %{public}s to %{public}s", errno, originPath, destinationPath); std::string originPathStr = originPath == nullptr ? "" : originPath; @@ -837,6 +874,10 @@ int SandboxUtils::DoAllMntPointsMount(const AppSpawningCtx *appProperty, if (actionStatus == g_statusCheck) { APPSPAWN_LOGE("DoAppSandboxMountOnce section %{public}s failed, %{public}s", section.c_str(), sandboxPath.c_str()); +#ifdef APPSPAWN_HISYSEVENT + ReportMountFail(bundleName.c_str(), srcPath.c_str(), sandboxPath.c_str(), errno); + ret = APPSPAWN_SANDBOX_MOUNT_FAIL; +#endif return ret; } } @@ -1581,9 +1622,19 @@ int32_t SandboxUtils::ChangeCurrentDir(std::string &sandboxPackagePath, const st return ret; } -static inline int EnableSandboxNamespace(AppSpawningCtx *appProperty, uint32_t sandboxNsFlags) +static int EnableSandboxNamespace(AppSpawningCtx *appProperty, uint32_t sandboxNsFlags) { +#ifdef APPSPAWN_HISYSEVENT + struct timespec startClock = {0}; + clock_gettime(CLOCK_MONOTONIC, &startClock); +#endif int rc = unshare(sandboxNsFlags); +#ifdef APPSPAWN_HISYSEVENT + struct timespec endClock = {0}; + clock_gettime(CLOCK_MONOTONIC, &endClock); + uint64_t diff = DiffTime(&startClock, &endClock); + APPSPAWN_CHECK_ONLY_EXPER(diff < FUNC_REPORT_DURATION, ReportAbnormalDuration("unshare", diff)); +#endif APPSPAWN_CHECK(rc == 0, return rc, "unshare failed, packagename is %{public}s", GetBundleName(appProperty)); if ((sandboxNsFlags & CLONE_NEWNET) == CLONE_NEWNET) { @@ -1629,16 +1680,14 @@ int32_t SandboxUtils::SetAppSandboxProperty(AppSpawningCtx *appProperty, uint32_ ACCESS_DLP_FILE_MODE.c_str()))) != 0); sandboxPackagePath += CheckAppMsgFlagsSet(appProperty, APP_FLAGS_ISOLATED_SANDBOX_TYPE) ? "isolated/" : ""; sandboxPackagePath += bundleName; - MakeDirRecursive(sandboxPackagePath.c_str(), FILE_MODE); + MakeDirRecursiveWithClock(sandboxPackagePath.c_str(), FILE_MODE); // add pid to a new mnt namespace int rc = EnableSandboxNamespace(appProperty, sandboxNsFlags); APPSPAWN_CHECK(rc == 0, return rc, "unshare failed, packagename is %{public}s", bundleName.c_str()); - if (SetPermissionWithParam(appProperty) != 0) { APPSPAWN_LOGW("Set app permission flag fail."); } - // check app sandbox switch if ((CheckTotalSandboxSwitchStatus(appProperty) == false) || (CheckAppSandboxSwitchStatus(appProperty) == false)) { @@ -1668,7 +1717,7 @@ int32_t SandboxUtils::SetAppSandboxPropertyNweb(AppSpawningCtx *appProperty, uin const std::string bundleName = GetBundleName(appProperty); bool sandboxSharedStatus = GetSandboxPrivateSharedStatus(bundleName, appProperty); sandboxPackagePath += bundleName; - MakeDirRecursive(sandboxPackagePath.c_str(), FILE_MODE); + MakeDirRecursiveWithClock(sandboxPackagePath.c_str(), FILE_MODE); // add pid to a new mnt namespace int rc = EnableSandboxNamespace(appProperty, sandboxNsFlags); diff --git a/modules/sysevent/hisysevent_adapter.cpp b/modules/sysevent/hisysevent_adapter.cpp new file mode 100644 index 0000000000000000000000000000000000000000..9c9bde95cfee6bbe221c1e1c34603f7ea75afbc7 --- /dev/null +++ b/modules/sysevent/hisysevent_adapter.cpp @@ -0,0 +1,217 @@ +/* + * Copyright (c) 2024 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +#include "hisysevent_adapter.h" +#include "securec.h" +#include "hisysevent.h" +#include "appspawn_utils.h" + +using namespace OHOS::HiviewDFX; +namespace { +// fail event +constexpr const char* SPAWN_CHILD_PROCESS_FAIL = "SPAWN_CHILD_PROCESS_FAIL"; + +// behavior event +constexpr const char* SPAWN_KEY_EVENT = "SPAWN_KEY_EVENT"; +constexpr const char* SPAWN_ABNORMAL_DURATION = "SPAWN_ABNORMAL_DURATION"; + +// statistic event +constexpr const char* SPAWN_PROCESS_DURATION = "SPAWN_PROCESS_DURATION"; + +// param +constexpr const char* PROCESS_NAME = "PROCESS_NAME"; +constexpr const char* ERROR_CODE = "ERROR_CODE"; +constexpr const char* SPAWN_RESULT = "SPAWN_RESULT"; +constexpr const char* SRC_PATH = "SRC_PATH"; +constexpr const char* TARGET_PATH = "TARGET_PATH"; + +constexpr const char* EVENT_NAME = "EVENT_NAME"; + +constexpr const char* SCENE_NAME = "SCENE_NAME"; +constexpr const char* DURATION = "DURATION"; + +constexpr const char* MAXDURATION = "MAXDURATION"; +constexpr const char* MINDURATION = "MINDURATION"; +constexpr const char* TOTALDURATION = "TOTALDURATION"; +constexpr const char* EVENTCOUNT = "EVENTCOUNT"; +constexpr const char* STAGE = "STAGE"; +constexpr const char* BOOTSTAGE = "BOOTSTAGE"; +constexpr const char* BOOTFINISHEDSTAGE = "BOOTFINISHEDSTAGE"; +} + +static void AddStatisticEvent(AppSpawnHisysevent *event, uint32_t duration) +{ + event->eventCount++; + event->totalDuration += duration; + if (duration > event->maxDuration) { + event->maxDuration = duration; + } + if (duration < event->minDuration) { + event->minDuration = duration; + } + APPSPAWN_LOGV("event->maxDuration is: %{public}d, event->minDuration is: %{public}d", + event->maxDuration, event->minDuration); +} + +void AddStatisticEventInfo(AppSpawnHisyseventInfo *hisyseventInfo, uint32_t duration, bool stage) +{ + APPSPAWN_CHECK(hisyseventInfo != NULL, return, "fail to get AppSpawnHisyseventInfo"); + if (stage) { + AddStatisticEvent(&hisyseventInfo->bootEvent, duration); + } else { + AddStatisticEvent(&hisyseventInfo->manualEvent, duration); + } +} + +static void InitStatisticEvent(AppSpawnHisysevent *event) +{ + event->eventCount = 0; + event->maxDuration = 0; + event->minDuration = UINT32_MAX; + event->totalDuration = 0; +} + +static void InitStatisticEventInfo(AppSpawnHisyseventInfo *appSpawnHisysInfo) +{ + InitStatisticEvent(&appSpawnHisysInfo->bootEvent); + InitStatisticEvent(&appSpawnHisysInfo->manualEvent); +} + +static int CreateHisysTimerLoop(AppSpawnHisyseventInfo *hisyseventInfo) +{ + LoopHandle loop = LE_GetDefaultLoop(); + TimerHandle timer = NULL; + int ret = LE_CreateTimer(loop, &timer, ReportSpawnStatisticDuration, (void *)hisyseventInfo); + APPSPAWN_CHECK(ret == 0, return -1, "fail to create HisysTimer, ret is: %{public}d", ret); + // start a timer to report event every 24h + ret = LE_StartTimer(loop, timer, APPSPAWN_HISYSEVENT_REPORT_TIME, INT64_MAX); + APPSPAWN_CHECK(ret == 0, return -1, "fail to start HisysTimer, ret is: %{public}d", ret); + return ret; +} + +AppSpawnHisyseventInfo *GetAppSpawnHisyseventInfo() +{ + AppSpawnHisyseventInfo *hisyseventInfo = + static_cast(malloc(sizeof(AppSpawnHisyseventInfo))); + APPSPAWN_CHECK(hisyseventInfo != NULL, return NULL, "fail to alloc memory for hisyseventInfo"); + int ret = memset_s(hisyseventInfo, sizeof(AppSpawnHisyseventInfo), 0, sizeof(AppSpawnHisyseventInfo)); + if (ret != 0) { + free(hisyseventInfo); + hisyseventInfo = NULL; + APPSPAWN_LOGE("Failed to memset hisyseventInfo"); + return NULL; + } + InitStatisticEventInfo(hisyseventInfo); + return hisyseventInfo; +} + +void DeleteHisyseventInfo(AppSpawnHisyseventInfo *hisyseventInfo) +{ + APPSPAWN_CHECK_ONLY_EXPER(hisyseventInfo != NULL, return); + free(hisyseventInfo); + hisyseventInfo = NULL; +} + +AppSpawnHisyseventInfo *InitHisyseventTimer() +{ + AppSpawnHisyseventInfo *hisyseventInfo = GetAppSpawnHisyseventInfo(); + APPSPAWN_CHECK(hisyseventInfo != NULL, return NULL, "fail to init hisyseventInfo"); + int ret = CreateHisysTimerLoop(hisyseventInfo); + if (ret != 0) { + DeleteHisyseventInfo(hisyseventInfo); + hisyseventInfo = NULL; + APPSPAWN_LOGE("fail to create hisys timer loop, ret: %{public}d", ret); + } + return hisyseventInfo; +} + +void ReportSpawnChildProcessFail(const char* processName, int32_t errorCode, int32_t spawnResult) +{ + if (spawnResult == APPSPAWN_SANDBOX_MOUNT_FAIL) { + return; + } + int ret = HiSysEventWrite(HiSysEvent::Domain::APPSPAWN, SPAWN_CHILD_PROCESS_FAIL, + HiSysEvent::EventType::FAULT, + PROCESS_NAME, processName, + ERROR_CODE, errorCode, + SPAWN_RESULT, spawnResult); + if (ret != 0) { + APPSPAWN_LOGE("ReportSpawnChildProcessFail error, ret: %{public}d", ret); + } +} + +void ReportMountFail(const char* bundleName, const char* srcPath, const char* targetPath, + int32_t spawnResult) +{ + if (srcPath == nullptr || (strstr(srcPath, "data/app/el1/") == nullptr && + strstr(srcPath, "data/app/el2/") == nullptr)) { + return; + } + int ret = HiSysEventWrite(HiSysEvent::Domain::APPSPAWN, SPAWN_CHILD_PROCESS_FAIL, + HiSysEvent::EventType::FAULT, + PROCESS_NAME, bundleName, + ERROR_CODE, ERR_APPSPAWN_CHILD_MOUNT_FAILED, + SRC_PATH, srcPath, + TARGET_PATH, targetPath, + SPAWN_RESULT, spawnResult); + if (ret != 0) { + APPSPAWN_LOGE("ReportMountFail error, ret: %{public}d", ret); + } +} + +void ReportKeyEvent(const char *eventName) +{ + int ret = HiSysEventWrite(HiSysEvent::Domain::APPSPAWN, SPAWN_KEY_EVENT, + HiSysEvent::EventType::BEHAVIOR, + EVENT_NAME, eventName); + if (ret != 0) { + APPSPAWN_LOGE("ReportKeyEvent error, ret: %{public}d", ret); + } +} + +void ReportAbnormalDuration(const char* scene, uint64_t duration) +{ + APPSPAWN_LOGI("ReportAbnormalDuration %{public}d with %{public}s %{public}" PRId64 " us", + getpid(), scene, duration); + int ret = HiSysEventWrite(HiSysEvent::Domain::APPSPAWN, SPAWN_ABNORMAL_DURATION, + HiSysEvent::EventType::BEHAVIOR, + SCENE_NAME, scene, + DURATION, duration); + if (ret != 0) { + APPSPAWN_LOGE("ReportAbnormalDuration error, ret: %{public}d", ret); + } +} + +void ReportSpawnProcessDuration(AppSpawnHisysevent *hisysevent, const char* stage) +{ + int ret = HiSysEventWrite(HiSysEvent::Domain::APPSPAWN, SPAWN_PROCESS_DURATION, + HiSysEvent::EventType::STATISTIC, + MAXDURATION, hisysevent->maxDuration, + MINDURATION, hisysevent->minDuration, + TOTALDURATION, hisysevent->totalDuration, + EVENTCOUNT, hisysevent->eventCount, + STAGE, stage); + if (ret != 0) { + APPSPAWN_LOGE("ReportSpawnProcessDuration error, ret: %{public}d", ret); + } +} + +void ReportSpawnStatisticDuration(const TimerHandle taskHandle, void *content) +{ + AppSpawnHisyseventInfo *hisyseventInfo = static_cast(content); + ReportSpawnProcessDuration(&hisyseventInfo->bootEvent, BOOTSTAGE); + ReportSpawnProcessDuration(&hisyseventInfo->manualEvent, BOOTFINISHEDSTAGE); + + InitStatisticEventInfo(hisyseventInfo); +} \ No newline at end of file diff --git a/modules/sysevent/hisysevent_adapter.h b/modules/sysevent/hisysevent_adapter.h new file mode 100644 index 0000000000000000000000000000000000000000..638417b06ba5b22f344b11ca777459c3ff4cf63b --- /dev/null +++ b/modules/sysevent/hisysevent_adapter.h @@ -0,0 +1,114 @@ +/* + * Copyright (c) 2024 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef APPSPAWN_HISYSEVENT_ADAPTER_H +#define APPSPAWN_HISYSEVENT_ADAPTER_H + +#include "appspawn_utils.h" +#include "loop_event.h" + +#ifdef __cplusplus +extern "C" { +#endif + + +// 错误码定义规范:子系统ID(28-21位)| 模块ID(20-16位)| 具体错误ID(15-0位) +#define APPSPAWN_HISYSEVENT_REPORT_TIME (24 * 60 * 60 * 1000) // 24h +#define SUBSYS_STARTUP_ID 39 +#define SUBSYSTEM_BIT_NUM 21 +#define MODULE_BIT_NUM 16 +#define ERR_MODULE_APPSPAWN 0x00 +#define ERR_MODULE_INIT 0x10 +#define ERR_APPSPAWN_BASE ((SUBSYS_STARTUP_ID << SUBSYSTEM_BIT_NUM) | (ERR_MODULE_APPSPAWN << MODULE_BIT_NUM)) +#define ERR_INIT_BASE ((SUBSYS_STARTUP_ID << SUBSYSTEM_BIT_NUM) | (ERR_MODULE_INIT << MODULE_BIT_NUM)) + +typedef enum { + // errcode for handle msg, reserved 128, 0x0001-0x0080 + ERR_APPSPAWN_MSG_TOO_LONG = ERR_APPSPAWN_BASE + 0x0001, // 81788929 + ERR_APPSPAWN_MSG_INVALID_HANDLE, + ERR_APPSPAWN_MSG_CREATE_MSG_FAILED, + ERR_APPSPAWN_COPY_MSG_FAILED, + ERR_APPSPAWN_ALLOC_MEMORY_FAILED, + ERR_APPSPAWN_MSG_DECODE_MSG_FAILED, + + // errcode for hnp, reserved 128, 0x0081 - 0x0100 + ERR_APPSPAWN_HNP = ERR_APPSPAWN_BASE + 0x0081, + + // errcode for device_dug, reserved 128, 0x0101 - 0x0180 + ERR_APPSPAWN_DEVICE_DUG = ERR_APPSPAWN_BASE + 0x0101, + + // errcode for process_exit, reserved 128, 0x0181 - 0x0200 + ERR_APPSPAWN_PROCESS_EXIT = ERR_APPSPAWN_BASE + 0x0181, + + // errcode for prefork, reserved 128, 0x0201 - 0x0280 + ERR_APPSPAWN_PREFORK = ERR_APPSPAWN_BASE + 0x0201, + + // errcode for sandbox, reserved 128, 0x0281 - 0x0300 + ERR_APPSPAWN_SANDBOX = ERR_APPSPAWN_BASE + 0x0281, + + // errcode for set permission, reserved 128, 0x0301 - 0x0380 + ERR_APPSPAWN_SET_PERMISSION = ERR_APPSPAWN_BASE + 0x0301, + ERR_APPSPAWN_SET_INTE_PERMISSION_FAIL, + ERR_APPSPAWN_SET_PROPERTIES_FAIL_SET_KEEP_CAP_FAIL, + ERR_APPSPAWN_SET_PROPERTIES_FAIL_SET_XPM_FAIL, + ERR_APPSPAWN_SET_PROPERTIES_FAIL_SET_PROCESSNAME_FAIL, + ERR_APPSPAWN_SET_PROPERTIES_FAIL_SET_UIDGID_FAIL, + ERR_APPSPAWN_SET_PROPERTIES_FAIL_SET_FD_FAIL, + ERR_APPSPAWN_SET_PROPERTIES_FAIL_SET_CAP_FAIL, + ERR_APPSPAWN_SET_PROPERTIES_FAIL_SET_SELINUXCON_FAIL, + + // errorcode for spawn child process fail, reserved 128, 0x0381 - 0x0400 + ERR_APPSPAWN_SPAWN_FAIL = ERR_APPSPAWN_BASE + 0x0381, + ERR_APPSPAWN_SPAWN_TIMEOUT, + ERR_APPSPAWN_CHILD_CRASH, + ERR_APPSPAWN_CHILD_MOUNT_FAILED, + ERR_APPSPAWN_MAX_FAILURES_EXCEEDED, +} AppSpawnHisysErrorCode; + +typedef struct { + uint32_t eventCount; + uint32_t maxDuration; + uint32_t minDuration; + uint32_t totalDuration; +} AppSpawnHisysevent; + +typedef struct { + AppSpawnHisysevent bootEvent; // bootStage + AppSpawnHisysevent manualEvent; // bootFinished +} AppSpawnHisyseventInfo; + +#define FUNC_REPORT_DURATION (20 * 1000) +#define SPAWN_DURATION (120 * 1000) +#define SPAWN_COLDRUN_DURATION (5 * 1000 * 1000) + +#define UNLOCK_SUCCESS "UNLOCK_SUCCESS" +#define LOCK_SUCCESS "LOCK_SUCCESS" +#define APPSPAWN_MAX_FAILURES_EXCEEDED "APPSPAWN_MAX_FAILURES_EXCEEDED" +AppSpawnHisyseventInfo *InitHisyseventTimer(); +AppSpawnHisyseventInfo *GetAppSpawnHisyseventInfo(); +void AddStatisticEventInfo(AppSpawnHisyseventInfo *hisyseventInfo, uint32_t duration, bool stage); +void DeleteHisyseventInfo(AppSpawnHisyseventInfo *hisyseventInfo); + +void ReportSpawnChildProcessFail(const char* processName, int32_t errorCode, int32_t spawnResult); +void ReportMountFail(const char* bundleName, const char* srcPath, const char* targetPath, + int32_t spawnResult); +void ReportKeyEvent(const char *eventName); +void ReportAbnormalDuration(const char* funcName, uint64_t duration); +void ReportSpawnStatisticDuration(const TimerHandle taskHandle, void* content); + +#ifdef __cplusplus +} +#endif +#endif // APPSPAWN_HISYSEVENT_ADAPTER_H \ No newline at end of file diff --git a/standard/BUILD.gn b/standard/BUILD.gn index d3ebddc4298898702f87f7a29cb947c8bd0321cd..dd8094496945c93781c01316e605680db90e9fdc 100644 --- a/standard/BUILD.gn +++ b/standard/BUILD.gn @@ -82,7 +82,10 @@ ohos_executable("appspawn") { if (appspawn_report_event) { defines += [ "APPSPAWN_HISYSEVENT" ] external_deps += [ "hisysevent:libhisysevent" ] - sources += [ "${appspawn_path}/modules/sysevent/appspawn_hisysevent.cpp" ] + sources += [ + "${appspawn_path}/modules/sysevent/appspawn_hisysevent.cpp", + "${appspawn_path}/modules/sysevent/hisysevent_adapter.cpp", + ] } if (appspawn_use_encaps) { @@ -189,7 +192,10 @@ ohos_executable("cjappspawn") { if (appspawn_report_event) { defines += [ "APPSPAWN_HISYSEVENT" ] external_deps += [ "hisysevent:libhisysevent" ] - sources += [ "${appspawn_path}/modules/sysevent/appspawn_hisysevent.cpp" ] + sources += [ + "${appspawn_path}/modules/sysevent/appspawn_hisysevent.cpp", + "${appspawn_path}/modules/sysevent/hisysevent_adapter.cpp", + ] } if (build_selinux) { defines += [ "WITH_SELINUX" ] @@ -256,7 +262,10 @@ ohos_executable("nativespawn") { if (appspawn_report_event) { defines += [ "APPSPAWN_HISYSEVENT" ] external_deps += [ "hisysevent:libhisysevent" ] - sources += [ "${appspawn_path}/modules/sysevent/appspawn_hisysevent.cpp" ] + sources += [ + "${appspawn_path}/modules/sysevent/appspawn_hisysevent.cpp", + "${appspawn_path}/modules/sysevent/hisysevent_adapter.cpp", + ] } if (build_selinux) { defines += [ "WITH_SELINUX" ] diff --git a/standard/appspawn_appmgr.c b/standard/appspawn_appmgr.c index dd92c3e6fc4c6471c619de930b5db278b46db167..cbd6448534255029af5b304441e9096be726ca6b 100644 --- a/standard/appspawn_appmgr.c +++ b/standard/appspawn_appmgr.c @@ -54,6 +54,9 @@ AppSpawnMgr *CreateAppSpawnMgr(int mode) appMgr->servicePid = getpid(); appMgr->server = NULL; appMgr->sigHandler = NULL; +#ifdef APPSPAWN_HISYSEVENT + appMgr->hisyseventInfo = NULL; +#endif OH_ListInit(&appMgr->appQueue); OH_ListInit(&appMgr->diedQueue); OH_ListInit(&appMgr->appSpawnQueue); @@ -97,6 +100,9 @@ void DeleteAppSpawnMgr(AppSpawnMgr *mgr) OH_ListRemoveAll(&mgr->diedQueue, NULL); OH_ListRemoveAll(&mgr->appSpawnQueue, SpawningQueueDestroy); OH_ListRemoveAll(&mgr->extData, ExtDataDestroy); +#ifdef APPSPAWN_HISYSEVENT + DeleteHisyseventInfo(mgr->hisyseventInfo); +#endif APPSPAWN_LOGV("DeleteAppSpawnMgr %{public}d %{public}d", mgr->servicePid, getpid()); free(mgr); diff --git a/standard/appspawn_manager.h b/standard/appspawn_manager.h index 9c78948ce3221ef802b10b8f87ae0fdb29dfad01..5c5280ac950208248313a009b6dcbf2d661b1763 100644 --- a/standard/appspawn_manager.h +++ b/standard/appspawn_manager.h @@ -27,6 +27,9 @@ #include "appspawn_utils.h" #include "list.h" #include "loop_event.h" +#ifdef APPSPAWN_HISYSEVENT +#include "hisysevent_adapter.h" +#endif #ifdef __cplusplus extern "C" { @@ -120,6 +123,9 @@ typedef struct TagAppSpawnMgr { struct timespec perLoadEnd; struct ListNode extData; struct SpawnTime spawnTime; +#ifdef APPSPAWN_HISYSEVENT + AppSpawnHisyseventInfo *hisyseventInfo; +#endif } AppSpawnMgr; /** diff --git a/standard/appspawn_service.c b/standard/appspawn_service.c index 3ec77d22d53d17138f3e67ccb8cd5c3ba0d37047..9eb95dbe6b12b834883f31da5d908ff62e85ba5b 100644 --- a/standard/appspawn_service.c +++ b/standard/appspawn_service.c @@ -46,6 +46,7 @@ #include "cJSON.h" #ifdef APPSPAWN_HISYSEVENT #include "appspawn_hisysevent.h" +#include "hisysevent_adapter.h" #endif #define PARAM_BUFFER_SIZE 10 @@ -927,9 +928,13 @@ static uint32_t g_crashTimes = 0; static void WaitChildDied(pid_t pid) { AppSpawningCtx *property = GetAppSpawningCtxByPid(pid); - if (property != NULL && property->state == APP_STATE_SPAWNING) { + if (property != NULL && property->message != NULL && property->state == APP_STATE_SPAWNING) { + const char *processName = GetProcessName(property); APPSPAWN_LOGI("Child process %{public}s fail \'child crash \'pid %{public}d appId: %{public}d", - GetProcessName(property), property->pid, property->client.id); + processName, property->pid, property->client.id); +#ifdef APPSPAWN_HISYSEVENT + ReportSpawnChildProcessFail(processName, ERR_APPSPAWN_CHILD_CRASH, APPSPAWN_CHILD_CRASH); +#endif if (property->client.id == g_lastDiedAppId + 1) { g_crashTimes++; } else { @@ -942,6 +947,9 @@ static void WaitChildDied(pid_t pid) if (g_crashTimes >= MAX_CRASH_TIME) { APPSPAWN_LOGW("Continuous failures in spawning the app, restart appspawn"); +#ifdef APPSPAWN_HISYSEVENT + ReportKeyEvent(APPSPAWN_MAX_FAILURES_EXCEEDED); +#endif StopAppSpawn(); } } @@ -958,6 +966,9 @@ static void WaitChildTimeout(const TimerHandle taskHandle, void *context) #endif kill(property->pid, SIGKILL); } +#ifdef APPSPAWN_HISYSEVENT + ReportSpawnChildProcessFail(GetProcessName(property), ERR_APPSPAWN_SPAWN_TIMEOUT, APPSPAWN_SPAWN_TIMEOUT); +#endif SendResponse(property->message->connection, &property->message->msgHeader, APPSPAWN_SPAWN_TIMEOUT, 0); DeleteAppSpawningCtx(property); } @@ -971,6 +982,9 @@ static int ProcessChildFdCheck(int fd, AppSpawningCtx *property) APPSPAWN_CHECK(property->message != NULL, return -1, "Invalid message in ctx %{public}d", property->client.id); if (result != 0) { +#ifdef APPSPAWN_HISYSEVENT + ReportSpawnChildProcessFail(GetProcessName(property), ERR_APPSPAWN_SPAWN_FAIL, result); +#endif SendResponse(property->message->connection, &property->message->msgHeader, result, property->pid); DeleteAppSpawningCtx(property); return -1; @@ -979,6 +993,26 @@ static int ProcessChildFdCheck(int fd, AppSpawningCtx *property) return 0; } +#ifdef APPSPAWN_HISYSEVENT +static void LogProcessSpawnDuration(AppSpawnedProcess *appInfo, AppSpawningCtx *property) +{ + APPSPAWN_CHECK_ONLY_EXPER(appInfo != NULL && property != NULL, return); + uint32_t spawnProcessDuration = (appInfo->spawnEnd.tv_sec - appInfo->spawnStart.tv_sec) * (APPSPAWN_USEC_TO_NSEC) + + (uint32_t)((appInfo->spawnEnd.tv_nsec - appInfo->spawnStart.tv_nsec)/(APPSPAWN_MSEC_TO_NSEC)); + + AppSpawnMgr *appspawnMgr = GetAppSpawnMgr(); + if (appspawnMgr != NULL) { + AddStatisticEventInfo(appspawnMgr->hisyseventInfo, spawnProcessDuration, IsBootFinished()); + } + +#ifndef ASAN_DETECTOR + uint64_t diff = DiffTime(&appInfo->spawnStart, &appInfo->spawnEnd); + APPSPAWN_CHECK_ONLY_EXPER(diff < (IsChildColdRun(property) ? SPAWN_COLDRUN_DURATION : SPAWN_DURATION), + ReportAbnormalDuration("SPAWNCHILD", diff)); +#endif +} +#endif + #define MSG_EXT_NAME_MAX_DECIMAL 10 #define MSG_EXT_NAME 1 static void ProcessChildResponse(const WatcherHandle taskHandle, int fd, uint32_t *events, const void *context) @@ -986,17 +1020,12 @@ static void ProcessChildResponse(const WatcherHandle taskHandle, int fd, uint32_ AppSpawningCtx *property = (AppSpawningCtx *)context; property->forkCtx.watcherHandle = NULL; // delete watcher LE_RemoveWatcher(LE_GetDefaultLoop(), (WatcherHandle)taskHandle); - - if (ProcessChildFdCheck(fd, property) != 0) { - return; - } - + APPSPAWN_CHECK_ONLY_EXPER(ProcessChildFdCheck(fd, property) == 0, return); // success bool isDebuggable = CheckAppMsgFlagsSet(property, APP_FLAGS_DEBUGGABLE); AppSpawnedProcess *appInfo = AddSpawnedProcess(property->pid, GetBundleName(property), isDebuggable); uint32_t len = 0; - char *pidMaxStr = NULL; - pidMaxStr = GetAppPropertyExt(property, MSG_EXT_NAME_MAX_CHILD_PROCCESS_MAX, &len); + char *pidMaxStr = GetAppPropertyExt(property, MSG_EXT_NAME_MAX_CHILD_PROCCESS_MAX, &len); uint32_t pidMax = 0; if (pidMaxStr != NULL && len != 0) { pidMax = strtoul(pidMaxStr, NULL, MSG_EXT_NAME_MAX_DECIMAL); @@ -1016,8 +1045,11 @@ static void ProcessChildResponse(const WatcherHandle taskHandle, int fd, uint32_ } #endif clock_gettime(CLOCK_MONOTONIC, &appInfo->spawnEnd); - // add max info } +#ifdef APPSPAWN_HISYSEVENT + //add process spawn duration into hisysevent,(ms) + LogProcessSpawnDuration(appInfo, property); +#endif WatchChildProcessFd(property); ProcessMgrHookExecute(STAGE_SERVER_APP_ADD, GetAppSpawnContent(), appInfo); // response @@ -1266,6 +1298,9 @@ AppSpawnContent *AppSpawnCreateContent(const char *socketName, char *longProcNam AppSpawnMgr *appSpawnContent = CreateAppSpawnMgr(mode); APPSPAWN_CHECK(appSpawnContent != NULL, return NULL, "Failed to alloc memory for appspawn"); +#ifdef APPSPAWN_HISYSEVENT + appSpawnContent->hisyseventInfo = InitHisyseventTimer(); +#endif appSpawnContent->content.longProcName = longProcName; appSpawnContent->content.longProcNameLen = nameLen; appSpawnContent->content.notifyResToParent = NotifyResToParent; diff --git a/test/unittest/app_spawn_standard_test/BUILD.gn b/test/unittest/app_spawn_standard_test/BUILD.gn index 022023c7cc93e0c114b3d8796652187673134c4d..e9823cf200bb07bfccb6ee58746f5de8b91ad933 100644 --- a/test/unittest/app_spawn_standard_test/BUILD.gn +++ b/test/unittest/app_spawn_standard_test/BUILD.gn @@ -539,6 +539,7 @@ ohos_unittest("AppSpawn_common_ut") { sources += [ "${appspawn_path}/modules/sysevent/appspawn_hisysevent.cpp", "${appspawn_path}/modules/sysevent/event_reporter.cpp", + "${appspawn_path}/modules/sysevent/hisysevent_adapter.cpp", ] }