Merge "Refactor timestamp for input events"
diff --git a/cmds/installd/dexopt.cpp b/cmds/installd/dexopt.cpp
index 25e5247..32c1313 100644
--- a/cmds/installd/dexopt.cpp
+++ b/cmds/installd/dexopt.cpp
@@ -660,7 +660,8 @@
                   const unique_fd& reference_profile_fd,
                   const std::vector<unique_fd>& apk_fds,
                   const std::vector<std::string>& dex_locations,
-                  bool copy_and_update) {
+                  bool copy_and_update,
+                  bool store_aggregation_counters) {
         const char* profman_bin =
                 is_debug_runtime() ? "/system/bin/profmand" : "/system/bin/profman";
 
@@ -688,6 +689,10 @@
             AddArg("--copy-and-update-profile-key");
         }
 
+        if (store_aggregation_counters) {
+            AddArg("--store-aggregation-counters");
+        }
+
         // Do not add after dex2oat_flags, they should override others for debugging.
         PrepareArgs(profman_bin);
     }
@@ -695,12 +700,14 @@
     void SetupMerge(const std::vector<unique_fd>& profiles_fd,
                     const unique_fd& reference_profile_fd,
                     const std::vector<unique_fd>& apk_fds = std::vector<unique_fd>(),
-                    const std::vector<std::string>& dex_locations = std::vector<std::string>()) {
+                    const std::vector<std::string>& dex_locations = std::vector<std::string>(),
+                    bool store_aggregation_counters = false) {
         SetupArgs(profiles_fd,
-                    reference_profile_fd,
-                    apk_fds,
-                    dex_locations,
-                    /*copy_and_update=*/false);
+                  reference_profile_fd,
+                  apk_fds,
+                  dex_locations,
+                  /*copy_and_update=*/false,
+                  store_aggregation_counters);
     }
 
     void SetupCopyAndUpdate(unique_fd&& profile_fd,
@@ -713,8 +720,12 @@
         apk_fds_.push_back(std::move(apk_fd));
         reference_profile_fd_ = std::move(reference_profile_fd);
         std::vector<std::string> dex_locations = {dex_location};
-        SetupArgs(profiles_fd_, reference_profile_fd_, apk_fds_, dex_locations,
-                  /*copy_and_update=*/true);
+        SetupArgs(profiles_fd_,
+                  reference_profile_fd_,
+                  apk_fds_,
+                  dex_locations,
+                  /*copy_and_update=*/true,
+                  /*store_aggregation_counters=*/false);
     }
 
     void SetupDump(const std::vector<unique_fd>& profiles_fd,
@@ -724,8 +735,12 @@
                    const unique_fd& output_fd) {
         AddArg("--dump-only");
         AddArg(StringPrintf("--dump-output-to-fd=%d", output_fd.get()));
-        SetupArgs(profiles_fd, reference_profile_fd, apk_fds, dex_locations,
-                  /*copy_and_update=*/false);
+        SetupArgs(profiles_fd,
+                  reference_profile_fd,
+                  apk_fds,
+                  dex_locations,
+                  /*copy_and_update=*/false,
+                  /*store_aggregation_counters=*/false);
     }
 
     void Exec() {
@@ -2618,7 +2633,11 @@
             }
         }
         RunProfman args;
-        args.SetupMerge(profiles_fd, snapshot_fd, apk_fds, dex_locations);
+        args.SetupMerge(profiles_fd,
+                        snapshot_fd,
+                        apk_fds,
+                        dex_locations,
+                        /*store_aggregation_counters=*/true);
         pid_t pid = fork();
         if (pid == 0) {
             /* child -- drop privileges before continuing */
diff --git a/headers/media_plugin/media/hardware/HardwareAPI.h b/headers/media_plugin/media/hardware/HardwareAPI.h
index 6c1ba3d..ae0220a 100644
--- a/headers/media_plugin/media/hardware/HardwareAPI.h
+++ b/headers/media_plugin/media/hardware/HardwareAPI.h
@@ -425,7 +425,7 @@
 
 // HDR color description parameters.
 // This is passed via OMX_SetConfig or OMX_GetConfig to video encoders and decoders when the
-// 'OMX.google.android.index.describeHDRColorInfo' extension is given and an HDR stream
+// 'OMX.google.android.index.describeHDRStaticInfo' extension is given and an HDR stream
 // is detected.  Component SHALL behave as described below if it supports this extension.
 //
 // Currently, only Static Metadata Descriptor Type 1 support is required.
@@ -496,6 +496,64 @@
     HDRStaticInfo sInfo;           // IN/OUT
 };
 
+// HDR10+ metadata configuration.
+//
+// nParamSize: size of the storage starting at nValue (must be at least 1 and at most
+//             MAX_HDR10PLUSINFO_SIZE). This field must not be modified by the component.
+// nParamSizeUsed: size of the actual HDR10+ metadata starting at nValue. For OMX_SetConfig,
+//                 it must not be modified by the component. For OMX_GetConfig, the component
+//                 should put the actual size of the retrieved config in this field (and in
+//                 case where nParamSize is smaller than nParamSizeUsed, the component should
+//                 still update nParamSizeUsed without actually copying the metadata to nValue).
+// nValue: storage of the HDR10+ metadata conforming to the user_data_registered_itu_t_t35()
+//         syntax of SEI message for ST 2094-40.
+//
+// This is passed via OMX_SetConfig or OMX_GetConfig to video encoders and decoders when the
+// 'OMX.google.android.index.describeHDR10PlusInfo' extension is given. In general, this config
+// is associated with a particular frame. A typical sequence of usage is as follows:
+//
+// a) OMX_SetConfig associates the config with the next input buffer sent in OMX_EmptyThisBuffer
+//    (input A);
+// b) The component sends OMX_EventConfigUpdate to notify the client that there is a config
+//    update  on the output port that is associated with the next output buffer that's about to
+//    be sent via FillBufferDone callback (output A);
+// c) The client, upon receiving the OMX_EventConfigUpdate, calls OMX_GetConfig to retrieve
+//    the config and associates it with output A.
+//
+// All config updates will be retrieved in the order reported, and the client is required to
+// call OMX_GetConfig for each OMX_EventConfigUpdate for this config. Note that the order of
+// OMX_EventConfigUpdate relative to FillBufferDone callback determines which output frame
+// the config should be associated with, the actual OMX_GetConfig for the config could happen
+// before or after the component calls the FillBufferDone callback.
+//
+// Depending on the video codec type (in particular, whether the codec uses in-band or out-of-
+// band HDR10+ metadata), the component shall behave as detailed below:
+//
+// VIDEO DECODERS:
+// 1) If the codec utilizes out-of-band HDR10+ metadata, the decoder must support the sequence
+//    a) ~ c) outlined above;
+// 2) If the codec utilizes in-band HDR10+ metadata, OMX_SetConfig for this config should be
+//    ignored (as the metadata is embedded in the input buffer), while the notification and
+//    retrieval of the config on the output as outlined in b) & c) must be supported.
+//
+// VIDEO ENCODERS:
+// 1) If the codec utilizes out-of-band HDR10+ metadata, the decoder must support the sequence
+//    a) ~ c) outlined above;
+// 2) If the codec utilizes in-band HDR10+ metadata, OMX_SetConfig for this config outlined in
+//    a) must be supported. The notification as outlined in b) must not be sent, and the
+//    retrieval of the config via OMX_GetConfig should be ignored (as the metadata is embedded
+//    in the output buffer).
+
+#define MAX_HDR10PLUSINFO_SIZE 1024
+struct DescribeHDR10PlusInfoParams {
+    OMX_U32 nSize;                 // IN
+    OMX_VERSIONTYPE nVersion;      // IN
+    OMX_U32 nPortIndex;            // IN
+    OMX_U32 nParamSize;            // IN
+    OMX_U32 nParamSizeUsed;        // IN/OUT
+    OMX_U8 nValue[1];              // IN/OUT
+};
+
 }  // namespace android
 
 extern android::OMXPluginBase *createOMXPlugin();
diff --git a/headers/media_plugin/media/openmax/OMX_Core.h b/headers/media_plugin/media/openmax/OMX_Core.h
index bb974b3..9ff934e 100644
--- a/headers/media_plugin/media/openmax/OMX_Core.h
+++ b/headers/media_plugin/media/openmax/OMX_Core.h
@@ -542,6 +542,20 @@
      *  fool-proof way to do that for video encoders.
      */
     OMX_EventDataSpaceChanged,
+
+    /**
+     * Event when a component has an updated configuration on output for the client to retrieve.
+     * |arg1| contains the port index (currently only output port is valid). |arg2| contains the
+     * index of the updated config.
+     *
+     * For config updates that's associated with one frame, the update should be applied to the
+     * next output frame that comes in EmptyBufferDone callback.
+     *
+     * Upon receiving this event, the client must call the corresponding OMX_GetConfig to retrieve
+     * the config update.
+     */
+    OMX_EventConfigUpdate,
+
     OMX_EventMax = 0x7FFFFFFF
 } OMX_EVENTTYPE;
 
diff --git a/headers/media_plugin/media/openmax/OMX_VideoExt.h b/headers/media_plugin/media/openmax/OMX_VideoExt.h
index bbf157b..435fcc8 100644
--- a/headers/media_plugin/media/openmax/OMX_VideoExt.h
+++ b/headers/media_plugin/media/openmax/OMX_VideoExt.h
@@ -164,6 +164,8 @@
     // HDR profiles also support passing HDR metadata
     OMX_VIDEO_VP9Profile2HDR = 0x1000,
     OMX_VIDEO_VP9Profile3HDR = 0x2000,
+    OMX_VIDEO_VP9Profile2HDR10Plus = 0x4000,
+    OMX_VIDEO_VP9Profile3HDR10Plus = 0x8000,
     OMX_VIDEO_VP9ProfileUnknown = 0x6EFFFFFF,
     OMX_VIDEO_VP9ProfileMax = 0x7FFFFFFF
 } OMX_VIDEO_VP9PROFILETYPE;
