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