1c1d0c72aSopenharmony_ci/*
2c1d0c72aSopenharmony_ci * Copyright (c) 2021 Huawei Device Co., Ltd.
3c1d0c72aSopenharmony_ci * Licensed under the Apache License, Version 2.0 (the "License");
4c1d0c72aSopenharmony_ci * you may not use this file except in compliance with the License.
5c1d0c72aSopenharmony_ci * You may obtain a copy of the License at
6c1d0c72aSopenharmony_ci *
7c1d0c72aSopenharmony_ci *     http://www.apache.org/licenses/LICENSE-2.0
8c1d0c72aSopenharmony_ci *
9c1d0c72aSopenharmony_ci * Unless required by applicable law or agreed to in writing, software
10c1d0c72aSopenharmony_ci * distributed under the License is distributed on an "AS IS" BASIS,
11c1d0c72aSopenharmony_ci * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12c1d0c72aSopenharmony_ci * See the License for the specific language governing permissions and
13c1d0c72aSopenharmony_ci * limitations under the License.
14c1d0c72aSopenharmony_ci */
15c1d0c72aSopenharmony_ci
16c1d0c72aSopenharmony_ci#include <errno.h>
17c1d0c72aSopenharmony_ci#include <limits.h>
18c1d0c72aSopenharmony_ci#include <sched.h>
19c1d0c72aSopenharmony_ci#include <signal.h>
20c1d0c72aSopenharmony_ci#include <stdlib.h>
21c1d0c72aSopenharmony_ci#include <sys/prctl.h>
22c1d0c72aSopenharmony_ci#include <sys/resource.h>
23c1d0c72aSopenharmony_ci#include <unistd.h>
24c1d0c72aSopenharmony_ci
25c1d0c72aSopenharmony_ci#include "securec.h"
26c1d0c72aSopenharmony_ci#include "parameter.h"
27c1d0c72aSopenharmony_ci#include "malloc.h"
28c1d0c72aSopenharmony_ci#include "devhost_dump.h"
29c1d0c72aSopenharmony_ci#include "devhost_service.h"
30c1d0c72aSopenharmony_ci#include "devhost_service_full.h"
31c1d0c72aSopenharmony_ci#include "hdf_base.h"
32c1d0c72aSopenharmony_ci#include "hdf_core_log.h"
33c1d0c72aSopenharmony_ci#include "hdf_power_manager.h"
34c1d0c72aSopenharmony_ci
35c1d0c72aSopenharmony_ci#define HDF_LOG_TAG                    hdf_device_host
36c1d0c72aSopenharmony_ci#define DEVHOST_MIN_INPUT_PARAM_NUM    5
37c1d0c72aSopenharmony_ci#define DEVHOST_INPUT_PARAM_HOSTID_POS 1
38c1d0c72aSopenharmony_ci#define DEVHOST_HOST_NAME_POS          2
39c1d0c72aSopenharmony_ci#define DEVHOST_PROCESS_PRI_POS        3
40c1d0c72aSopenharmony_ci#define DEVHOST_THREAD_PRI_POS         4
41c1d0c72aSopenharmony_ci#define PARAM_BUF_LEN 128
42c1d0c72aSopenharmony_ci#define MALLOPT_PARA_CNT 2
43c1d0c72aSopenharmony_ci#define INVALID_PRIORITY "0"
44c1d0c72aSopenharmony_ci
45c1d0c72aSopenharmony_cistatic void StartMemoryHook(const char* processName)
46c1d0c72aSopenharmony_ci{
47c1d0c72aSopenharmony_ci    const char defaultValue[PARAM_BUF_LEN] = { 0 };
48c1d0c72aSopenharmony_ci    const char targetPrefix[] = "startup:";
49c1d0c72aSopenharmony_ci    const int targetPrefixLen = strlen(targetPrefix);
50c1d0c72aSopenharmony_ci    char paramValue[PARAM_BUF_LEN] = { 0 };
51c1d0c72aSopenharmony_ci    int retParam = GetParameter("libc.hook_mode", defaultValue, paramValue, sizeof(paramValue));
52c1d0c72aSopenharmony_ci    if (retParam <= 0 || strncmp(paramValue, targetPrefix, targetPrefixLen) != 0) {
53c1d0c72aSopenharmony_ci        return;
54c1d0c72aSopenharmony_ci    }
55c1d0c72aSopenharmony_ci    if (strstr(paramValue + targetPrefixLen, processName) != NULL) {
56c1d0c72aSopenharmony_ci        const int hookSignal = 36; // 36: native memory hooked signal
57c1d0c72aSopenharmony_ci        HDF_LOGE("raise hook signal %{public}d to %{public}s", hookSignal, processName);
58c1d0c72aSopenharmony_ci        raise(hookSignal);
59c1d0c72aSopenharmony_ci    }
60c1d0c72aSopenharmony_ci}
61c1d0c72aSopenharmony_ci
62c1d0c72aSopenharmony_cibool HdfStringToInt(const char *str, int *value)
63c1d0c72aSopenharmony_ci{
64c1d0c72aSopenharmony_ci    if (str == NULL || value == NULL) {
65c1d0c72aSopenharmony_ci        return false;
66c1d0c72aSopenharmony_ci    }
67c1d0c72aSopenharmony_ci
68c1d0c72aSopenharmony_ci    char *end = NULL;
69c1d0c72aSopenharmony_ci    errno = 0;
70c1d0c72aSopenharmony_ci    const int base = 10;
71c1d0c72aSopenharmony_ci    long result = strtol(str, &end, base);
72c1d0c72aSopenharmony_ci    if (end == str || end[0] != '\0' || errno == ERANGE || result > INT_MAX || result < INT_MIN) {
73c1d0c72aSopenharmony_ci        return false;
74c1d0c72aSopenharmony_ci    }
75c1d0c72aSopenharmony_ci
76c1d0c72aSopenharmony_ci    *value = (int)result;
77c1d0c72aSopenharmony_ci    return true;
78c1d0c72aSopenharmony_ci}
79c1d0c72aSopenharmony_ci
80c1d0c72aSopenharmony_cistatic void SetProcTitle(char **argv, const char *newTitle)
81c1d0c72aSopenharmony_ci{
82c1d0c72aSopenharmony_ci    size_t len = strlen(argv[0]);
83c1d0c72aSopenharmony_ci    if (strlen(newTitle) > len) {
84c1d0c72aSopenharmony_ci        HDF_LOGE("failed to set new process title because the '%{public}s' is too long", newTitle);
85c1d0c72aSopenharmony_ci        return;
86c1d0c72aSopenharmony_ci    }
87c1d0c72aSopenharmony_ci    (void)memset_s(argv[0], len, 0, len);
88c1d0c72aSopenharmony_ci    if (strcpy_s(argv[0], len + 1, newTitle) != EOK) {
89c1d0c72aSopenharmony_ci        HDF_LOGE("failed to set new process title");
90c1d0c72aSopenharmony_ci        return;
91c1d0c72aSopenharmony_ci    }
92c1d0c72aSopenharmony_ci    prctl(PR_SET_NAME, newTitle);
93c1d0c72aSopenharmony_ci}
94c1d0c72aSopenharmony_ci
95c1d0c72aSopenharmony_cistatic void HdfSetProcPriority(char **argv)
96c1d0c72aSopenharmony_ci{
97c1d0c72aSopenharmony_ci    int32_t schedPriority = 0;
98c1d0c72aSopenharmony_ci    int32_t procPriority = 0;
99c1d0c72aSopenharmony_ci
100c1d0c72aSopenharmony_ci    if (!HdfStringToInt(argv[DEVHOST_PROCESS_PRI_POS], &procPriority)) {
101c1d0c72aSopenharmony_ci        HDF_LOGE("procPriority parameter error: %{public}s", argv[DEVHOST_PROCESS_PRI_POS]);
102c1d0c72aSopenharmony_ci        return;
103c1d0c72aSopenharmony_ci    }
104c1d0c72aSopenharmony_ci    if (!HdfStringToInt(argv[DEVHOST_THREAD_PRI_POS], &schedPriority)) {
105c1d0c72aSopenharmony_ci        HDF_LOGE("schedPriority parameter error: %{public}s", argv[DEVHOST_THREAD_PRI_POS]);
106c1d0c72aSopenharmony_ci        return;
107c1d0c72aSopenharmony_ci    }
108c1d0c72aSopenharmony_ci
109c1d0c72aSopenharmony_ci    if (setpriority(PRIO_PROCESS, 0, procPriority) != 0) {
110c1d0c72aSopenharmony_ci        HDF_LOGE("host setpriority failed: %{public}d", errno);
111c1d0c72aSopenharmony_ci    }
112c1d0c72aSopenharmony_ci
113c1d0c72aSopenharmony_ci    struct sched_param param = {0};
114c1d0c72aSopenharmony_ci    param.sched_priority = schedPriority;
115c1d0c72aSopenharmony_ci    if (sched_setscheduler(0, SCHED_FIFO, &param) != 0) {
116c1d0c72aSopenharmony_ci        HDF_LOGE("host sched_setscheduler failed: %{public}d", errno);
117c1d0c72aSopenharmony_ci    } else {
118c1d0c72aSopenharmony_ci        HDF_LOGI("host sched_setscheduler succeed:%{public}d %{public}d", procPriority, schedPriority);
119c1d0c72aSopenharmony_ci    }
120c1d0c72aSopenharmony_ci}
121c1d0c72aSopenharmony_ci
122c1d0c72aSopenharmony_cistatic void SetMallopt(int argc, char **argv)
123c1d0c72aSopenharmony_ci{
124c1d0c72aSopenharmony_ci    for (int i = DEVHOST_MIN_INPUT_PARAM_NUM; i < argc - 1; i += MALLOPT_PARA_CNT) {
125c1d0c72aSopenharmony_ci        int32_t malloptKey = 0;
126c1d0c72aSopenharmony_ci        int32_t malloptValue = 0;
127c1d0c72aSopenharmony_ci        int ret = 0;
128c1d0c72aSopenharmony_ci        if (!HdfStringToInt(argv[i], &malloptKey)) {
129c1d0c72aSopenharmony_ci            HDF_LOGE("malloptKey parameter error:%{public}s", argv[i]);
130c1d0c72aSopenharmony_ci            continue;
131c1d0c72aSopenharmony_ci        }
132c1d0c72aSopenharmony_ci        if (!HdfStringToInt(argv[i + 1], &malloptValue)) {
133c1d0c72aSopenharmony_ci            HDF_LOGE("malloptValue parameter error:%{public}s", argv[i + 1]);
134c1d0c72aSopenharmony_ci            continue;
135c1d0c72aSopenharmony_ci        }
136c1d0c72aSopenharmony_ci        ret = mallopt(malloptKey, malloptValue);
137c1d0c72aSopenharmony_ci        if (ret != 1) {
138c1d0c72aSopenharmony_ci            HDF_LOGE("mallopt failed, malloptKey:%{public}d, malloptValue:%{public}d, ret:%{public}d",
139c1d0c72aSopenharmony_ci                malloptKey, malloptValue, ret);
140c1d0c72aSopenharmony_ci            continue;
141c1d0c72aSopenharmony_ci        }
142c1d0c72aSopenharmony_ci        HDF_LOGI("host set mallopt succeed, mallopt:%{public}d %{public}d", malloptKey, malloptValue);
143c1d0c72aSopenharmony_ci    }
144c1d0c72aSopenharmony_ci    return;
145c1d0c72aSopenharmony_ci}
146c1d0c72aSopenharmony_ci
147c1d0c72aSopenharmony_cistatic void SetHostProperties(int argc, char **argv, const char *hostName)
148c1d0c72aSopenharmony_ci{
149c1d0c72aSopenharmony_ci    SetProcTitle(argv, hostName);
150c1d0c72aSopenharmony_ci    StartMemoryHook(hostName);
151c1d0c72aSopenharmony_ci    if ((strcmp(argv[DEVHOST_PROCESS_PRI_POS], INVALID_PRIORITY) != 0) &&
152c1d0c72aSopenharmony_ci        (strcmp(argv[DEVHOST_THREAD_PRI_POS], INVALID_PRIORITY) != 0)) {
153c1d0c72aSopenharmony_ci        HdfSetProcPriority(argv);
154c1d0c72aSopenharmony_ci    }
155c1d0c72aSopenharmony_ci    if (argc > DEVHOST_MIN_INPUT_PARAM_NUM) {
156c1d0c72aSopenharmony_ci        SetMallopt(argc, argv);
157c1d0c72aSopenharmony_ci    }
158c1d0c72aSopenharmony_ci}
159c1d0c72aSopenharmony_ci
160c1d0c72aSopenharmony_ciint main(int argc, char **argv)
161c1d0c72aSopenharmony_ci{
162c1d0c72aSopenharmony_ci    if (argc < DEVHOST_MIN_INPUT_PARAM_NUM) {
163c1d0c72aSopenharmony_ci        HDF_LOGE("Devhost main parameter error, argc: %{public}d", argc);
164c1d0c72aSopenharmony_ci        return HDF_ERR_INVALID_PARAM;
165c1d0c72aSopenharmony_ci    }
166c1d0c72aSopenharmony_ci    prctl(PR_SET_PDEATHSIG, SIGKILL); // host process should exit with devmgr process
167c1d0c72aSopenharmony_ci    int hostId = 0;
168c1d0c72aSopenharmony_ci    if (!HdfStringToInt(argv[DEVHOST_INPUT_PARAM_HOSTID_POS], &hostId)) {
169c1d0c72aSopenharmony_ci        HDF_LOGE("Devhost main parameter error, argv[1]: %{public}s", argv[DEVHOST_INPUT_PARAM_HOSTID_POS]);
170c1d0c72aSopenharmony_ci        return HDF_ERR_INVALID_PARAM;
171c1d0c72aSopenharmony_ci    }
172c1d0c72aSopenharmony_ci    const char *hostName = argv[DEVHOST_HOST_NAME_POS];
173c1d0c72aSopenharmony_ci    HDF_LOGI("hdf device host %{public}s %{public}d start", hostName, hostId);
174c1d0c72aSopenharmony_ci    SetHostProperties(argc, argv, hostName);
175c1d0c72aSopenharmony_ci    struct IDevHostService *instance = DevHostServiceNewInstance(hostId, hostName);
176c1d0c72aSopenharmony_ci    if (instance == NULL || instance->StartService == NULL) {
177c1d0c72aSopenharmony_ci        HDF_LOGE("DevHostServiceGetInstance fail");
178c1d0c72aSopenharmony_ci        return HDF_ERR_INVALID_OBJECT;
179c1d0c72aSopenharmony_ci    }
180c1d0c72aSopenharmony_ci    HDF_LOGD("create IDevHostService of %{public}s success", hostName);
181c1d0c72aSopenharmony_ci    DevHostDumpInit();
182c1d0c72aSopenharmony_ci    HDF_LOGD("%{public}s start device service begin", hostName);
183c1d0c72aSopenharmony_ci    int status = instance->StartService(instance);
184c1d0c72aSopenharmony_ci    if (status != HDF_SUCCESS) {
185c1d0c72aSopenharmony_ci        HDF_LOGE("Devhost StartService fail, return: %{public}d", status);
186c1d0c72aSopenharmony_ci        DevHostServiceFreeInstance(instance);
187c1d0c72aSopenharmony_ci        DevHostDumpDeInit();
188c1d0c72aSopenharmony_ci        return status;
189c1d0c72aSopenharmony_ci    }
190c1d0c72aSopenharmony_ci    HdfPowerManagerInit();
191c1d0c72aSopenharmony_ci    struct DevHostServiceFull *fullService = (struct DevHostServiceFull *)instance;
192c1d0c72aSopenharmony_ci    struct HdfMessageLooper *looper = &fullService->looper;
193c1d0c72aSopenharmony_ci    if ((looper != NULL) && (looper->Start != NULL)) {
194c1d0c72aSopenharmony_ci        HDF_LOGI("%{public}s start loop", hostName);
195c1d0c72aSopenharmony_ci        looper->Start(looper);
196c1d0c72aSopenharmony_ci    }
197c1d0c72aSopenharmony_ci    HdfPowerManagerExit();
198c1d0c72aSopenharmony_ci    DevHostDumpDeInit();
199c1d0c72aSopenharmony_ci    HDF_LOGI("hdf device host %{public}s %{public}d %{public}d exit", hostName, hostId, status);
200c1d0c72aSopenharmony_ci    if (strcmp(hostName, "camera_host") == 0) {
201c1d0c72aSopenharmony_ci        _exit(status);
202c1d0c72aSopenharmony_ci    }
203c1d0c72aSopenharmony_ci    return status;
204c1d0c72aSopenharmony_ci}
205