blob: 8e883b33d810ae73f6d37e1be30c637752fb15ab [file] [log] [blame]
Jesse Hall90b25ed2016-12-12 12:56:46 -08001/*
2 * Copyright 2017 The Android Open Source Project
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
17//#define LOG_NDEBUG 1
18#define LOG_TAG "GraphicsEnv"
Jiyong Park27c39e12017-05-08 13:00:02 +090019#include <graphicsenv/GraphicsEnv.h>
Jesse Hall90b25ed2016-12-12 12:56:46 -080020
Yiwei Zhang9df2a652018-11-27 19:58:29 -080021#include <dlfcn.h>
Jesse Hall53457db2016-12-14 16:54:06 -080022
Yiwei Zhang9df2a652018-11-27 19:58:29 -080023#include <android-base/file.h>
24#include <android-base/properties.h>
25#include <android-base/strings.h>
Jiyong Park9b816a82018-01-02 17:37:37 +090026#include <android/dlext.h>
Jesse Hall90b25ed2016-12-12 12:56:46 -080027#include <log/log.h>
Yiwei Zhang9df2a652018-11-27 19:58:29 -080028#include <sys/prctl.h>
29
30#include <mutex>
Jesse Hall90b25ed2016-12-12 12:56:46 -080031
Jesse Hall57de0ff2017-05-05 16:41:35 -070032// TODO(b/37049319) Get this from a header once one exists
33extern "C" {
Yiwei Zhang9df2a652018-11-27 19:58:29 -080034android_namespace_t* android_get_exported_namespace(const char*);
35android_namespace_t* android_create_namespace(const char* name, const char* ld_library_path,
36 const char* default_library_path, uint64_t type,
37 const char* permitted_when_isolated_path,
38 android_namespace_t* parent);
39bool android_link_namespaces(android_namespace_t* from, android_namespace_t* to,
40 const char* shared_libs_sonames);
Jiyong Park9b816a82018-01-02 17:37:37 +090041
Yiwei Zhang9df2a652018-11-27 19:58:29 -080042enum {
43 ANDROID_NAMESPACE_TYPE_ISOLATED = 1,
44 ANDROID_NAMESPACE_TYPE_SHARED = 2,
45};
Jesse Hall57de0ff2017-05-05 16:41:35 -070046}
47
Jesse Hall90b25ed2016-12-12 12:56:46 -080048namespace android {
49
Yiwei Zhang9df2a652018-11-27 19:58:29 -080050enum NativeLibrary {
51 LLNDK = 0,
52 VNDKSP = 1,
53};
54
55static constexpr const char* kNativeLibrariesSystemConfigPath[] = {"/etc/llndk.libraries.txt",
56 "/etc/vndksp.libraries.txt"};
57
58static std::string vndkVersionStr() {
59#ifdef __BIONIC__
60 std::string version = android::base::GetProperty("ro.vndk.version", "");
61 if (version != "" && version != "current") {
62 return "." + version;
63 }
64#endif
65 return "";
66}
67
68static void insertVndkVersionStr(std::string* fileName) {
69 LOG_ALWAYS_FATAL_IF(!fileName, "fileName should never be nullptr");
70 size_t insertPos = fileName->find_last_of(".");
71 if (insertPos == std::string::npos) {
72 insertPos = fileName->length();
73 }
74 fileName->insert(insertPos, vndkVersionStr());
75}
76
77static bool readConfig(const std::string& configFile, std::vector<std::string>* soNames) {
78 // Read list of public native libraries from the config file.
79 std::string fileContent;
80 if (!base::ReadFileToString(configFile, &fileContent)) {
81 return false;
82 }
83
84 std::vector<std::string> lines = base::Split(fileContent, "\n");
85
86 for (auto& line : lines) {
87 auto trimmedLine = base::Trim(line);
88 if (!trimmedLine.empty()) {
89 soNames->push_back(trimmedLine);
90 }
91 }
92
93 return true;
94}
95
96static const std::string getSystemNativeLibraries(NativeLibrary type) {
97 static const char* androidRootEnv = getenv("ANDROID_ROOT");
98 static const std::string rootDir = androidRootEnv != nullptr ? androidRootEnv : "/system";
99
100 std::string nativeLibrariesSystemConfig = rootDir + kNativeLibrariesSystemConfigPath[type];
101
102 insertVndkVersionStr(&nativeLibrariesSystemConfig);
103
104 std::vector<std::string> soNames;
105 if (!readConfig(nativeLibrariesSystemConfig, &soNames)) {
106 ALOGE("Failed to retrieve library names from %s", nativeLibrariesSystemConfig.c_str());
107 return "";
108 }
109
110 return base::Join(soNames, ':');
111}
112
Jesse Hall90b25ed2016-12-12 12:56:46 -0800113/*static*/ GraphicsEnv& GraphicsEnv::getInstance() {
114 static GraphicsEnv env;
115 return env;
116}
117
118void GraphicsEnv::setDriverPath(const std::string path) {
119 if (!mDriverPath.empty()) {
Yiwei Zhang9df2a652018-11-27 19:58:29 -0800120 ALOGV("ignoring attempt to change driver path from '%s' to '%s'", mDriverPath.c_str(),
121 path.c_str());
Jesse Hall90b25ed2016-12-12 12:56:46 -0800122 return;
123 }
124 ALOGV("setting driver path to '%s'", path.c_str());
125 mDriverPath = path;
126}
127
Victor Khimenkobbf77002018-08-16 22:38:36 +0200128void GraphicsEnv::setLayerPaths(NativeLoaderNamespace* appNamespace, const std::string layerPaths) {
Cody Northropd2aa3ab2017-10-20 09:01:53 -0600129 if (mLayerPaths.empty()) {
130 mLayerPaths = layerPaths;
131 mAppNamespace = appNamespace;
132 } else {
133 ALOGV("Vulkan layer search path already set, not clobbering with '%s' for namespace %p'",
Yiwei Zhang9df2a652018-11-27 19:58:29 -0800134 layerPaths.c_str(), appNamespace);
Cody Northropd2aa3ab2017-10-20 09:01:53 -0600135 }
136}
137
Victor Khimenkobbf77002018-08-16 22:38:36 +0200138NativeLoaderNamespace* GraphicsEnv::getAppNamespace() {
Cody Northropd2aa3ab2017-10-20 09:01:53 -0600139 return mAppNamespace;
140}
141
142const std::string GraphicsEnv::getLayerPaths(){
143 return mLayerPaths;
144}
145
146const std::string GraphicsEnv::getDebugLayers() {
147 return mDebugLayers;
148}
149
150void GraphicsEnv::setDebugLayers(const std::string layers) {
151 mDebugLayers = layers;
152}
153
Jesse Hall53457db2016-12-14 16:54:06 -0800154android_namespace_t* GraphicsEnv::getDriverNamespace() {
155 static std::once_flag once;
156 std::call_once(once, [this]() {
Yiwei Zhang9df2a652018-11-27 19:58:29 -0800157 if (mDriverPath.empty()) return;
158
159 auto vndkNamespace = android_get_exported_namespace("vndk");
160 if (!vndkNamespace) return;
161
Jesse Hall57de0ff2017-05-05 16:41:35 -0700162 mDriverNamespace = android_create_namespace("gfx driver",
Peiyong Lina6498682018-10-24 11:18:07 -0700163 mDriverPath.c_str(), // ld_library_path
Jesse Hall57de0ff2017-05-05 16:41:35 -0700164 mDriverPath.c_str(), // default_library_path
Yiwei Zhang9df2a652018-11-27 19:58:29 -0800165 ANDROID_NAMESPACE_TYPE_ISOLATED,
Jesse Hall57de0ff2017-05-05 16:41:35 -0700166 nullptr, // permitted_when_isolated_path
Yiwei Zhang9df2a652018-11-27 19:58:29 -0800167 nullptr);
168
169 const std::string llndkLibraries = getSystemNativeLibraries(NativeLibrary::LLNDK);
170 if (llndkLibraries.empty()) {
171 mDriverNamespace = nullptr;
172 return;
173 }
174 if (!android_link_namespaces(mDriverNamespace, nullptr, llndkLibraries.c_str())) {
175 ALOGE("Failed to link default namespace[%s]", dlerror());
176 mDriverNamespace = nullptr;
177 return;
178 }
179
180 const std::string vndkspLibraries = getSystemNativeLibraries(NativeLibrary::VNDKSP);
181 if (vndkspLibraries.empty()) {
182 mDriverNamespace = nullptr;
183 return;
184 }
185 if (!android_link_namespaces(mDriverNamespace, vndkNamespace, vndkspLibraries.c_str())) {
186 ALOGE("Failed to link vndk namespace[%s]", dlerror());
187 mDriverNamespace = nullptr;
188 return;
189 }
Jesse Hall53457db2016-12-14 16:54:06 -0800190 });
Yiwei Zhang9df2a652018-11-27 19:58:29 -0800191
Jesse Hall53457db2016-12-14 16:54:06 -0800192 return mDriverNamespace;
193}
194
Jesse Hall90b25ed2016-12-12 12:56:46 -0800195} // namespace android
Jesse Hall7a8d83e2016-12-20 15:24:28 -0800196
197extern "C" android_namespace_t* android_getDriverNamespace() {
198 return android::GraphicsEnv::getInstance().getDriverNamespace();
199}