@@ -216,6 +218,7 @@
     OMX_VIDEO_HEVCProfileMainStill    = 0x4,
     // Main10 profile with HDR SEI support.
     OMX_VIDEO_HEVCProfileMain10HDR10  = 0x1000,
+    OMX_VIDEO_HEVCProfileMain10HDR10Plus  = 0x2000,
     OMX_VIDEO_HEVCProfileMax          = 0x7FFFFFFF
 } OMX_VIDEO_HEVCPROFILETYPE;
 
diff --git a/libs/binderthreadstate/Android.bp b/libs/binderthreadstate/Android.bp
index 7106cbb..512b069 100644
--- a/libs/binderthreadstate/Android.bp
+++ b/libs/binderthreadstate/Android.bp
@@ -24,11 +24,13 @@
         "IPCThreadStateBase.cpp",
     ],
 
+    header_libs: [
+        "libbase_headers",
+        "libutils_headers",
+    ],
+
     shared_libs: [
-        "libbase",
         "liblog",
-        "libcutils",
-        "libutils",
     ],
 
     export_include_dirs: ["include"],
diff --git a/libs/graphicsenv/GraphicsEnv.cpp b/libs/graphicsenv/GraphicsEnv.cpp
index dfdda0c..9dc7431 100644
--- a/libs/graphicsenv/GraphicsEnv.cpp
+++ b/libs/graphicsenv/GraphicsEnv.cpp
@@ -19,6 +19,7 @@
 #include <graphicsenv/GraphicsEnv.h>
 
 #include <dlfcn.h>
+#include <unistd.h>
 
 #include <android-base/file.h>
 #include <android-base/properties.h>
@@ -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" {
@@ -46,6 +51,20 @@
 };
 }
 
+// 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 {
@@ -134,39 +153,186 @@
     mDriverPath = path;
 }
 
