diff options
| -rw-r--r-- | core/java/android/os/GraphicsEnvironment.java | 227 |
1 files changed, 115 insertions, 112 deletions
diff --git a/core/java/android/os/GraphicsEnvironment.java b/core/java/android/os/GraphicsEnvironment.java index df1f1b21eba3..52ee04c169c1 100644 --- a/core/java/android/os/GraphicsEnvironment.java +++ b/core/java/android/os/GraphicsEnvironment.java @@ -29,6 +29,7 @@ import android.content.pm.ResolveInfo; import android.content.res.AssetFileDescriptor; import android.content.res.AssetManager; import android.provider.Settings; +import android.text.TextUtils; import android.util.Log; import android.widget.Toast; @@ -43,11 +44,14 @@ import java.io.IOException; import java.io.InputStreamReader; import java.util.ArrayList; import java.util.Arrays; -import java.util.HashMap; import java.util.List; -import java.util.Map; -/** @hide */ +/** + * GraphicsEnvironment sets up necessary properties for the graphics environment of the + * application process. + * + * @hide + */ public class GraphicsEnvironment { private static final GraphicsEnvironment sInstance = new GraphicsEnvironment(); @@ -64,27 +68,35 @@ public class GraphicsEnvironment { private static final String SYSTEM_DRIVER_NAME = "system"; private static final String SYSTEM_DRIVER_VERSION_NAME = ""; private static final long SYSTEM_DRIVER_VERSION_CODE = 0; + + // System properties related to updatable graphics drivers. private static final String PROPERTY_GFX_DRIVER_PRODUCTION = "ro.gfx.driver.0"; private static final String PROPERTY_GFX_DRIVER_PRERELEASE = "ro.gfx.driver.1"; private static final String PROPERTY_GFX_DRIVER_BUILD_TIME = "ro.gfx.driver_build_time"; + + // Metadata flags within the <application> tag in the AndroidManifest.xml file. private static final String METADATA_DRIVER_BUILD_TIME = "com.android.graphics.driver.build_time"; private static final String METADATA_DEVELOPER_DRIVER_ENABLE = "com.android.graphics.developerdriver.enable"; private static final String METADATA_INJECT_LAYERS_ENABLE = "com.android.graphics.injectLayers.enable"; + + private static final String UPDATABLE_DRIVER_ALLOWLIST_ALL = "*"; + private static final String UPDATABLE_DRIVER_SPHAL_LIBRARIES_FILENAME = "sphal_libraries.txt"; + + // ANGLE related properties. private static final String ANGLE_RULES_FILE = "a4a_rules.json"; private static final String ANGLE_TEMP_RULES = "debug.angle.rules"; private static final String ACTION_ANGLE_FOR_ANDROID = "android.app.action.ANGLE_FOR_ANDROID"; private static final String ACTION_ANGLE_FOR_ANDROID_TOAST_MESSAGE = "android.app.action.ANGLE_FOR_ANDROID_TOAST_MESSAGE"; private static final String INTENT_KEY_A4A_TOAST_MESSAGE = "A4A Toast Message"; - private static final String UPDATABLE_DRIVER_ALLOWLIST_ALL = "*"; - private static final String UPDATABLE_DRIVER_SPHAL_LIBRARIES_FILENAME = "sphal_libraries.txt"; + private static final int VULKAN_1_0 = 0x00400000; private static final int VULKAN_1_1 = 0x00401000; - // UPDATABLE_DRIVER_ALL_APPS + // Values for UPDATABLE_DRIVER_ALL_APPS // 0: Default (Invalid values fallback to default as well) // 1: All apps use updatable production driver // 2: All apps use updatable prerelease driver @@ -94,6 +106,15 @@ public class GraphicsEnvironment { private static final int UPDATABLE_DRIVER_GLOBAL_OPT_IN_PRERELEASE_DRIVER = 2; private static final int UPDATABLE_DRIVER_GLOBAL_OPT_IN_OFF = 3; + // Values for GLOBAL_SETTINGS_ANGLE_GL_DRIVER_ALL_ANGLE + private static final int ANGLE_GL_DRIVER_ALL_ANGLE_ON = 1; + private static final int ANGLE_GL_DRIVER_ALL_ANGLE_OFF = 0; + + // Values for GLOBAL_SETTINGS_ANGLE_GL_DRIVER_SELECTION_VALUES + private static final String ANGLE_GL_DRIVER_CHOICE_DEFAULT = "default"; + private static final String ANGLE_GL_DRIVER_CHOICE_ANGLE = "angle"; + private static final String ANGLE_GL_DRIVER_CHOICE_NATIVE = "native"; + private ClassLoader mClassLoader; private String mLibrarySearchPaths; private String mLibraryPermittedPaths; @@ -106,12 +127,15 @@ public class GraphicsEnvironment { final String packageName = context.getPackageName(); final ApplicationInfo appInfoWithMetaData = getAppInfoWithMetadata(context, pm, packageName); + Trace.traceBegin(Trace.TRACE_TAG_GRAPHICS, "setupGpuLayers"); setupGpuLayers(context, coreSettings, pm, packageName, appInfoWithMetaData); Trace.traceEnd(Trace.TRACE_TAG_GRAPHICS); + Trace.traceBegin(Trace.TRACE_TAG_GRAPHICS, "setupAngle"); setupAngle(context, coreSettings, pm, packageName); Trace.traceEnd(Trace.TRACE_TAG_GRAPHICS); + Trace.traceBegin(Trace.TRACE_TAG_GRAPHICS, "chooseDriver"); if (!chooseDriver(context, coreSettings, pm, packageName, appInfoWithMetaData)) { setGpuStats(SYSTEM_DRIVER_NAME, SYSTEM_DRIVER_VERSION_NAME, SYSTEM_DRIVER_VERSION_CODE, @@ -132,36 +156,30 @@ public class GraphicsEnvironment { */ public static boolean shouldUseAngle(Context context, Bundle coreSettings, String packageName) { - if (packageName.isEmpty()) { - Log.v(TAG, "No package name available yet, ANGLE should not be used"); + if (TextUtils.isEmpty(packageName)) { + Log.v(TAG, "No package name specified, ANGLE should not be used"); return false; } - final String devOptIn = getDriverForPkg(context, coreSettings, packageName); - if (DEBUG) { - Log.v(TAG, "ANGLE Developer option for '" + packageName + "' " - + "set to: '" + devOptIn + "'"); - } + final String devOptIn = getDriverForPackage(context, coreSettings, packageName); + Log.v(TAG, "ANGLE Developer option for '" + packageName + "' " + + "set to: '" + devOptIn + "'"); - // We only want to use ANGLE if the app is allowlisted or the developer has + // We only want to use ANGLE if the app is in the allowlist, or the developer has // explicitly chosen something other than default driver. // The allowlist will be generated by the ANGLE APK at both boot time and // ANGLE update time. It will only include apps mentioned in the rules file. - final boolean allowlisted = checkAngleAllowlist(context, coreSettings, packageName); - final boolean requested = devOptIn.equals(sDriverMap.get(OpenGlDriverChoice.ANGLE)); - final boolean useAngle = (allowlisted || requested); - if (!useAngle) { - return false; - } + final boolean allowed = checkAngleAllowlist(context, coreSettings, packageName); + final boolean requested = devOptIn.equals(ANGLE_GL_DRIVER_CHOICE_ANGLE); - if (allowlisted) { + if (allowed) { Log.v(TAG, "ANGLE allowlist includes " + packageName); } if (requested) { Log.v(TAG, "ANGLE developer option for " + packageName + ": " + devOptIn); } - return true; + return allowed || requested; } private static int getVulkanVersion(PackageManager pm) { @@ -315,23 +333,6 @@ public class GraphicsEnvironment { setLayerPaths(mClassLoader, layerPaths); } - enum OpenGlDriverChoice { - DEFAULT, - NATIVE, - ANGLE - } - - private static final Map<OpenGlDriverChoice, String> sDriverMap = buildMap(); - private static Map<OpenGlDriverChoice, String> buildMap() { - final Map<OpenGlDriverChoice, String> map = new HashMap<>(); - map.put(OpenGlDriverChoice.DEFAULT, "default"); - map.put(OpenGlDriverChoice.ANGLE, "angle"); - map.put(OpenGlDriverChoice.NATIVE, "native"); - - return map; - } - - private static List<String> getGlobalSettingsString(ContentResolver contentResolver, Bundle bundle, String globalSetting) { @@ -378,18 +379,25 @@ public class GraphicsEnvironment { return ai; } - private static String getDriverForPkg(Context context, Bundle bundle, String packageName) { - final String allUseAngle; + private static String getDriverForPackage(Context context, Bundle bundle, String packageName) { + final int allUseAngle; if (bundle != null) { allUseAngle = - bundle.getString(Settings.Global.GLOBAL_SETTINGS_ANGLE_GL_DRIVER_ALL_ANGLE); + bundle.getInt(Settings.Global.GLOBAL_SETTINGS_ANGLE_GL_DRIVER_ALL_ANGLE); } else { ContentResolver contentResolver = context.getContentResolver(); - allUseAngle = Settings.Global.getString(contentResolver, - Settings.Global.GLOBAL_SETTINGS_ANGLE_GL_DRIVER_ALL_ANGLE); + allUseAngle = Settings.Global.getInt(contentResolver, + Settings.Global.GLOBAL_SETTINGS_ANGLE_GL_DRIVER_ALL_ANGLE, + ANGLE_GL_DRIVER_ALL_ANGLE_OFF); + } + if (allUseAngle == ANGLE_GL_DRIVER_ALL_ANGLE_ON) { + Log.v(TAG, "Turn on ANGLE for all applications."); + return ANGLE_GL_DRIVER_CHOICE_ANGLE; } - if ((allUseAngle != null) && allUseAngle.equals("1")) { - return sDriverMap.get(OpenGlDriverChoice.ANGLE); + + // Make sure we have a good package name + if (TextUtils.isEmpty(packageName)) { + return ANGLE_GL_DRIVER_CHOICE_DEFAULT; } final ContentResolver contentResolver = context.getContentResolver(); @@ -400,25 +408,21 @@ public class GraphicsEnvironment { getGlobalSettingsString(contentResolver, bundle, Settings.Global.GLOBAL_SETTINGS_ANGLE_GL_DRIVER_SELECTION_VALUES); - // Make sure we have a good package name - if ((packageName == null) || (packageName.isEmpty())) { - return sDriverMap.get(OpenGlDriverChoice.DEFAULT); - } // Make sure we have good settings to use if (globalSettingsDriverPkgs.size() != globalSettingsDriverValues.size()) { Log.w(TAG, "Global.Settings values are invalid: " - + "globalSettingsDriverPkgs.size = " + + "number of packages: " + globalSettingsDriverPkgs.size() + ", " - + "globalSettingsDriverValues.size = " + + "number of values: " + globalSettingsDriverValues.size()); - return sDriverMap.get(OpenGlDriverChoice.DEFAULT); + return ANGLE_GL_DRIVER_CHOICE_DEFAULT; } final int pkgIndex = getGlobalSettingsPkgIndex(packageName, globalSettingsDriverPkgs); if (pkgIndex < 0) { - return sDriverMap.get(OpenGlDriverChoice.DEFAULT); + return ANGLE_GL_DRIVER_CHOICE_DEFAULT; } return globalSettingsDriverValues.get(pkgIndex); @@ -446,27 +450,28 @@ public class GraphicsEnvironment { } /** - * Check for ANGLE debug package, but only for apps that can load them (dumpable) + * Check for ANGLE debug package, but only for apps that can load them. + * An application can load ANGLE debug package if it is a debuggable application, or + * the device is debuggable. */ private String getAngleDebugPackage(Context context, Bundle coreSettings) { - if (isDebuggable()) { - String debugPackage; - - if (coreSettings != null) { - debugPackage = - coreSettings.getString(Settings.Global.GLOBAL_SETTINGS_ANGLE_DEBUG_PACKAGE); - } else { - ContentResolver contentResolver = context.getContentResolver(); - debugPackage = Settings.Global.getString(contentResolver, - Settings.Global.GLOBAL_SETTINGS_ANGLE_DEBUG_PACKAGE); - } - - if ((debugPackage != null) && (!debugPackage.isEmpty())) { - return debugPackage; - } + if (!isDebuggable()) { + return ""; } + final String debugPackage; - return ""; + if (coreSettings != null) { + debugPackage = + coreSettings.getString(Settings.Global.GLOBAL_SETTINGS_ANGLE_DEBUG_PACKAGE); + } else { + ContentResolver contentResolver = context.getContentResolver(); + debugPackage = Settings.Global.getString(contentResolver, + Settings.Global.GLOBAL_SETTINGS_ANGLE_DEBUG_PACKAGE); + } + if (TextUtils.isEmpty(debugPackage)) { + return ""; + } + return debugPackage; } /** @@ -491,7 +496,7 @@ public class GraphicsEnvironment { final String angleTempRules = SystemProperties.get(ANGLE_TEMP_RULES); - if ((angleTempRules == null) || angleTempRules.isEmpty()) { + if (TextUtils.isEmpty(angleTempRules)) { Log.v(TAG, "System property '" + ANGLE_TEMP_RULES + "' is not set or is empty"); return false; } @@ -583,11 +588,12 @@ public class GraphicsEnvironment { * * @param context * @param bundle - * @param packageName + * @param pm + * @param packageName - package name of the application. * @return true: ANGLE setup successfully * false: ANGLE not setup (not on allowlist, ANGLE not present, etc.) */ - public boolean setupAngle(Context context, Bundle bundle, PackageManager pm, + private boolean setupAngle(Context context, Bundle bundle, PackageManager pm, String packageName) { if (!shouldUseAngle(context, bundle, packageName)) { @@ -612,18 +618,18 @@ public class GraphicsEnvironment { // Otherwise, check to see if ANGLE is properly installed if (angleInfo == null) { anglePkgName = getAnglePackageName(pm); - if (!anglePkgName.isEmpty()) { - Log.i(TAG, "ANGLE package enabled: " + anglePkgName); - try { - // Production ANGLE libraries must be pre-installed as a system app - angleInfo = pm.getApplicationInfo(anglePkgName, - PackageManager.MATCH_SYSTEM_ONLY); - } catch (PackageManager.NameNotFoundException e) { - Log.w(TAG, "ANGLE package '" + anglePkgName + "' not installed"); - return false; - } - } else { - Log.e(TAG, "Failed to find ANGLE package."); + if (TextUtils.isEmpty(anglePkgName)) { + Log.w(TAG, "Failed to find ANGLE package."); + return false; + } + + Log.i(TAG, "ANGLE package enabled: " + anglePkgName); + try { + // Production ANGLE libraries must be pre-installed as a system app + angleInfo = pm.getApplicationInfo(anglePkgName, + PackageManager.MATCH_SYSTEM_ONLY); + } catch (PackageManager.NameNotFoundException e) { + Log.w(TAG, "ANGLE package '" + anglePkgName + "' not installed"); return false; } } @@ -645,7 +651,7 @@ public class GraphicsEnvironment { // load a driver, GraphicsEnv::getShouldUseAngle() has seen the package name before // and can confidently answer yes/no based on the previously set developer // option value. - final String devOptIn = getDriverForPkg(context, bundle, packageName); + final String devOptIn = getDriverForPackage(context, bundle, packageName); if (setupAngleWithTempRulesFile(context, packageName, paths, devOptIn)) { // We setup ANGLE with a temp rules file, so we're done here. @@ -730,18 +736,18 @@ public class GraphicsEnvironment { final boolean hasPrereleaseDriver = prereleaseDriver != null && !prereleaseDriver.isEmpty(); if (!hasProductionDriver && !hasPrereleaseDriver) { - if (DEBUG) { - Log.v(TAG, - "Neither updatable production driver nor prerelease driver is supported."); - } + Log.v(TAG, "Neither updatable production driver nor prerelease driver is supported."); return null; } - // To minimize risk of driver updates crippling the device beyond user repair, never use an - // updated driver for privileged or non-updated system apps. Presumably pre-installed apps - // were tested thoroughly with the pre-installed driver. + // To minimize risk of driver updates crippling the device beyond user repair, never use the + // updatable drivers for privileged or non-updated system apps. Presumably pre-installed + // apps were tested thoroughly with the system driver. if (ai.isPrivilegedApp() || (ai.isSystemApp() && !ai.isUpdatedSystemApp())) { - if (DEBUG) Log.v(TAG, "Ignoring driver package for privileged/non-updated system app."); + if (DEBUG) { + Log.v(TAG, + "Ignore updatable driver package for privileged/non-updated system app."); + } return null; } @@ -758,13 +764,13 @@ public class GraphicsEnvironment { // 6. UPDATABLE_DRIVER_PRODUCTION_ALLOWLIST switch (coreSettings.getInt(Settings.Global.UPDATABLE_DRIVER_ALL_APPS, 0)) { case UPDATABLE_DRIVER_GLOBAL_OPT_IN_OFF: - if (DEBUG) Log.v(TAG, "updatable driver is turned off on this device."); + Log.v(TAG, "The updatable driver is turned off on this device."); return null; case UPDATABLE_DRIVER_GLOBAL_OPT_IN_PRODUCTION_DRIVER: - if (DEBUG) Log.v(TAG, "All apps opt in to use updatable production driver."); + Log.v(TAG, "All apps opt in to use updatable production driver."); return hasProductionDriver ? productionDriver : null; case UPDATABLE_DRIVER_GLOBAL_OPT_IN_PRERELEASE_DRIVER: - if (DEBUG) Log.v(TAG, "All apps opt in to use updatable prerelease driver."); + Log.v(TAG, "All apps opt in to use updatable prerelease driver."); return hasPrereleaseDriver && enablePrereleaseDriver ? prereleaseDriver : null; case UPDATABLE_DRIVER_GLOBAL_OPT_IN_DEFAULT: default: @@ -775,20 +781,20 @@ public class GraphicsEnvironment { if (getGlobalSettingsString(null, coreSettings, Settings.Global.UPDATABLE_DRIVER_PRODUCTION_OPT_OUT_APPS) .contains(appPackageName)) { - if (DEBUG) Log.v(TAG, "App opts out for updatable production driver."); + Log.v(TAG, "App opts out for updatable production driver."); return null; } if (getGlobalSettingsString( null, coreSettings, Settings.Global.UPDATABLE_DRIVER_PRERELEASE_OPT_IN_APPS) .contains(appPackageName)) { - if (DEBUG) Log.v(TAG, "App opts in for updatable prerelease driver."); + Log.v(TAG, "App opts in for updatable prerelease driver."); return hasPrereleaseDriver && enablePrereleaseDriver ? prereleaseDriver : null; } // Early return here since the rest logic is only for updatable production Driver. if (!hasProductionDriver) { - if (DEBUG) Log.v(TAG, "Updatable production driver is not supported on the device."); + Log.v(TAG, "Updatable production driver is not supported on the device."); return null; } @@ -801,7 +807,7 @@ public class GraphicsEnvironment { Settings.Global.UPDATABLE_DRIVER_PRODUCTION_ALLOWLIST); if (!isOptIn && allowlist.indexOf(UPDATABLE_DRIVER_ALLOWLIST_ALL) != 0 && !allowlist.contains(appPackageName)) { - if (DEBUG) Log.v(TAG, "App is not on the allowlist for updatable production driver."); + Log.v(TAG, "App is not on the allowlist for updatable production driver."); return null; } @@ -811,7 +817,7 @@ public class GraphicsEnvironment { && getGlobalSettingsString( null, coreSettings, Settings.Global.UPDATABLE_DRIVER_PRODUCTION_DENYLIST) .contains(appPackageName)) { - if (DEBUG) Log.v(TAG, "App is on the denylist for updatable production driver."); + Log.v(TAG, "App is on the denylist for updatable production driver."); return null; } @@ -834,7 +840,7 @@ public class GraphicsEnvironment { driverPackageInfo = pm.getPackageInfo(driverPackageName, PackageManager.MATCH_SYSTEM_ONLY | PackageManager.GET_META_DATA); } catch (PackageManager.NameNotFoundException e) { - Log.w(TAG, "driver package '" + driverPackageName + "' not installed"); + Log.w(TAG, "updatable driver package '" + driverPackageName + "' not installed"); return false; } @@ -843,7 +849,7 @@ public class GraphicsEnvironment { final ApplicationInfo driverAppInfo = driverPackageInfo.applicationInfo; if (driverAppInfo.targetSdkVersion < Build.VERSION_CODES.O) { if (DEBUG) { - Log.w(TAG, "updated driver package is not known to be compatible with O"); + Log.w(TAG, "updatable driver package is not compatible with O"); } return false; } @@ -853,7 +859,7 @@ public class GraphicsEnvironment { if (DEBUG) { // This is the normal case for the pre-installed empty driver package, don't spam if (driverAppInfo.isUpdatedSystemApp()) { - Log.w(TAG, "updated driver package has no compatible native libraries"); + Log.w(TAG, "Updatable driver package has no compatible native libraries"); } } return false; @@ -867,11 +873,8 @@ public class GraphicsEnvironment { .append(abi); final String paths = sb.toString(); final String sphalLibraries = getSphalLibraries(context, driverPackageName); - if (DEBUG) { - Log.v(TAG, - "gfx driver package search path: " + paths - + ", required sphal libraries: " + sphalLibraries); - } + Log.v(TAG, "Updatable driver package search path: " + paths + + ", required sphal libraries: " + sphalLibraries); setDriverPathAndSphalLibraries(paths, sphalLibraries); if (driverAppInfo.metaData == null) { @@ -880,7 +883,7 @@ public class GraphicsEnvironment { String driverBuildTime = driverAppInfo.metaData.getString(METADATA_DRIVER_BUILD_TIME); if (driverBuildTime == null || driverBuildTime.length() <= 1) { - Log.v(TAG, "com.android.graphics.driver.build_time is not set"); + Log.w(TAG, "com.android.graphics.driver.build_time is not set"); driverBuildTime = "L0"; } // driver_build_time in the meta-data is in "L<Unix epoch timestamp>" format. e.g. L123456. |