• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 //
2 // Copyright 2018 The ANGLE Project Authors. All rights reserved.
3 // Use of this source code is governed by a BSD-style license that can be
4 // found in the LICENSE file.
5 //
6 
7 // system_utils.cpp: Implementation of common functions
8 
9 #include "common/system_utils.h"
10 
11 #include <stdlib.h>
12 
13 #if defined(ANGLE_PLATFORM_ANDROID)
14 #    include <sys/system_properties.h>
15 #endif
16 
17 namespace angle
18 {
GetExecutableName()19 std::string GetExecutableName()
20 {
21 #if defined(ANGLE_PLATFORM_ANDROID) && __ANDROID_API__ >= 21
22     // Support for "getprogname" function in bionic was introduced in L (API level 21)
23     const char *executableName = getprogname();
24     return (executableName) ? std::string(executableName) : "ANGLE";
25 #else
26     std::string executableName = GetExecutablePath();
27     size_t lastPathSepLoc      = executableName.find_last_of(GetPathSeparator());
28     return (lastPathSepLoc > 0 ? executableName.substr(lastPathSepLoc + 1, executableName.length())
29                                : "ANGLE");
30 #endif  // ANGLE_PLATFORM_ANDROID
31 }
32 
33 // On Android return value cached in the process environment, if none, call
34 // GetEnvironmentVarOrUnCachedAndroidProperty if not in environment.
GetEnvironmentVarOrAndroidProperty(const char * variableName,const char * propertyName)35 std::string GetEnvironmentVarOrAndroidProperty(const char *variableName, const char *propertyName)
36 {
37 #if defined(ANGLE_PLATFORM_ANDROID) && __ANDROID_API__ >= 21
38     // Can't use GetEnvironmentVar here because that won't allow us to distinguish between the
39     // environment being set to an empty string vs. not set at all.
40     const char *variableValue = getenv(variableName);
41     if (variableValue != nullptr)
42     {
43         std::string value(variableValue);
44         return value;
45     }
46 #endif
47     return GetEnvironmentVarOrUnCachedAndroidProperty(variableName, propertyName);
48 }
49 
50 // On Android call out to 'getprop' on a shell to get an Android property.  On desktop, return
51 // the value of the environment variable.
GetEnvironmentVarOrUnCachedAndroidProperty(const char * variableName,const char * propertyName)52 std::string GetEnvironmentVarOrUnCachedAndroidProperty(const char *variableName,
53                                                        const char *propertyName)
54 {
55 #if defined(ANGLE_PLATFORM_ANDROID) && __ANDROID_API__ >= 26
56     std::string propertyValue;
57 
58     const prop_info *propertyInfo = __system_property_find(propertyName);
59     if (propertyInfo != nullptr)
60     {
61         __system_property_read_callback(
62             propertyInfo,
63             [](void *cookie, const char *, const char *value, unsigned) {
64                 auto propertyValue = reinterpret_cast<std::string *>(cookie);
65                 *propertyValue     = value;
66             },
67             &propertyValue);
68     }
69 
70     return propertyValue;
71 #else
72     // Return the environment variable's value.
73     return GetEnvironmentVar(variableName);
74 #endif  // ANGLE_PLATFORM_ANDROID
75 }
76 
77 // Look up a property and add it to the application's environment.
78 // Adding to the env is a performance optimization, as getting properties is expensive.
79 // This should only be used in non-Release paths, i.e. when using FrameCapture or DebugUtils.
80 // It can cause race conditions in stress testing. See http://anglebug.com/6822
GetAndSetEnvironmentVarOrUnCachedAndroidProperty(const char * variableName,const char * propertyName)81 std::string GetAndSetEnvironmentVarOrUnCachedAndroidProperty(const char *variableName,
82                                                              const char *propertyName)
83 {
84     std::string value = GetEnvironmentVarOrUnCachedAndroidProperty(variableName, propertyName);
85 
86 #if defined(ANGLE_PLATFORM_ANDROID)
87     if (!value.empty())
88     {
89         // Set the environment variable with the value to improve future lookups (avoids
90         SetEnvironmentVar(variableName, value.c_str());
91     }
92 #endif
93 
94     return value;
95 }
96 
GetBoolEnvironmentVar(const char * variableName)97 bool GetBoolEnvironmentVar(const char *variableName)
98 {
99     std::string envVarString = GetEnvironmentVar(variableName);
100     return (!envVarString.empty() && envVarString == "1");
101 }
102 
PrependPathToEnvironmentVar(const char * variableName,const char * path)103 bool PrependPathToEnvironmentVar(const char *variableName, const char *path)
104 {
105     std::string oldValue = GetEnvironmentVar(variableName);
106     const char *newValue = nullptr;
107     std::string buf;
108     if (oldValue.empty())
109     {
110         newValue = path;
111     }
112     else
113     {
114         buf = path;
115         buf += GetPathSeparatorForEnvironmentVar();
116         buf += oldValue;
117         newValue = buf.c_str();
118     }
119     return SetEnvironmentVar(variableName, newValue);
120 }
121 
IsFullPath(std::string dirName)122 bool IsFullPath(std::string dirName)
123 {
124     if (dirName.find(GetRootDirectory()) == 0)
125     {
126         return true;
127     }
128     return false;
129 }
130 
ConcatenatePath(std::string first,std::string second)131 std::string ConcatenatePath(std::string first, std::string second)
132 {
133     if (first.empty())
134     {
135         return second;
136     }
137     if (second.empty())
138     {
139         return first;
140     }
141     if (IsFullPath(second))
142     {
143         return second;
144     }
145     bool firstRedundantPathSeparator = first.find_last_of(GetPathSeparator()) == first.length() - 1;
146     bool secondRedundantPathSeparator = second.find(GetPathSeparator()) == 0;
147     if (firstRedundantPathSeparator && secondRedundantPathSeparator)
148     {
149         return first + second.substr(1);
150     }
151     else if (firstRedundantPathSeparator || secondRedundantPathSeparator)
152     {
153         return first + second;
154     }
155     return first + GetPathSeparator() + second;
156 }
157 
PageFaultHandler(PageFaultCallback callback)158 PageFaultHandler::PageFaultHandler(PageFaultCallback callback) : mCallback(callback) {}
~PageFaultHandler()159 PageFaultHandler::~PageFaultHandler() {}
160 
OpenSharedLibrary(const char * libraryName,SearchType searchType)161 Library *OpenSharedLibrary(const char *libraryName, SearchType searchType)
162 {
163     void *libraryHandle = OpenSystemLibraryAndGetError(libraryName, searchType, nullptr);
164     return new Library(libraryHandle);
165 }
166 
OpenSharedLibraryWithExtension(const char * libraryName,SearchType searchType)167 Library *OpenSharedLibraryWithExtension(const char *libraryName, SearchType searchType)
168 {
169     void *libraryHandle =
170         OpenSystemLibraryWithExtensionAndGetError(libraryName, searchType, nullptr);
171     return new Library(libraryHandle);
172 }
173 
OpenSharedLibraryAndGetError(const char * libraryName,SearchType searchType,std::string * errorOut)174 Library *OpenSharedLibraryAndGetError(const char *libraryName,
175                                       SearchType searchType,
176                                       std::string *errorOut)
177 {
178     void *libraryHandle = OpenSystemLibraryAndGetError(libraryName, searchType, errorOut);
179     return new Library(libraryHandle);
180 }
181 
OpenSharedLibraryWithExtensionAndGetError(const char * libraryName,SearchType searchType,std::string * errorOut)182 Library *OpenSharedLibraryWithExtensionAndGetError(const char *libraryName,
183                                                    SearchType searchType,
184                                                    std::string *errorOut)
185 {
186     void *libraryHandle =
187         OpenSystemLibraryWithExtensionAndGetError(libraryName, searchType, errorOut);
188     return new Library(libraryHandle);
189 }
190 
OpenSystemLibrary(const char * libraryName,SearchType searchType)191 void *OpenSystemLibrary(const char *libraryName, SearchType searchType)
192 {
193     return OpenSystemLibraryAndGetError(libraryName, searchType, nullptr);
194 }
195 
OpenSystemLibraryWithExtension(const char * libraryName,SearchType searchType)196 void *OpenSystemLibraryWithExtension(const char *libraryName, SearchType searchType)
197 {
198     return OpenSystemLibraryWithExtensionAndGetError(libraryName, searchType, nullptr);
199 }
200 
OpenSystemLibraryAndGetError(const char * libraryName,SearchType searchType,std::string * errorOut)201 void *OpenSystemLibraryAndGetError(const char *libraryName,
202                                    SearchType searchType,
203                                    std::string *errorOut)
204 {
205     std::string libraryWithExtension = std::string(libraryName) + "." + GetSharedLibraryExtension();
206     return OpenSystemLibraryWithExtensionAndGetError(libraryWithExtension.c_str(), searchType,
207                                                      errorOut);
208 }
209 }  // namespace angle
210