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