Merge "EGL: add color space validation"
diff --git a/cmds/dumpstate/dumpstate.cpp b/cmds/dumpstate/dumpstate.cpp
index 089e66c..2f8840b 100644
--- a/cmds/dumpstate/dumpstate.cpp
+++ b/cmds/dumpstate/dumpstate.cpp
@@ -126,7 +126,8 @@
 static const std::string kDumpstateBoardPath = "/bugreports/";
 static const std::string kDumpstateBoardFiles[] = {
     "dumpstate_board.txt",
-    "dumpstate_board.bin"
+    // TODO: rename to dumpstate_board.bin once vendors can handle it
+    "modem_log_all.tar"
 };
 static const int NUM_OF_DUMPS = arraysize(kDumpstateBoardFiles);
 
diff --git a/include/gui b/include/gui
new file mode 120000
index 0000000..3b796f3
--- /dev/null
+++ b/include/gui
@@ -0,0 +1 @@
+../libs/gui/include/gui
\ No newline at end of file
diff --git a/include/private/gui b/include/private/gui
new file mode 120000
index 0000000..99de2dc
--- /dev/null
+++ b/include/private/gui
@@ -0,0 +1 @@
+../../libs/gui/include/private/gui
\ No newline at end of file
diff --git a/libs/binder/Android.bp b/libs/binder/Android.bp
index 204fdb5..3a353c2 100644
--- a/libs/binder/Android.bp
+++ b/libs/binder/Android.bp
@@ -15,6 +15,7 @@
 cc_library_headers {
     name: "libbinder_headers",
     export_include_dirs: ["include"],
+    vendor_available: true,
 }
 
 cc_library {
@@ -74,13 +75,18 @@
         "libcutils",
         "libutils",
     ],
+
+    header_libs: [
+        "libbinder_headers",
+    ],
+
     export_shared_lib_headers: [
         "libbase",
         "libutils",
     ],
 
