169570cc8Sopenharmony_ci/*
269570cc8Sopenharmony_ci * Copyright (c) 2024 Huawei Device Co., Ltd.
369570cc8Sopenharmony_ci * Licensed under the Apache License, Version 2.0 (the "License");
469570cc8Sopenharmony_ci * you may not use this file except in compliance with the License.
569570cc8Sopenharmony_ci * You may obtain a copy of the License at
669570cc8Sopenharmony_ci *
769570cc8Sopenharmony_ci *     http://www.apache.org/licenses/LICENSE-2.0
869570cc8Sopenharmony_ci *
969570cc8Sopenharmony_ci * Unless required by applicable law or agreed to in writing, software
1069570cc8Sopenharmony_ci * distributed under the License is distributed on an "AS IS" BASIS,
1169570cc8Sopenharmony_ci * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
1269570cc8Sopenharmony_ci * See the License for the specific language governing permissions and
1369570cc8Sopenharmony_ci * limitations under the License.
1469570cc8Sopenharmony_ci */
1569570cc8Sopenharmony_ci
1669570cc8Sopenharmony_ci#include <fcntl.h>
1769570cc8Sopenharmony_ci#include <stdio.h>
1869570cc8Sopenharmony_ci#include "appspawn_kickdog.h"
1969570cc8Sopenharmony_ci
2069570cc8Sopenharmony_cistatic int OpenAndWriteToProc(const char *procName, const char *writeStr, size_t writeLen)
2169570cc8Sopenharmony_ci{
2269570cc8Sopenharmony_ci    if (writeStr == NULL) {
2369570cc8Sopenharmony_ci        APPSPAWN_LOGE("Write string is null");
2469570cc8Sopenharmony_ci        return -1;
2569570cc8Sopenharmony_ci    }
2669570cc8Sopenharmony_ci
2769570cc8Sopenharmony_ci    int procFd = open(procName, O_RDWR | O_CLOEXEC);
2869570cc8Sopenharmony_ci    if (procFd == -1) {
2969570cc8Sopenharmony_ci        APPSPAWN_LOGE("open %{public}s fail,errno:%{public}d", procName, errno);
3069570cc8Sopenharmony_ci        return procFd;
3169570cc8Sopenharmony_ci    }
3269570cc8Sopenharmony_ci
3369570cc8Sopenharmony_ci    int writeResult = write(procFd, writeStr, writeLen);
3469570cc8Sopenharmony_ci    if (writeResult != (int)writeLen) {
3569570cc8Sopenharmony_ci        APPSPAWN_LOGE("write %{public}s fail,result:%{public}d", writeStr, writeResult);
3669570cc8Sopenharmony_ci    } else {
3769570cc8Sopenharmony_ci        APPSPAWN_LOGI("write %{public}s success", writeStr);
3869570cc8Sopenharmony_ci    }
3969570cc8Sopenharmony_ci
4069570cc8Sopenharmony_ci    close(procFd);
4169570cc8Sopenharmony_ci    return writeResult;
4269570cc8Sopenharmony_ci}
4369570cc8Sopenharmony_ci
4469570cc8Sopenharmony_ci// Enable watchdog monitoring
4569570cc8Sopenharmony_cistatic int OpenAppSpawnWatchdogFile(AppSpawnContent *content)
4669570cc8Sopenharmony_ci{
4769570cc8Sopenharmony_ci    APPSPAWN_LOGI("OpenAppSpawnWatchdogFile");
4869570cc8Sopenharmony_ci    int result = 0;
4969570cc8Sopenharmony_ci    if (access(LINUX_APPSPAWN_WATCHDOG_FILE, F_OK) == 0) {
5069570cc8Sopenharmony_ci        result = OpenAndWriteToProc(LINUX_APPSPAWN_WATCHDOG_FILE, LINUX_APPSPAWN_WATCHDOG_ON,
5169570cc8Sopenharmony_ci            strlen(LINUX_APPSPAWN_WATCHDOG_ON));
5269570cc8Sopenharmony_ci    } else {
5369570cc8Sopenharmony_ci        result = OpenAndWriteToProc(HM_APPSPAWN_WATCHDOG_FILE, HM_APPSPAWN_WATCHDOG_ON,
5469570cc8Sopenharmony_ci            strlen(HM_APPSPAWN_WATCHDOG_ON));
5569570cc8Sopenharmony_ci    }
5669570cc8Sopenharmony_ci    content->wdgOpened = (result != -1);
5769570cc8Sopenharmony_ci    APPSPAWN_LOGI("open finish,result:%{public}d", result);
5869570cc8Sopenharmony_ci    return result;
5969570cc8Sopenharmony_ci}
6069570cc8Sopenharmony_ci
6169570cc8Sopenharmony_cistatic void KickAppSpawnWatchdog(void)
6269570cc8Sopenharmony_ci{
6369570cc8Sopenharmony_ci    APPSPAWN_LOGI("kick proc begin");
6469570cc8Sopenharmony_ci    int result = 0;
6569570cc8Sopenharmony_ci    if (access(LINUX_APPSPAWN_WATCHDOG_FILE, F_OK) == 0) {
6669570cc8Sopenharmony_ci        result = OpenAndWriteToProc(LINUX_APPSPAWN_WATCHDOG_FILE, LINUX_APPSPAWN_WATCHDOG_KICK,
6769570cc8Sopenharmony_ci            strlen(LINUX_APPSPAWN_WATCHDOG_KICK));
6869570cc8Sopenharmony_ci    } else {
6969570cc8Sopenharmony_ci        result = OpenAndWriteToProc(HM_APPSPAWN_WATCHDOG_FILE, HM_APPSPAWN_WATCHDOG_KICK,
7069570cc8Sopenharmony_ci            strlen(HM_APPSPAWN_WATCHDOG_KICK));
7169570cc8Sopenharmony_ci    }
7269570cc8Sopenharmony_ci    APPSPAWN_LOGI("kick end,result:%{public}d", result);
7369570cc8Sopenharmony_ci}
7469570cc8Sopenharmony_ci
7569570cc8Sopenharmony_cistatic void ProcessTimerHandle(const TimerHandle taskHandle, void *context)
7669570cc8Sopenharmony_ci{
7769570cc8Sopenharmony_ci    AppSpawnContent *wdgContent = (AppSpawnContent *)context;
7869570cc8Sopenharmony_ci
7969570cc8Sopenharmony_ci    APPSPAWN_LOGI("kick appspawn dog start");
8069570cc8Sopenharmony_ci
8169570cc8Sopenharmony_ci    if (!wdgContent->wdgOpened) {  //first time deal kernel file
8269570cc8Sopenharmony_ci        OpenAppSpawnWatchdogFile(wdgContent);
8369570cc8Sopenharmony_ci        return;
8469570cc8Sopenharmony_ci    }
8569570cc8Sopenharmony_ci
8669570cc8Sopenharmony_ci    KickAppSpawnWatchdog();
8769570cc8Sopenharmony_ci}
8869570cc8Sopenharmony_ci
8969570cc8Sopenharmony_cistatic void CreateTimerLoopTask(AppSpawnContent *content)
9069570cc8Sopenharmony_ci{
9169570cc8Sopenharmony_ci    LoopHandle loop = LE_GetDefaultLoop();
9269570cc8Sopenharmony_ci    TimerHandle timer = NULL;
9369570cc8Sopenharmony_ci    int ret = LE_CreateTimer(loop, &timer, ProcessTimerHandle, (void *)content);
9469570cc8Sopenharmony_ci    APPSPAWN_CHECK(ret == 0, return, "Failed to create timerLoopTask ret %{public}d", ret);
9569570cc8Sopenharmony_ci    // start a timer to write kernel file every 10s
9669570cc8Sopenharmony_ci    ret = LE_StartTimer(loop, timer, APPSPAWN_WATCHDOG_KICKTIME, INT64_MAX);
9769570cc8Sopenharmony_ci    APPSPAWN_CHECK(ret == 0, return, "Failed to start timerLoopTask ret %{public}d", ret);
9869570cc8Sopenharmony_ci}
9969570cc8Sopenharmony_ci
10069570cc8Sopenharmony_civoid AppSpawnKickDogStart(AppSpawnContent *content)
10169570cc8Sopenharmony_ci{
10269570cc8Sopenharmony_ci    CreateTimerLoopTask(content);
10369570cc8Sopenharmony_ci    OpenAppSpawnWatchdogFile(content);
10469570cc8Sopenharmony_ci}