1/*
2 * Copyright (c) 2024 Huawei Device Co., Ltd.
3 * Licensed under the Apache License, Version 2.0 (the "License");
4 * you may not use this file except in compliance with the License.
5 * You may obtain a copy of the License at
6 *
7 *     http://www.apache.org/licenses/LICENSE-2.0
8 *
9 * Unless required by applicable law or agreed to in writing, software
10 * distributed under the License is distributed on an "AS IS" BASIS,
11 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 * See the License for the specific language governing permissions and
13 * limitations under the License.
14 */
15
16#include <fcntl.h>
17#include <stdio.h>
18#include "appspawn_kickdog.h"
19
20static int OpenAndWriteToProc(const char *procName, const char *writeStr, size_t writeLen)
21{
22    if (writeStr == NULL) {
23        APPSPAWN_LOGE("Write string is null");
24        return -1;
25    }
26
27    int procFd = open(procName, O_RDWR | O_CLOEXEC);
28    if (procFd == -1) {
29        APPSPAWN_LOGE("open %{public}s fail,errno:%{public}d", procName, errno);
30        return procFd;
31    }
32
33    int writeResult = write(procFd, writeStr, writeLen);
34    if (writeResult != (int)writeLen) {
35        APPSPAWN_LOGE("write %{public}s fail,result:%{public}d", writeStr, writeResult);
36    } else {
37        APPSPAWN_LOGI("write %{public}s success", writeStr);
38    }
39
40    close(procFd);
41    return writeResult;
42}
43
44// Enable watchdog monitoring
45static int OpenAppSpawnWatchdogFile(AppSpawnContent *content)
46{
47    APPSPAWN_LOGI("OpenAppSpawnWatchdogFile");
48    int result = 0;
49    if (access(LINUX_APPSPAWN_WATCHDOG_FILE, F_OK) == 0) {
50        result = OpenAndWriteToProc(LINUX_APPSPAWN_WATCHDOG_FILE, LINUX_APPSPAWN_WATCHDOG_ON,
51            strlen(LINUX_APPSPAWN_WATCHDOG_ON));
52    } else {
53        result = OpenAndWriteToProc(HM_APPSPAWN_WATCHDOG_FILE, HM_APPSPAWN_WATCHDOG_ON,
54            strlen(HM_APPSPAWN_WATCHDOG_ON));
55    }
56    content->wdgOpened = (result != -1);
57    APPSPAWN_LOGI("open finish,result:%{public}d", result);
58    return result;
59}
60
61static void KickAppSpawnWatchdog(void)
62{
63    APPSPAWN_LOGI("kick proc begin");
64    int result = 0;
65    if (access(LINUX_APPSPAWN_WATCHDOG_FILE, F_OK) == 0) {
66        result = OpenAndWriteToProc(LINUX_APPSPAWN_WATCHDOG_FILE, LINUX_APPSPAWN_WATCHDOG_KICK,
67            strlen(LINUX_APPSPAWN_WATCHDOG_KICK));
68    } else {
69        result = OpenAndWriteToProc(HM_APPSPAWN_WATCHDOG_FILE, HM_APPSPAWN_WATCHDOG_KICK,
70            strlen(HM_APPSPAWN_WATCHDOG_KICK));
71    }
72    APPSPAWN_LOGI("kick end,result:%{public}d", result);
73}
74
75static void ProcessTimerHandle(const TimerHandle taskHandle, void *context)
76{
77    AppSpawnContent *wdgContent = (AppSpawnContent *)context;
78
79    APPSPAWN_LOGI("kick appspawn dog start");
80
81    if (!wdgContent->wdgOpened) {  //first time deal kernel file
82        OpenAppSpawnWatchdogFile(wdgContent);
83        return;
84    }
85
86    KickAppSpawnWatchdog();
87}
88
89static void CreateTimerLoopTask(AppSpawnContent *content)
90{
91    LoopHandle loop = LE_GetDefaultLoop();
92    TimerHandle timer = NULL;
93    int ret = LE_CreateTimer(loop, &timer, ProcessTimerHandle, (void *)content);
94    APPSPAWN_CHECK(ret == 0, return, "Failed to create timerLoopTask ret %{public}d", ret);
95    // start a timer to write kernel file every 10s
96    ret = LE_StartTimer(loop, timer, APPSPAWN_WATCHDOG_KICKTIME, INT64_MAX);
97    APPSPAWN_CHECK(ret == 0, return, "Failed to start timerLoopTask ret %{public}d", ret);
98}
99
100void AppSpawnKickDogStart(AppSpawnContent *content)
101{
102    CreateTimerLoopTask(content);
103    OpenAppSpawnWatchdogFile(content);
104}