-    export_include_dirs: [
-        "include",
+    export_header_lib_headers: [
+        "libbinder_headers",
     ],
 
     clang: true,
diff --git a/libs/gui/Android.bp b/libs/gui/Android.bp
index c0ae3d7..afa046d 100644
--- a/libs/gui/Android.bp
+++ b/libs/gui/Android.bp
@@ -11,9 +11,15 @@
 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 // See the License for the specific language governing permissions and
 // limitations under the License.
+cc_library_headers {
+    name: "libgui_headers",
+    vendor_available: true,
+    export_include_dirs: ["include"],
+}
 
 cc_library_shared {
     name: "libgui",
+    vendor_available: true,
 
     clang: true,
     cppflags: [
@@ -57,7 +63,7 @@
         brillo: {
             cflags: ["-DHAVE_NO_SURFACE_FLINGER"],
         },
-        debuggable: {
+        eng: {
             cppflags: [
                 "-UDEBUG_ONLY_CODE",
                 "-DDEBUG_ONLY_CODE=1",
@@ -119,6 +125,7 @@
 
     header_libs: [
         "libnativebase_headers",
+        "libgui_headers",
     ],
 
     export_shared_lib_headers: [
@@ -129,6 +136,10 @@
         "android.hardware.graphics.bufferqueue@1.0",
     ],
 
+    export_header_lib_headers: [
+        "libgui_headers",
+    ],
+
     export_include_dirs: [
         "include",
     ],
diff --git a/include/gui/BufferItem.h b/libs/gui/include/gui/BufferItem.h
similarity index 100%
rename from include/gui/BufferItem.h
rename to libs/gui/include/gui/BufferItem.h
diff --git a/include/gui/BufferItemConsumer.h b/libs/gui/include/gui/BufferItemConsumer.h
similarity index 100%
rename from include/gui/BufferItemConsumer.h
rename to libs/gui/include/gui/BufferItemConsumer.h
diff --git a/include/gui/BufferQueue.h b/libs/gui/include/gui/BufferQueue.h
similarity index 100%
rename from include/gui/BufferQueue.h
rename to libs/gui/include/gui/BufferQueue.h
diff --git a/include/gui/BufferQueueConsumer.h b/libs/gui/include/gui/BufferQueueConsumer.h
similarity index 100%
rename from include/gui/BufferQueueConsumer.h
rename to libs/gui/include/gui/BufferQueueConsumer.h
diff --git a/include/gui/BufferQueueCore.h b/libs/gui/include/gui/BufferQueueCore.h
similarity index 100%
rename from include/gui/BufferQueueCore.h
rename to libs/gui/include/gui/BufferQueueCore.h
diff --git a/include/gui/BufferQueueDefs.h b/libs/gui/include/gui/BufferQueueDefs.h
similarity index 100%
rename from include/gui/BufferQueueDefs.h
rename to libs/gui/include/gui/BufferQueueDefs.h
diff --git a/include/gui/BufferQueueProducer.h b/libs/gui/include/gui/BufferQueueProducer.h
similarity index 100%
rename from include/gui/BufferQueueProducer.h
rename to libs/gui/include/gui/BufferQueueProducer.h
diff --git a/include/gui/BufferSlot.h b/libs/gui/include/gui/BufferSlot.h
similarity index 100%
rename from include/gui/BufferSlot.h
rename to libs/gui/include/gui/BufferSlot.h
diff --git a/include/gui/ConsumerBase.h b/libs/gui/include/gui/ConsumerBase.h
similarity index 100%
rename from include/gui/ConsumerBase.h
rename to libs/gui/include/gui/ConsumerBase.h
diff --git a/include/gui/CpuConsumer.h b/libs/gui/include/gui/CpuConsumer.h
similarity index 100%
rename from include/gui/CpuConsumer.h
rename to libs/gui/include/gui/CpuConsumer.h
diff --git a/include/gui/DisplayEventReceiver.h b/libs/gui/include/gui/DisplayEventReceiver.h
similarity index 100%
rename from include/gui/DisplayEventReceiver.h
rename to libs/gui/include/gui/DisplayEventReceiver.h
diff --git a/include/gui/FrameTimestamps.h b/libs/gui/include/gui/FrameTimestamps.h
similarity index 100%
rename from include/gui/FrameTimestamps.h
rename to libs/gui/include/gui/FrameTimestamps.h
diff --git a/include/gui/GLConsumer.h b/libs/gui/include/gui/GLConsumer.h
similarity index 100%
rename from include/gui/GLConsumer.h
rename to libs/gui/include/gui/GLConsumer.h
diff --git a/include/gui/GuiConfig.h b/libs/gui/include/gui/GuiConfig.h
similarity index 100%
rename from include/gui/GuiConfig.h
rename to libs/gui/include/gui/GuiConfig.h
diff --git a/include/gui/IConsumerListener.h b/libs/gui/include/gui/IConsumerListener.h
similarity index 100%
rename from include/gui/IConsumerListener.h
rename to libs/gui/include/gui/IConsumerListener.h
diff --git a/include/gui/IDisplayEventConnection.h b/libs/gui/include/gui/IDisplayEventConnection.h
similarity index 100%
rename from include/gui/IDisplayEventConnection.h
rename to libs/gui/include/gui/IDisplayEventConnection.h
diff --git a/include/gui/IGraphicBufferConsumer.h b/libs/gui/include/gui/IGraphicBufferConsumer.h
similarity index 100%
rename from include/gui/IGraphicBufferConsumer.h
rename to libs/gui/include/gui/IGraphicBufferConsumer.h
diff --git a/include/gui/IGraphicBufferProducer.h b/libs/gui/include/gui/IGraphicBufferProducer.h
similarity index 100%
rename from include/gui/IGraphicBufferProducer.h
rename to libs/gui/include/gui/IGraphicBufferProducer.h
diff --git a/include/gui/IProducerListener.h b/libs/gui/include/gui/IProducerListener.h
similarity index 100%
rename from include/gui/IProducerListener.h
rename to libs/gui/include/gui/IProducerListener.h
diff --git a/include/gui/ISurfaceComposer.h b/libs/gui/include/gui/ISurfaceComposer.h
similarity index 100%
rename from include/gui/ISurfaceComposer.h
rename to libs/gui/include/gui/ISurfaceComposer.h
diff --git a/include/gui/ISurfaceComposerClient.h b/libs/gui/include/gui/ISurfaceComposerClient.h
similarity index 100%
rename from include/gui/ISurfaceComposerClient.h
rename to libs/gui/include/gui/ISurfaceComposerClient.h
diff --git a/include/gui/OccupancyTracker.h b/libs/gui/include/gui/OccupancyTracker.h
similarity index 100%
rename from include/gui/OccupancyTracker.h
rename to libs/gui/include/gui/OccupancyTracker.h
diff --git a/include/gui/StreamSplitter.h b/libs/gui/include/gui/StreamSplitter.h
similarity index 100%
rename from include/gui/StreamSplitter.h
rename to libs/gui/include/gui/StreamSplitter.h
diff --git a/include/gui/Surface.h b/libs/gui/include/gui/Surface.h
similarity index 100%
rename from include/gui/Surface.h
rename to libs/gui/include/gui/Surface.h
diff --git a/include/gui/SurfaceComposerClient.h b/libs/gui/include/gui/SurfaceComposerClient.h
similarity index 100%
rename from include/gui/SurfaceComposerClient.h
rename to libs/gui/include/gui/SurfaceComposerClient.h
diff --git a/include/gui/SurfaceControl.h b/libs/gui/include/gui/SurfaceControl.h
similarity index 100%
rename from include/gui/SurfaceControl.h
rename to libs/gui/include/gui/SurfaceControl.h
diff --git a/include/gui/bufferqueue/1.0/B2HProducerListener.h b/libs/gui/include/gui/bufferqueue/1.0/B2HProducerListener.h
similarity index 100%
rename from include/gui/bufferqueue/1.0/B2HProducerListener.h
rename to libs/gui/include/gui/bufferqueue/1.0/B2HProducerListener.h
diff --git a/include/gui/bufferqueue/1.0/H2BGraphicBufferProducer.h b/libs/gui/include/gui/bufferqueue/1.0/H2BGraphicBufferProducer.h
similarity index 100%
rename from include/gui/bufferqueue/1.0/H2BGraphicBufferProducer.h
rename to libs/gui/include/gui/bufferqueue/1.0/H2BGraphicBufferProducer.h
diff --git a/include/gui/view/Surface.h b/libs/gui/include/gui/view/Surface.h
similarity index 100%
rename from include/gui/view/Surface.h
rename to libs/gui/include/gui/view/Surface.h
diff --git a/include/private/gui/ComposerService.h b/libs/gui/include/private/gui/ComposerService.h
similarity index 100%
rename from include/private/gui/ComposerService.h
rename to libs/gui/include/private/gui/ComposerService.h
diff --git a/include/private/gui/LayerState.h b/libs/gui/include/private/gui/LayerState.h
similarity index 100%
rename from include/private/gui/LayerState.h
rename to libs/gui/include/private/gui/LayerState.h
diff --git a/include/private/gui/SyncFeatures.h b/libs/gui/include/private/gui/SyncFeatures.h
similarity index 100%
rename from include/private/gui/SyncFeatures.h
rename to libs/gui/include/private/gui/SyncFeatures.h
diff --git a/libs/ui/Android.bp b/libs/ui/Android.bp
index d9cfed7..6630d90 100644
--- a/libs/ui/Android.bp
+++ b/libs/ui/Android.bp
@@ -89,6 +89,7 @@
 
     header_libs: [
         "libnativebase_headers",
+        "libhardware_headers",
     ],
 
     export_include_dirs: ["include"],
@@ -100,6 +101,7 @@
 
     export_header_lib_headers: [
         "libnativebase_headers",
+        "libhardware_headers",
     ],
 }
 
diff --git a/opengl/Android.bp b/opengl/Android.bp
index c520bda..aec5a95 100644
--- a/opengl/Android.bp
+++ b/opengl/Android.bp
@@ -52,6 +52,12 @@
     license: "include/KHR/NOTICE",
 }
 
+cc_library_headers {
+    name: "gl_headers",
+    vendor_available: true,
+    export_include_dirs: ["include"],
+}
+
 subdirs = [
     "*",
 ]
diff --git a/opengl/libs/Android.bp b/opengl/libs/Android.bp
index 4e275db..a344636 100644
--- a/opengl/libs/Android.bp
+++ b/opengl/libs/Android.bp
@@ -64,6 +64,16 @@
         "liblog",
         "libdl",
     ],
+    static_libs: [
+        "libarect",
+    ],
+    header_libs: [
+        "gl_headers",
+        "libsystem_headers",
+        "libhardware_headers",
+        "libnativebase_headers",
+    ],
+    export_header_lib_headers: ["gl_headers"],
 
     // we need to access the private Bionic header <bionic_tls.h>
     include_dirs: ["bionic/libc/private"],
@@ -75,6 +85,7 @@
 cc_defaults {
     name: "egl_libs_defaults",
     defaults: ["gl_libs_defaults"],
+    vendor_available: true,
     cflags: [
         "-DLOG_TAG=\"libEGL\"",
     ],
@@ -85,6 +96,11 @@
         "libnativewindow",
         "libbacktrace",
     ],
+    target: {
+        vendor: {
+            exclude_shared_libs: ["libgraphicsenv"],
+        },
+    },
 }
 
 cc_library_static {
@@ -129,6 +145,7 @@
 cc_defaults {
     name: "gles_libs_defaults",
     defaults: ["gl_libs_defaults"],
+    vendor_available: true,
     arch: {
         arm: {
             instruction_set: "arm",
diff --git a/opengl/libs/EGL/Loader.cpp b/opengl/libs/EGL/Loader.cpp
index 6e5c510..32f8caa 100644
--- a/opengl/libs/EGL/Loader.cpp
+++ b/opengl/libs/EGL/Loader.cpp
@@ -28,7 +28,9 @@
 #include <cutils/properties.h>
 #include <log/log.h>
 
+#ifndef __ANDROID_VNDK__
 #include <graphicsenv/GraphicsEnv.h>
+#endif
 #include <vndksupport/linker.h>
 
 #include "egl_trace.h"
@@ -477,10 +479,12 @@
     ATRACE_CALL();
 
     void* dso = nullptr;
+#ifndef __ANDROID_VNDK__
     android_namespace_t* ns = android_getDriverNamespace();
     if (ns) {
         dso = load_updated_driver(kind, ns);
     }
+#endif
     if (!dso) {
         dso = load_system_driver(kind);
         if (!dso)
diff --git a/opengl/libs/EGL/eglApi.cpp b/opengl/libs/EGL/eglApi.cpp
index deccb7d..c5feb89 100644
--- a/opengl/libs/EGL/eglApi.cpp
+++ b/opengl/libs/EGL/eglApi.cpp
@@ -2053,8 +2053,15 @@
 
 EGLClientBuffer eglGetNativeClientBufferANDROID(const AHardwareBuffer *buffer) {
     clearError();
+    // AHardwareBuffer_to_ANativeWindowBuffer is a platform-only symbol and thus
+    // this function cannot be implemented when this libEGL is built for
+    // vendors.
+#ifndef __ANDROID_VNDK__
     if (!buffer) return setError(EGL_BAD_PARAMETER, (EGLClientBuffer)0);
     return const_cast<ANativeWindowBuffer *>(AHardwareBuffer_to_ANativeWindowBuffer(buffer));
+#else
+    return setError(EGL_BAD_PARAMETER, (EGLClientBuffer)0);
+#endif
 }
 
 // ----------------------------------------------------------------------------
diff --git a/opengl/libs/EGL/egl_cache.cpp b/opengl/libs/EGL/egl_cache.cpp
index dc1a4af..579e422 100644
--- a/opengl/libs/EGL/egl_cache.cpp
+++ b/opengl/libs/EGL/egl_cache.cpp
@@ -26,6 +26,7 @@
 #include <inttypes.h>
 #include <sys/mman.h>
 #include <sys/stat.h>
+#include <unistd.h>
 
 #include <thread>
 
diff --git a/services/sensorservice/SensorEventConnection.cpp b/services/sensorservice/SensorEventConnection.cpp
index fad046c..bfe4c09 100644
--- a/services/sensorservice/SensorEventConnection.cpp
+++ b/services/sensorservice/SensorEventConnection.cpp
@@ -477,7 +477,14 @@
     // separately before the next batch of events.
     for (int j = 0; j < numEventsDropped; ++j) {
         if (scratch[j].type == SENSOR_TYPE_META_DATA) {
-            FlushInfo& flushInfo = mSensorInfo.editValueFor(scratch[j].meta_data.sensor);
+            ssize_t index = mSensorInfo.indexOfKey(scratch[j].meta_data.sensor);
+            if (index < 0) {
+                ALOGW("%s: sensor 0x%x is not found in connection",
+                      __func__, scratch[j].meta_data.sensor);
+                continue;
+            }
+
+            FlushInfo& flushInfo = mSensorInfo.editValueAt(index);
             flushInfo.mPendingFlushEventsToSend++;
             ALOGD_IF(DEBUG_CONNECTIONS, "increment pendingFlushCount %d",
                      flushInfo.mPendingFlushEventsToSend);
diff --git a/services/surfaceflinger/DisplayHardware/ComposerHal.cpp b/services/surfaceflinger/DisplayHardware/ComposerHal.cpp
index ae628e1..e34fa16 100644
--- a/services/surfaceflinger/DisplayHardware/ComposerHal.cpp
+++ b/services/surfaceflinger/DisplayHardware/ComposerHal.cpp
@@ -553,6 +553,29 @@
     return Error::NONE;
 }
 
+Error Composer::presentOrValidateDisplay(Display display, uint32_t* outNumTypes,
+                               uint32_t* outNumRequests, int* outPresentFence, uint32_t* state) {
+   mWriter.selectDisplay(display);
+   mWriter.presentOrvalidateDisplay();
+
+   Error error = execute();
+   if (error != Error::NONE) {
+       return error;
+   }
+
+   mReader.takePresentOrValidateStage(display, state);
+
+   if (*state == 1) { // Present succeeded
+       mReader.takePresentFence(display, outPresentFence);
+   }
+
+   if (*state == 0) { // Validate succeeded.
+       mReader.hasChanges(display, outNumTypes, outNumRequests);
+   }
+
+   return Error::NONE;
+}
+
 Error Composer::setCursorPosition(Display display, Layer layer,
         int32_t x, int32_t y)
 {
@@ -770,7 +793,8 @@
             auto command = mWriter.getCommand(cmdErr.location);
 
             if (command == IComposerClient::Command::VALIDATE_DISPLAY ||
-                command == IComposerClient::Command::PRESENT_DISPLAY) {
+                command == IComposerClient::Command::PRESENT_DISPLAY ||
+                command == IComposerClient::Command::PRESENT_OR_VALIDATE_DISPLAY) {
                 error = cmdErr.error;
             } else {
                 ALOGW("command 0x%x generated error %d",
@@ -821,6 +845,9 @@
         case IComposerClient::Command::SET_RELEASE_FENCES:
             parsed = parseSetReleaseFences(length);
             break;
+        case IComposerClient::Command ::SET_PRESENT_OR_VALIDATE_DISPLAY_RESULT:
+            parsed = parseSetPresentOrValidateDisplayResult(length);
+            break;
         default:
             parsed = false;
             break;
@@ -949,6 +976,15 @@
     return true;
 }
 
+bool CommandReader::parseSetPresentOrValidateDisplayResult(uint16_t length)
+{
+    if (length != CommandWriterBase::kPresentOrValidateDisplayResultLength || !mCurrentReturnData) {
+        return false;
+    }
+    mCurrentReturnData->presentOrValidateState = read();
+    return true;
+}
+
 void CommandReader::resetData()
 {
     mErrors.clear();
@@ -1058,6 +1094,16 @@
     data.presentFence = -1;
 }
 
+void CommandReader::takePresentOrValidateStage(Display display, uint32_t* state) {
+    auto found = mReturnData.find(display);
+    if (found == mReturnData.end()) {
+        *state= -1;
+        return;
+    }
+    ReturnData& data = found->second;
+    *state = data.presentOrValidateState;
+}
+
 } // namespace Hwc2
 
 } // namespace android
diff --git a/services/surfaceflinger/DisplayHardware/ComposerHal.h b/services/surfaceflinger/DisplayHardware/ComposerHal.h
index 68d6e6f..96dd833 100644
--- a/services/surfaceflinger/DisplayHardware/ComposerHal.h
+++ b/services/surfaceflinger/DisplayHardware/ComposerHal.h
@@ -93,6 +93,9 @@
     // Get and clear saved present fence.
     void takePresentFence(Display display, int* outPresentFence);
 
+    // Get what stage succeeded during PresentOrValidate: Present or Validate
+    void takePresentOrValidateStage(Display display, uint32_t * state);
+
 private:
     void resetData();
 
@@ -102,6 +105,7 @@
     bool parseSetDisplayRequests(uint16_t length);
     bool parseSetPresentFence(uint16_t length);
     bool parseSetReleaseFences(uint16_t length);
+    bool parseSetPresentOrValidateDisplayResult(uint16_t length);
 
     struct ReturnData {
         uint32_t displayRequests = 0;
@@ -116,6 +120,8 @@
 
         std::vector<Layer> releasedLayers;
         std::vector<int> releaseFences;
+
+        uint32_t presentOrValidateState;
     };
 
     std::vector<CommandError> mErrors;
@@ -202,6 +208,11 @@
     Error validateDisplay(Display display, uint32_t* outNumTypes,
             uint32_t* outNumRequests);
 
+    Error presentOrValidateDisplay(Display display, uint32_t* outNumTypes,
+                                   uint32_t* outNumRequests,
+                                   int* outPresentFence,
+                                   uint32_t* state);
+
     Error setCursorPosition(Display display, Layer layer,
             int32_t x, int32_t y);
     /* see setClientTarget for the purpose of slot */
diff --git a/services/surfaceflinger/DisplayHardware/HWC2.cpp b/services/surfaceflinger/DisplayHardware/HWC2.cpp
index 263ff00..270a732 100644
--- a/services/surfaceflinger/DisplayHardware/HWC2.cpp
+++ b/services/surfaceflinger/DisplayHardware/HWC2.cpp
@@ -695,6 +695,34 @@
     return error;
 }
 
+Error Display::presentOrValidate(uint32_t* outNumTypes, uint32_t* outNumRequests,
+                                 sp<android::Fence>* outPresentFence, uint32_t* state) {
+
+    uint32_t numTypes = 0;
+    uint32_t numRequests = 0;
+    int32_t presentFenceFd = -1;
+    auto intError = mDevice.mComposer->presentOrValidateDisplay(mId, &numTypes, &numRequests, &presentFenceFd, state);
+    auto error = static_cast<Error>(intError);
+    if (error != Error::None && error != Error::HasChanges) {
+        return error;
+    }
+
+    if (*state == 1) {
+        *outPresentFence = new Fence(presentFenceFd);
+    }
+
+    if (*state == 0) {
+        *outNumTypes = numTypes;
+        *outNumRequests = numRequests;
+    }
+    return error;
+}
+
+void Display::discardCommands()
+{
+    mDevice.mComposer->resetCommands();
+}
+
 // For use by Device
 
 int32_t Display::getAttribute(hwc2_config_t configId, Attribute attribute)
diff --git a/services/surfaceflinger/DisplayHardware/HWC2.h b/services/surfaceflinger/DisplayHardware/HWC2.h
index b7376d0..404bb28 100644
--- a/services/surfaceflinger/DisplayHardware/HWC2.h
+++ b/services/surfaceflinger/DisplayHardware/HWC2.h
@@ -255,6 +255,15 @@
     [[clang::warn_unused_result]] Error setVsyncEnabled(Vsync enabled);
     [[clang::warn_unused_result]] Error validate(uint32_t* outNumTypes,
             uint32_t* outNumRequests);
+    [[clang::warn_unused_result]] Error presentOrValidate(uint32_t* outNumTypes,
+                                                 uint32_t* outNumRequests,
+                                                          android::sp<android::Fence>* outPresentFence, uint32_t* state);
+
+    // Most methods in this class write a command to a command buffer.  The
+    // command buffer is implicitly submitted in validate, present, and
+    // presentOrValidate.  This method provides a way to discard the commands,
+    // which can be used to discard stale commands.
+    void discardCommands();
 
     // Other Display methods
 
diff --git a/services/surfaceflinger/DisplayHardware/HWComposer.cpp b/services/surfaceflinger/DisplayHardware/HWComposer.cpp
index 42be935..ac2dde2 100644
--- a/services/surfaceflinger/DisplayHardware/HWComposer.cpp
+++ b/services/surfaceflinger/DisplayHardware/HWComposer.cpp
@@ -455,7 +455,34 @@
 
     uint32_t numTypes = 0;
     uint32_t numRequests = 0;
-    auto error = hwcDisplay->validate(&numTypes, &numRequests);
+
+    HWC2::Error error = HWC2::Error::None;
+
+    // First try to skip validate altogether if the HWC supports it.
+    displayData.validateWasSkipped = false;
+    if (hasCapability(HWC2::Capability::SkipValidate) &&
+            !displayData.hasClientComposition) {
+        sp<android::Fence> outPresentFence;
+        uint32_t state = UINT32_MAX;
+        error = hwcDisplay->presentOrValidate(&numTypes, &numRequests, &outPresentFence , &state);
+        if (error != HWC2::Error::None && error != HWC2::Error::HasChanges) {
+            ALOGV("skipValidate: Failed to Present or Validate");
+            return UNKNOWN_ERROR;
+        }
+        if (state == 1) { //Present Succeeded.
+            std::unordered_map<std::shared_ptr<HWC2::Layer>, sp<Fence>> releaseFences;
+            error = hwcDisplay->getReleaseFences(&releaseFences);
+            displayData.releaseFences = std::move(releaseFences);
+            displayData.lastPresentFence = outPresentFence;
+            displayData.validateWasSkipped = true;
+            displayData.presentError = error;
+            return NO_ERROR;
+        }
+        // Present failed but Validate ran.
+    } else {
+        error = hwcDisplay->validate(&numTypes, &numRequests);
+    }
+    ALOGV("SkipValidate failed, Falling back to SLOW validate/present");
     if (error != HWC2::Error::None && error != HWC2::Error::HasChanges) {
         ALOGE("prepare: validate failed for display %d: %s (%d)", displayId,
                 to_string(error).c_str(), static_cast<int32_t>(error));
@@ -592,6 +619,18 @@
 
     auto& displayData = mDisplayData[displayId];
     auto& hwcDisplay = displayData.hwcDisplay;
+
+    if (displayData.validateWasSkipped) {
+        hwcDisplay->discardCommands();
+        auto error = displayData.presentError;
+        if (error != HWC2::Error::None) {
+            ALOGE("skipValidate: failed for display %d: %s (%d)",
+                  displayId, to_string(error).c_str(), static_cast<int32_t>(error));
+            return UNKNOWN_ERROR;
+        }
+        return NO_ERROR;
+    }
+
     auto error = hwcDisplay->present(&displayData.lastPresentFence);
     if (error != HWC2::Error::None) {
         ALOGE("presentAndGetReleaseFences: failed for display %d: %s (%d)",
diff --git a/services/surfaceflinger/DisplayHardware/HWComposer.h b/services/surfaceflinger/DisplayHardware/HWComposer.h
index 3eb968d..7463362 100644
--- a/services/surfaceflinger/DisplayHardware/HWComposer.h
+++ b/services/surfaceflinger/DisplayHardware/HWComposer.h
@@ -202,6 +202,9 @@
 
         // protected by mVsyncLock
         HWC2::Vsync vsyncEnabled;
+
+        bool validateWasSkipped;
+        HWC2::Error presentError;
     };
 
     std::unique_ptr<HWC2::Device>   mHwcDevice;