Loading libs/graphicsenv/GraphicsEnv.cpp +192 −43 Original line number Diff line number Diff line Loading @@ -19,6 +19,7 @@ #include <graphicsenv/GraphicsEnv.h> #include <dlfcn.h> #include <unistd.h> #include <android-base/file.h> #include <android-base/properties.h> Loading @@ -28,7 +29,11 @@ #include <log/log.h> #include <sys/prctl.h> #include <memory> #include <mutex> #include <string> #include <dlfcn.h> // TODO(b/37049319) Get this from a header once one exists extern "C" { Loading @@ -46,6 +51,20 @@ enum { }; } // TODO(ianelliott@): Get the following from an ANGLE header: #define CURRENT_ANGLE_API_VERSION 2 // Current API verion we are targetting // Version-2 API: typedef bool (*fpANGLEGetFeatureSupportUtilAPIVersion)(unsigned int* versionToUse); typedef bool (*fpANGLEAndroidParseRulesString)(const char* rulesString, void** rulesHandle, int* rulesVersion); typedef bool (*fpANGLEGetSystemInfo)(void** handle); typedef bool (*fpANGLEAddDeviceInfoToSystemInfo)(const char* deviceMfr, const char* deviceModel, void* handle); typedef bool (*fpANGLEShouldBeUsedForApplication)(void* rulesHandle, int rulesVersion, void* systemInfoHandle, const char* appName); typedef bool (*fpANGLEFreeRulesHandle)(void* handle); typedef bool (*fpANGLEFreeSystemInfoHandle)(void* handle); namespace android { enum NativeLibrary { Loading Loading @@ -134,39 +153,186 @@ void GraphicsEnv::setDriverPath(const std::string path) { mDriverPath = path; } void GraphicsEnv::setAngleInfo(const std::string path, const std::string appName, const std::string developerOptIn, const int rulesFd, const long rulesOffset, const long rulesLength) { if (!mAnglePath.empty()) { ALOGV("ignoring attempt to change ANGLE path from '%s' to '%s'", mAnglePath.c_str(), path.c_str()); void* GraphicsEnv::loadLibrary(std::string name) { const android_dlextinfo dlextinfo = { .flags = ANDROID_DLEXT_USE_NAMESPACE, .library_namespace = getAngleNamespace(), }; std::string libName = std::string("lib") + name + "_angle.so"; void* so = android_dlopen_ext(libName.c_str(), RTLD_LOCAL | RTLD_NOW, &dlextinfo); if (so) { ALOGD("dlopen_ext from APK (%s) success at %p", libName.c_str(), so); return so; } else { ALOGV("setting ANGLE path to '%s'", path.c_str()); mAnglePath = path; ALOGE("dlopen_ext(\"%s\") failed: %s", libName.c_str(), dlerror()); } return nullptr; } if (!mAngleAppName.empty()) { ALOGV("ignoring attempt to change ANGLE app name from '%s' to '%s'", mAngleAppName.c_str(), bool GraphicsEnv::checkAngleRules(void* so) { char manufacturer[PROPERTY_VALUE_MAX]; char model[PROPERTY_VALUE_MAX]; property_get("ro.product.manufacturer", manufacturer, "UNSET"); property_get("ro.product.model", model, "UNSET"); auto ANGLEGetFeatureSupportUtilAPIVersion = (fpANGLEGetFeatureSupportUtilAPIVersion)dlsym(so, "ANGLEGetFeatureSupportUtilAPIVersion"); if (!ANGLEGetFeatureSupportUtilAPIVersion) { ALOGW("Cannot find ANGLEGetFeatureSupportUtilAPIVersion function"); return false; } // Negotiate the interface version by requesting most recent known to the platform unsigned int versionToUse = CURRENT_ANGLE_API_VERSION; if (!(ANGLEGetFeatureSupportUtilAPIVersion)(&versionToUse)) { ALOGW("Cannot use ANGLE feature-support library, it is older than supported by EGL, " "requested version %u", versionToUse); return false; } // Add and remove versions below as needed bool useAngle = false; switch (versionToUse) { case 2: { ALOGV("Using version %d of ANGLE feature-support library", versionToUse); void* rulesHandle = nullptr; int rulesVersion = 0; void* systemInfoHandle = nullptr; // Get the symbols for the feature-support-utility library: #define GET_SYMBOL(symbol) \ fp##symbol symbol = (fp##symbol)dlsym(so, #symbol); \ if (!symbol) { \ ALOGW("Cannot find " #symbol " in ANGLE feature-support library"); \ break; \ } GET_SYMBOL(ANGLEAndroidParseRulesString); GET_SYMBOL(ANGLEGetSystemInfo); GET_SYMBOL(ANGLEAddDeviceInfoToSystemInfo); GET_SYMBOL(ANGLEShouldBeUsedForApplication); GET_SYMBOL(ANGLEFreeRulesHandle); GET_SYMBOL(ANGLEFreeSystemInfoHandle); // Parse the rules, obtain the SystemInfo, and evaluate the // application against the rules: if (!(ANGLEAndroidParseRulesString)(mRulesBuffer.data(), &rulesHandle, &rulesVersion)) { ALOGW("ANGLE feature-support library cannot parse rules file"); break; } if (!(ANGLEGetSystemInfo)(&systemInfoHandle)) { ALOGW("ANGLE feature-support library cannot obtain SystemInfo"); break; } if (!(ANGLEAddDeviceInfoToSystemInfo)(manufacturer, model, systemInfoHandle)) { ALOGW("ANGLE feature-support library cannot add device info to SystemInfo"); break; } useAngle = (ANGLEShouldBeUsedForApplication)(rulesHandle, rulesVersion, systemInfoHandle, mAngleAppName.c_str()); (ANGLEFreeRulesHandle)(rulesHandle); (ANGLEFreeSystemInfoHandle)(systemInfoHandle); } break; default: ALOGW("Version %u of ANGLE feature-support library is NOT supported.", versionToUse); } ALOGV("Close temporarily-loaded ANGLE opt-in/out logic"); return useAngle; } bool GraphicsEnv::shouldUseAngle(std::string appName) { if (appName != mAngleAppName) { // Make sure we are checking the app we were init'ed for ALOGE("App name does not match: expected '%s', got '%s'", mAngleAppName.c_str(), appName.c_str()); } else { ALOGV("setting ANGLE app name to '%s'", appName.c_str()); mAngleAppName = appName; return false; } return shouldUseAngle(); } if (!mAngleDeveloperOptIn.empty()) { ALOGV("ignoring attempt to change ANGLE application opt-in from '%s' to '%s'", mAngleDeveloperOptIn.c_str(), developerOptIn.c_str()); bool GraphicsEnv::shouldUseAngle() { // Make sure we are init'ed if (mAngleAppName.empty()) { ALOGE("App name is empty. setAngleInfo() must be called first to enable ANGLE."); return false; } return mUseAngle; } void GraphicsEnv::updateUseAngle() { mUseAngle = false; const char* ANGLE_PREFER_ANGLE = "angle"; const char* ANGLE_PREFER_NATIVE = "native"; if (mAngleDeveloperOptIn == ANGLE_PREFER_ANGLE) { ALOGV("User set \"Developer Options\" to force the use of ANGLE"); mUseAngle = true; } else if (mAngleDeveloperOptIn == ANGLE_PREFER_NATIVE) { ALOGV("User set \"Developer Options\" to force the use of Native"); mUseAngle = false; } else { // The "Developer Options" value wasn't set to force the use of ANGLE. Need to temporarily // load ANGLE and call the updatable opt-in/out logic: // Check if ANGLE is enabled. Workaround for several bugs: // b/119305693 b/119322355 b/119305887 // Something is not working correctly in the feature library char prop[PROPERTY_VALUE_MAX]; property_get("debug.angle.enable", prop, "0"); void* featureSo = nullptr; if (atoi(prop)) { featureSo = loadLibrary("feature_support"); } if (featureSo) { ALOGV("loaded ANGLE's opt-in/out logic from namespace"); mUseAngle = checkAngleRules(featureSo); dlclose(featureSo); featureSo = nullptr; } else { ALOGV("Could not load the ANGLE opt-in/out logic, cannot use ANGLE."); } } } void GraphicsEnv::setAngleInfo(const std::string path, const std::string appName, const std::string developerOptIn, const int rulesFd, const long rulesOffset, const long rulesLength) { ALOGV("setting ANGLE path to '%s'", path.c_str()); mAnglePath = path; ALOGV("setting ANGLE app name to '%s'", appName.c_str()); mAngleAppName = appName; ALOGV("setting ANGLE application opt-in to '%s'", developerOptIn.c_str()); mAngleDeveloperOptIn = developerOptIn; lseek(rulesFd, rulesOffset, SEEK_SET); mRulesBuffer = std::vector<char>(rulesLength + 1); ssize_t numBytesRead = read(rulesFd, mRulesBuffer.data(), rulesLength); if (numBytesRead < 0) { ALOGE("Cannot read rules file: numBytesRead = %zd", numBytesRead); numBytesRead = 0; } else if (numBytesRead == 0) { ALOGW("Empty rules file"); } if (numBytesRead != rulesLength) { ALOGW("Did not read all of the necessary bytes from the rules file." "expected: %ld, got: %zd", rulesLength, numBytesRead); } mRulesBuffer[numBytesRead] = '\0'; ALOGV("setting ANGLE rules file descriptor to '%i'", rulesFd); mAngleRulesFd = rulesFd; ALOGV("setting ANGLE rules offset to '%li'", rulesOffset); mAngleRulesOffset = rulesOffset; ALOGV("setting ANGLE rules length to '%li'", rulesLength); mAngleRulesLength = rulesLength; // Update the current status of whether we should use ANGLE or not updateUseAngle(); } void GraphicsEnv::setLayerPaths(NativeLoaderNamespace* appNamespace, const std::string layerPaths) { Loading @@ -183,25 +349,8 @@ NativeLoaderNamespace* GraphicsEnv::getAppNamespace() { return mAppNamespace; } const char* GraphicsEnv::getAngleAppName() { if (mAngleAppName.empty()) return nullptr; return mAngleAppName.c_str(); } const char* GraphicsEnv::getAngleDeveloperOptIn() { return mAngleDeveloperOptIn.c_str(); } int GraphicsEnv::getAngleRulesFd() { return mAngleRulesFd; } long GraphicsEnv::getAngleRulesOffset() { return mAngleRulesOffset; } long GraphicsEnv::getAngleRulesLength() { return mAngleRulesLength; std::string& GraphicsEnv::getAngleAppName() { return mAngleAppName; } const std::string& GraphicsEnv::getLayerPaths() { Loading libs/graphicsenv/include/graphicsenv/GraphicsEnv.h +10 −9 Original line number Diff line number Diff line Loading @@ -18,6 +18,7 @@ #define ANDROID_UI_GRAPHICS_ENV_H 1 #include <string> #include <vector> struct android_namespace_t; Loading @@ -39,6 +40,8 @@ public: void setDriverPath(const std::string path); android_namespace_t* getDriverNamespace(); bool shouldUseAngle(std::string appName); bool shouldUseAngle(); // Set a search path for loading ANGLE libraries. The path is a list of // directories separated by ':'. A directory can be contained in a zip file // (libraries must be stored uncompressed and page aligned); such elements Loading @@ -47,12 +50,7 @@ public: void setAngleInfo(const std::string path, const std::string appName, std::string devOptIn, const int rulesFd, const long rulesOffset, const long rulesLength); android_namespace_t* getAngleNamespace(); const char* getAngleAppName(); const char* getAngleAppPref(); const char* getAngleDeveloperOptIn(); int getAngleRulesFd(); long getAngleRulesOffset(); long getAngleRulesLength(); std::string& getAngleAppName(); void setLayerPaths(NativeLoaderNamespace* appNamespace, const std::string layerPaths); NativeLoaderNamespace* getAppNamespace(); Loading @@ -65,14 +63,17 @@ public: const std::string& getDebugLayersGLES(); private: void* loadLibrary(std::string name); bool checkAngleRules(void* so); void updateUseAngle(); GraphicsEnv() = default; std::string mDriverPath; std::string mAnglePath; std::string mAngleAppName; std::string mAngleDeveloperOptIn; int mAngleRulesFd; long mAngleRulesOffset; long mAngleRulesLength; std::vector<char> mRulesBuffer; bool mUseAngle; std::string mDebugLayers; std::string mDebugLayersGLES; std::string mLayerPaths; Loading opengl/libs/EGL/Loader.cpp +27 −196 Original line number Diff line number Diff line Loading @@ -17,7 +17,7 @@ //#define LOG_NDEBUG 0 #define ATRACE_TAG ATRACE_TAG_GRAPHICS #include "Loader.h" #include <EGL/Loader.h> #include <string> Loading @@ -38,38 +38,6 @@ #include "egldefs.h" #include <EGL/eglext_angle.h> extern "C" { android_namespace_t* android_get_exported_namespace(const char*); typedef enum ANGLEPreference { ANGLE_PREFER_DEFAULT = 0, ANGLE_PREFER_NATIVE = 1, ANGLE_PREFER_ANGLE = 2, } ANGLEPreference; // TODO(ianelliott@): Get the following from an ANGLE header: // Version-1 API: typedef bool (*fpANGLEGetUtilityAPI)(unsigned int* versionToUse); typedef bool (*fpAndroidUseANGLEForApplication)(int fd, long offset, long length, const char* appName, const char* deviceMfr, const char* deviceModel); // Version-2 API: typedef bool (*fpANGLEGetFeatureSupportUtilAPIVersion)(unsigned int* versionToUse); typedef bool (*fpANGLEAndroidParseRulesString)(const char *rulesString, void** rulesHandle, int* rulesVersion); typedef bool (*fpANGLEGetSystemInfo)(void** handle); typedef bool (*fpANGLEAddDeviceInfoToSystemInfo)(const char* deviceMfr, const char* deviceModel, void* handle); typedef bool (*fpANGLEShouldBeUsedForApplication)(void* rules_handle, int rules_version, void* system_info_handle, const char *appName); typedef bool (*fpANGLEFreeRulesHandle)(void* handle); typedef bool (*fpANGLEFreeSystemInfoHandle)(void* handle); } // ---------------------------------------------------------------------------- namespace android { // ---------------------------------------------------------------------------- Loading Loading @@ -255,6 +223,13 @@ void* Loader::open(egl_connection_t* cnx) setEmulatorGlesValue(); // Check if we should use ANGLE early, so loading each driver doesn't require repeated queries. if (android::GraphicsEnv::getInstance().shouldUseAngle()) { cnx->shouldUseAngle = true; } else { cnx->shouldUseAngle = false; } dso = load_driver("GLES", cnx, EGL | GLESv1_CM | GLESv2); if (dso) { hnd = new driver_t(dso); Loading Loading @@ -289,11 +264,7 @@ void Loader::close(egl_connection_t* cnx) delete hnd; cnx->dso = nullptr; if (cnx->featureSo) { dlclose(cnx->featureSo); cnx->featureSo = nullptr; } cnx->shouldUseAngle = false; cnx->angleDecided = false; cnx->useAngle = false; Loading Loading @@ -530,173 +501,32 @@ static void* load_angle_from_namespace(const char* kind, android_namespace_t* ns return nullptr; } static ANGLEPreference getAngleDevOption(const char* devOption) { if (devOption == nullptr) return ANGLE_PREFER_DEFAULT; if (strcmp(devOption, "angle") == 0) { return ANGLE_PREFER_ANGLE; } else if (strcmp(devOption, "native") == 0) { return ANGLE_PREFER_NATIVE; } return ANGLE_PREFER_DEFAULT; } static bool check_angle_rules(void* so, const char* app_name) { bool use_angle = false; const int rules_fd = android::GraphicsEnv::getInstance().getAngleRulesFd(); const long rules_offset = android::GraphicsEnv::getInstance().getAngleRulesOffset(); const long rules_length = android::GraphicsEnv::getInstance().getAngleRulesLength(); std::string app_name_str = app_name ? app_name : ""; char manufacturer[PROPERTY_VALUE_MAX]; char model[PROPERTY_VALUE_MAX]; property_get("ro.product.manufacturer", manufacturer, "UNSET"); property_get("ro.product.model", model, "UNSET"); fpANGLEGetFeatureSupportUtilAPIVersion ANGLEGetFeatureSupportUtilAPIVersion = (fpANGLEGetFeatureSupportUtilAPIVersion)dlsym(so, "ANGLEGetFeatureSupportUtilAPIVersion"); if (ANGLEGetFeatureSupportUtilAPIVersion) { // Negotiate the interface version by requesting most recent known to the platform unsigned int versionToUse = 2; if ((ANGLEGetFeatureSupportUtilAPIVersion)(&versionToUse)) { // Add and remove versions below as needed switch(versionToUse) { case 2: { ALOGV("Using version 2 of ANGLE feature-support library"); void* rules_handle = nullptr; int rules_version = 0; void* system_info_handle = nullptr; // Get the symbols for the feature-support-utility library: #define GET_SYMBOL(symbol) \ fp##symbol symbol = (fp##symbol)dlsym(so, #symbol); \ if (!symbol) { \ ALOGW("Cannot find "#symbol" in ANGLE feature-support library"); \ break; \ } GET_SYMBOL(ANGLEAndroidParseRulesString); GET_SYMBOL(ANGLEGetSystemInfo); GET_SYMBOL(ANGLEAddDeviceInfoToSystemInfo); GET_SYMBOL(ANGLEShouldBeUsedForApplication); GET_SYMBOL(ANGLEFreeRulesHandle); GET_SYMBOL(ANGLEFreeSystemInfoHandle); // Read the contents of the file into a string: off_t fileSize = rules_length; off_t startOfContent = rules_offset; lseek(rules_fd, startOfContent, SEEK_SET); char *buffer = new char[fileSize + 1]; ssize_t numBytesRead = read(rules_fd, buffer, fileSize); if (numBytesRead < 0) { ALOGW("Cannot read rules file"); break; } if (numBytesRead == 0) { ALOGW("Empty rules file"); break; } buffer[numBytesRead] = '\0'; std::string rule_file_contents = std::string(buffer); delete[] buffer; // Parse the rules, obtain the SystemInfo, and evaluate the // application against the rules: if (!(ANGLEAndroidParseRulesString)(rule_file_contents.c_str(), &rules_handle, &rules_version)) { ALOGW("ANGLE feature-support library cannot parse rules file"); break; } if (!(ANGLEGetSystemInfo)(&system_info_handle)) { ALOGW("ANGLE feature-support library cannot obtain SystemInfo"); break; } if (!(ANGLEAddDeviceInfoToSystemInfo)(manufacturer, model, system_info_handle)) { ALOGW("ANGLE feature-support library cannot add device info to SystemInfo"); break; } use_angle = (ANGLEShouldBeUsedForApplication)(rules_handle, rules_version, system_info_handle, app_name_str.c_str()); (ANGLEFreeRulesHandle)(rules_handle); (ANGLEFreeSystemInfoHandle)(system_info_handle); } break; default: ALOGW("Cannot find supported version of ANGLE feature-support library, found version %u", versionToUse); } } else { ALOGW("Cannot use ANGLE feature-support library, it is older than supported by EGL, requested version %u", versionToUse); } } else { ALOGW("Cannot find ANGLEGetFeatureSupportUtilAPIVersion function"); } ALOGV("Close temporarily-loaded ANGLE opt-in/out logic"); return use_angle; } static void* load_angle(const char* kind, android_namespace_t* ns, egl_connection_t* cnx) { // Only attempt to load ANGLE libs if (strcmp(kind, "EGL") != 0 && strcmp(kind, "GLESv2") != 0 && strcmp(kind, "GLESv1_CM") != 0) if (strcmp(kind, "EGL") != 0 && strcmp(kind, "GLESv2") != 0 && strcmp(kind, "GLESv1_CM") != 0) { return nullptr; std::string name; char prop[PROPERTY_VALUE_MAX]; const char* app_name = android::GraphicsEnv::getInstance().getAngleAppName(); const char* developer_opt_in = android::GraphicsEnv::getInstance().getAngleDeveloperOptIn(); // Determine whether or not to use ANGLE: ANGLEPreference developer_option = getAngleDevOption(developer_opt_in); bool use_angle = (developer_option == ANGLE_PREFER_ANGLE); if (use_angle) { ALOGV("User set \"Developer Options\" to force the use of ANGLE"); } else if (cnx->angleDecided) { use_angle = cnx->useAngle; } else if (developer_option == ANGLE_PREFER_NATIVE) { ALOGV("User set \"Developer Options\" to force the use of Native"); use_angle = false; } else { // The "Developer Options" value wasn't set to force the use of ANGLE. Need to temporarily // load ANGLE and call the updatable opt-in/out logic: // Check if ANGLE is enabled. Workaround for several bugs: // b/119305693 b/119322355 b/119305887 // Something is not working correctly in the feature library property_get("debug.angle.enable", prop, "0"); if (atoi(prop)) { cnx->featureSo = load_angle_from_namespace("feature_support", ns); } if (cnx->featureSo) { ALOGV("loaded ANGLE's opt-in/out logic from namespace"); use_angle = check_angle_rules(cnx->featureSo, app_name); } else { // We weren't able to load and call the updateable opt-in/out logic. // If we can't load the library, there is no ANGLE available. use_angle = false; ALOGV("Could not load the ANGLE opt-in/out logic, cannot use ANGLE."); } cnx->angleDecided = true; } void* so = nullptr; if (use_angle) { if ((cnx->shouldUseAngle) || android::GraphicsEnv::getInstance().shouldUseAngle()) { so = load_angle_from_namespace(kind, ns); cnx->shouldUseAngle = true; } else { cnx->shouldUseAngle = false; } if (so) { ALOGV("Loaded ANGLE %s library for %s (instead of native)", kind, app_name ? app_name : "nullptr"); ALOGV("Loaded ANGLE %s library for '%s' (instead of native)", kind, android::GraphicsEnv::getInstance().getAngleAppName().c_str()); cnx->useAngle = true; char prop[PROPERTY_VALUE_MAX]; property_get("debug.hwui.renderer", prop, "UNSET"); ALOGV("Skia's renderer set to %s", prop); cnx->useAngle = true; EGLint angleBackendDefault = EGL_PLATFORM_ANGLE_TYPE_VULKAN_ANGLE; char prop[PROPERTY_VALUE_MAX]; property_get("debug.angle.backend", prop, "0"); switch (atoi(prop)) { case 1: Loading @@ -716,13 +546,14 @@ static void* load_angle(const char* kind, android_namespace_t* ns, egl_connectio // Find and load vendor libEGL for ANGLE's GL back-end to use. cnx->vendorEGL = load_system_driver("EGL"); } return so; } else { ALOGV("Loaded native %s library for %s (instead of ANGLE)", kind, app_name ? app_name : "nullptr"); ALOGV("Loaded native %s library for '%s' (instead of ANGLE)", kind, android::GraphicsEnv::getInstance().getAngleAppName().c_str()); cnx->useAngle = false; } cnx->angleDecided = true; return nullptr; return so; } static const char* HAL_SUBNAME_KEY_PROPERTIES[2] = { Loading opengl/libs/EGL/egldefs.h +3 −3 Original line number Diff line number Diff line Loading @@ -76,11 +76,11 @@ struct egl_connection_t { void* libGles1; void* libGles2; bool angleDecided; bool useAngle; bool shouldUseAngle; // Should we attempt to load ANGLE bool angleDecided; // Have we tried to load ANGLE bool useAngle; // Was ANGLE successfully loaded EGLint angleBackend; void* vendorEGL; void* featureSo; }; // clang-format on Loading Loading
libs/graphicsenv/GraphicsEnv.cpp +192 −43 Original line number Diff line number Diff line Loading @@ -19,6 +19,7 @@ #include <graphicsenv/GraphicsEnv.h> #include <dlfcn.h> #include <unistd.h> #include <android-base/file.h> #include <android-base/properties.h> Loading @@ -28,7 +29,11 @@ #include <log/log.h> #include <sys/prctl.h> #include <memory> #include <mutex> #include <string> #include <dlfcn.h> // TODO(b/37049319) Get this from a header once one exists extern "C" { Loading @@ -46,6 +51,20 @@ enum { }; } // TODO(ianelliott@): Get the following from an ANGLE header: #define CURRENT_ANGLE_API_VERSION 2 // Current API verion we are targetting // Version-2 API: typedef bool (*fpANGLEGetFeatureSupportUtilAPIVersion)(unsigned int* versionToUse); typedef bool (*fpANGLEAndroidParseRulesString)(const char* rulesString, void** rulesHandle, int* rulesVersion); typedef bool (*fpANGLEGetSystemInfo)(void** handle); typedef bool (*fpANGLEAddDeviceInfoToSystemInfo)(const char* deviceMfr, const char* deviceModel, void* handle); typedef bool (*fpANGLEShouldBeUsedForApplication)(void* rulesHandle, int rulesVersion, void* systemInfoHandle, const char* appName); typedef bool (*fpANGLEFreeRulesHandle)(void* handle); typedef bool (*fpANGLEFreeSystemInfoHandle)(void* handle); namespace android { enum NativeLibrary { Loading Loading @@ -134,39 +153,186 @@ void GraphicsEnv::setDriverPath(const std::string path) { mDriverPath = path; } void GraphicsEnv::setAngleInfo(const std::string path, const std::string appName, const std::string developerOptIn, const int rulesFd, const long rulesOffset, const long rulesLength) { if (!mAnglePath.empty()) { ALOGV("ignoring attempt to change ANGLE path from '%s' to '%s'", mAnglePath.c_str(), path.c_str()); void* GraphicsEnv::loadLibrary(std::string name) { const android_dlextinfo dlextinfo = { .flags = ANDROID_DLEXT_USE_NAMESPACE, .library_namespace = getAngleNamespace(), }; std::string libName = std::string("lib") + name + "_angle.so"; void* so = android_dlopen_ext(libName.c_str(), RTLD_LOCAL | RTLD_NOW, &dlextinfo); if (so) { ALOGD("dlopen_ext from APK (%s) success at %p", libName.c_str(), so); return so; } else { ALOGV("setting ANGLE path to '%s'", path.c_str()); mAnglePath = path; ALOGE("dlopen_ext(\"%s\") failed: %s", libName.c_str(), dlerror()); } return nullptr; } if (!mAngleAppName.empty()) { ALOGV("ignoring attempt to change ANGLE app name from '%s' to '%s'", mAngleAppName.c_str(), bool GraphicsEnv::checkAngleRules(void* so) { char manufacturer[PROPERTY_VALUE_MAX]; char model[PROPERTY_VALUE_MAX]; property_get("ro.product.manufacturer", manufacturer, "UNSET"); property_get("ro.product.model", model, "UNSET"); auto ANGLEGetFeatureSupportUtilAPIVersion = (fpANGLEGetFeatureSupportUtilAPIVersion)dlsym(so, "ANGLEGetFeatureSupportUtilAPIVersion"); if (!ANGLEGetFeatureSupportUtilAPIVersion) { ALOGW("Cannot find ANGLEGetFeatureSupportUtilAPIVersion function"); return false; } // Negotiate the interface version by requesting most recent known to the platform unsigned int versionToUse = CURRENT_ANGLE_API_VERSION; if (!(ANGLEGetFeatureSupportUtilAPIVersion)(&versionToUse)) { ALOGW("Cannot use ANGLE feature-support library, it is older than supported by EGL, " "requested version %u", versionToUse); return false; } // Add and remove versions below as needed bool useAngle = false; switch (versionToUse) { case 2: { ALOGV("Using version %d of ANGLE feature-support library", versionToUse); void* rulesHandle = nullptr; int rulesVersion = 0; void* systemInfoHandle = nullptr; // Get the symbols for the feature-support-utility library: #define GET_SYMBOL(symbol) \ fp##symbol symbol = (fp##symbol)dlsym(so, #symbol); \ if (!symbol) { \ ALOGW("Cannot find " #symbol " in ANGLE feature-support library"); \ break; \ } GET_SYMBOL(ANGLEAndroidParseRulesString); GET_SYMBOL(ANGLEGetSystemInfo); GET_SYMBOL(ANGLEAddDeviceInfoToSystemInfo); GET_SYMBOL(ANGLEShouldBeUsedForApplication); GET_SYMBOL(ANGLEFreeRulesHandle); GET_SYMBOL(ANGLEFreeSystemInfoHandle); // Parse the rules, obtain the SystemInfo, and evaluate the // application against the rules: if (!(ANGLEAndroidParseRulesString)(mRulesBuffer.data(), &rulesHandle, &rulesVersion)) { ALOGW("ANGLE feature-support library cannot parse rules file"); break; } if (!(ANGLEGetSystemInfo)(&systemInfoHandle)) { ALOGW("ANGLE feature-support library cannot obtain SystemInfo"); break; } if (!(ANGLEAddDeviceInfoToSystemInfo)(manufacturer, model, systemInfoHandle)) { ALOGW("ANGLE feature-support library cannot add device info to SystemInfo"); break; } useAngle = (ANGLEShouldBeUsedForApplication)(rulesHandle, rulesVersion, systemInfoHandle, mAngleAppName.c_str()); (ANGLEFreeRulesHandle)(rulesHandle); (ANGLEFreeSystemInfoHandle)(systemInfoHandle); } break; default: ALOGW("Version %u of ANGLE feature-support library is NOT supported.", versionToUse); } ALOGV("Close temporarily-loaded ANGLE opt-in/out logic"); return useAngle; } bool GraphicsEnv::shouldUseAngle(std::string appName) { if (appName != mAngleAppName) { // Make sure we are checking the app we were init'ed for ALOGE("App name does not match: expected '%s', got '%s'", mAngleAppName.c_str(), appName.c_str()); } else { ALOGV("setting ANGLE app name to '%s'", appName.c_str()); mAngleAppName = appName; return false; } return shouldUseAngle(); } if (!mAngleDeveloperOptIn.empty()) { ALOGV("ignoring attempt to change ANGLE application opt-in from '%s' to '%s'", mAngleDeveloperOptIn.c_str(), developerOptIn.c_str()); bool GraphicsEnv::shouldUseAngle() { // Make sure we are init'ed if (mAngleAppName.empty()) { ALOGE("App name is empty. setAngleInfo() must be called first to enable ANGLE."); return false; } return mUseAngle; } void GraphicsEnv::updateUseAngle() { mUseAngle = false; const char* ANGLE_PREFER_ANGLE = "angle"; const char* ANGLE_PREFER_NATIVE = "native"; if (mAngleDeveloperOptIn == ANGLE_PREFER_ANGLE) { ALOGV("User set \"Developer Options\" to force the use of ANGLE"); mUseAngle = true; } else if (mAngleDeveloperOptIn == ANGLE_PREFER_NATIVE) { ALOGV("User set \"Developer Options\" to force the use of Native"); mUseAngle = false; } else { // The "Developer Options" value wasn't set to force the use of ANGLE. Need to temporarily // load ANGLE and call the updatable opt-in/out logic: // Check if ANGLE is enabled. Workaround for several bugs: // b/119305693 b/119322355 b/119305887 // Something is not working correctly in the feature library char prop[PROPERTY_VALUE_MAX]; property_get("debug.angle.enable", prop, "0"); void* featureSo = nullptr; if (atoi(prop)) { featureSo = loadLibrary("feature_support"); } if (featureSo) { ALOGV("loaded ANGLE's opt-in/out logic from namespace"); mUseAngle = checkAngleRules(featureSo); dlclose(featureSo); featureSo = nullptr; } else { ALOGV("Could not load the ANGLE opt-in/out logic, cannot use ANGLE."); } } } void GraphicsEnv::setAngleInfo(const std::string path, const std::string appName, const std::string developerOptIn, const int rulesFd, const long rulesOffset, const long rulesLength) { ALOGV("setting ANGLE path to '%s'", path.c_str()); mAnglePath = path; ALOGV("setting ANGLE app name to '%s'", appName.c_str()); mAngleAppName = appName; ALOGV("setting ANGLE application opt-in to '%s'", developerOptIn.c_str()); mAngleDeveloperOptIn = developerOptIn; lseek(rulesFd, rulesOffset, SEEK_SET); mRulesBuffer = std::vector<char>(rulesLength + 1); ssize_t numBytesRead = read(rulesFd, mRulesBuffer.data(), rulesLength); if (numBytesRead < 0) { ALOGE("Cannot read rules file: numBytesRead = %zd", numBytesRead); numBytesRead = 0; } else if (numBytesRead == 0) { ALOGW("Empty rules file"); } if (numBytesRead != rulesLength) { ALOGW("Did not read all of the necessary bytes from the rules file." "expected: %ld, got: %zd", rulesLength, numBytesRead); } mRulesBuffer[numBytesRead] = '\0'; ALOGV("setting ANGLE rules file descriptor to '%i'", rulesFd); mAngleRulesFd = rulesFd; ALOGV("setting ANGLE rules offset to '%li'", rulesOffset); mAngleRulesOffset = rulesOffset; ALOGV("setting ANGLE rules length to '%li'", rulesLength); mAngleRulesLength = rulesLength; // Update the current status of whether we should use ANGLE or not updateUseAngle(); } void GraphicsEnv::setLayerPaths(NativeLoaderNamespace* appNamespace, const std::string layerPaths) { Loading @@ -183,25 +349,8 @@ NativeLoaderNamespace* GraphicsEnv::getAppNamespace() { return mAppNamespace; } const char* GraphicsEnv::getAngleAppName() { if (mAngleAppName.empty()) return nullptr; return mAngleAppName.c_str(); } const char* GraphicsEnv::getAngleDeveloperOptIn() { return mAngleDeveloperOptIn.c_str(); } int GraphicsEnv::getAngleRulesFd() { return mAngleRulesFd; } long GraphicsEnv::getAngleRulesOffset() { return mAngleRulesOffset; } long GraphicsEnv::getAngleRulesLength() { return mAngleRulesLength; std::string& GraphicsEnv::getAngleAppName() { return mAngleAppName; } const std::string& GraphicsEnv::getLayerPaths() { Loading
libs/graphicsenv/include/graphicsenv/GraphicsEnv.h +10 −9 Original line number Diff line number Diff line Loading @@ -18,6 +18,7 @@ #define ANDROID_UI_GRAPHICS_ENV_H 1 #include <string> #include <vector> struct android_namespace_t; Loading @@ -39,6 +40,8 @@ public: void setDriverPath(const std::string path); android_namespace_t* getDriverNamespace(); bool shouldUseAngle(std::string appName); bool shouldUseAngle(); // Set a search path for loading ANGLE libraries. The path is a list of // directories separated by ':'. A directory can be contained in a zip file // (libraries must be stored uncompressed and page aligned); such elements Loading @@ -47,12 +50,7 @@ public: void setAngleInfo(const std::string path, const std::string appName, std::string devOptIn, const int rulesFd, const long rulesOffset, const long rulesLength); android_namespace_t* getAngleNamespace(); const char* getAngleAppName(); const char* getAngleAppPref(); const char* getAngleDeveloperOptIn(); int getAngleRulesFd(); long getAngleRulesOffset(); long getAngleRulesLength(); std::string& getAngleAppName(); void setLayerPaths(NativeLoaderNamespace* appNamespace, const std::string layerPaths); NativeLoaderNamespace* getAppNamespace(); Loading @@ -65,14 +63,17 @@ public: const std::string& getDebugLayersGLES(); private: void* loadLibrary(std::string name); bool checkAngleRules(void* so); void updateUseAngle(); GraphicsEnv() = default; std::string mDriverPath; std::string mAnglePath; std::string mAngleAppName; std::string mAngleDeveloperOptIn; int mAngleRulesFd; long mAngleRulesOffset; long mAngleRulesLength; std::vector<char> mRulesBuffer; bool mUseAngle; std::string mDebugLayers; std::string mDebugLayersGLES; std::string mLayerPaths; Loading
opengl/libs/EGL/Loader.cpp +27 −196 Original line number Diff line number Diff line Loading @@ -17,7 +17,7 @@ //#define LOG_NDEBUG 0 #define ATRACE_TAG ATRACE_TAG_GRAPHICS #include "Loader.h" #include <EGL/Loader.h> #include <string> Loading @@ -38,38 +38,6 @@ #include "egldefs.h" #include <EGL/eglext_angle.h> extern "C" { android_namespace_t* android_get_exported_namespace(const char*); typedef enum ANGLEPreference { ANGLE_PREFER_DEFAULT = 0, ANGLE_PREFER_NATIVE = 1, ANGLE_PREFER_ANGLE = 2, } ANGLEPreference; // TODO(ianelliott@): Get the following from an ANGLE header: // Version-1 API: typedef bool (*fpANGLEGetUtilityAPI)(unsigned int* versionToUse); typedef bool (*fpAndroidUseANGLEForApplication)(int fd, long offset, long length, const char* appName, const char* deviceMfr, const char* deviceModel); // Version-2 API: typedef bool (*fpANGLEGetFeatureSupportUtilAPIVersion)(unsigned int* versionToUse); typedef bool (*fpANGLEAndroidParseRulesString)(const char *rulesString, void** rulesHandle, int* rulesVersion); typedef bool (*fpANGLEGetSystemInfo)(void** handle); typedef bool (*fpANGLEAddDeviceInfoToSystemInfo)(const char* deviceMfr, const char* deviceModel, void* handle); typedef bool (*fpANGLEShouldBeUsedForApplication)(void* rules_handle, int rules_version, void* system_info_handle, const char *appName); typedef bool (*fpANGLEFreeRulesHandle)(void* handle); typedef bool (*fpANGLEFreeSystemInfoHandle)(void* handle); } // ---------------------------------------------------------------------------- namespace android { // ---------------------------------------------------------------------------- Loading Loading @@ -255,6 +223,13 @@ void* Loader::open(egl_connection_t* cnx) setEmulatorGlesValue(); // Check if we should use ANGLE early, so loading each driver doesn't require repeated queries. if (android::GraphicsEnv::getInstance().shouldUseAngle()) { cnx->shouldUseAngle = true; } else { cnx->shouldUseAngle = false; } dso = load_driver("GLES", cnx, EGL | GLESv1_CM | GLESv2); if (dso) { hnd = new driver_t(dso); Loading Loading @@ -289,11 +264,7 @@ void Loader::close(egl_connection_t* cnx) delete hnd; cnx->dso = nullptr; if (cnx->featureSo) { dlclose(cnx->featureSo); cnx->featureSo = nullptr; } cnx->shouldUseAngle = false; cnx->angleDecided = false; cnx->useAngle = false; Loading Loading @@ -530,173 +501,32 @@ static void* load_angle_from_namespace(const char* kind, android_namespace_t* ns return nullptr; } static ANGLEPreference getAngleDevOption(const char* devOption) { if (devOption == nullptr) return ANGLE_PREFER_DEFAULT; if (strcmp(devOption, "angle") == 0) { return ANGLE_PREFER_ANGLE; } else if (strcmp(devOption, "native") == 0) { return ANGLE_PREFER_NATIVE; } return ANGLE_PREFER_DEFAULT; } static bool check_angle_rules(void* so, const char* app_name) { bool use_angle = false; const int rules_fd = android::GraphicsEnv::getInstance().getAngleRulesFd(); const long rules_offset = android::GraphicsEnv::getInstance().getAngleRulesOffset(); const long rules_length = android::GraphicsEnv::getInstance().getAngleRulesLength(); std::string app_name_str = app_name ? app_name : ""; char manufacturer[PROPERTY_VALUE_MAX]; char model[PROPERTY_VALUE_MAX]; property_get("ro.product.manufacturer", manufacturer, "UNSET"); property_get("ro.product.model", model, "UNSET"); fpANGLEGetFeatureSupportUtilAPIVersion ANGLEGetFeatureSupportUtilAPIVersion = (fpANGLEGetFeatureSupportUtilAPIVersion)dlsym(so, "ANGLEGetFeatureSupportUtilAPIVersion"); if (ANGLEGetFeatureSupportUtilAPIVersion) { // Negotiate the interface version by requesting most recent known to the platform unsigned int versionToUse = 2; if ((ANGLEGetFeatureSupportUtilAPIVersion)(&versionToUse)) { // Add and remove versions below as needed switch(versionToUse) { case 2: { ALOGV("Using version 2 of ANGLE feature-support library"); void* rules_handle = nullptr; int rules_version = 0; void* system_info_handle = nullptr; // Get the symbols for the feature-support-utility library: #define GET_SYMBOL(symbol) \ fp##symbol symbol = (fp##symbol)dlsym(so, #symbol); \ if (!symbol) { \ ALOGW("Cannot find "#symbol" in ANGLE feature-support library"); \ break; \ } GET_SYMBOL(ANGLEAndroidParseRulesString); GET_SYMBOL(ANGLEGetSystemInfo); GET_SYMBOL(ANGLEAddDeviceInfoToSystemInfo); GET_SYMBOL(ANGLEShouldBeUsedForApplication); GET_SYMBOL(ANGLEFreeRulesHandle); GET_SYMBOL(ANGLEFreeSystemInfoHandle); // Read the contents of the file into a string: off_t fileSize = rules_length; off_t startOfContent = rules_offset; lseek(rules_fd, startOfContent, SEEK_SET); char *buffer = new char[fileSize + 1]; ssize_t numBytesRead = read(rules_fd, buffer, fileSize); if (numBytesRead < 0) { ALOGW("Cannot read rules file"); break; } if (numBytesRead == 0) { ALOGW("Empty rules file"); break; } buffer[numBytesRead] = '\0'; std::string rule_file_contents = std::string(buffer); delete[] buffer; // Parse the rules, obtain the SystemInfo, and evaluate the // application against the rules: if (!(ANGLEAndroidParseRulesString)(rule_file_contents.c_str(), &rules_handle, &rules_version)) { ALOGW("ANGLE feature-support library cannot parse rules file"); break; } if (!(ANGLEGetSystemInfo)(&system_info_handle)) { ALOGW("ANGLE feature-support library cannot obtain SystemInfo"); break; } if (!(ANGLEAddDeviceInfoToSystemInfo)(manufacturer, model, system_info_handle)) { ALOGW("ANGLE feature-support library cannot add device info to SystemInfo"); break; } use_angle = (ANGLEShouldBeUsedForApplication)(rules_handle, rules_version, system_info_handle, app_name_str.c_str()); (ANGLEFreeRulesHandle)(rules_handle); (ANGLEFreeSystemInfoHandle)(system_info_handle); } break; default: ALOGW("Cannot find supported version of ANGLE feature-support library, found version %u", versionToUse); } } else { ALOGW("Cannot use ANGLE feature-support library, it is older than supported by EGL, requested version %u", versionToUse); } } else { ALOGW("Cannot find ANGLEGetFeatureSupportUtilAPIVersion function"); } ALOGV("Close temporarily-loaded ANGLE opt-in/out logic"); return use_angle; } static void* load_angle(const char* kind, android_namespace_t* ns, egl_connection_t* cnx) { // Only attempt to load ANGLE libs if (strcmp(kind, "EGL") != 0 && strcmp(kind, "GLESv2") != 0 && strcmp(kind, "GLESv1_CM") != 0) if (strcmp(kind, "EGL") != 0 && strcmp(kind, "GLESv2") != 0 && strcmp(kind, "GLESv1_CM") != 0) { return nullptr; std::string name; char prop[PROPERTY_VALUE_MAX]; const char* app_name = android::GraphicsEnv::getInstance().getAngleAppName(); const char* developer_opt_in = android::GraphicsEnv::getInstance().getAngleDeveloperOptIn(); // Determine whether or not to use ANGLE: ANGLEPreference developer_option = getAngleDevOption(developer_opt_in); bool use_angle = (developer_option == ANGLE_PREFER_ANGLE); if (use_angle) { ALOGV("User set \"Developer Options\" to force the use of ANGLE"); } else if (cnx->angleDecided) { use_angle = cnx->useAngle; } else if (developer_option == ANGLE_PREFER_NATIVE) { ALOGV("User set \"Developer Options\" to force the use of Native"); use_angle = false; } else { // The "Developer Options" value wasn't set to force the use of ANGLE. Need to temporarily // load ANGLE and call the updatable opt-in/out logic: // Check if ANGLE is enabled. Workaround for several bugs: // b/119305693 b/119322355 b/119305887 // Something is not working correctly in the feature library property_get("debug.angle.enable", prop, "0"); if (atoi(prop)) { cnx->featureSo = load_angle_from_namespace("feature_support", ns); } if (cnx->featureSo) { ALOGV("loaded ANGLE's opt-in/out logic from namespace"); use_angle = check_angle_rules(cnx->featureSo, app_name); } else { // We weren't able to load and call the updateable opt-in/out logic. // If we can't load the library, there is no ANGLE available. use_angle = false; ALOGV("Could not load the ANGLE opt-in/out logic, cannot use ANGLE."); } cnx->angleDecided = true; } void* so = nullptr; if (use_angle) { if ((cnx->shouldUseAngle) || android::GraphicsEnv::getInstance().shouldUseAngle()) { so = load_angle_from_namespace(kind, ns); cnx->shouldUseAngle = true; } else { cnx->shouldUseAngle = false; } if (so) { ALOGV("Loaded ANGLE %s library for %s (instead of native)", kind, app_name ? app_name : "nullptr"); ALOGV("Loaded ANGLE %s library for '%s' (instead of native)", kind, android::GraphicsEnv::getInstance().getAngleAppName().c_str()); cnx->useAngle = true; char prop[PROPERTY_VALUE_MAX]; property_get("debug.hwui.renderer", prop, "UNSET"); ALOGV("Skia's renderer set to %s", prop); cnx->useAngle = true; EGLint angleBackendDefault = EGL_PLATFORM_ANGLE_TYPE_VULKAN_ANGLE; char prop[PROPERTY_VALUE_MAX]; property_get("debug.angle.backend", prop, "0"); switch (atoi(prop)) { case 1: Loading @@ -716,13 +546,14 @@ static void* load_angle(const char* kind, android_namespace_t* ns, egl_connectio // Find and load vendor libEGL for ANGLE's GL back-end to use. cnx->vendorEGL = load_system_driver("EGL"); } return so; } else { ALOGV("Loaded native %s library for %s (instead of ANGLE)", kind, app_name ? app_name : "nullptr"); ALOGV("Loaded native %s library for '%s' (instead of ANGLE)", kind, android::GraphicsEnv::getInstance().getAngleAppName().c_str()); cnx->useAngle = false; } cnx->angleDecided = true; return nullptr; return so; } static const char* HAL_SUBNAME_KEY_PROPERTIES[2] = { Loading
opengl/libs/EGL/egldefs.h +3 −3 Original line number Diff line number Diff line Loading @@ -76,11 +76,11 @@ struct egl_connection_t { void* libGles1; void* libGles2; bool angleDecided; bool useAngle; bool shouldUseAngle; // Should we attempt to load ANGLE bool angleDecided; // Have we tried to load ANGLE bool useAngle; // Was ANGLE successfully loaded EGLint angleBackend; void* vendorEGL; void* featureSo; }; // clang-format on Loading