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, ¶m) != 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