• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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             WLOGD("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 
GetSquidHapLayerPaths()162 static std::vector<std::string> GetSquidHapLayerPaths()
163 {
164     WLOGD("GetSquidHapLayerPaths");
165     std::vector<std::string> layerPaths = {};
166     std::string pathStr(DEBUG_SANDBOX_DIR);
167 
168     std::string appLibPath = g_bundleInfo.applicationInfo.nativeLibraryPath;
169     if (!appLibPath.empty()) {
170         layerPaths.push_back(pathStr + appLibPath + "/");
171     }
172 
173     for (auto hapModuleInfo: g_bundleInfo.hapModuleInfos) {
174         if (!hapModuleInfo.nativeLibraryPath.empty()) {
175             layerPaths.push_back(hapModuleInfo.nativeLibraryPath + "/");
176         }
177     }
178     return layerPaths;
179 }
180 
GetInstance()181 EglWrapperLayer& EglWrapperLayer::GetInstance()
182 {
183     static EglWrapperLayer layer;
184     return layer;
185 }
186 
~EglWrapperLayer()187 EglWrapperLayer::~EglWrapperLayer()
188 {
189     WLOGD("");
190     if (dlhandle_) {
191         dlclose(dlhandle_);
192         dlhandle_ = nullptr;
193     }
194 }
195 
Init(EglWrapperDispatchTable * table)196 bool EglWrapperLayer::Init(EglWrapperDispatchTable *table)
197 {
198     WLOGD("");
199     if (initialized_) {
200         WLOGI("EglWrapperLayer is already loaded.");
201         return true;
202     }
203 
204     if (table == nullptr) {
205         WLOGE("table is nullptr.");
206         return false;
207     }
208 
209     if (!LoadLayers()) {
210         WLOGE("LoadLayers failed.");
211         return false;
212     }
213 
214     InitLayers(table);
215 
216     initialized_ = true;
217     return true;
218 }
219 
InitBundleInfo()220 bool EglWrapperLayer::InitBundleInfo()
221 {
222     std::string debugHap = system::GetParameter(DEBUG_HAP_NAME, "");
223     if (debugHap.empty()) {
224         WLOGD("The parameter for debug hap name is not set!");
225         return false;
226     }
227     auto eglBundleMgrHelper = DelayedSingleton<AppExecFwk::EGLBundleMgrHelper>::GetInstance();
228     if (eglBundleMgrHelper == nullptr) {
229         WLOGE("eglBundleMgrHelper is null!");
230         return false;
231     }
232 
233     if (eglBundleMgrHelper->GetBundleInfoForSelf(
234         AppExecFwk::GetBundleInfoFlag::GET_BUNDLE_INFO_WITH_APPLICATION, g_bundleInfo) == ERR_OK) {
235         if (g_bundleInfo.name == debugHap) {
236             return true;
237         } else {
238             WLOGD("this hap is %{public}s, the debug hap is %{public}s",
239                 g_bundleInfo.name.c_str(), debugHap.c_str());
240         }
241     } else {
242         WLOGE("Call GetBundleInfoForSelf func failed!");
243     }
244     return false;
245 }
246 
SetupLayerFuncTbl(EglWrapperDispatchTable * table)247 void EglWrapperLayer::SetupLayerFuncTbl(EglWrapperDispatchTable *table)
248 {
249     layerFuncTbl_.resize(layerSetup_.size() + 1);
250     char const * const *entries;
251     EglWrapperFuncPointer *curr;
252 
253     entries = gWrapperApiNames;
254     curr = reinterpret_cast<EglWrapperFuncPointer*>(&table->wrapper);
255     SetupFuncMaps(layerFuncTbl_[0], entries, curr);
256 
257     entries = gGlApiNames2;
258     curr = reinterpret_cast<EglWrapperFuncPointer*>(&table->gl.table2);
259     SetupFuncMaps(layerFuncTbl_[0], entries, curr);
260 
261     entries = gGlApiNames3;
262     curr = reinterpret_cast<EglWrapperFuncPointer*>(&table->gl.table3);
263     SetupFuncMaps(layerFuncTbl_[0], entries, curr);
264 
265     for (uint32_t i = 0; i < layerSetup_.size(); i++) {
266         layerInit_[i](reinterpret_cast<void*>(&layerFuncTbl_[i]),
267             reinterpret_cast<GetNextLayerAddr>(GetNextLayerProcAddr));
268 
269         entries = gWrapperApiNames;
270         curr = reinterpret_cast<EglWrapperFuncPointer *>(&table->wrapper);
271         UpdateApiEntries(layerSetup_[i], curr, entries);
272         SetupFuncMaps(layerFuncTbl_[i + 1], entries, curr);
273 
274         entries = gGlApiNames2;
275         curr = reinterpret_cast<EglWrapperFuncPointer*>(&table->gl.table2);
276         UpdateApiEntries(layerSetup_[i], curr, entries);
277         SetupFuncMaps(layerFuncTbl_[i + 1], entries, curr);
278 
279         entries = gGlApiNames3;
280         curr = reinterpret_cast<EglWrapperFuncPointer*>(&table->gl.table3);
281         UpdateApiEntries(layerSetup_[i], curr, entries);
282         SetupFuncMaps(layerFuncTbl_[i + 1], entries, curr);
283     }
284 }
285 
LoadLayers()286 bool EglWrapperLayer::LoadLayers()
287 {
288     WLOGD("");
289     std::vector<std::string> layers = GetDebugLayers();
290 
291     std::vector<std::string> systemLayers = eglSystemLayersManager_.GetSystemLayers();
292 
293 #if USE_IGRAPHICS_EXTENDS_HOOKS
294     std::string iGraphicsLibName("iGraphicsCore.z");
295     for (const auto &i : systemLayers) {
296         if (i == iGraphicsLibName) {
297             iGraphicsLogic = true;
298         } else {
299             layers.push_back(i);
300         }
301     }
302 #else
303     layers.insert(layers.end(), systemLayers.begin(), systemLayers.end());
304 #endif
305 
306     if (layers.empty()) {
307         WLOGD("layers is empty");
308         return false;
309     }
310 
311     if (!InitBundleInfo()) {
312         WLOGD("Get BundleInfo failed.");
313     } else {
314         WLOGD("Get BundleInfo ok.");
315     }
316 
317     WLOGD("appProvisionType is %{public}s !", g_bundleInfo.applicationInfo.appProvisionType.c_str());
318     if (std::find(layers.begin(), layers.end(), "squid") != layers.end() &&
319         g_bundleInfo.applicationInfo.appProvisionType == "release") {
320         WLOGD("appProvisionType is release.");
321         return false;
322     }
323     return DoLoadLayers(layers);
324 }
325 
LoadLayers(const std::string & libname,const std::vector<std::string> & layerPaths)326 bool EglWrapperLayer::LoadLayers(const std::string& libname, const std::vector<std::string> &layerPaths)
327 {
328     bool success = false;
329     for (auto layerPath : layerPaths) {
330         layerPath += libname;
331         std::string realLayerPath;
332         WLOGD("LoadLayers layerPath=%{public}s", layerPath.c_str());
333         if (!PathToRealPath(layerPath, realLayerPath)) {
334             WLOGD("LoadLayers PathToRealPath is failed");
335             continue;
336         }
337         WLOGD("LoadLayers realLayerPath=%{private}s", realLayerPath.c_str());
338         if (!LoadLayerFuncs(realLayerPath)) {
339             WLOGD("LoadLayers LoadLayerFuncs is failed");
340             return false;
341         } else {
342             success = true;
343         }
344     }
345     return success;
346 }
347 
DoLoadLayers(const std::vector<std::string> & layers)348 bool EglWrapperLayer::DoLoadLayers(const std::vector<std::string>& layers)
349 {
350     for (int32_t i = static_cast<int32_t>(layers.size()) - 1; i >= 0; i--) {
351         std::string layerLib = std::string(DEBUG_LAYERS_PREFIX) + layers[i] + std::string(DEBUG_LAYERS_SUFFIX);
352         std::vector<std::string> allLayerPaths;
353         if (layerLib == "libsquid.so") {
354             allLayerPaths = GetSquidHapLayerPaths();
355             if (!LoadLayers(layerLib, allLayerPaths) && !LoadLayerFuncs(layerLib)) {
356                 WLOGD("LoadLayers squid is faild");
357                 return false;
358             } else {
359                 WLOGD("LoadLayers squid is ok!");
360             }
361         } else {
362             allLayerPaths = GetDebugLayerPaths();
363             WLOGD("LoadLayerFuncs layerLib=%{public}s", layerLib.c_str());
364             if (!LoadLayers(layerLib, allLayerPaths)) {
365                 return false;
366             } else {
367                 WLOGD("LoadLayerFuncs is ok!");
368             }
369         }
370     }
371     return true;
372 }
373 
LoadLayerFuncs(const std::string & realLayerPath)374 bool EglWrapperLayer::LoadLayerFuncs(const std::string& realLayerPath)
375 {
376     dlhandle_ = dlopen(realLayerPath.c_str(), RTLD_NOW | RTLD_LOCAL);
377     if (dlhandle_ == nullptr) {
378         WLOGE("dlopen failed. error: %{public}s.", dlerror());
379         return false;
380     }
381 
382     LayerInitFunc initFunc = (LayerInitFunc)dlsym(dlhandle_, DEBUG_LAYER_INIT_FUNC);
383     if (initFunc == nullptr) {
384         WLOGE("can't find %{public}s in debug layer library.", DEBUG_LAYER_INIT_FUNC);
385         dlclose(dlhandle_);
386         dlhandle_ = nullptr;
387         return false;
388     }
389     layerInit_.push_back(initFunc);
390 
391     LayerSetupFunc setupFunc = (LayerSetupFunc)dlsym(dlhandle_, DEBUG_LAYER_GET_PROC_ADDR_FUNC);
392     if (setupFunc == nullptr) {
393         WLOGE("can't find %{public}s in debug layer library.", DEBUG_LAYER_GET_PROC_ADDR_FUNC);
394         dlclose(dlhandle_);
395         dlhandle_ = nullptr;
396         return false;
397     }
398     layerSetup_.push_back(setupFunc);
399     return true;
400 }
401 
InitLayers(EglWrapperDispatchTable * table)402 void EglWrapperLayer::InitLayers(EglWrapperDispatchTable *table)
403 {
404     WLOGD("");
405     if (layerInit_.empty() || layerSetup_.empty()) {
406         return;
407     }
408 
409     SetupLayerFuncTbl(table);
410 #ifdef EGL_WRAPPER_DEBUG_ENABLE
411     WLOGD("layer function table info: ");
412     int count = 0;
413     for (const auto &table : layerFuncTbl_) {
414         WLOGD("===table%{public}d===: ", count++);
415         for (const auto &item : table) {
416             WLOGD("name: %{public}s : %{public}s", item.first.c_str(),
417                 (item.second != nullptr) ? "valid" : "invalid");
418         }
419     }
420 #endif
421 }
422 } // namespace OHOS
423