1190978c3Sopenharmony_ci/*
2190978c3Sopenharmony_ci * Copyright (c) 2023 Huawei Device Co., Ltd.
3190978c3Sopenharmony_ci * Licensed under the Apache License, Version 2.0 (the "License");
4190978c3Sopenharmony_ci * you may not use this file except in compliance with the License.
5190978c3Sopenharmony_ci * You may obtain a copy of the License at
6190978c3Sopenharmony_ci *
7190978c3Sopenharmony_ci *     http://www.apache.org/licenses/LICENSE-2.0
8190978c3Sopenharmony_ci *
9190978c3Sopenharmony_ci * Unless required by applicable law or agreed to in writing, software
10190978c3Sopenharmony_ci * distributed under the License is distributed on an "AS IS" BASIS,
11190978c3Sopenharmony_ci * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12190978c3Sopenharmony_ci * See the License for the specific language governing permissions and
13190978c3Sopenharmony_ci * limitations under the License.
14190978c3Sopenharmony_ci */
15190978c3Sopenharmony_ci
16190978c3Sopenharmony_ci#include <climits>
17190978c3Sopenharmony_ci#include <dlfcn.h>
18190978c3Sopenharmony_ci#include <map>
19190978c3Sopenharmony_ci#include <thread>
20190978c3Sopenharmony_ci
21190978c3Sopenharmony_ci#include "../include/module_log.h"
22190978c3Sopenharmony_ci#include "../include/module_manager.h"
23190978c3Sopenharmony_ci
24190978c3Sopenharmony_cinamespace OHOS {
25190978c3Sopenharmony_cinamespace UpdateEngine {
26190978c3Sopenharmony_cistd::map<uint32_t, RequestFuncType> ModuleManager::onRemoteRequestFuncMap_;
27190978c3Sopenharmony_cistd::map<std::string, LifeCycleFuncType> ModuleManager::onStartOnStopFuncMap_;
28190978c3Sopenharmony_cistd::map<std::string, LifeCycleFuncReturnType> ModuleManager::onIdleFuncMap_;
29190978c3Sopenharmony_cistd::map<std::string, LifeCycleFuncDumpType> ModuleManager::onDumpFuncMap_;
30190978c3Sopenharmony_cistd::mutex ModuleManager::onRemoteRequestFuncMapMutex_;
31190978c3Sopenharmony_cistd::mutex ModuleManager::onStartOnStopFuncMapMutex_;
32190978c3Sopenharmony_cistd::mutex ModuleManager::onIdleFuncMapMutex_;
33190978c3Sopenharmony_cistd::mutex ModuleManager::onDumpFuncMapMutex_;
34190978c3Sopenharmony_ci
35190978c3Sopenharmony_cibool ModuleManager::isLoaded = false;
36190978c3Sopenharmony_ci
37190978c3Sopenharmony_civoid ModuleManager::LoadModule(std::string libPath)
38190978c3Sopenharmony_ci{
39190978c3Sopenharmony_ci    std::string prefix = "/system/lib64/updateext";
40190978c3Sopenharmony_ci    std::string modulePrefix = "/module_update/3006/lib64/updateext";
41190978c3Sopenharmony_ci    std::string suffix = ".so";
42190978c3Sopenharmony_ci    if ((libPath.substr(0, prefix.length()) != prefix &&
43190978c3Sopenharmony_ci        libPath.substr(0, modulePrefix.length()) != modulePrefix) ||
44190978c3Sopenharmony_ci        (libPath.substr(libPath.length() - suffix.length(), suffix.length()) != suffix)) {
45190978c3Sopenharmony_ci            UTILS_LOGE("LoadModule lib path invalid");
46190978c3Sopenharmony_ci            return;
47190978c3Sopenharmony_ci    }
48190978c3Sopenharmony_ci    UTILS_LOGD("LoadModule so path: %{public}s", libPath.c_str());
49190978c3Sopenharmony_ci    if (dueModuleHandler == nullptr) {
50190978c3Sopenharmony_ci        constexpr int32_t maxRetryTimes = 1;
51190978c3Sopenharmony_ci        int32_t retryTimes = 0;
52190978c3Sopenharmony_ci        char dealPath[PATH_MAX] = {};
53190978c3Sopenharmony_ci        if (realpath(libPath.c_str(), dealPath) == nullptr) {
54190978c3Sopenharmony_ci            UTILS_LOGE("soPath %{private}s is not exist or invalid", libPath.c_str());
55190978c3Sopenharmony_ci            return;
56190978c3Sopenharmony_ci        }
57190978c3Sopenharmony_ci        do {
58190978c3Sopenharmony_ci            dueModuleHandler = dlopen(dealPath, RTLD_LAZY);
59190978c3Sopenharmony_ci            if (dueModuleHandler != nullptr) {
60190978c3Sopenharmony_ci                isLoaded = true;
61190978c3Sopenharmony_ci                break;
62190978c3Sopenharmony_ci            }
63190978c3Sopenharmony_ci            UTILS_LOGE("openSo path: %{public}s fail", libPath.c_str());
64190978c3Sopenharmony_ci            retryTimes++;
65190978c3Sopenharmony_ci            if (retryInterval_ > 0 && retryTimes <= maxRetryTimes) {
66190978c3Sopenharmony_ci                std::this_thread::sleep_for(std::chrono::milliseconds(retryInterval_));
67190978c3Sopenharmony_ci            }
68190978c3Sopenharmony_ci        } while (retryTimes <= maxRetryTimes);
69190978c3Sopenharmony_ci    } else {
70190978c3Sopenharmony_ci        isLoaded = true;
71190978c3Sopenharmony_ci        UTILS_LOGD("openSo ok");
72190978c3Sopenharmony_ci    }
73190978c3Sopenharmony_ci}
74190978c3Sopenharmony_ci
75190978c3Sopenharmony_ciModuleManager& ModuleManager::GetInstance()
76190978c3Sopenharmony_ci{
77190978c3Sopenharmony_ci    static ModuleManager moduleManager;
78190978c3Sopenharmony_ci    return moduleManager;
79190978c3Sopenharmony_ci}
80190978c3Sopenharmony_ci
81190978c3Sopenharmony_civoid ModuleManager::HookFunc(std::vector<uint32_t> codes, RequestFuncType handleRemoteRequest)
82190978c3Sopenharmony_ci{
83190978c3Sopenharmony_ci    std::lock_guard<std::mutex> guard(onRemoteRequestFuncMapMutex_);
84190978c3Sopenharmony_ci    for (const uint32_t code : codes) {
85190978c3Sopenharmony_ci        if (!IsMapFuncExist(code)) {
86190978c3Sopenharmony_ci            UTILS_LOGI("add code %{public}d", code);
87190978c3Sopenharmony_ci            onRemoteRequestFuncMap_.insert(std::make_pair(code, handleRemoteRequest));
88190978c3Sopenharmony_ci        } else {
89190978c3Sopenharmony_ci            UTILS_LOGI("code %{public}d already exist", code);
90190978c3Sopenharmony_ci        }
91190978c3Sopenharmony_ci    }
92190978c3Sopenharmony_ci}
93190978c3Sopenharmony_ci
94190978c3Sopenharmony_ciint32_t ModuleManager::HandleFunc(uint32_t code, MessageParcel &data, MessageParcel &reply, MessageOption &option)
95190978c3Sopenharmony_ci{
96190978c3Sopenharmony_ci    if (!IsMapFuncExist(code)) {
97190978c3Sopenharmony_ci        UTILS_LOGI("code %{public}d not exist", code);
98190978c3Sopenharmony_ci    } else {
99190978c3Sopenharmony_ci        UTILS_LOGI("code %{public}d called", code);
100190978c3Sopenharmony_ci        return ((RequestFuncType)onRemoteRequestFuncMap_[code])(code, data, reply, option);
101190978c3Sopenharmony_ci    }
102190978c3Sopenharmony_ci    return 0;
103190978c3Sopenharmony_ci}
104190978c3Sopenharmony_ci
105190978c3Sopenharmony_ciModuleManager::ModuleManager() {}
106190978c3Sopenharmony_ci
107190978c3Sopenharmony_cibool ModuleManager::IsModuleLoaded()
108190978c3Sopenharmony_ci{
109190978c3Sopenharmony_ci    return isLoaded;
110190978c3Sopenharmony_ci}
111190978c3Sopenharmony_ci
112190978c3Sopenharmony_civoid ModuleManager::HookOnStartOnStopFunc(std::string phase, LifeCycleFuncType handleSAOnStartOnStop)
113190978c3Sopenharmony_ci{
114190978c3Sopenharmony_ci    std::lock_guard<std::mutex> guard(onStartOnStopFuncMapMutex_);
115190978c3Sopenharmony_ci    if (onStartOnStopFuncMap_.find(phase) == onStartOnStopFuncMap_.end()) {
116190978c3Sopenharmony_ci        UTILS_LOGI("add phase %{public}s", phase.c_str());
117190978c3Sopenharmony_ci        onStartOnStopFuncMap_.insert(std::make_pair(phase, handleSAOnStartOnStop));
118190978c3Sopenharmony_ci    } else {
119190978c3Sopenharmony_ci        UTILS_LOGI("phase %{public}s exist", phase.c_str());
120190978c3Sopenharmony_ci        onStartOnStopFuncMap_[phase] = handleSAOnStartOnStop;
121190978c3Sopenharmony_ci    }
122190978c3Sopenharmony_ci}
123190978c3Sopenharmony_ci
124190978c3Sopenharmony_civoid ModuleManager::HandleOnStartOnStopFunc(std::string phase, const OHOS::SystemAbilityOnDemandReason &reason)
125190978c3Sopenharmony_ci{
126190978c3Sopenharmony_ci    if (onStartOnStopFuncMap_.find(phase) == onStartOnStopFuncMap_.end()) {
127190978c3Sopenharmony_ci        UTILS_LOGI("phase %{public}s not exist", phase.c_str());
128190978c3Sopenharmony_ci        return;
129190978c3Sopenharmony_ci    }
130190978c3Sopenharmony_ci    UTILS_LOGI("HandleOnStartOnStopFunc phase %{public}s exist", phase.c_str());
131190978c3Sopenharmony_ci    ((LifeCycleFuncType)onStartOnStopFuncMap_[phase])(reason);
132190978c3Sopenharmony_ci}
133190978c3Sopenharmony_ci
134190978c3Sopenharmony_civoid ModuleManager::HookOnIdleFunc(std::string phase, LifeCycleFuncReturnType handleSAOnIdle)
135190978c3Sopenharmony_ci{
136190978c3Sopenharmony_ci    std::lock_guard<std::mutex> guard(onIdleFuncMapMutex_);
137190978c3Sopenharmony_ci    if (onIdleFuncMap_.find(phase) == onIdleFuncMap_.end()) {
138190978c3Sopenharmony_ci        UTILS_LOGI("add phase %{public}s", phase.c_str());
139190978c3Sopenharmony_ci        onIdleFuncMap_.insert(std::make_pair(phase, handleSAOnIdle));
140190978c3Sopenharmony_ci    } else {
141190978c3Sopenharmony_ci        UTILS_LOGI("phase %{public}s already exist", phase.c_str());
142190978c3Sopenharmony_ci        onIdleFuncMap_[phase] = handleSAOnIdle;
143190978c3Sopenharmony_ci    }
144190978c3Sopenharmony_ci}
145190978c3Sopenharmony_ci
146190978c3Sopenharmony_ciint32_t ModuleManager::HandleOnIdleFunc(std::string phase, const OHOS::SystemAbilityOnDemandReason &reason)
147190978c3Sopenharmony_ci{
148190978c3Sopenharmony_ci    if (onIdleFuncMap_.find(phase) == onIdleFuncMap_.end()) {
149190978c3Sopenharmony_ci        UTILS_LOGI("phase %{public}s not exist", phase.c_str());
150190978c3Sopenharmony_ci    } else {
151190978c3Sopenharmony_ci        UTILS_LOGI("phase %{public}s already exist", phase.c_str());
152190978c3Sopenharmony_ci        return ((LifeCycleFuncReturnType)onIdleFuncMap_[phase])(reason);
153190978c3Sopenharmony_ci    }
154190978c3Sopenharmony_ci    return 0;
155190978c3Sopenharmony_ci}
156190978c3Sopenharmony_ci
157190978c3Sopenharmony_civoid ModuleManager::HookDumpFunc(std::string phase, LifeCycleFuncDumpType handleSADump)
158190978c3Sopenharmony_ci{
159190978c3Sopenharmony_ci    std::lock_guard<std::mutex> guard(onDumpFuncMapMutex_);
160190978c3Sopenharmony_ci    if (onDumpFuncMap_.find(phase) == onDumpFuncMap_.end()) {
161190978c3Sopenharmony_ci        UTILS_LOGI("add phase %{public}s", phase.c_str());
162190978c3Sopenharmony_ci        onDumpFuncMap_.insert(std::make_pair(phase, handleSADump));
163190978c3Sopenharmony_ci    } else {
164190978c3Sopenharmony_ci        UTILS_LOGI("phase %{public}s already exist", phase.c_str());
165190978c3Sopenharmony_ci        onDumpFuncMap_[phase] = handleSADump;
166190978c3Sopenharmony_ci    }
167190978c3Sopenharmony_ci}
168190978c3Sopenharmony_ci
169190978c3Sopenharmony_ciint ModuleManager::HandleDumpFunc(std::string phase, int fd, const std::vector<std::u16string> &args)
170190978c3Sopenharmony_ci{
171190978c3Sopenharmony_ci    if (onDumpFuncMap_.find(phase) == onDumpFuncMap_.end()) {
172190978c3Sopenharmony_ci        UTILS_LOGI("phase %{public}s not exist", phase.c_str());
173190978c3Sopenharmony_ci    } else {
174190978c3Sopenharmony_ci        UTILS_LOGI("phase %{public}s already exist", phase.c_str());
175190978c3Sopenharmony_ci        return ((LifeCycleFuncDumpType)onDumpFuncMap_[phase])(fd, args);
176190978c3Sopenharmony_ci    }
177190978c3Sopenharmony_ci    return 0;
178190978c3Sopenharmony_ci}
179190978c3Sopenharmony_ci
180190978c3Sopenharmony_cibool ModuleManager::IsMapFuncExist(uint32_t code)
181190978c3Sopenharmony_ci{
182190978c3Sopenharmony_ci    return onRemoteRequestFuncMap_.count(code);
183190978c3Sopenharmony_ci}
184190978c3Sopenharmony_ci} // namespace UpdateEngine
185190978c3Sopenharmony_ci} // namespace OHOS
186