+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 {
+        ALOGE("dlopen_ext(\"%s\") failed: %s", libName.c_str(), dlerror());
+    }
+
+    return nullptr;
+}
+
+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());
+        return false;
+    }
+
+    return shouldUseAngle();
+}
+
+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) {
-    if (!mAnglePath.empty()) {
-        ALOGV("ignoring attempt to change ANGLE path from '%s' to '%s'", mAnglePath.c_str(),
-              path.c_str());
-    } else {
-        ALOGV("setting ANGLE path to '%s'", path.c_str());
-        mAnglePath = path;
-    }
+    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;
 
-    if (!mAngleAppName.empty()) {
-        ALOGV("ignoring attempt to change ANGLE app name from '%s' to '%s'", mAngleAppName.c_str(),
-              appName.c_str());
-    } else {
-        ALOGV("setting ANGLE app name to '%s'", appName.c_str());
-        mAngleAppName = appName;
+    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 (!mAngleDeveloperOptIn.empty()) {
-        ALOGV("ignoring attempt to change ANGLE application opt-in from '%s' to '%s'",
-              mAngleDeveloperOptIn.c_str(), developerOptIn.c_str());
-    } else {
-        ALOGV("setting ANGLE application opt-in to '%s'", developerOptIn.c_str());
-        mAngleDeveloperOptIn = developerOptIn;
+    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) {
@@ -183,25 +349,8 @@
     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() {
diff --git a/libs/graphicsenv/include/graphicsenv/GraphicsEnv.h b/libs/graphicsenv/include/graphicsenv/GraphicsEnv.h
index 4ec53f1..37c24ef 100644
--- a/libs/graphicsenv/include/graphicsenv/GraphicsEnv.h
+++ b/libs/graphicsenv/include/graphicsenv/GraphicsEnv.h
@@ -18,6 +18,7 @@
 #define ANDROID_UI_GRAPHICS_ENV_H 1
 
 #include <string>
+#include <vector>
 
 struct android_namespace_t;
 
@@ -39,6 +40,8 @@
     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
@@ -47,12 +50,7 @@
     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();
@@ -65,14 +63,17 @@
     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;
diff --git a/libs/renderengine/gl/GLESRenderEngine.cpp b/libs/renderengine/gl/GLESRenderEngine.cpp
index 53b0e4c..51cf188 100644
--- a/libs/renderengine/gl/GLESRenderEngine.cpp
+++ b/libs/renderengine/gl/GLESRenderEngine.cpp
@@ -648,27 +648,89 @@
     return success;
 }
 
-status_t GLESRenderEngine::drawLayers(const DisplaySettings& /*settings*/,
-                                      const std::vector<LayerSettings>& /*layers*/,
-                                      ANativeWindowBuffer* const /*buffer*/,
-                                      base::unique_fd* /*displayFence*/) const {
+status_t GLESRenderEngine::drawLayers(const DisplaySettings& display,
+                                      const std::vector<LayerSettings>& layers,
+                                      ANativeWindowBuffer* const buffer,
+                                      base::unique_fd* drawFence) {
+    if (layers.empty()) {
+        ALOGV("Drawing empty layer stack");
+        return NO_ERROR;
+    }
+
+    BindNativeBufferAsFramebuffer fbo(*this, buffer);
+
+    if (fbo.getStatus() != NO_ERROR) {
+        ALOGE("Failed to bind framebuffer! Aborting GPU composition for buffer (%p).",
+              buffer->handle);
+        checkErrors();
+        return fbo.getStatus();
+    }
+
+    setViewportAndProjection(display.physicalDisplay, display.clip);
+
+    setOutputDataSpace(display.outputDataspace);
+    setDisplayMaxLuminance(display.maxLuminance);
+
+    mat4 projectionMatrix = mState.projectionMatrix * display.globalTransform;
+
+    Mesh mesh(Mesh::TRIANGLE_FAN, 4, 2);
+    for (auto layer : layers) {
+        // for now, assume that all pixel sources are solid colors.
+        // TODO(alecmouri): support buffer sources
+        if (layer.source.buffer.buffer != nullptr) {
+            continue;
+        }
+
+        setColorTransform(display.colorTransform * layer.colorTransform);
+
+        mState.projectionMatrix = projectionMatrix * layer.geometry.positionTransform;
+
+        FloatRect bounds = layer.geometry.boundaries;
+        Mesh::VertexArray<vec2> position(mesh.getPositionArray<vec2>());
+        position[0] = vec2(bounds.left, bounds.top);
+        position[1] = vec2(bounds.left, bounds.bottom);
+        position[2] = vec2(bounds.right, bounds.bottom);
+        position[3] = vec2(bounds.right, bounds.top);
+
+        half3 solidColor = layer.source.solidColor;
+        half4 color = half4(solidColor.r, solidColor.g, solidColor.b, layer.alpha);
+        setupLayerBlending(/*premultipliedAlpha=*/true, /*opaque=*/false, /*disableTexture=*/true,
+                           color, /*cornerRadius=*/0.0);
+        setSourceDataSpace(layer.sourceDataspace);
+
+        drawMesh(mesh);
+    }
+
+    *drawFence = flush();
+    // If flush failed or we don't support native fences, we need to force the
+    // gl command stream to be executed.
+    if (drawFence->get() < 0) {
+        bool success = finish();
+        if (!success) {
+            ALOGE("Failed to flush RenderEngine commands");
+            checkErrors();
+            // Chances are, something illegal happened (either the caller passed
+            // us bad parameters, or we messed up our shader generation).
+            return INVALID_OPERATION;
+        }
+    }
+
+    checkErrors();
     return NO_ERROR;
 }
 
 void GLESRenderEngine::setViewportAndProjection(size_t vpw, size_t vph, Rect sourceCrop,
                                                 ui::Transform::orientation_flags rotation) {
-    int32_t l = sourceCrop.left;
-    int32_t r = sourceCrop.right;
-    int32_t b = sourceCrop.bottom;
-    int32_t t = sourceCrop.top;
-    std::swap(t, b);
-    mat4 m = mat4::ortho(l, r, b, t, 0, 1);
+    setViewportAndProjection(Rect(vpw, vph), sourceCrop);
+
+    if (rotation == ui::Transform::ROT_0) {
+        return;
+    }
 
     // Apply custom rotation to the projection.
     float rot90InRadians = 2.0f * static_cast<float>(M_PI) / 4.0f;
+    mat4 m = mState.projectionMatrix;
     switch (rotation) {
-        case ui::Transform::ROT_0:
-            break;
         case ui::Transform::ROT_90:
             m = mat4::rotate(rot90InRadians, vec3(0, 0, 1)) * m;
             break;
@@ -681,11 +743,18 @@
         default:
             break;
     }
-
-    glViewport(0, 0, vpw, vph);
     mState.projectionMatrix = m;
-    mVpWidth = vpw;
-    mVpHeight = vph;
+}
+
+void GLESRenderEngine::setViewportAndProjection(Rect viewport, Rect clip) {
+    mVpWidth = viewport.getWidth();
+    mVpHeight = viewport.getHeight();
+
+    // We pass the the top left corner instead of the bottom left corner,
+    // because since we're rendering off-screen first.
+    glViewport(viewport.left, viewport.top, mVpWidth, mVpHeight);
+
+    mState.projectionMatrix = mat4::ortho(clip.left, clip.right, clip.top, clip.bottom, 0, 1);
 }
 
 void GLESRenderEngine::setupLayerBlending(bool premultipliedAlpha, bool opaque, bool disableTexture,
diff --git a/libs/renderengine/gl/GLESRenderEngine.h b/libs/renderengine/gl/GLESRenderEngine.h
index 07e5585..b6fff33 100644
--- a/libs/renderengine/gl/GLESRenderEngine.h
+++ b/libs/renderengine/gl/GLESRenderEngine.h
@@ -72,9 +72,8 @@
     bool isProtected() const override { return mInProtectedContext; }
     bool supportsProtectedContent() const override;
     bool useProtectedContext(bool useProtectedContext) override;
-    status_t drawLayers(const DisplaySettings& settings, const std::vector<LayerSettings>& layers,
-                        ANativeWindowBuffer* const buffer,
-                        base::unique_fd* displayFence) const override;
+    status_t drawLayers(const DisplaySettings& display, const std::vector<LayerSettings>& layers,
+                        ANativeWindowBuffer* buffer, base::unique_fd* drawFence) override;
 
     // internal to RenderEngine
     EGLDisplay getEGLDisplay() const { return mEGLDisplay; }
@@ -125,6 +124,9 @@
     // with PQ or HLG transfer function.
     bool isHdrDataSpace(const ui::Dataspace dataSpace) const;
     bool needsXYZTransformMatrix() const;
+    // Defines the viewport, and sets the projection matrix to the projection
+    // defined by the clip.
+    void setViewportAndProjection(Rect viewport, Rect clip);
 
     EGLDisplay mEGLDisplay;
     EGLConfig mEGLConfig;
diff --git a/libs/renderengine/include/renderengine/DisplaySettings.h b/libs/renderengine/include/renderengine/DisplaySettings.h
index aa4e319..0c92353 100644
--- a/libs/renderengine/include/renderengine/DisplaySettings.h
+++ b/libs/renderengine/include/renderengine/DisplaySettings.h
@@ -41,7 +41,7 @@
     mat4 globalTransform = mat4();
 
     // Maximum luminance pulled from the display's HDR capabilities.
-    float maxLuminence = 1.0f;
+    float maxLuminance = 1.0f;
 
     // Output dataspace that will be populated if wide color gamut is used, or
     // DataSpace::UNKNOWN otherwise.
diff --git a/libs/renderengine/include/renderengine/LayerSettings.h b/libs/renderengine/include/renderengine/LayerSettings.h
index 38dee40..93abf5c 100644
--- a/libs/renderengine/include/renderengine/LayerSettings.h
+++ b/libs/renderengine/include/renderengine/LayerSettings.h
@@ -85,7 +85,11 @@
     half alpha = half(0.0);
 
     // Color space describing how the source pixels should be interpreted.
-    ui::Dataspace sourceDataspace = ui::Dataspace::UNKNOWN;
+    ui::Dataspace sourceDataspace;
+
+    // Additional layer-specific color transform to be applied before the global
+    // transform.
+    mat4 colorTransform;
 };
 
 } // namespace renderengine
diff --git a/libs/renderengine/include/renderengine/RenderEngine.h b/libs/renderengine/include/renderengine/RenderEngine.h
index 5e88159..20dd996 100644
--- a/libs/renderengine/include/renderengine/RenderEngine.h
+++ b/libs/renderengine/include/renderengine/RenderEngine.h
@@ -161,12 +161,12 @@
 
     // Renders layers for a particular display via GPU composition. This method
     // should be called for every display that needs to be rendered via the GPU.
-    // @param settings The display-wide settings that should be applied prior to
+    // @param display The display-wide settings that should be applied prior to
     // drawing any layers.
     // @param layers The layers to draw onto the display, in Z-order.
     // @param buffer The buffer which will be drawn to. This buffer will be
     // ready once displayFence fires.
-    // @param displayFence A pointer to a fence, which will fire when the buffer
+    // @param drawFence A pointer to a fence, which will fire when the buffer
     // has been drawn to and is ready to be examined. The fence will be
     // initialized by this method. The caller will be responsible for owning the
     // fence.
@@ -174,10 +174,9 @@
     // now, this always returns NO_ERROR.
     // TODO(alecmouri): Consider making this a multi-display API, so that the
     // caller deoes not need to handle multiple fences.
-    virtual status_t drawLayers(const DisplaySettings& settings,
+    virtual status_t drawLayers(const DisplaySettings& display,
                                 const std::vector<LayerSettings>& layers,
-                                ANativeWindowBuffer* const buffer,
-                                base::unique_fd* displayFence) const = 0;
+                                ANativeWindowBuffer* buffer, base::unique_fd* drawFence) = 0;
 
     // TODO(alecmouri): Expose something like bindTexImage() so that devices
     // that don't support native sync fences can get rid of code duplicated
diff --git a/libs/renderengine/tests/Android.bp b/libs/renderengine/tests/Android.bp
index 051b8b6..9b483ef 100644
--- a/libs/renderengine/tests/Android.bp
+++ b/libs/renderengine/tests/Android.bp
@@ -31,6 +31,7 @@
         "libgui",
         "liblog",
         "libnativewindow",
+        "libsync",
         "libui",
         "libutils",
     ],
diff --git a/libs/renderengine/tests/RenderEngineTest.cpp b/libs/renderengine/tests/RenderEngineTest.cpp
index 345c7ea..a0542dd 100644
--- a/libs/renderengine/tests/RenderEngineTest.cpp
+++ b/libs/renderengine/tests/RenderEngineTest.cpp
@@ -17,36 +17,430 @@
 #include <gtest/gtest.h>
 
 #include <renderengine/RenderEngine.h>
+#include <sync/sync.h>
 #include <ui/PixelFormat.h>
 
+constexpr int DEFAULT_DISPLAY_WIDTH = 128;
+constexpr int DEFAULT_DISPLAY_HEIGHT = 256;
+constexpr int DEFAULT_DISPLAY_OFFSET = 64;
+
 namespace android {
 
-class RenderEngineTest : public ::testing::Test {
-public:
-    RenderEngineTest() {
-        // Initialize with some sane defaults.
-        // TODO(alecmouri): This should probably be the same instance used by
-        // SurfaceFlinger eventually.
-        mRE = renderengine::RenderEngine::create(static_cast<int32_t>(ui::PixelFormat::RGBA_8888),
-                                                 0);
+struct RenderEngineTest : public ::testing::Test {
+    sp<GraphicBuffer> allocateDefaultBuffer() {
+        return new GraphicBuffer(DEFAULT_DISPLAY_WIDTH, DEFAULT_DISPLAY_HEIGHT,
+                                 HAL_PIXEL_FORMAT_RGBA_8888, 1,
+                                 GRALLOC_USAGE_SW_READ_OFTEN | GRALLOC_USAGE_SW_WRITE_OFTEN,
+                                 "output");
     }
 
-    status_t drawEmptyLayers() {
+    RenderEngineTest() { mBuffer = allocateDefaultBuffer(); }
+
+    void expectBufferColor(const Rect& region, uint8_t r, uint8_t g, uint8_t b, uint8_t a,
+                           uint8_t tolerance = 0) {
+        uint8_t* pixels;
+        mBuffer->lock(GRALLOC_USAGE_SW_READ_OFTEN | GRALLOC_USAGE_SW_WRITE_OFTEN,
+                      reinterpret_cast<void**>(&pixels));
+
+        auto colorCompare = [tolerance](uint8_t a, uint8_t b) {
+            uint8_t tmp = a >= b ? a - b : b - a;
+            return tmp <= tolerance;
+        };
+        int32_t maxFails = 10;
+        int32_t fails = 0;
+        for (int32_t j = 0; j < region.getHeight(); j++) {
+            const uint8_t* src =
+                    pixels + (mBuffer->getStride() * (region.top + j) + region.left) * 4;
+            for (int32_t i = 0; i < region.getWidth(); i++) {
+                const uint8_t expected[4] = {r, g, b, a};
+                bool equal = std::equal(src, src + 4, expected, colorCompare);
+                EXPECT_TRUE(equal)
+                        << "pixel @ (" << region.left + i << ", " << region.top + j << "): "
+                        << "expected (" << static_cast<uint32_t>(r) << ", "
+                        << static_cast<uint32_t>(g) << ", " << static_cast<uint32_t>(b) << ", "
+                        << static_cast<uint32_t>(a) << "), "
+                        << "got (" << static_cast<uint32_t>(src[0]) << ", "
+                        << static_cast<uint32_t>(src[1]) << ", " << static_cast<uint32_t>(src[2])
+                        << ", " << static_cast<uint32_t>(src[3]) << ")";
+                src += 4;
+                if (!equal && ++fails >= maxFails) {
+                    break;
+                }
+            }
+            if (fails >= maxFails) {
+                break;
+            }
+        }
+        mBuffer->unlock();
+    }
+
+    static Rect fullscreenRect() { return Rect(DEFAULT_DISPLAY_WIDTH, DEFAULT_DISPLAY_HEIGHT); }
+
+    static Rect offsetRect() {
+        return Rect(DEFAULT_DISPLAY_OFFSET, DEFAULT_DISPLAY_OFFSET, DEFAULT_DISPLAY_WIDTH,
+                    DEFAULT_DISPLAY_HEIGHT);
+    }
+
+    static Rect offsetRectAtZero() {
+        return Rect(DEFAULT_DISPLAY_WIDTH - DEFAULT_DISPLAY_OFFSET,
+                    DEFAULT_DISPLAY_HEIGHT - DEFAULT_DISPLAY_OFFSET);
+    }
+
+    static void invokeDraw(renderengine::DisplaySettings settings,
+                           std::vector<renderengine::LayerSettings> layers,
+                           sp<GraphicBuffer> buffer) {
+        base::unique_fd fence;
+        status_t status = sRE->drawLayers(settings, layers, buffer->getNativeBuffer(), &fence);
+
+        int fd = fence.release();
+        if (fd >= 0) {
+            sync_wait(fd, -1);
+            close(fd);
+        }
+
+        ASSERT_EQ(NO_ERROR, status);
+    }
+
+    static void drawEmptyLayers() {
         renderengine::DisplaySettings settings;
         std::vector<renderengine::LayerSettings> layers;
         // Meaningless buffer since we don't do any drawing
         sp<GraphicBuffer> buffer = new GraphicBuffer();
-        base::unique_fd fence;
-        return mRE->drawLayers(settings, layers, buffer->getNativeBuffer(), &fence);
+        invokeDraw(settings, layers, buffer);
     }
 
-private:
-    std::unique_ptr<renderengine::RenderEngine> mRE;
+    template <typename SourceVariant>
+    void fillBuffer(half r, half g, half b, half a);
+
+    template <typename SourceVariant>
+    void fillRedBuffer();
+
+    template <typename SourceVariant>
+    void fillGreenBuffer();
+
+    template <typename SourceVariant>
+    void fillBlueBuffer();
+
+    template <typename SourceVariant>
+    void fillRedTransparentBuffer();
+
+    template <typename SourceVariant>
+    void fillRedOffsetBuffer();
+
+    template <typename SourceVariant>
+    void fillBufferPhysicalOffset();
+
+    template <typename SourceVariant>
+    void fillBufferCheckers(mat4 transform);
+
+    template <typename SourceVariant>
+    void fillBufferCheckersRotate0();
+
+    template <typename SourceVariant>
+    void fillBufferCheckersRotate90();
+
+    template <typename SourceVariant>
+    void fillBufferCheckersRotate180();
+
+    template <typename SourceVariant>
+    void fillBufferCheckersRotate270();
+
+    template <typename SourceVariant>
+    void fillBufferLayerTransform();
+
+    template <typename SourceVariant>
+    void fillBufferColorTransform();
+
+    // Dumb hack to get aroud the fact that tear-down for renderengine isn't
+    // well defined right now, so we can't create multiple instances
+    static std::unique_ptr<renderengine::RenderEngine> sRE;
+
+    sp<GraphicBuffer> mBuffer;
 };
 
-TEST_F(RenderEngineTest, drawLayers_noLayersToDraw_works) {
-    status_t result = drawEmptyLayers();
-    ASSERT_EQ(NO_ERROR, result);
+std::unique_ptr<renderengine::RenderEngine> RenderEngineTest::sRE =
+        renderengine::RenderEngine::create(static_cast<int32_t>(ui::PixelFormat::RGBA_8888), 0);
+
+struct ColorSourceVariant {
+    static void fillColor(renderengine::LayerSettings& layer, half r, half g, half b) {
+        layer.source.solidColor = half3(r, g, b);
+    }
+};
+
+template <typename SourceVariant>
+void RenderEngineTest::fillBuffer(half r, half g, half b, half a) {
+    renderengine::DisplaySettings settings;
+    settings.physicalDisplay = fullscreenRect();
+    settings.clip = fullscreenRect();
+
+    std::vector<renderengine::LayerSettings> layers;
+
+    renderengine::LayerSettings layer;
+    layer.geometry.boundaries = fullscreenRect().toFloatRect();
+    SourceVariant::fillColor(layer, r, g, b);
+    layer.alpha = a;
+
+    layers.push_back(layer);
+
+    invokeDraw(settings, layers, mBuffer);
+}
+
+template <typename SourceVariant>
+void RenderEngineTest::fillRedBuffer() {
+    fillBuffer<SourceVariant>(1.0f, 0.0f, 0.0f, 1.0f);
+    expectBufferColor(fullscreenRect(), 255, 0, 0, 255);
+}
+
+template <typename SourceVariant>
+void RenderEngineTest::fillGreenBuffer() {
+    fillBuffer<SourceVariant>(0.0f, 1.0f, 0.0f, 1.0f);
+    expectBufferColor(fullscreenRect(), 0, 255, 0, 255);
+}
+
+template <typename SourceVariant>
+void RenderEngineTest::fillBlueBuffer() {
+    fillBuffer<SourceVariant>(0.0f, 0.0f, 1.0f, 1.0f);
+    expectBufferColor(fullscreenRect(), 0, 0, 255, 255);
+}
+
+template <typename SourceVariant>
+void RenderEngineTest::fillRedTransparentBuffer() {
+    fillBuffer<SourceVariant>(1.0f, 0.0f, 0.0f, .2f);
+    expectBufferColor(fullscreenRect(), 51, 0, 0, 51);
+}
+
+template <typename SourceVariant>
+void RenderEngineTest::fillRedOffsetBuffer() {
+    renderengine::DisplaySettings settings;
+    settings.physicalDisplay = offsetRect();
+    settings.clip = offsetRectAtZero();
+
+    std::vector<renderengine::LayerSettings> layers;
+
+    renderengine::LayerSettings layer;
+    layer.geometry.boundaries = offsetRectAtZero().toFloatRect();
+    SourceVariant::fillColor(layer, 1.0f, 0.0f, 0.0f);
+    layer.alpha = 1.0f;
+
+    layers.push_back(layer);
+    invokeDraw(settings, layers, mBuffer);
+}
+
+template <typename SourceVariant>
+void RenderEngineTest::fillBufferPhysicalOffset() {
+    fillRedOffsetBuffer<SourceVariant>();
+
+    expectBufferColor(Rect(DEFAULT_DISPLAY_OFFSET, DEFAULT_DISPLAY_OFFSET, DEFAULT_DISPLAY_WIDTH,
+                           DEFAULT_DISPLAY_HEIGHT),
+                      255, 0, 0, 255);
+    Rect offsetRegionLeft(DEFAULT_DISPLAY_OFFSET, DEFAULT_DISPLAY_HEIGHT);
+    Rect offsetRegionTop(DEFAULT_DISPLAY_WIDTH, DEFAULT_DISPLAY_OFFSET);
+
+    expectBufferColor(offsetRegionLeft, 0, 0, 0, 0);
+    expectBufferColor(offsetRegionTop, 0, 0, 0, 0);
+}
+
+template <typename SourceVariant>
+void RenderEngineTest::fillBufferCheckers(mat4 transform) {
+    renderengine::DisplaySettings settings;
+    settings.physicalDisplay = fullscreenRect();
+    // Here logical space is 2x2
+    settings.clip = Rect(2, 2);
+    settings.globalTransform = transform;
+
+    std::vector<renderengine::LayerSettings> layers;
+
+    renderengine::LayerSettings layerOne;
+    Rect rectOne(0, 0, 1, 1);
+    layerOne.geometry.boundaries = rectOne.toFloatRect();
+    SourceVariant::fillColor(layerOne, 1.0f, 0.0f, 0.0f);
+    layerOne.alpha = 1.0f;
+
+    renderengine::LayerSettings layerTwo;
+    Rect rectTwo(0, 1, 1, 2);
+    layerTwo.geometry.boundaries = rectTwo.toFloatRect();
+    SourceVariant::fillColor(layerTwo, 0.0f, 1.0f, 0.0f);
+    layerTwo.alpha = 1.0f;
+
+    renderengine::LayerSettings layerThree;
+    Rect rectThree(1, 0, 2, 1);
+    layerThree.geometry.boundaries = rectThree.toFloatRect();
+    SourceVariant::fillColor(layerThree, 0.0f, 0.0f, 1.0f);
+    layerThree.alpha = 1.0f;
+
+    layers.push_back(layerOne);
+    layers.push_back(layerTwo);
+    layers.push_back(layerThree);
+
+    invokeDraw(settings, layers, mBuffer);
+}
+
+template <typename SourceVariant>
+void RenderEngineTest::fillBufferCheckersRotate0() {
+    fillBufferCheckers<SourceVariant>(mat4());
+    expectBufferColor(Rect(0, 0, DEFAULT_DISPLAY_WIDTH / 2, DEFAULT_DISPLAY_HEIGHT / 2), 255, 0, 0,
+                      255);
+    expectBufferColor(Rect(DEFAULT_DISPLAY_WIDTH / 2, 0, DEFAULT_DISPLAY_WIDTH,
+                           DEFAULT_DISPLAY_HEIGHT / 2),
+                      0, 0, 255, 255);
+    expectBufferColor(Rect(DEFAULT_DISPLAY_WIDTH / 2, DEFAULT_DISPLAY_HEIGHT / 2,
+                           DEFAULT_DISPLAY_WIDTH, DEFAULT_DISPLAY_HEIGHT),
+                      0, 0, 0, 0);
+    expectBufferColor(Rect(0, DEFAULT_DISPLAY_HEIGHT / 2, DEFAULT_DISPLAY_WIDTH / 2,
+                           DEFAULT_DISPLAY_HEIGHT),
+                      0, 255, 0, 255);
+}
+
+template <typename SourceVariant>
+void RenderEngineTest::fillBufferCheckersRotate90() {
+    mat4 matrix = mat4(0, 1, 0, 0, -1, 0, 0, 0, 0, 0, 1, 0, 2, 0, 0, 1);
+    fillBufferCheckers<SourceVariant>(matrix);
+    expectBufferColor(Rect(0, 0, DEFAULT_DISPLAY_WIDTH / 2, DEFAULT_DISPLAY_HEIGHT / 2), 0, 255, 0,
+                      255);
+    expectBufferColor(Rect(DEFAULT_DISPLAY_WIDTH / 2, 0, DEFAULT_DISPLAY_WIDTH,
+                           DEFAULT_DISPLAY_HEIGHT / 2),
+                      255, 0, 0, 255);
+    expectBufferColor(Rect(DEFAULT_DISPLAY_WIDTH / 2, DEFAULT_DISPLAY_HEIGHT / 2,
+                           DEFAULT_DISPLAY_WIDTH, DEFAULT_DISPLAY_HEIGHT),
+                      0, 0, 255, 255);
+    expectBufferColor(Rect(0, DEFAULT_DISPLAY_HEIGHT / 2, DEFAULT_DISPLAY_WIDTH / 2,
+                           DEFAULT_DISPLAY_HEIGHT),
+                      0, 0, 0, 0);
+}
+
+template <typename SourceVariant>
+void RenderEngineTest::fillBufferCheckersRotate180() {
+    mat4 matrix = mat4(-1, 0, 0, 0, 0, -1, 0, 0, 0, 0, 1, 0, 2, 2, 0, 1);
+    fillBufferCheckers<SourceVariant>(matrix);
+    expectBufferColor(Rect(0, 0, DEFAULT_DISPLAY_WIDTH / 2, DEFAULT_DISPLAY_HEIGHT / 2), 0, 0, 0,
+                      0);
+    expectBufferColor(Rect(DEFAULT_DISPLAY_WIDTH / 2, 0, DEFAULT_DISPLAY_WIDTH,
+                           DEFAULT_DISPLAY_HEIGHT / 2),
+                      0, 255, 0, 255);
+    expectBufferColor(Rect(DEFAULT_DISPLAY_WIDTH / 2, DEFAULT_DISPLAY_HEIGHT / 2,
+                           DEFAULT_DISPLAY_WIDTH, DEFAULT_DISPLAY_HEIGHT),
+                      255, 0, 0, 255);
+    expectBufferColor(Rect(0, DEFAULT_DISPLAY_HEIGHT / 2, DEFAULT_DISPLAY_WIDTH / 2,
+                           DEFAULT_DISPLAY_HEIGHT),
+                      0, 0, 255, 255);
+}
+
+template <typename SourceVariant>
+void RenderEngineTest::fillBufferCheckersRotate270() {
+    mat4 matrix = mat4(0, -1, 0, 0, 1, 0, 0, 0, 0, 0, 1, 0, 0, 2, 0, 1);
+    fillBufferCheckers<SourceVariant>(matrix);
+    expectBufferColor(Rect(0, 0, DEFAULT_DISPLAY_WIDTH / 2, DEFAULT_DISPLAY_HEIGHT / 2), 0, 0, 255,
+                      255);
+    expectBufferColor(Rect(DEFAULT_DISPLAY_WIDTH / 2, 0, DEFAULT_DISPLAY_WIDTH,
+                           DEFAULT_DISPLAY_HEIGHT / 2),
+                      0, 0, 0, 0);
+    expectBufferColor(Rect(DEFAULT_DISPLAY_WIDTH / 2, DEFAULT_DISPLAY_HEIGHT / 2,
+                           DEFAULT_DISPLAY_WIDTH, DEFAULT_DISPLAY_HEIGHT),
+                      0, 255, 0, 255);
+    expectBufferColor(Rect(0, DEFAULT_DISPLAY_HEIGHT / 2, DEFAULT_DISPLAY_WIDTH / 2,
+                           DEFAULT_DISPLAY_HEIGHT),
+                      255, 0, 0, 255);
+}
+
+template <typename SourceVariant>
+void RenderEngineTest::fillBufferLayerTransform() {
+    renderengine::DisplaySettings settings;
+    settings.physicalDisplay = fullscreenRect();
+    // Here logical space is 2x2
+    settings.clip = Rect(2, 2);
+
+    std::vector<renderengine::LayerSettings> layers;
+
+    renderengine::LayerSettings layer;
+    layer.geometry.boundaries = Rect(1, 1).toFloatRect();
+    // Translate one pixel diagonally
+    layer.geometry.positionTransform = mat4(1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, 1, 1, 0, 1);
+    layer.source.solidColor = half3(1.0f, 0.0f, 0.0f);
+    layer.alpha = 1.0f;
+
+    layers.push_back(layer);
+
+    invokeDraw(settings, layers, mBuffer);
+
+    expectBufferColor(Rect(0, 0, DEFAULT_DISPLAY_WIDTH, DEFAULT_DISPLAY_HEIGHT / 2), 0, 0, 0, 0);
+    expectBufferColor(Rect(0, 0, DEFAULT_DISPLAY_WIDTH / 2, DEFAULT_DISPLAY_HEIGHT), 0, 0, 0, 0);
+    expectBufferColor(Rect(DEFAULT_DISPLAY_WIDTH / 2, DEFAULT_DISPLAY_HEIGHT / 2,
+                           DEFAULT_DISPLAY_WIDTH, DEFAULT_DISPLAY_HEIGHT),
+                      255, 0, 0, 255);
+}
+
+template <typename SourceVariant>
+void RenderEngineTest::fillBufferColorTransform() {
+    renderengine::DisplaySettings settings;
+    settings.physicalDisplay = fullscreenRect();
+    settings.clip = Rect(1, 1);
+
+    std::vector<renderengine::LayerSettings> layers;
+
+    renderengine::LayerSettings layer;
+    layer.geometry.boundaries = Rect(1, 1).toFloatRect();
+    layer.source.solidColor = half3(0.5f, 0.25f, 0.125f);
+    layer.alpha = 1.0f;
+
+    // construct a fake color matrix
+    // annihilate green and blue channels
+    settings.colorTransform = mat4::scale(vec4(1, 0, 0, 1));
+    // set red channel to red + green
+    layer.colorTransform = mat4(1, 0, 0, 0, 1, 1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1);
+
+    layers.push_back(layer);
+
+    invokeDraw(settings, layers, mBuffer);
+
+    expectBufferColor(fullscreenRect(), 191, 0, 0, 255);
+}
+
+TEST_F(RenderEngineTest, drawLayers_noLayersToDraw) {
+    drawEmptyLayers();
+}
+
+TEST_F(RenderEngineTest, drawLayers_fillRedBuffer_colorSource) {
+    fillRedBuffer<ColorSourceVariant>();
+}
+
+TEST_F(RenderEngineTest, drawLayers_fillGreenBuffer_colorSource) {
+    fillGreenBuffer<ColorSourceVariant>();
+}
+
+TEST_F(RenderEngineTest, drawLayers_fillBlueBuffer_colorSource) {
+    fillBlueBuffer<ColorSourceVariant>();
+}
+
+TEST_F(RenderEngineTest, drawLayers_fillRedTransparentBuffer_colorSource) {
+    fillRedTransparentBuffer<ColorSourceVariant>();
+}
+
+TEST_F(RenderEngineTest, drawLayers_fillBufferPhysicalOffset_colorSource) {
+    fillBufferPhysicalOffset<ColorSourceVariant>();
+}
+
+TEST_F(RenderEngineTest, drawLayers_fillBufferCheckersRotate0_colorSource) {
+    fillBufferCheckersRotate0<ColorSourceVariant>();
+}
+
+TEST_F(RenderEngineTest, drawLayers_fillBufferCheckersRotate90_colorSource) {
+    fillBufferCheckersRotate90<ColorSourceVariant>();
+}
+
+TEST_F(RenderEngineTest, drawLayers_fillBufferCheckersRotate180_colorSource) {
+    fillBufferCheckersRotate180<ColorSourceVariant>();
+}
+
+TEST_F(RenderEngineTest, drawLayers_fillBufferCheckersRotate270_colorSource) {
+    fillBufferCheckersRotate270<ColorSourceVariant>();
+}
+
+TEST_F(RenderEngineTest, drawLayers_fillBufferLayerTransform_colorSource) {
+    fillBufferLayerTransform<ColorSourceVariant>();
+}
+
+TEST_F(RenderEngineTest, drawLayers_fillBufferColorTransform_colorSource) {
+    fillBufferLayerTransform<ColorSourceVariant>();
 }
 
 } // namespace android
diff --git a/opengl/libs/EGL/Loader.cpp b/opengl/libs/EGL/Loader.cpp
index f5cf3dc..8a409ae 100644
--- a/opengl/libs/EGL/Loader.cpp
+++ b/opengl/libs/EGL/Loader.cpp
@@ -17,7 +17,7 @@
 //#define LOG_NDEBUG 0
 #define ATRACE_TAG ATRACE_TAG_GRAPHICS
 
-#include "Loader.h"
+#include <EGL/Loader.h>
 
 #include <string>
 
@@ -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 {
 // ----------------------------------------------------------------------------
@@ -255,6 +223,13 @@
 
     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);
@@ -289,11 +264,7 @@
     delete hnd;
     cnx->dso = nullptr;
 
-    if (cnx->featureSo) {
-        dlclose(cnx->featureSo);
-        cnx->featureSo = nullptr;
-    }
-
+    cnx->shouldUseAngle = false;
     cnx->angleDecided = false;
     cnx->useAngle = false;
 
@@ -530,173 +501,32 @@
     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");
-        property_get("debug.hwui.renderer", prop, "UNSET");
-        ALOGV("Skia's renderer set to %s", prop);
+        ALOGV("Loaded ANGLE %s library for '%s' (instead of native)", kind,
+            android::GraphicsEnv::getInstance().getAngleAppName().c_str());
         cnx->useAngle = true;
 
-        EGLint angleBackendDefault = EGL_PLATFORM_ANGLE_TYPE_VULKAN_ANGLE;
-
         char prop[PROPERTY_VALUE_MAX];
+
+        property_get("debug.hwui.renderer", prop, "UNSET");
+        ALOGV("Skia's renderer set to %s", prop);
+
+        EGLint angleBackendDefault = EGL_PLATFORM_ANGLE_TYPE_VULKAN_ANGLE;
         property_get("debug.angle.backend", prop, "0");
         switch (atoi(prop)) {
             case 1:
@@ -716,13 +546,14 @@
             // 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] = {
diff --git a/opengl/libs/EGL/egldefs.h b/opengl/libs/EGL/egldefs.h
index cca0053..9e112cc 100644
--- a/opengl/libs/EGL/egldefs.h
+++ b/opengl/libs/EGL/egldefs.h
@@ -76,11 +76,11 @@
     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
 
diff --git a/services/bufferhub/tests/Android.bp b/services/bufferhub/tests/Android.bp
index e565374..8d29923 100644
--- a/services/bufferhub/tests/Android.bp
+++ b/services/bufferhub/tests/Android.bp
@@ -8,6 +8,8 @@
         "-DLOG_TAG=\"BufferHubServer_test\"",
         "-DTRACE=0",
         "-DATRACE_TAG=ATRACE_TAG_GRAPHICS",
+        "-Wall",
+        "-Werror",
     ],
     header_libs: [
         "libdvr_headers",
diff --git a/services/bufferhub/tests/BufferHubIdGenerator_test.cpp b/services/bufferhub/tests/BufferHubIdGenerator_test.cpp
index 4eddfe0..fe01013 100644
--- a/services/bufferhub/tests/BufferHubIdGenerator_test.cpp
+++ b/services/bufferhub/tests/BufferHubIdGenerator_test.cpp
@@ -27,7 +27,7 @@
     // resulting IDs should still keep incresing.
     const size_t kTestSize = 10U;
     uint32_t ids[kTestSize];
-    for (int i = 0; i < kTestSize; ++i) {
+    for (size_t i = 0UL; i < kTestSize; ++i) {
         ids[i] = mIdGenerator->getId();
         EXPECT_NE(ids[i], BufferHubIdGenerator::kInvalidId);
         if (i >= 1) {
diff --git a/services/bufferhub/tests/BufferNode_test.cpp b/services/bufferhub/tests/BufferNode_test.cpp
index dbf10e8..ccb1197 100644
--- a/services/bufferhub/tests/BufferNode_test.cpp
+++ b/services/bufferhub/tests/BufferNode_test.cpp
@@ -74,7 +74,7 @@
 
     for (int i = 0; i < BufferHubDefs::kMaxNumberOfClients; ++i) {
         new_client_state_mask = buffer_node->AddNewActiveClientsBitToMask();
-        EXPECT_NE(new_client_state_mask, 0);
+        EXPECT_NE(new_client_state_mask, 0U);
         EXPECT_FALSE(new_client_state_mask & current_mask);
         expected_mask = current_mask | new_client_state_mask;
         current_mask = buffer_node->GetActiveClientsBitMask();
diff --git a/services/inputflinger/InputDispatcher.cpp b/services/inputflinger/InputDispatcher.cpp
index 6879a73..7fa9cb6 100644
--- a/services/inputflinger/InputDispatcher.cpp
+++ b/services/inputflinger/InputDispatcher.cpp
@@ -4024,172 +4024,174 @@
 
 bool InputDispatcher::afterKeyEventLockedInterruptible(const sp<Connection>& connection,
         DispatchEntry* dispatchEntry, KeyEntry* keyEntry, bool handled) {
-    if (!(keyEntry->flags & AKEY_EVENT_FLAG_FALLBACK)) {
-        // Get the fallback key state.
-        // Clear it out after dispatching the UP.
-        int32_t originalKeyCode = keyEntry->keyCode;
-        int32_t fallbackKeyCode = connection->inputState.getFallbackKey(originalKeyCode);
-        if (keyEntry->action == AKEY_EVENT_ACTION_UP) {
-            connection->inputState.removeFallbackKey(originalKeyCode);
-        }
+    if (keyEntry->flags & AKEY_EVENT_FLAG_FALLBACK) {
+        return false;
+    }
 
-        if (handled || !dispatchEntry->hasForegroundTarget()) {
-            // If the application handles the original key for which we previously
-            // generated a fallback or if the window is not a foreground window,
-            // then cancel the associated fallback key, if any.
-            if (fallbackKeyCode != -1) {
-                // Dispatch the unhandled key to the policy with the cancel flag.
+    // Get the fallback key state.
+    // Clear it out after dispatching the UP.
+    int32_t originalKeyCode = keyEntry->keyCode;
+    int32_t fallbackKeyCode = connection->inputState.getFallbackKey(originalKeyCode);
+    if (keyEntry->action == AKEY_EVENT_ACTION_UP) {
+        connection->inputState.removeFallbackKey(originalKeyCode);
+    }
+
+    if (handled || !dispatchEntry->hasForegroundTarget()) {
+        // If the application handles the original key for which we previously
+        // generated a fallback or if the window is not a foreground window,
+        // then cancel the associated fallback key, if any.
+        if (fallbackKeyCode != -1) {
+            // Dispatch the unhandled key to the policy with the cancel flag.
 #if DEBUG_OUTBOUND_EVENT_DETAILS
-                ALOGD("Unhandled key event: Asking policy to cancel fallback action.  "
-                        "keyCode=%d, action=%d, repeatCount=%d, policyFlags=0x%08x",
-                        keyEntry->keyCode, keyEntry->action, keyEntry->repeatCount,
-                        keyEntry->policyFlags);
-#endif
-                KeyEvent event;
-                initializeKeyEvent(&event, keyEntry);
-                event.setFlags(event.getFlags() | AKEY_EVENT_FLAG_CANCELED);
-
-                mLock.unlock();
-
-                mPolicy->dispatchUnhandledKey(connection->inputChannel->getToken(),
-                        &event, keyEntry->policyFlags, &event);
-
-                mLock.lock();
-
-                // Cancel the fallback key.
-                if (fallbackKeyCode != AKEYCODE_UNKNOWN) {
-                    CancelationOptions options(CancelationOptions::CANCEL_FALLBACK_EVENTS,
-                            "application handled the original non-fallback key "
-                            "or is no longer a foreground target, "
-                            "canceling previously dispatched fallback key");
-                    options.keyCode = fallbackKeyCode;
-                    synthesizeCancelationEventsForConnectionLocked(connection, options);
-                }
-                connection->inputState.removeFallbackKey(originalKeyCode);
-            }
-        } else {
-            // If the application did not handle a non-fallback key, first check
-            // that we are in a good state to perform unhandled key event processing
-            // Then ask the policy what to do with it.
-            bool initialDown = keyEntry->action == AKEY_EVENT_ACTION_DOWN
-                    && keyEntry->repeatCount == 0;
-            if (fallbackKeyCode == -1 && !initialDown) {
-#if DEBUG_OUTBOUND_EVENT_DETAILS
-                ALOGD("Unhandled key event: Skipping unhandled key event processing "
-                        "since this is not an initial down.  "
-                        "keyCode=%d, action=%d, repeatCount=%d, policyFlags=0x%08x",
-                        originalKeyCode, keyEntry->action, keyEntry->repeatCount,
-                        keyEntry->policyFlags);
-#endif
-                return false;
-            }
-
-            // Dispatch the unhandled key to the policy.
-#if DEBUG_OUTBOUND_EVENT_DETAILS
-            ALOGD("Unhandled key event: Asking policy to perform fallback action.  "
+            ALOGD("Unhandled key event: Asking policy to cancel fallback action.  "
                     "keyCode=%d, action=%d, repeatCount=%d, policyFlags=0x%08x",
                     keyEntry->keyCode, keyEntry->action, keyEntry->repeatCount,
                     keyEntry->policyFlags);
 #endif
             KeyEvent event;
             initializeKeyEvent(&event, keyEntry);
+            event.setFlags(event.getFlags() | AKEY_EVENT_FLAG_CANCELED);
 
             mLock.unlock();
 
-            bool fallback = mPolicy->dispatchUnhandledKey(connection->inputChannel->getToken(),
-                    &event, keyEntry->policyFlags, &event);
+            mPolicy->dispatchUnhandledKey(connection->inputChannel->getToken(),
+                                          &event, keyEntry->policyFlags, &event);
 
             mLock.lock();
 
-            if (connection->status != Connection::STATUS_NORMAL) {
-                connection->inputState.removeFallbackKey(originalKeyCode);
-                return false;
-            }
-
-            // Latch the fallback keycode for this key on an initial down.
-            // The fallback keycode cannot change at any other point in the lifecycle.
-            if (initialDown) {
-                if (fallback) {
-                    fallbackKeyCode = event.getKeyCode();
-                } else {
-                    fallbackKeyCode = AKEYCODE_UNKNOWN;
-                }
-                connection->inputState.setFallbackKey(originalKeyCode, fallbackKeyCode);
-            }
-
-            ALOG_ASSERT(fallbackKeyCode != -1);
-
-            // Cancel the fallback key if the policy decides not to send it anymore.
-            // We will continue to dispatch the key to the policy but we will no
-            // longer dispatch a fallback key to the application.
-            if (fallbackKeyCode != AKEYCODE_UNKNOWN
-                    && (!fallback || fallbackKeyCode != event.getKeyCode())) {
-#if DEBUG_OUTBOUND_EVENT_DETAILS
-                if (fallback) {
-                    ALOGD("Unhandled key event: Policy requested to send key %d"
-                            "as a fallback for %d, but on the DOWN it had requested "
-                            "to send %d instead.  Fallback canceled.",
-                            event.getKeyCode(), originalKeyCode, fallbackKeyCode);
-                } else {
-                    ALOGD("Unhandled key event: Policy did not request fallback for %d, "
-                            "but on the DOWN it had requested to send %d.  "
-                            "Fallback canceled.",
-                            originalKeyCode, fallbackKeyCode);
-                }
-#endif
-
+            // Cancel the fallback key.
+            if (fallbackKeyCode != AKEYCODE_UNKNOWN) {
                 CancelationOptions options(CancelationOptions::CANCEL_FALLBACK_EVENTS,
-                        "canceling fallback, policy no longer desires it");
+                                           "application handled the original non-fallback key "
+                                           "or is no longer a foreground target, "
+                                           "canceling previously dispatched fallback key");
                 options.keyCode = fallbackKeyCode;
                 synthesizeCancelationEventsForConnectionLocked(connection, options);
-
-                fallback = false;
-                fallbackKeyCode = AKEYCODE_UNKNOWN;
-                if (keyEntry->action != AKEY_EVENT_ACTION_UP) {
-                    connection->inputState.setFallbackKey(originalKeyCode,
-                            fallbackKeyCode);
-                }
             }
-
+            connection->inputState.removeFallbackKey(originalKeyCode);
+        }
+    } else {
+        // If the application did not handle a non-fallback key, first check
+        // that we are in a good state to perform unhandled key event processing
+        // Then ask the policy what to do with it.
+        bool initialDown = keyEntry->action == AKEY_EVENT_ACTION_DOWN
+                && keyEntry->repeatCount == 0;
+        if (fallbackKeyCode == -1 && !initialDown) {
 #if DEBUG_OUTBOUND_EVENT_DETAILS
-            {
-                std::string msg;
-                const KeyedVector<int32_t, int32_t>& fallbackKeys =
-                        connection->inputState.getFallbackKeys();
-                for (size_t i = 0; i < fallbackKeys.size(); i++) {
-                    msg += StringPrintf(", %d->%d", fallbackKeys.keyAt(i),
-                            fallbackKeys.valueAt(i));
-                }
-                ALOGD("Unhandled key event: %zu currently tracked fallback keys%s.",
-                        fallbackKeys.size(), msg.c_str());
-            }
+            ALOGD("Unhandled key event: Skipping unhandled key event processing "
+                    "since this is not an initial down.  "
+                    "keyCode=%d, action=%d, repeatCount=%d, policyFlags=0x%08x",
+                    originalKeyCode, keyEntry->action, keyEntry->repeatCount,
+                    keyEntry->policyFlags);
 #endif
+            return false;
+        }
 
+        // Dispatch the unhandled key to the policy.
+#if DEBUG_OUTBOUND_EVENT_DETAILS
+        ALOGD("Unhandled key event: Asking policy to perform fallback action.  "
+                "keyCode=%d, action=%d, repeatCount=%d, policyFlags=0x%08x",
+                keyEntry->keyCode, keyEntry->action, keyEntry->repeatCount,
+                keyEntry->policyFlags);
+#endif
+        KeyEvent event;
+        initializeKeyEvent(&event, keyEntry);
+
+        mLock.unlock();
+
+        bool fallback = mPolicy->dispatchUnhandledKey(connection->inputChannel->getToken(),
+                                                      &event, keyEntry->policyFlags, &event);
+
+        mLock.lock();
+
+        if (connection->status != Connection::STATUS_NORMAL) {
+            connection->inputState.removeFallbackKey(originalKeyCode);
+            return false;
+        }
+
+        // Latch the fallback keycode for this key on an initial down.
+        // The fallback keycode cannot change at any other point in the lifecycle.
+        if (initialDown) {
             if (fallback) {
-                // Restart the dispatch cycle using the fallback key.
-                keyEntry->eventTime = event.getEventTime();
-                keyEntry->deviceId = event.getDeviceId();
-                keyEntry->source = event.getSource();
-                keyEntry->displayId = event.getDisplayId();
-                keyEntry->flags = event.getFlags() | AKEY_EVENT_FLAG_FALLBACK;
-                keyEntry->keyCode = fallbackKeyCode;
-                keyEntry->scanCode = event.getScanCode();
-                keyEntry->metaState = event.getMetaState();
-                keyEntry->repeatCount = event.getRepeatCount();
-                keyEntry->downTime = event.getDownTime();
-                keyEntry->syntheticRepeat = false;
+                fallbackKeyCode = event.getKeyCode();
+            } else {
+                fallbackKeyCode = AKEYCODE_UNKNOWN;
+            }
+            connection->inputState.setFallbackKey(originalKeyCode, fallbackKeyCode);
+        }
+
+        ALOG_ASSERT(fallbackKeyCode != -1);
+
+        // Cancel the fallback key if the policy decides not to send it anymore.
+        // We will continue to dispatch the key to the policy but we will no
+        // longer dispatch a fallback key to the application.
+        if (fallbackKeyCode != AKEYCODE_UNKNOWN
+                && (!fallback || fallbackKeyCode != event.getKeyCode())) {
+#if DEBUG_OUTBOUND_EVENT_DETAILS
+            if (fallback) {
+                ALOGD("Unhandled key event: Policy requested to send key %d"
+                        "as a fallback for %d, but on the DOWN it had requested "
+                        "to send %d instead.  Fallback canceled.",
+                        event.getKeyCode(), originalKeyCode, fallbackKeyCode);
+            } else {
+                ALOGD("Unhandled key event: Policy did not request fallback for %d, "
+                        "but on the DOWN it had requested to send %d.  "
+                        "Fallback canceled.",
+                        originalKeyCode, fallbackKeyCode);
+            }
+#endif
+
+            CancelationOptions options(CancelationOptions::CANCEL_FALLBACK_EVENTS,
+                                       "canceling fallback, policy no longer desires it");
+            options.keyCode = fallbackKeyCode;
+            synthesizeCancelationEventsForConnectionLocked(connection, options);
+
+            fallback = false;
+            fallbackKeyCode = AKEYCODE_UNKNOWN;
+            if (keyEntry->action != AKEY_EVENT_ACTION_UP) {
+                connection->inputState.setFallbackKey(originalKeyCode,
+                                                      fallbackKeyCode);
+            }
+        }
 
 #if DEBUG_OUTBOUND_EVENT_DETAILS
-                ALOGD("Unhandled key event: Dispatching fallback key.  "
-                        "originalKeyCode=%d, fallbackKeyCode=%d, fallbackMetaState=%08x",
-                        originalKeyCode, fallbackKeyCode, keyEntry->metaState);
-#endif
-                return true; // restart the event
-            } else {
-#if DEBUG_OUTBOUND_EVENT_DETAILS
-                ALOGD("Unhandled key event: No fallback key.");
-#endif
+        {
+            std::string msg;
+            const KeyedVector<int32_t, int32_t>& fallbackKeys =
+                    connection->inputState.getFallbackKeys();
+            for (size_t i = 0; i < fallbackKeys.size(); i++) {
+                msg += StringPrintf(", %d->%d", fallbackKeys.keyAt(i),
+                        fallbackKeys.valueAt(i));
             }
+            ALOGD("Unhandled key event: %zu currently tracked fallback keys%s.",
+                    fallbackKeys.size(), msg.c_str());
+        }
+#endif
+
+        if (fallback) {
+            // Restart the dispatch cycle using the fallback key.
+            keyEntry->eventTime = event.getEventTime();
+            keyEntry->deviceId = event.getDeviceId();
+            keyEntry->source = event.getSource();
+            keyEntry->displayId = event.getDisplayId();
+            keyEntry->flags = event.getFlags() | AKEY_EVENT_FLAG_FALLBACK;
+            keyEntry->keyCode = fallbackKeyCode;
+            keyEntry->scanCode = event.getScanCode();
+            keyEntry->metaState = event.getMetaState();
+            keyEntry->repeatCount = event.getRepeatCount();
+            keyEntry->downTime = event.getDownTime();
+            keyEntry->syntheticRepeat = false;
+
+#if DEBUG_OUTBOUND_EVENT_DETAILS
+            ALOGD("Unhandled key event: Dispatching fallback key.  "
+                    "originalKeyCode=%d, fallbackKeyCode=%d, fallbackMetaState=%08x",
+                    originalKeyCode, fallbackKeyCode, keyEntry->metaState);
+#endif
+            return true; // restart the event
+        } else {
+#if DEBUG_OUTBOUND_EVENT_DETAILS
+            ALOGD("Unhandled key event: No fallback key.");
+#endif
         }
     }
     return false;
diff --git a/services/surfaceflinger/tests/unittests/mock/RenderEngine/MockRenderEngine.h b/services/surfaceflinger/tests/unittests/mock/RenderEngine/MockRenderEngine.h
index 1bee271..81a7768 100644
--- a/services/surfaceflinger/tests/unittests/mock/RenderEngine/MockRenderEngine.h
+++ b/services/surfaceflinger/tests/unittests/mock/RenderEngine/MockRenderEngine.h
@@ -77,9 +77,9 @@
     MOCK_CONST_METHOD0(isProtected, bool());
     MOCK_CONST_METHOD0(supportsProtectedContent, bool());
     MOCK_METHOD1(useProtectedContext, bool(bool));
-    MOCK_CONST_METHOD4(drawLayers,
-                       status_t(const DisplaySettings&, const std::vector<LayerSettings>&,
-                                ANativeWindowBuffer* const, base::unique_fd*));
+    MOCK_METHOD4(drawLayers,
+                 status_t(const DisplaySettings&, const std::vector<LayerSettings>&,
+                          ANativeWindowBuffer*, base::unique_fd*));
 };
 
 class Image : public renderengine::Image {
diff --git a/vulkan/api/vulkan.api b/vulkan/api/vulkan.api
index 6c971be..7f6b9aa 100644
--- a/vulkan/api/vulkan.api
+++ b/vulkan/api/vulkan.api
@@ -28,7 +28,7 @@
 // API version (major.minor.patch)
 define VERSION_MAJOR 1
 define VERSION_MINOR 1
-define VERSION_PATCH 94
+define VERSION_PATCH 95
 
 // API limits
 define VK_MAX_PHYSICAL_DEVICE_NAME_SIZE 256
@@ -287,6 +287,10 @@
 @extension("VK_EXT_conditional_rendering") define VK_EXT_CONDITIONAL_RENDERING_SPEC_VERSION 1
 @extension("VK_EXT_conditional_rendering") define VK_EXT_CONDITIONAL_RENDERING_EXTENSION_NAME "VK_EXT_conditional_rendering"
 
+// 83
+@extension("VK_KHR_shader_float16_int8") define VK_KHR_SHADER_FLOAT16_INT8_SPEC_VERSION 1
+@extension("VK_KHR_shader_float16_int8") define VK_KHR_SHADER_FLOAT16_INT8_EXTENSION_NAME "VK_KHR_shader_float16_int8"
+
 // 84
 @extension("VK_KHR_16bit_storage") define VK_KHR_16BIT_STORAGE_SPEC_VERSION 1
 @extension("VK_KHR_16bit_storage") define VK_KHR_16BIT_STORAGE_EXTENSION_NAME "VK_KHR_16bit_storage"
@@ -575,6 +579,10 @@
 @extension("VK_KHR_driver_properties") define VK_KHR_DRIVER_PROPERTIES_SPEC_VERSION 1
 @extension("VK_KHR_driver_properties") define VK_KHR_DRIVER_PROPERTIES_EXTENSION_NAME "VK_KHR_driver_properties"
 
+// 198
+@extension("VK_KHR_shader_float_controls") define VK_KHR_SHADER_FLOAT_CONTROLS_SPEC_VERSION 1
+@extension("VK_KHR_shader_float_controls") define VK_KHR_SHADER_FLOAT_CONTROLS_EXTENSION_NAME "VK_KHR_shader_float_controls"
+
 // 199
 @extension("VK_NV_shader_subgroup_partitioned") define VK_NV_SHADER_SUBGROUP_PARTITIONED_SPEC_VERSION 1
 @extension("VK_NV_shader_subgroup_partitioned") define VK_NV_SHADER_SUBGROUP_PARTITIONED_EXTENSION_NAME "VK_NV_shader_subgroup_partitioned"
@@ -1615,6 +1623,9 @@
     VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_CONDITIONAL_RENDERING_FEATURES_EXT        = 1000081001,
     VK_STRUCTURE_TYPE_CONDITIONAL_RENDERING_BEGIN_INFO_EXT                      = 1000081002,
 
+    //@extension("VK_KHR_shader_float16_int8") // 83
+    VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_FLOAT16_INT8_FEATURES_KHR     = 1000082000,
+
     //@extension("VK_KHR_descriptor_update_template") // 86
     VK_STRUCTURE_TYPE_DESCRIPTOR_UPDATE_TEMPLATE_CREATE_INFO_KHR    = 1000085000,
 
@@ -1848,6 +1859,9 @@
     //@extension("VK_KHR_driver_properties") // 197
     VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_DRIVER_PROPERTIES_KHR             = 1000196000,
 
+    //@extension("VK_KHR_shader_float_controls") // 198
+    VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_FLOAT_CONTROLS_PROPERTIES_KHR     = 1000197000,
+
     //@extension("VK_AMD_shader_core_properties") // 186
     VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_SHADER_CORE_PROPERTIES_AMD        = 1000185000,
 
@@ -6092,6 +6106,14 @@
     VkBool32                                    conditionalRenderingEnable
 }
 
+@extension("VK_KHR_shader_float16_int8") // 83
+class VkPhysicalDeviceFloat16Int8FeaturesKHR {
+    VkStructureType                             sType
+    void*                                       pNext
+    VkBool32                                    shaderFloat16
+    VkBool32                                    shaderInt8
+}
+
 @extension("VK_KHR_16bit_storage") // 84
 class VkPhysicalDevice16BitStorageFeaturesKHR {
     VkStructureType                             sType
@@ -6776,11 +6798,11 @@
     s32                                             messageIdNumber
     const char*                                     pMessage
     u32                                             queueLabelCount
-    VkDebugUtilsLabelEXT*                           pQueueLabels
+    const VkDebugUtilsLabelEXT*                     pQueueLabels
     u32                                             cmdBufLabelCount
-    VkDebugUtilsLabelEXT*                           pCmdBufLabels
+    const VkDebugUtilsLabelEXT*                     pCmdBufLabels
     u32                                             objectCount
-    VkDebugUtilsObjectNameInfoEXT*                  pObjects
+    const VkDebugUtilsObjectNameInfoEXT*            pObjects
 }
 
 @extension("VK_EXT_debug_utils") // 129
@@ -7598,6 +7620,29 @@
     VkConformanceVersionKHR                         conformanceVersion
 }
 
+@extension("VK_KHR_shader_float_controls") // 198
+class VkPhysicalDeviceFloatControlsPropertiesKHR {
+    VkStructureType                                 sType
+    void*                                           pNext
+    VkBool32                                        separateDenormSettings
+    VkBool32                                        separateRoundingModeSettings
+    VkBool32                                        shaderSignedZeroInfNanPreserveFloat16
+    VkBool32                                        shaderSignedZeroInfNanPreserveFloat32
+    VkBool32                                        shaderSignedZeroInfNanPreserveFloat64
+    VkBool32                                        shaderDenormPreserveFloat16
+    VkBool32                                        shaderDenormPreserveFloat32
+    VkBool32                                        shaderDenormPreserveFloat64
+    VkBool32                                        shaderDenormFlushToZeroFloat16
+    VkBool32                                        shaderDenormFlushToZeroFloat32
+    VkBool32                                        shaderDenormFlushToZeroFloat64
+    VkBool32                                        shaderRoundingModeRTEFloat16
+    VkBool32                                        shaderRoundingModeRTEFloat32
+    VkBool32                                        shaderRoundingModeRTEFloat64
+    VkBool32                                        shaderRoundingModeRTZFloat16
+    VkBool32                                        shaderRoundingModeRTZFloat32
+    VkBool32                                        shaderRoundingModeRTZFloat64
+}
+
 @extension("VK_NV_compute_shader_derivatives") // 202
 class VkPhysicalDeviceComputeShaderDerivativesFeaturesNV {
     VkStructureType                                 sType
diff --git a/vulkan/include/vulkan/vulkan_core.h b/vulkan/include/vulkan/vulkan_core.h
index bdbf800..5006410 100644
--- a/vulkan/include/vulkan/vulkan_core.h
+++ b/vulkan/include/vulkan/vulkan_core.h
@@ -43,7 +43,7 @@
 #define VK_VERSION_MINOR(version) (((uint32_t)(version) >> 12) & 0x3ff)
 #define VK_VERSION_PATCH(version) ((uint32_t)(version) & 0xfff)
 // Version of this file
-#define VK_HEADER_VERSION 94
+#define VK_HEADER_VERSION 95
 
 
 #define VK_NULL_HANDLE 0
@@ -327,6 +327,7 @@
     VK_STRUCTURE_TYPE_COMMAND_BUFFER_INHERITANCE_CONDITIONAL_RENDERING_INFO_EXT = 1000081000,
     VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_CONDITIONAL_RENDERING_FEATURES_EXT = 1000081001,
     VK_STRUCTURE_TYPE_CONDITIONAL_RENDERING_BEGIN_INFO_EXT = 1000081002,
+    VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_FLOAT16_INT8_FEATURES_KHR = 1000082000,
     VK_STRUCTURE_TYPE_PRESENT_REGIONS_KHR = 1000084000,
     VK_STRUCTURE_TYPE_OBJECT_TABLE_CREATE_INFO_NVX = 1000086000,
     VK_STRUCTURE_TYPE_INDIRECT_COMMANDS_LAYOUT_CREATE_INFO_NVX = 1000086001,
@@ -442,6 +443,7 @@
     VK_STRUCTURE_TYPE_PIPELINE_VERTEX_INPUT_DIVISOR_STATE_CREATE_INFO_EXT = 1000190001,
     VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_VERTEX_ATTRIBUTE_DIVISOR_FEATURES_EXT = 1000190002,
     VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_DRIVER_PROPERTIES_KHR = 1000196000,
+    VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_FLOAT_CONTROLS_PROPERTIES_KHR = 1000197000,
     VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_COMPUTE_SHADER_DERIVATIVES_FEATURES_NV = 1000201000,
     VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_MESH_SHADER_FEATURES_NV = 1000202000,
     VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_MESH_SHADER_PROPERTIES_NV = 1000202001,
@@ -5493,6 +5495,19 @@
     const void*                                 pData);
 #endif
 
+#define VK_KHR_shader_float16_int8 1
+#define VK_KHR_SHADER_FLOAT16_INT8_SPEC_VERSION 1
+#define VK_KHR_SHADER_FLOAT16_INT8_EXTENSION_NAME "VK_KHR_shader_float16_int8"
+
+typedef struct VkPhysicalDeviceFloat16Int8FeaturesKHR {
+    VkStructureType    sType;
+    void*              pNext;
+    VkBool32           shaderFloat16;
+    VkBool32           shaderInt8;
+} VkPhysicalDeviceFloat16Int8FeaturesKHR;
+
+
+
 #define VK_KHR_16bit_storage 1
 #define VK_KHR_16BIT_STORAGE_SPEC_VERSION 1
 #define VK_KHR_16BIT_STORAGE_EXTENSION_NAME "VK_KHR_16bit_storage"
@@ -6149,6 +6164,34 @@
 
 
 
+#define VK_KHR_shader_float_controls 1
+#define VK_KHR_SHADER_FLOAT_CONTROLS_SPEC_VERSION 1
+#define VK_KHR_SHADER_FLOAT_CONTROLS_EXTENSION_NAME "VK_KHR_shader_float_controls"
+
+typedef struct VkPhysicalDeviceFloatControlsPropertiesKHR {
+    VkStructureType    sType;
+    void*              pNext;
+    VkBool32           separateDenormSettings;
+    VkBool32           separateRoundingModeSettings;
+    VkBool32           shaderSignedZeroInfNanPreserveFloat16;
+    VkBool32           shaderSignedZeroInfNanPreserveFloat32;
+    VkBool32           shaderSignedZeroInfNanPreserveFloat64;
+    VkBool32           shaderDenormPreserveFloat16;
+    VkBool32           shaderDenormPreserveFloat32;
+    VkBool32           shaderDenormPreserveFloat64;
+    VkBool32           shaderDenormFlushToZeroFloat16;
+    VkBool32           shaderDenormFlushToZeroFloat32;
+    VkBool32           shaderDenormFlushToZeroFloat64;
+    VkBool32           shaderRoundingModeRTEFloat16;
+    VkBool32           shaderRoundingModeRTEFloat32;
+    VkBool32           shaderRoundingModeRTEFloat64;
+    VkBool32           shaderRoundingModeRTZFloat16;
+    VkBool32           shaderRoundingModeRTZFloat32;
+    VkBool32           shaderRoundingModeRTZFloat64;
+} VkPhysicalDeviceFloatControlsPropertiesKHR;
+
+
+
 #define VK_KHR_swapchain_mutable_format 1
 #define VK_KHR_SWAPCHAIN_MUTABLE_FORMAT_SPEC_VERSION 1
 #define VK_KHR_SWAPCHAIN_MUTABLE_FORMAT_EXTENSION_NAME "VK_KHR_swapchain_mutable_format"
@@ -7475,11 +7518,11 @@
     int32_t                                      messageIdNumber;
     const char*                                  pMessage;
     uint32_t                                     queueLabelCount;
-    VkDebugUtilsLabelEXT*                        pQueueLabels;
+    const VkDebugUtilsLabelEXT*                  pQueueLabels;
     uint32_t                                     cmdBufLabelCount;
-    VkDebugUtilsLabelEXT*                        pCmdBufLabels;
+    const VkDebugUtilsLabelEXT*                  pCmdBufLabels;
     uint32_t                                     objectCount;
-    VkDebugUtilsObjectNameInfoEXT*               pObjects;
+    const VkDebugUtilsObjectNameInfoEXT*         pObjects;
 } VkDebugUtilsMessengerCallbackDataEXT;
 
 typedef VkBool32 (VKAPI_PTR *PFN_vkDebugUtilsMessengerCallbackEXT)(