1 /*
2 * Copyright (c) 2022 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 #include "egl_wrapper_layer.h"
16
17 #include <dlfcn.h>
18 #include <cstdlib>
19 #include <parameter.h>
20 #include <parameters.h>
21 #include <sstream>
22
23 #include "wrapper_log.h"
24 #include "directory_ex.h"
25 #include "egl_bundle_mgr_helper.h"
26
27 namespace OHOS {
28 namespace {
29 #if (defined(__aarch64__) || defined(__x86_64__))
30 constexpr const char *DEBUG_LAYERS_LIB_DIR = "/system/lib64/";
31 #else
32 constexpr const char *DEBUG_LAYERS_LIB_DIR = "/system/lib/";
33 #endif
34 constexpr const char *DEBUG_LAYERS_PREFIX = "lib";
35 constexpr const char *DEBUG_LAYERS_SUFFIX = ".so";
36 constexpr const char *DEBUG_LAYERS_DELIMITER = ":";
37 constexpr const char *DEBUG_LAYER_INIT_FUNC = "DebugLayerInitialize";
38 constexpr const char *DEBUG_LAYER_GET_PROC_ADDR_FUNC = "DebugLayerGetProcAddr";
39 constexpr const char *DEBUG_LAYER_NAME = "debug.graphic.debug_layer";
40 constexpr const char *DEBUG_HAP_NAME = "debug.graphic.debug_hap";
41 constexpr const char *DEBUG_SANDBOX_DIR = "/data/storage/el1/bundle/";
42 }
43
44 static std::string g_strLayers;
45 static AppExecFwk::BundleInfo g_bundleInfo;
46
GetWrapperDebugLayers(const char * key,const char * value,void * context)47 static void GetWrapperDebugLayers(const char *key, const char *value, void *context)
48 {
49 WLOGD("");
50 g_strLayers = std::string(value);
51 WLOGD("g_strLayers is %{public}s", g_strLayers.c_str());
52 }
53
UpdateApiEntries(LayerSetupFunc func,EglWrapperFuncPointer * curr,char const * const * entries)54 static void UpdateApiEntries(LayerSetupFunc func,
55 EglWrapperFuncPointer *curr, char const * const *entries)
56 {
57 WLOGD("");
58 while (*entries) {
59 char const *name = *entries;
60 EglWrapperFuncPointer layerFunc = func(name, *curr);
61 if (layerFunc == nullptr) {
62 WLOGW("LayerSetupFunc(%{public}s) return nullptr.", name);
63 } else if (layerFunc != *curr) {
64 WLOGI("Update api entry for %{public}s", name);
65 *curr = layerFunc;
66 }
67 curr++;
68 entries++;
69 }
70 }
71
SetupFuncMaps(FunctionTable & table,char const * const * entries,EglWrapperFuncPointer * curr)72 static void SetupFuncMaps(FunctionTable &table,
73 char const * const *entries, EglWrapperFuncPointer *curr)
74 {
75 WLOGD("");
76 while (*entries) {
77 const char *name = *entries;
78 if (table.find(name) == table.end()) {
79 table[name] = *curr;
80 } else {
81 WLOGD("duplicate function name(%{public}s)", name);
82 }
83
84 entries++;
85 curr++;
86 }
87 }
88
GetNextLayerProcAddr(void * funcTable,const char * name)89 static const void *GetNextLayerProcAddr(void *funcTable, const char *name)
90 {
91 WLOGD("name = %{public}s", name);
92 auto table = reinterpret_cast<FunctionTable *>(funcTable);
93 if (table->find(name) == table->end()) {
94 WLOGE("not found in function table, name = %{public}s", name);
95 return nullptr;
96 }
97
98 EglWrapperFuncPointer val = (*table)[name];
99 return reinterpret_cast<void *>(val);
100 }
101
SplitEnvString(std::string str,std::vector<std::string> * layers)102 static void SplitEnvString(std::string str, std::vector<std::string> *layers)
103 {
104 WLOGD("");
105 size_t pos1 = 0;
106 size_t pos2 = str.find(DEBUG_LAYERS_DELIMITER);
107 while (pos2 != std::string::npos) {
108 layers->emplace_back(str.substr(pos1, pos2-pos1));
109 pos1 = pos2 + 1;
110 pos2 = str.find(DEBUG_LAYERS_DELIMITER, pos1);
111 }
112
113 if (pos1 != str.length()) {
114 layers->emplace_back(str.substr(pos1));
115 }
116 }
117
GetDebugLayers(void)118 static std::vector<std::string> GetDebugLayers(void)
119 {
120 WLOGD("");
121 std::vector<std::string> layers;
122
123 g_strLayers = system::GetParameter(DEBUG_LAYER_NAME, "");
124 WLOGD("g_strLayers is %{public}s", g_strLayers.c_str());
125 auto ret = WatchParameter(DEBUG_LAYER_NAME, GetWrapperDebugLayers, nullptr);
126 if (ret) {
127 WLOGD("WatchParameter faild.");
128 }
129
130 if (!g_strLayers.empty()) {
131 SplitEnvString(g_strLayers, &layers);
132 } else {
133 WLOGD("OPENGL_WRAPPER_DEBUG_LAYERS is not set.");
134 }
135
136 for (auto i : layers) {
137 WLOGD("OPENGL_WRAPPER_DEBUG_LAYERS layer = %{public}s\n", i.c_str());
138 }
139
140 return layers;
141 }
142
GetDebugLayerPaths()143 static std::vector<std::string> GetDebugLayerPaths()
144 {
145 WLOGD("GetDebugLayerPaths");
146 std::vector<std::string> layerPaths = {std::string(DEBUG_LAYERS_LIB_DIR)};
147 std::string pathStr(DEBUG_SANDBOX_DIR);
148
149 std::string appLibPath = g_bundleInfo.applicationInfo.nativeLibraryPath;
150 if (!appLibPath.empty()) {
151 layerPaths.push_back(pathStr + appLibPath + "/");
152 }
153
154 for (auto hapModuleInfo: g_bundleInfo.hapModuleInfos) {
155 if (!hapModuleInfo.nativeLibraryPath.empty()) {
156 layerPaths.push_back(hapModuleInfo.nativeLibraryPath + "/");
157 }
158 }
159 return layerPaths;
160 }
161
GetInstance()162 EglWrapperLayer& EglWrapperLayer::GetInstance()
163 {
164 static EglWrapperLayer layer;
165 return layer;
166 }
167
~EglWrapperLayer()168 EglWrapperLayer::~EglWrapperLayer()
169 {
170 WLOGD("");
171 if (dlhandle_) {
172 dlclose(dlhandle_);
173 dlhandle_ = nullptr;
174 }
175 }
176
Init(EglWrapperDispatchTable * table)177 bool EglWrapperLayer::Init(EglWrapperDispatchTable *table)
178 {
179 WLOGD("");
180 if (initialized_) {
181 WLOGI("EglWrapperLayer is already loaded.");
182 return true;
183 }
184
185 if (table == nullptr) {
186 WLOGE("table is nullptr.");
187 return false;
188 }
189
190 if (!LoadLayers()) {
191 WLOGE("LoadLayers failed.");
192 return false;
193 }
194
195 InitLayers(table);
196
197 initialized_ = true;
198 return true;
199 }
200
InitBundleInfo()201 bool EglWrapperLayer::InitBundleInfo()
202 {
203 std::string debugHap = system::GetParameter(DEBUG_HAP_NAME, "");
204 if (debugHap.empty()) {
205 WLOGD("The parameter for debug hap name is not set!");
206 return false;
207 }
208 auto eglBundleMgrHelper = DelayedSingleton<AppExecFwk::EGLBundleMgrHelper>::GetInstance();
209 if (eglBundleMgrHelper == nullptr) {
210 WLOGE("eglBundleMgrHelper is null!");
211 return false;
212 }
213
214 if (eglBundleMgrHelper->GetBundleInfoForSelf(
215 AppExecFwk::GetBundleInfoFlag::GET_BUNDLE_INFO_WITH_APPLICATION, g_bundleInfo) == ERR_OK) {
216 if (g_bundleInfo.name == debugHap) {
217 return true;
218 } else {
219 WLOGD("this hap is %{public}s, the debug hap is %{public}s",
220 g_bundleInfo.name.c_str(), debugHap.c_str());
221 }
222 } else {
223 WLOGE("Call GetBundleInfoForSelf func failed!");
224 }
225 return false;
226 }
227
SetupLayerFuncTbl(EglWrapperDispatchTable * table)228 void EglWrapperLayer::SetupLayerFuncTbl(EglWrapperDispatchTable *table)
229 {
230 layerFuncTbl_.resize(layerSetup_.size() + 1);
231 char const * const *entries;
232 EglWrapperFuncPointer *curr;
233
234 entries = gWrapperApiNames;
235 curr = reinterpret_cast<EglWrapperFuncPointer*>(&table->wrapper);
236 SetupFuncMaps(layerFuncTbl_[0], entries, curr);
237
238 entries = gGlApiNames2;
239 curr = reinterpret_cast<EglWrapperFuncPointer*>(&table->gl.table2);
240 SetupFuncMaps(layerFuncTbl_[0], entries, curr);
241
242 entries = gGlApiNames3;
243 curr = reinterpret_cast<EglWrapperFuncPointer*>(&table->gl.table3);
244 SetupFuncMaps(layerFuncTbl_[0], entries, curr);
245
246 for (uint32_t i = 0; i < layerSetup_.size(); i++) {
247 layerInit_[i](reinterpret_cast<void*>(&layerFuncTbl_[i]),
248 reinterpret_cast<GetNextLayerAddr>(GetNextLayerProcAddr));
249
250 entries = gWrapperApiNames;
251 curr = reinterpret_cast<EglWrapperFuncPointer *>(&table->wrapper);
252 UpdateApiEntries(layerSetup_[i], curr, entries);
253 SetupFuncMaps(layerFuncTbl_[i + 1], entries, curr);
254
255 entries = gGlApiNames2;
256 curr = reinterpret_cast<EglWrapperFuncPointer*>(&table->gl.table2);
257 UpdateApiEntries(layerSetup_[i], curr, entries);
258 SetupFuncMaps(layerFuncTbl_[i + 1], entries, curr);
259
260 entries = gGlApiNames3;
261 curr = reinterpret_cast<EglWrapperFuncPointer*>(&table->gl.table3);
262 UpdateApiEntries(layerSetup_[i], curr, entries);
263 SetupFuncMaps(layerFuncTbl_[i + 1], entries, curr);
264 }
265 }
266
LoadLayers()267 bool EglWrapperLayer::LoadLayers()
268 {
269 WLOGD("");
270 std::vector<std::string> layers = GetDebugLayers();
271
272 std::vector<std::string> systemLayers = eglSystemLayersManager_.GetSystemLayers();
273
274 #if USE_IGRAPHICS_EXTENDS_HOOKS
275 std::string iGraphicsLibName("iGraphicsCore.z");
276 for (const auto &i : systemLayers) {
277 if (i == iGraphicsLibName) {
278 iGraphicsLogic = true;
279 } else {
280 layers.push_back(i);
281 }
282 }
283 #else
284 layers.insert(layers.end(), systemLayers.begin(), systemLayers.end());
285 #endif
286
287 if (layers.empty()) {
288 WLOGD("layers is empty");
289 return false;
290 }
291
292 if (!InitBundleInfo()) {
293 WLOGD("Get BundleInfo failed.");
294 }
295
296 for (int32_t i = layers.size() - 1; i >= 0; i--) {
297 std::string layerLib = std::string(DEBUG_LAYERS_PREFIX) + layers[i] + std::string(DEBUG_LAYERS_SUFFIX);
298 std::vector<std::string> allLayerPaths = GetDebugLayerPaths();
299 for (std::string layerPath: allLayerPaths) {
300 layerPath += layerLib;
301 std::string realLayerPath;
302 if (!PathToRealPath(layerPath, realLayerPath)) {
303 continue;
304 }
305 if (!LoadLayerFuncs(realLayerPath)) {
306 return false;
307 }
308 }
309 }
310 return true;
311 }
312
LoadLayerFuncs(const std::string & realLayerPath)313 bool EglWrapperLayer::LoadLayerFuncs(const std::string& realLayerPath)
314 {
315 dlhandle_ = dlopen(realLayerPath.c_str(), RTLD_NOW | RTLD_LOCAL);
316 if (dlhandle_ == nullptr) {
317 WLOGE("dlopen failed. error: %{public}s.", dlerror());
318 return false;
319 }
320
321 LayerInitFunc initFunc = (LayerInitFunc)dlsym(dlhandle_, DEBUG_LAYER_INIT_FUNC);
322 if (initFunc == nullptr) {
323 WLOGE("can't find %{public}s in debug layer library.", DEBUG_LAYER_INIT_FUNC);
324 dlclose(dlhandle_);
325 dlhandle_ = nullptr;
326 return false;
327 }
328 layerInit_.push_back(initFunc);
329
330 LayerSetupFunc setupFunc = (LayerSetupFunc)dlsym(dlhandle_, DEBUG_LAYER_GET_PROC_ADDR_FUNC);
331 if (setupFunc == nullptr) {
332 WLOGE("can't find %{public}s in debug layer library.", DEBUG_LAYER_GET_PROC_ADDR_FUNC);
333 dlclose(dlhandle_);
334 dlhandle_ = nullptr;
335 return false;
336 }
337 layerSetup_.push_back(setupFunc);
338 return true;
339 }
340
InitLayers(EglWrapperDispatchTable * table)341 void EglWrapperLayer::InitLayers(EglWrapperDispatchTable *table)
342 {
343 WLOGD("");
344 if (layerInit_.empty() || layerSetup_.empty()) {
345 return;
346 }
347
348 SetupLayerFuncTbl(table);
349 #ifdef EGL_WRAPPER_DEBUG_ENABLE
350 WLOGD("layer function table info: ");
351 int count = 0;
352 for (const auto &table : layerFuncTbl_) {
353 WLOGD("===table%{public}d===: ", count++);
354 for (const auto &item : table) {
355 WLOGD("name: %{public}s : %{public}s", item.first.c_str(),
356 (item.second != nullptr) ? "valid" : "invalid");
357 }
358 }
359 #endif
360 }
361 } // namespace OHOS
362