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