1/*
2 * Copyright (c) 2023 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 <climits>
17#include <dlfcn.h>
18#include <map>
19#include <thread>
20
21#include "../include/module_log.h"
22#include "../include/module_manager.h"
23
24namespace OHOS {
25namespace UpdateEngine {
26std::map<uint32_t, RequestFuncType> ModuleManager::onRemoteRequestFuncMap_;
27std::map<std::string, LifeCycleFuncType> ModuleManager::onStartOnStopFuncMap_;
28std::map<std::string, LifeCycleFuncReturnType> ModuleManager::onIdleFuncMap_;
29std::map<std::string, LifeCycleFuncDumpType> ModuleManager::onDumpFuncMap_;
30std::mutex ModuleManager::onRemoteRequestFuncMapMutex_;
31std::mutex ModuleManager::onStartOnStopFuncMapMutex_;
32std::mutex ModuleManager::onIdleFuncMapMutex_;
33std::mutex ModuleManager::onDumpFuncMapMutex_;
34
35bool ModuleManager::isLoaded = false;
36
37void ModuleManager::LoadModule(std::string libPath)
38{
39    std::string prefix = "/system/lib64/updateext";
40    std::string modulePrefix = "/module_update/3006/lib64/updateext";
41    std::string suffix = ".so";
42    if ((libPath.substr(0, prefix.length()) != prefix &&
43        libPath.substr(0, modulePrefix.length()) != modulePrefix) ||
44        (libPath.substr(libPath.length() - suffix.length(), suffix.length()) != suffix)) {
45            UTILS_LOGE("LoadModule lib path invalid");
46            return;
47    }
48    UTILS_LOGD("LoadModule so path: %{public}s", libPath.c_str());
49    if (dueModuleHandler == nullptr) {
50        constexpr int32_t maxRetryTimes = 1;
51        int32_t retryTimes = 0;
52        char dealPath[PATH_MAX] = {};
53        if (realpath(libPath.c_str(), dealPath) == nullptr) {
54            UTILS_LOGE("soPath %{private}s is not exist or invalid", libPath.c_str());
55            return;
56        }
57        do {
58            dueModuleHandler = dlopen(dealPath, RTLD_LAZY);
59            if (dueModuleHandler != nullptr) {
60                isLoaded = true;
61                break;
62            }
63            UTILS_LOGE("openSo path: %{public}s fail", libPath.c_str());
64            retryTimes++;
65            if (retryInterval_ > 0 && retryTimes <= maxRetryTimes) {
66                std::this_thread::sleep_for(std::chrono::milliseconds(retryInterval_));
67            }
68        } while (retryTimes <= maxRetryTimes);
69    } else {
70        isLoaded = true;
71        UTILS_LOGD("openSo ok");
72    }
73}
74
75ModuleManager& ModuleManager::GetInstance()
76{
77    static ModuleManager moduleManager;
78    return moduleManager;
79}
80
81void ModuleManager::HookFunc(std::vector<uint32_t> codes, RequestFuncType handleRemoteRequest)
82{
83    std::lock_guard<std::mutex> guard(onRemoteRequestFuncMapMutex_);
84    for (const uint32_t code : codes) {
85        if (!IsMapFuncExist(code)) {
86            UTILS_LOGI("add code %{public}d", code);
87            onRemoteRequestFuncMap_.insert(std::make_pair(code, handleRemoteRequest));
88        } else {
89            UTILS_LOGI("code %{public}d already exist", code);
90        }
91    }
92}
93
94int32_t ModuleManager::HandleFunc(uint32_t code, MessageParcel &data, MessageParcel &reply, MessageOption &option)
95{
96    if (!IsMapFuncExist(code)) {
97        UTILS_LOGI("code %{public}d not exist", code);
98    } else {
99        UTILS_LOGI("code %{public}d called", code);
100        return ((RequestFuncType)onRemoteRequestFuncMap_[code])(code, data, reply, option);
101    }
102    return 0;
103}
104
105ModuleManager::ModuleManager() {}
106
107bool ModuleManager::IsModuleLoaded()
108{
109    return isLoaded;
110}
111
112void ModuleManager::HookOnStartOnStopFunc(std::string phase, LifeCycleFuncType handleSAOnStartOnStop)
113{
114    std::lock_guard<std::mutex> guard(onStartOnStopFuncMapMutex_);
115    if (onStartOnStopFuncMap_.find(phase) == onStartOnStopFuncMap_.end()) {
116        UTILS_LOGI("add phase %{public}s", phase.c_str());
117        onStartOnStopFuncMap_.insert(std::make_pair(phase, handleSAOnStartOnStop));
118    } else {
119        UTILS_LOGI("phase %{public}s exist", phase.c_str());
120        onStartOnStopFuncMap_[phase] = handleSAOnStartOnStop;
121    }
122}
123
124void ModuleManager::HandleOnStartOnStopFunc(std::string phase, const OHOS::SystemAbilityOnDemandReason &reason)
125{
126    if (onStartOnStopFuncMap_.find(phase) == onStartOnStopFuncMap_.end()) {
127        UTILS_LOGI("phase %{public}s not exist", phase.c_str());
128        return;
129    }
130    UTILS_LOGI("HandleOnStartOnStopFunc phase %{public}s exist", phase.c_str());
131    ((LifeCycleFuncType)onStartOnStopFuncMap_[phase])(reason);
132}
133
134void ModuleManager::HookOnIdleFunc(std::string phase, LifeCycleFuncReturnType handleSAOnIdle)
135{
136    std::lock_guard<std::mutex> guard(onIdleFuncMapMutex_);
137    if (onIdleFuncMap_.find(phase) == onIdleFuncMap_.end()) {
138        UTILS_LOGI("add phase %{public}s", phase.c_str());
139        onIdleFuncMap_.insert(std::make_pair(phase, handleSAOnIdle));
140    } else {
141        UTILS_LOGI("phase %{public}s already exist", phase.c_str());
142        onIdleFuncMap_[phase] = handleSAOnIdle;
143    }
144}
145
146int32_t ModuleManager::HandleOnIdleFunc(std::string phase, const OHOS::SystemAbilityOnDemandReason &reason)
147{
148    if (onIdleFuncMap_.find(phase) == onIdleFuncMap_.end()) {
149        UTILS_LOGI("phase %{public}s not exist", phase.c_str());
150    } else {
151        UTILS_LOGI("phase %{public}s already exist", phase.c_str());
152        return ((LifeCycleFuncReturnType)onIdleFuncMap_[phase])(reason);
153    }
154    return 0;
155}
156
157void ModuleManager::HookDumpFunc(std::string phase, LifeCycleFuncDumpType handleSADump)
158{
159    std::lock_guard<std::mutex> guard(onDumpFuncMapMutex_);
160    if (onDumpFuncMap_.find(phase) == onDumpFuncMap_.end()) {
161        UTILS_LOGI("add phase %{public}s", phase.c_str());
162        onDumpFuncMap_.insert(std::make_pair(phase, handleSADump));
163    } else {
164        UTILS_LOGI("phase %{public}s already exist", phase.c_str());
165        onDumpFuncMap_[phase] = handleSADump;
166    }
167}
168
169int ModuleManager::HandleDumpFunc(std::string phase, int fd, const std::vector<std::u16string> &args)
170{
171    if (onDumpFuncMap_.find(phase) == onDumpFuncMap_.end()) {
172        UTILS_LOGI("phase %{public}s not exist", phase.c_str());
173    } else {
174        UTILS_LOGI("phase %{public}s already exist", phase.c_str());
175        return ((LifeCycleFuncDumpType)onDumpFuncMap_[phase])(fd, args);
176    }
177    return 0;
178}
179
180bool ModuleManager::IsMapFuncExist(uint32_t code)
181{
182    return onRemoteRequestFuncMap_.count(code);
183}
184} // namespace UpdateEngine
185} // namespace OHOS
186