• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (c) 2024 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 "egl_system_layers_manager.h"
17 
18 #include <climits>
19 #include <cstdlib>
20 #include <dlfcn.h>
21 #include <fstream>
22 #include <string>
23 #include <unistd.h>
24 #include <vector>
25 
26 #include "json/json.h"
27 #include "config_policy_utils.h"
28 #include "wrapper_log.h"
29 
30 namespace OHOS {
31 
32 namespace {
33 
34 const std::string JSON_CONFIG_PATH = "etc/graphics_game/config/graphics_game.json";
35 
36 const std::string DEFAULT_JSON_CONFIG = R"__(
37 {
38     "enableAppMode" : true,
39     "appMode" : {
40         "enableDefaultAppMode" : true,
41         "default" : ["iGraphicsCore.z"],
42     }
43 }
44 )__";
45 
46 } // end of anonymous namespace
47 
GetProcessName(pid_t pid,char * pname,int len)48 bool EglSystemLayersManager::GetProcessName(pid_t pid, char *pname, int len)
49 {
50     std::string const fileName = std::string{"/proc/"} + std::to_string(pid) + std::string("/cmdline");
51     char realFileName[PATH_MAX] = { '\0' };
52 
53     if (realpath(fileName.c_str(), realFileName) == nullptr) {
54         WLOGE("realpath failed");
55         return false;
56     }
57 
58     FILE *f = fopen(realFileName, "r");
59     if (f == nullptr) {
60         WLOGE("fopen %{private}s cmdline file failed", realFileName);
61         *pname = 0;
62         return false;
63     }
64 
65     if (fgets(pname, len, f) == nullptr) {
66         WLOGE("fgets of cmdline failed");
67         *pname = 0;
68         if (fclose(f)) {
69             WLOGE("failed to close %{private}s file", realFileName);
70         }
71         return false;
72     }
73 
74     if (*pname == 0) {
75         WLOGE("process name is empty");
76         if (fclose(f)) {
77             WLOGE("failed to close %{private}s file", realFileName);
78         }
79         return false;
80     }
81 
82     if (fclose(f)) {
83         WLOGE("failed to close %{private}s file", realFileName);
84     }
85     return true;
86 }
87 
GetDefaultJsonConfig(Json::Value & configData)88 bool EglSystemLayersManager::GetDefaultJsonConfig(Json::Value &configData)
89 {
90     WLOGD("Read default json config");
91 
92     Json::CharReaderBuilder builder;
93     Json::CharReader *charReader = builder.newCharReader();
94     if (!charReader) {
95         WLOGE("Failed to create new Json::CharReader");
96         return false;
97     }
98 
99     const std::unique_ptr<Json::CharReader> reader(charReader);
100     JSONCPP_STRING errs;
101     bool ret = reader->parse(DEFAULT_JSON_CONFIG.c_str(),
102         DEFAULT_JSON_CONFIG.c_str() + static_cast<int>(DEFAULT_JSON_CONFIG.length()), &configData, &errs);
103     if (!ret) {
104         WLOGE("default json config parse error: %{private}s", errs.c_str());
105         return false;
106     } else {
107         WLOGD("default json config parse success");
108     }
109 
110     return true;
111 }
112 
GetJsonConfig(Json::Value & configData)113 bool EglSystemLayersManager::GetJsonConfig(Json::Value &configData)
114 {
115     char pathBuf[MAX_PATH_LEN] = {'\0'};
116     char *path = GetOneCfgFile(JSON_CONFIG_PATH.c_str(), pathBuf, MAX_PATH_LEN);
117     if (!path) {
118         WLOGE("Failed to find system config path");
119         return GetDefaultJsonConfig(configData);
120     }
121 
122     std::ifstream configFile(std::string(pathBuf), std::ifstream::in);
123     if (!configFile.good()) {
124         WLOGE("Failed to open system json config file");
125         return GetDefaultJsonConfig(configData);
126     }
127 
128     Json::CharReaderBuilder builder;
129     JSONCPP_STRING errs;
130     bool readSuccess = Json::parseFromStream(builder, configFile, &configData, &errs);
131     if (!readSuccess) {
132         WLOGE("Failed to parse system json config file, error: %{private}s", errs.c_str());
133         return GetDefaultJsonConfig(configData);
134     }
135 
136     std::string hookLayerName("HOOK_LAYER");
137     if (!configData.isMember(hookLayerName)) {
138         WLOGE("Failed to find %{private}s section in system json config file", hookLayerName.c_str());
139         return GetDefaultJsonConfig(configData);
140     }
141 
142     configData = configData[hookLayerName];
143     return true;
144 }
145 
GetStringVectorFromJson(const Json::Value & jsonVector)146 std::vector<std::string> EglSystemLayersManager::GetStringVectorFromJson(const Json::Value &jsonVector)
147 {
148     std::vector<std::string> stringVector{};
149 
150     for (const auto &i : jsonVector) {
151         if (i.isString()) {
152             stringVector.push_back(i.asString());
153         } else {
154             WLOGD("%{private}s is not a string", i.asString().c_str());
155         }
156     }
157 
158     return stringVector;
159 }
160 
GetSystemLayersFromConfig(Json::Value & appModeSection,const std::string & processName)161 std::vector<std::string> EglSystemLayersManager::GetSystemLayersFromConfig(Json::Value &appModeSection,
162     const std::string &processName)
163 {
164     if (!appModeSection.isMember(processName)) {
165         std::string enableDefaultAppModeName("enableDefaultAppMode");
166         if (!appModeSection.isMember(enableDefaultAppModeName)) {
167             WLOGE("Failed to find %{private}s section", enableDefaultAppModeName.c_str());
168             return std::vector<std::string>{};
169         }
170 
171         if (!appModeSection[enableDefaultAppModeName].isBool()) {
172             WLOGE("Failed to get value of %{private}s section, not a boolean", enableDefaultAppModeName.c_str());
173             return std::vector<std::string>{};
174         }
175 
176         if (!appModeSection[enableDefaultAppModeName].asBool()) {
177             return std::vector<std::string>{};
178         }
179 
180         std::string defaultName("default");
181         if (!appModeSection.isMember(defaultName)) {
182             WLOGE("Failed to find default app mode");
183             return std::vector<std::string>{};
184         }
185 
186         const Json::Value defaultArray = appModeSection[defaultName];
187         if (!defaultArray.isArray()) {
188             WLOGE("%{private}s value is not array", defaultName.c_str());
189             return std::vector<std::string>{};
190         }
191 
192         return EglSystemLayersManager::GetStringVectorFromJson(defaultArray);
193     }
194 
195     const Json::Value layersArray = appModeSection[processName];
196     if (!layersArray.isArray()) {
197         WLOGE("%{private}s value is not array", processName.c_str());
198         return std::vector<std::string>{};
199     }
200 
201     return EglSystemLayersManager::GetStringVectorFromJson(layersArray);
202 }
203 
GetSystemLayers()204 std::vector<std::string> EglSystemLayersManager::GetSystemLayers()
205 {
206     Json::Value configData{};
207     if (!GetJsonConfig(configData)) {
208         WLOGE("Failed to get json config");
209         return std::vector<std::string>{};
210     }
211 
212     std::string enableAppModeName("enableAppMode");
213     if (!configData.isMember(enableAppModeName)) {
214         WLOGE("Failed to find %{private}s parameter in json config", enableAppModeName.c_str());
215         return std::vector<std::string>{};
216     }
217 
218     if (!configData[enableAppModeName].isBool()) {
219         WLOGE("Failed to get %{private}s parameter form config, not a boolean", enableAppModeName.c_str());
220         return std::vector<std::string>{};
221     }
222 
223     if (!configData[enableAppModeName].asBool()) {
224         return std::vector<std::string>{};
225     }
226 
227     const std::string appModeSectionName("appMode");
228     if (!configData.isMember(appModeSectionName)) {
229         WLOGE("Failed to find %{private}s section in config", appModeSectionName.c_str());
230         return std::vector<std::string>{};
231     }
232 
233     constexpr int pnameLen = 512;
234     char pname[pnameLen + 1] = {0};
235     bool res = EglSystemLayersManager::GetProcessName(getpid(), pname, pnameLen);
236     if (!res) {
237         WLOGE("Failed to get process name");
238         return std::vector<std::string>{};
239     } else {
240         WLOGD("GetProcessName() = %{public}s", pname);
241     }
242 
243     Json::Value appModeSection = configData[appModeSectionName];
244 
245     return GetSystemLayersFromConfig(appModeSection, std::string(pname));
246 }
247 
248 } //namespace OHOS
249