Merge "libbinder*: ParcelableHolder assert stability read"
diff --git a/cmds/dumpstate/dumpstate.cpp b/cmds/dumpstate/dumpstate.cpp
index 0e9ce89..24b201f 100644
--- a/cmds/dumpstate/dumpstate.cpp
+++ b/cmds/dumpstate/dumpstate.cpp
@@ -2418,7 +2418,7 @@
     // Given that bugreport is required to diagnose failures, it's better to set an arbitrary amount
     // of timeout for IDumpstateDevice than to block the rest of bugreport. In the timeout case, we
     // will kill the HAL and grab whatever it dumped in time.
-    constexpr size_t timeout_sec = 30;
+    constexpr size_t timeout_sec = 45;
 
     if (dumpstate_hal_handle_aidl != nullptr) {
         DoDumpstateBoardAidl(dumpstate_hal_handle_aidl, dumpstate_fds, options_->bugreport_mode,
diff --git a/libs/binder/MemoryHeapBase.cpp b/libs/binder/MemoryHeapBase.cpp
index e1cbc19..8132d46 100644
--- a/libs/binder/MemoryHeapBase.cpp
+++ b/libs/binder/MemoryHeapBase.cpp
@@ -18,10 +18,13 @@
 
 #include <errno.h>
 #include <fcntl.h>
+#include <linux/memfd.h>
 #include <stdint.h>
 #include <stdlib.h>
 #include <sys/ioctl.h>
+#include <sys/mman.h>
 #include <sys/stat.h>
+#include <sys/syscall.h>
 #include <sys/types.h>
 #include <unistd.h>
 
@@ -34,6 +37,24 @@
 
 // ---------------------------------------------------------------------------
 
+#ifdef __BIONIC__
+static int memfd_create_region(const char* name, size_t size) {
+    int fd = memfd_create(name, MFD_CLOEXEC | MFD_ALLOW_SEALING);
+    if (fd == -1) {
+        ALOGE("%s: memfd_create(%s, %zd) failed: %s\n", __func__, name, size, strerror(errno));
+        return -1;
+    }
+
+    if (ftruncate(fd, size) == -1) {
+        ALOGE("%s, ftruncate(%s, %zd) failed for memfd creation: %s\n", __func__, name, size,
+              strerror(errno));
+        close(fd);
+        return -1;
+    }
+    return fd;
+}
+#endif
+
 MemoryHeapBase::MemoryHeapBase()
     : mFD(-1), mSize(0), mBase(MAP_FAILED),
       mDevice(nullptr), mNeedUnmap(false), mOffset(0)
@@ -45,15 +66,36 @@
       mDevice(nullptr), mNeedUnmap(false), mOffset(0)
 {
     const size_t pagesize = getpagesize();
-    size = ((size + pagesize-1) & ~(pagesize-1));
-    int fd = ashmem_create_region(name == nullptr ? "MemoryHeapBase" : name, size);
-    ALOGE_IF(fd<0, "error creating ashmem region: %s", strerror(errno));
-    if (fd >= 0) {
-        if (mapfd(fd, true, size) == NO_ERROR) {
-            if (flags & READ_ONLY) {
-                ashmem_set_prot_region(fd, PROT_READ);
-            }
+    size = ((size + pagesize - 1) & ~(pagesize - 1));
+    int fd = -1;
+    if (mFlags & FORCE_MEMFD) {
+#ifdef __BIONIC__
+        ALOGV("MemoryHeapBase: Attempting to force MemFD");
+        fd = memfd_create_region(name ? name : "MemoryHeapBase", size);
+        if (fd < 0 || (mapfd(fd, true, size) != NO_ERROR)) return;
+        const int SEAL_FLAGS = ((mFlags & READ_ONLY) ? F_SEAL_FUTURE_WRITE : 0) |
+                ((mFlags & MEMFD_ALLOW_SEALING) ? 0 : F_SEAL_SEAL);
+        if (SEAL_FLAGS && (fcntl(fd, F_ADD_SEALS, SEAL_FLAGS) == -1)) {
+            ALOGE("MemoryHeapBase: MemFD %s sealing with flags %x failed with error  %s", name,
+                  SEAL_FLAGS, strerror(errno));
+            munmap(mBase, mSize);
+            mBase = nullptr;
+            mSize = 0;
+            close(fd);
         }
+        return;
+#else
+        mFlags &= ~(FORCE_MEMFD | MEMFD_ALLOW_SEALING);
+#endif
+    }
+    if (mFlags & MEMFD_ALLOW_SEALING) {
+      LOG_ALWAYS_FATAL("Invalid Flags. MEMFD_ALLOW_SEALING only valid with FORCE_MEMFD.");
+    }
+    fd = ashmem_create_region(name ? name : "MemoryHeapBase", size);
+    ALOGE_IF(fd < 0, "MemoryHeapBase: error creating ashmem region: %s", strerror(errno));
+    if (fd < 0 || (mapfd(fd, true, size) != NO_ERROR)) return;
+    if (mFlags & READ_ONLY) {
+        ashmem_set_prot_region(fd, PROT_READ);
     }
 }
 
@@ -61,6 +103,9 @@
     : mFD(-1), mSize(0), mBase(MAP_FAILED), mFlags(flags),
       mDevice(nullptr), mNeedUnmap(false), mOffset(0)
 {
+    if (flags & (FORCE_MEMFD | MEMFD_ALLOW_SEALING)) {
+        LOG_ALWAYS_FATAL("FORCE_MEMFD, MEMFD_ALLOW_SEALING only valid with creating constructor");
+    }
     int open_flags = O_RDWR;
     if (flags & NO_CACHING)
         open_flags |= O_SYNC;
@@ -80,6 +125,9 @@
     : mFD(-1), mSize(0), mBase(MAP_FAILED), mFlags(flags),
       mDevice(nullptr), mNeedUnmap(false), mOffset(0)
 {
+    if (flags & (FORCE_MEMFD | MEMFD_ALLOW_SEALING)) {
+        LOG_ALWAYS_FATAL("FORCE_MEMFD, MEMFD_ALLOW_SEALING only valid with creating constructor");
+    }
     const size_t pagesize = getpagesize();
     size = ((size + pagesize-1) & ~(pagesize-1));
     mapfd(fcntl(fd, F_DUPFD_CLOEXEC, 0), false, size, offset);
diff --git a/libs/binder/RpcSession.cpp b/libs/binder/RpcSession.cpp
index e79cb86..d40778a 100644
--- a/libs/binder/RpcSession.cpp
+++ b/libs/binder/RpcSession.cpp
@@ -853,10 +853,16 @@
         }
 
         if (session->mConnections.mOutgoing.size() == 0) {
-            ALOGE("Session has no client connections. This is required for an RPC server to make "
-                  "any non-nested (e.g. oneway or on another thread) calls. Use: %d. Server "
-                  "connections: %zu",
-                  static_cast<int>(use), session->mConnections.mIncoming.size());
+            ALOGE("Session has no outgoing connections. This is required for an RPC server to make "
+                  "any non-nested (e.g. oneway or on another thread) calls. Use code request "
+                  "reason: %d. Incoming connections: %zu. %s.",
+                  static_cast<int>(use), session->mConnections.mIncoming.size(),
+                  (session->server()
+                           ? "This is a server session, so see RpcSession::setMaxIncomingThreads "
+                             "for the corresponding client"
+                           : "This is a client session, so see RpcSession::setMaxOutgoingThreads "
+                             "for this client or RpcServer::setMaxThreads for the corresponding "
+                             "server"));
             return WOULD_BLOCK;
         }
 
diff --git a/libs/binder/include/binder/MemoryHeapBase.h b/libs/binder/include/binder/MemoryHeapBase.h
index dd76943..15dd28f 100644
--- a/libs/binder/include/binder/MemoryHeapBase.h
+++ b/libs/binder/include/binder/MemoryHeapBase.h
@@ -34,7 +34,21 @@
         // memory won't be mapped locally, but will be mapped in the remote
         // process.
         DONT_MAP_LOCALLY = 0x00000100,
-        NO_CACHING = 0x00000200
+        NO_CACHING = 0x00000200,
+        // Bypass ashmem-libcutils to create a memfd shared region.
+        // Ashmem-libcutils will eventually migrate to memfd.
+        // Memfd has security benefits and supports file sealing.
+        // Calling process will need to modify selinux permissions to
+        // open access to tmpfs files. See audioserver for examples.
+        // This is only valid for size constructor.
+        // For host compilation targets, memfd is stubbed in favor of /tmp
+        // files so sealing is not enforced.
+        FORCE_MEMFD = 0x00000400,
+        // Default opt-out of sealing behavior in memfd to avoid potential DOS.
+        // Clients of shared files can seal at anytime via syscall, leading to
+        // TOC/TOU issues if additional seals prevent access from the creating
+        // process. Alternatively, seccomp fcntl().
+        MEMFD_ALLOW_SEALING = 0x00000800
     };
 
     /*
diff --git a/libs/binder/tests/Android.bp b/libs/binder/tests/Android.bp
index ff55d6e..a3533d8 100644
--- a/libs/binder/tests/Android.bp
+++ b/libs/binder/tests/Android.bp
@@ -99,6 +99,7 @@
         "binderParcelUnitTest.cpp",
         "binderBinderUnitTest.cpp",
         "binderStatusUnitTest.cpp",
+        "binderMemoryHeapBaseUnitTest.cpp",
     ],
     shared_libs: [
         "libbinder",
diff --git a/libs/binder/tests/binderMemoryHeapBaseUnitTest.cpp b/libs/binder/tests/binderMemoryHeapBaseUnitTest.cpp
new file mode 100644
index 0000000..21cb70b
--- /dev/null
+++ b/libs/binder/tests/binderMemoryHeapBaseUnitTest.cpp
@@ -0,0 +1,97 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * 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.
+ */
+
+#include <binder/MemoryHeapBase.h>
+#include <cutils/ashmem.h>
+#include <fcntl.h>
+
+#include <gtest/gtest.h>
+using namespace android;
+#ifdef __BIONIC__
+TEST(MemoryHeapBase, ForceMemfdRespected) {
+    auto mHeap = sp<MemoryHeapBase>::make(10, MemoryHeapBase::FORCE_MEMFD, "Test mapping");
+    int fd = mHeap->getHeapID();
+    EXPECT_NE(fd, -1);
+    EXPECT_FALSE(ashmem_valid(fd));
+    EXPECT_NE(fcntl(fd, F_GET_SEALS), -1);
+}
+
+TEST(MemoryHeapBase, MemfdSealed) {
+    auto mHeap = sp<MemoryHeapBase>::make(8192,
+                                          MemoryHeapBase::FORCE_MEMFD,
+                                          "Test mapping");
+    int fd = mHeap->getHeapID();
+    EXPECT_NE(fd, -1);
+    EXPECT_EQ(fcntl(fd, F_GET_SEALS), F_SEAL_SEAL);
+}
+
+TEST(MemoryHeapBase, MemfdUnsealed) {
+    auto mHeap = sp<MemoryHeapBase>::make(8192,
+                                          MemoryHeapBase::FORCE_MEMFD |
+                                          MemoryHeapBase::MEMFD_ALLOW_SEALING,
+                                          "Test mapping");
+    int fd = mHeap->getHeapID();
+    EXPECT_NE(fd, -1);
+    EXPECT_EQ(fcntl(fd, F_GET_SEALS), 0);
+}
+
+TEST(MemoryHeapBase, MemfdSealedProtected) {
+    auto mHeap = sp<MemoryHeapBase>::make(8192,
+                                          MemoryHeapBase::FORCE_MEMFD |
+                                          MemoryHeapBase::READ_ONLY,
+                                          "Test mapping");
+    int fd = mHeap->getHeapID();
+    EXPECT_NE(fd, -1);
+    EXPECT_EQ(fcntl(fd, F_GET_SEALS), F_SEAL_SEAL | F_SEAL_FUTURE_WRITE);
+}
+
+TEST(MemoryHeapBase, MemfdUnsealedProtected) {
+    auto mHeap = sp<MemoryHeapBase>::make(8192,
+                                          MemoryHeapBase::FORCE_MEMFD |
+                                          MemoryHeapBase::READ_ONLY |
+                                          MemoryHeapBase::MEMFD_ALLOW_SEALING,
+                                          "Test mapping");
+    int fd = mHeap->getHeapID();
+    EXPECT_NE(fd, -1);
+    EXPECT_EQ(fcntl(fd, F_GET_SEALS), F_SEAL_FUTURE_WRITE);
+}
+
+#else
+TEST(MemoryHeapBase, HostMemfdExpected) {
+    auto mHeap = sp<MemoryHeapBase>::make(8192,
+                                          MemoryHeapBase::READ_ONLY,
+                                          "Test mapping");
+    int fd = mHeap->getHeapID();
+    void* ptr = mHeap->getBase();
+    EXPECT_NE(ptr, MAP_FAILED);
+    EXPECT_TRUE(ashmem_valid(fd));
+    EXPECT_EQ(mHeap->getFlags(), MemoryHeapBase::READ_ONLY);
+}
+
+TEST(MemoryHeapBase,HostMemfdException) {
+    auto mHeap = sp<MemoryHeapBase>::make(8192,
+                                          MemoryHeapBase::FORCE_MEMFD |
+                                          MemoryHeapBase::READ_ONLY |
+                                          MemoryHeapBase::MEMFD_ALLOW_SEALING,
+                                          "Test mapping");
+    int fd = mHeap->getHeapID();
+    void* ptr = mHeap->getBase();
+    EXPECT_EQ(mHeap->getFlags(), MemoryHeapBase::READ_ONLY);
+    EXPECT_TRUE(ashmem_valid(fd));
+    EXPECT_NE(ptr, MAP_FAILED);
+}
+
+#endif
diff --git a/libs/binder/tests/parcel_fuzzer/Android.bp b/libs/binder/tests/parcel_fuzzer/Android.bp
index 38bde3a..57d496d 100644
--- a/libs/binder/tests/parcel_fuzzer/Android.bp
+++ b/libs/binder/tests/parcel_fuzzer/Android.bp
@@ -66,10 +66,13 @@
     srcs: [
         "random_fd.cpp",
         "random_parcel.cpp",
+        "libbinder_driver.cpp",
+        "libbinder_ndk_driver.cpp",
     ],
     shared_libs: [
         "libbase",
         "libbinder",
+        "libbinder_ndk",
         "libcutils",
         "libutils",
     ],
diff --git a/libs/binder/tests/parcel_fuzzer/include_random_parcel/fuzzbinder/libbinder_driver.h b/libs/binder/tests/parcel_fuzzer/include_random_parcel/fuzzbinder/libbinder_driver.h
new file mode 100644
index 0000000..a9a6197
--- /dev/null
+++ b/libs/binder/tests/parcel_fuzzer/include_random_parcel/fuzzbinder/libbinder_driver.h
@@ -0,0 +1,37 @@
+/*
+ * Copyright (C) 2022 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * 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.
+ */
+
+#pragma once
+
+#include <binder/IBinder.h>
+#include <fuzzer/FuzzedDataProvider.h>
+
+namespace android {
+/**
+ * Based on the random data in provider, construct an arbitrary number of
+ * Parcel objects and send them to the service in serial.
+ *
+ * Usage:
+ *
+ *   extern "C" int LLVMFuzzerTestOneInput(const uint8_t* data, size_t size) {
+ *       FuzzedDataProvider provider = FuzzedDataProvider(data, size);
+ *       // can use provider here to create a service with different options
+ *       sp<IFoo> myService = sp<IFoo>::make(...);
+ *       fuzzService(myService, std::move(provider));
+ *   }
+ */
+void fuzzService(const sp<IBinder>& binder, FuzzedDataProvider&& provider);
+} // namespace android
diff --git a/libs/binder/tests/parcel_fuzzer/include_random_parcel/fuzzbinder/libbinder_ndk_driver.h b/libs/binder/tests/parcel_fuzzer/include_random_parcel/fuzzbinder/libbinder_ndk_driver.h
new file mode 100644
index 0000000..f2b7823
--- /dev/null
+++ b/libs/binder/tests/parcel_fuzzer/include_random_parcel/fuzzbinder/libbinder_ndk_driver.h
@@ -0,0 +1,37 @@
+/*
+ * Copyright (C) 2022 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * 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.
+ */
+
+#pragma once
+
+#include <android/binder_parcel.h>
+#include <fuzzer/FuzzedDataProvider.h>
+
+namespace android {
+/**
+ * Based on the random data in provider, construct an arbitrary number of
+ * Parcel objects and send them to the service in serial.
+ *
+ * Usage:
+ *
+ *   extern "C" int LLVMFuzzerTestOneInput(const uint8_t* data, size_t size) {
+ *       FuzzedDataProvider provider = FuzzedDataProvider(data, size);
+ *       // can use provider here to create a service with different options
+ *       std::shared_ptr<IFoo> myService = ndk::SharedRefBase<IFoo>::make(...);
+ *       fuzzService(myService->asBinder().get(), std::move(provider));
+ *   }
+ */
+void fuzzService(AIBinder* binder, FuzzedDataProvider&& provider);
+} // namespace android
diff --git a/libs/binder/tests/parcel_fuzzer/libbinder_driver.cpp b/libs/binder/tests/parcel_fuzzer/libbinder_driver.cpp
new file mode 100644
index 0000000..e849c9b
--- /dev/null
+++ b/libs/binder/tests/parcel_fuzzer/libbinder_driver.cpp
@@ -0,0 +1,37 @@
+/*
+ * Copyright (C) 2022 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * 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.
+ */
+#include <fuzzbinder/libbinder_driver.h>
+
+#include <fuzzbinder/random_parcel.h>
+
+namespace android {
+
+void fuzzService(const sp<IBinder>& binder, FuzzedDataProvider&& provider) {
+    while (provider.remaining_bytes() > 0) {
+        uint32_t code = provider.ConsumeIntegral<uint32_t>();
+        uint32_t flags = provider.ConsumeIntegral<uint32_t>();
+        Parcel data;
+
+        std::vector<uint8_t> subData = provider.ConsumeBytes<uint8_t>(
+                provider.ConsumeIntegralInRange<size_t>(0, provider.remaining_bytes()));
+        fillRandomParcel(&data, FuzzedDataProvider(subData.data(), subData.size()));
+
+        Parcel reply;
+        (void)binder->transact(code, data, &reply, flags);
+    }
+}
+
+} // namespace android
diff --git a/libs/binder/tests/parcel_fuzzer/libbinder_ndk_driver.cpp b/libs/binder/tests/parcel_fuzzer/libbinder_ndk_driver.cpp
new file mode 100644
index 0000000..462ef9a
--- /dev/null
+++ b/libs/binder/tests/parcel_fuzzer/libbinder_ndk_driver.cpp
@@ -0,0 +1,31 @@
+/*
+ * Copyright (C) 2022 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * 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.
+ */
+#include <fuzzbinder/libbinder_ndk_driver.h>
+
+#include <fuzzbinder/libbinder_driver.h>
+#include <fuzzbinder/random_parcel.h>
+
+// libbinder_ndk doesn't export this header which breaks down its API for NDK
+// and APEX users, but we need access to it to fuzz.
+#include "../../ndk/ibinder_internal.h"
+
+namespace android {
+
+void fuzzService(AIBinder* binder, FuzzedDataProvider&& provider) {
+    fuzzService(binder->getBinder(), std::move(provider));
+}
+
+} // namespace android
diff --git a/vulkan/libvulkan/driver.cpp b/vulkan/libvulkan/driver.cpp
index cf774fd..0c5d61b 100644
--- a/vulkan/libvulkan/driver.cpp
+++ b/vulkan/libvulkan/driver.cpp
@@ -624,8 +624,10 @@
         switch (ext_bit) {
             case ProcHook::KHR_android_surface:
             case ProcHook::KHR_surface:
+            case ProcHook::KHR_surface_protected_capabilities:
             case ProcHook::EXT_swapchain_colorspace:
             case ProcHook::KHR_get_surface_capabilities2:
+            case ProcHook::GOOGLE_surfaceless_query:
                 hook_extensions_.set(ext_bit);
                 // return now as these extensions do not require HAL support
                 return;
@@ -701,8 +703,10 @@
             case ProcHook::KHR_external_fence_capabilities:
             case ProcHook::KHR_get_surface_capabilities2:
             case ProcHook::KHR_surface:
+            case ProcHook::KHR_surface_protected_capabilities:
             case ProcHook::EXT_debug_report:
             case ProcHook::EXT_swapchain_colorspace:
+            case ProcHook::GOOGLE_surfaceless_query:
             case ProcHook::ANDROID_native_buffer:
             case ProcHook::EXTENSION_CORE_1_0:
             case ProcHook::EXTENSION_CORE_1_1:
@@ -913,6 +917,9 @@
     loader_extensions.push_back({
         VK_KHR_SURFACE_EXTENSION_NAME,
         VK_KHR_SURFACE_SPEC_VERSION});
+    loader_extensions.push_back(
+        {VK_KHR_SURFACE_PROTECTED_CAPABILITIES_EXTENSION_NAME,
+         VK_KHR_SURFACE_PROTECTED_CAPABILITIES_SPEC_VERSION});
     loader_extensions.push_back({
         VK_KHR_ANDROID_SURFACE_EXTENSION_NAME,
         VK_KHR_ANDROID_SURFACE_SPEC_VERSION});
@@ -922,6 +929,8 @@
     loader_extensions.push_back({
         VK_KHR_GET_SURFACE_CAPABILITIES_2_EXTENSION_NAME,
         VK_KHR_GET_SURFACE_CAPABILITIES_2_SPEC_VERSION});
+    loader_extensions.push_back({VK_GOOGLE_SURFACELESS_QUERY_EXTENSION_NAME,
+                                 VK_GOOGLE_SURFACELESS_QUERY_SPEC_VERSION});
 
     static const VkExtensionProperties loader_debug_report_extension = {
         VK_EXT_DEBUG_REPORT_EXTENSION_NAME, VK_EXT_DEBUG_REPORT_SPEC_VERSION,
diff --git a/vulkan/libvulkan/driver_gen.cpp b/vulkan/libvulkan/driver_gen.cpp
index 5f37a50..b436db1 100644
--- a/vulkan/libvulkan/driver_gen.cpp
+++ b/vulkan/libvulkan/driver_gen.cpp
@@ -565,11 +565,13 @@
     if (strcmp(name, "VK_EXT_hdr_metadata") == 0) return ProcHook::EXT_hdr_metadata;
     if (strcmp(name, "VK_EXT_swapchain_colorspace") == 0) return ProcHook::EXT_swapchain_colorspace;
     if (strcmp(name, "VK_GOOGLE_display_timing") == 0) return ProcHook::GOOGLE_display_timing;
+    if (strcmp(name, "VK_GOOGLE_surfaceless_query") == 0) return ProcHook::GOOGLE_surfaceless_query;
     if (strcmp(name, "VK_KHR_android_surface") == 0) return ProcHook::KHR_android_surface;
     if (strcmp(name, "VK_KHR_get_surface_capabilities2") == 0) return ProcHook::KHR_get_surface_capabilities2;
     if (strcmp(name, "VK_KHR_incremental_present") == 0) return ProcHook::KHR_incremental_present;
     if (strcmp(name, "VK_KHR_shared_presentable_image") == 0) return ProcHook::KHR_shared_presentable_image;
     if (strcmp(name, "VK_KHR_surface") == 0) return ProcHook::KHR_surface;
+    if (strcmp(name, "VK_KHR_surface_protected_capabilities") == 0) return ProcHook::KHR_surface_protected_capabilities;
     if (strcmp(name, "VK_KHR_swapchain") == 0) return ProcHook::KHR_swapchain;
     if (strcmp(name, "VK_ANDROID_external_memory_android_hardware_buffer") == 0) return ProcHook::ANDROID_external_memory_android_hardware_buffer;
     if (strcmp(name, "VK_KHR_bind_memory2") == 0) return ProcHook::KHR_bind_memory2;
diff --git a/vulkan/libvulkan/driver_gen.h b/vulkan/libvulkan/driver_gen.h
index 047e774..688630c 100644
--- a/vulkan/libvulkan/driver_gen.h
+++ b/vulkan/libvulkan/driver_gen.h
@@ -41,11 +41,13 @@
         EXT_hdr_metadata,
         EXT_swapchain_colorspace,
         GOOGLE_display_timing,
+        GOOGLE_surfaceless_query,
         KHR_android_surface,
         KHR_get_surface_capabilities2,
         KHR_incremental_present,
         KHR_shared_presentable_image,
         KHR_surface,
+        KHR_surface_protected_capabilities,
         KHR_swapchain,
         ANDROID_external_memory_android_hardware_buffer,
         KHR_bind_memory2,
diff --git a/vulkan/libvulkan/swapchain.cpp b/vulkan/libvulkan/swapchain.cpp
index 6191063..ec67312 100644
--- a/vulkan/libvulkan/swapchain.cpp
+++ b/vulkan/libvulkan/swapchain.cpp
@@ -614,42 +614,65 @@
 
 VKAPI_ATTR
 VkResult GetPhysicalDeviceSurfaceCapabilitiesKHR(
-    VkPhysicalDevice /*pdev*/,
+    VkPhysicalDevice pdev,
     VkSurfaceKHR surface,
     VkSurfaceCapabilitiesKHR* capabilities) {
     ATRACE_CALL();
 
     int err;
-    ANativeWindow* window = SurfaceFromHandle(surface)->window.get();
-
     int width, height;
-    err = window->query(window, NATIVE_WINDOW_DEFAULT_WIDTH, &width);
-    if (err != android::OK) {
-        ALOGE("NATIVE_WINDOW_DEFAULT_WIDTH query failed: %s (%d)",
-              strerror(-err), err);
-        return VK_ERROR_SURFACE_LOST_KHR;
-    }
-    err = window->query(window, NATIVE_WINDOW_DEFAULT_HEIGHT, &height);
-    if (err != android::OK) {
-        ALOGE("NATIVE_WINDOW_DEFAULT_WIDTH query failed: %s (%d)",
-              strerror(-err), err);
-        return VK_ERROR_SURFACE_LOST_KHR;
-    }
-
     int transform_hint;
-    err = window->query(window, NATIVE_WINDOW_TRANSFORM_HINT, &transform_hint);
-    if (err != android::OK) {
-        ALOGE("NATIVE_WINDOW_TRANSFORM_HINT query failed: %s (%d)",
-              strerror(-err), err);
-        return VK_ERROR_SURFACE_LOST_KHR;
-    }
-
     int max_buffer_count;
-    err = window->query(window, NATIVE_WINDOW_MAX_BUFFER_COUNT, &max_buffer_count);
-    if (err != android::OK) {
-        ALOGE("NATIVE_WINDOW_MAX_BUFFER_COUNT query failed: %s (%d)",
-              strerror(-err), err);
-        return VK_ERROR_SURFACE_LOST_KHR;
+    if (surface == VK_NULL_HANDLE) {
+        const InstanceData& instance_data = GetData(pdev);
+        ProcHook::Extension surfaceless = ProcHook::GOOGLE_surfaceless_query;
+        bool surfaceless_enabled =
+            instance_data.hook_extensions.test(surfaceless);
+        if (!surfaceless_enabled) {
+            // It is an error to pass a surface==VK_NULL_HANDLE unless the
+            // VK_GOOGLE_surfaceless_query extension is enabled
+            return VK_ERROR_SURFACE_LOST_KHR;
+        }
+        // Support for VK_GOOGLE_surfaceless_query.  The primary purpose of this
+        // extension for this function is for
+        // VkSurfaceProtectedCapabilitiesKHR::supportsProtected.  The following
+        // four values cannot be known without a surface.  Default values will
+        // be supplied anyway, but cannot be relied upon.
+        width = 1000;
+        height = 1000;
+        transform_hint = VK_SURFACE_TRANSFORM_IDENTITY_BIT_KHR;
+        max_buffer_count = 10;
+    } else {
+        ANativeWindow* window = SurfaceFromHandle(surface)->window.get();
+
+        err = window->query(window, NATIVE_WINDOW_DEFAULT_WIDTH, &width);
+        if (err != android::OK) {
+            ALOGE("NATIVE_WINDOW_DEFAULT_WIDTH query failed: %s (%d)",
+                  strerror(-err), err);
+            return VK_ERROR_SURFACE_LOST_KHR;
+        }
+        err = window->query(window, NATIVE_WINDOW_DEFAULT_HEIGHT, &height);
+        if (err != android::OK) {
+            ALOGE("NATIVE_WINDOW_DEFAULT_WIDTH query failed: %s (%d)",
+                  strerror(-err), err);
+            return VK_ERROR_SURFACE_LOST_KHR;
+        }
+
+        err = window->query(window, NATIVE_WINDOW_TRANSFORM_HINT,
+                            &transform_hint);
+        if (err != android::OK) {
+            ALOGE("NATIVE_WINDOW_TRANSFORM_HINT query failed: %s (%d)",
+                  strerror(-err), err);
+            return VK_ERROR_SURFACE_LOST_KHR;
+        }
+
+        err = window->query(window, NATIVE_WINDOW_MAX_BUFFER_COUNT,
+                            &max_buffer_count);
+        if (err != android::OK) {
+            ALOGE("NATIVE_WINDOW_MAX_BUFFER_COUNT query failed: %s (%d)",
+                  strerror(-err), err);
+            return VK_ERROR_SURFACE_LOST_KHR;
+        }
     }
     capabilities->minImageCount = std::min(max_buffer_count, 3);
     capabilities->maxImageCount = static_cast<uint32_t>(max_buffer_count);
@@ -690,23 +713,43 @@
     const InstanceData& instance_data = GetData(pdev);
 
     bool wide_color_support = false;
-    Surface& surface = *SurfaceFromHandle(surface_handle);
-    int err = native_window_get_wide_color_support(surface.window.get(),
-                                                   &wide_color_support);
-    if (err) {
-        return VK_ERROR_SURFACE_LOST_KHR;
-    }
-    ALOGV("wide_color_support is: %d", wide_color_support);
-    wide_color_support =
-        wide_color_support &&
+    uint64_t consumer_usage = 0;
+    bool swapchain_ext =
         instance_data.hook_extensions.test(ProcHook::EXT_swapchain_colorspace);
+    if (surface_handle == VK_NULL_HANDLE) {
+        ProcHook::Extension surfaceless = ProcHook::GOOGLE_surfaceless_query;
+        bool surfaceless_enabled =
+            instance_data.hook_extensions.test(surfaceless);
+        if (!surfaceless_enabled) {
+            return VK_ERROR_SURFACE_LOST_KHR;
+        }
+        // Support for VK_GOOGLE_surfaceless_query.  The EGL loader
+        // unconditionally supports wide color formats, even if they will cause
+        // a SurfaceFlinger fallback.  Based on that, wide_color_support will be
+        // set to true in this case.
+        wide_color_support = true;
+
+        // TODO(b/203826952): research proper value; temporarily use the
+        // values seen on Pixel
+        consumer_usage = AHARDWAREBUFFER_USAGE_COMPOSER_OVERLAY;
+    } else {
+        Surface& surface = *SurfaceFromHandle(surface_handle);
+        int err = native_window_get_wide_color_support(surface.window.get(),
+                                                       &wide_color_support);
+        if (err) {
+            return VK_ERROR_SURFACE_LOST_KHR;
+        }
+        ALOGV("wide_color_support is: %d", wide_color_support);
+
+        consumer_usage = surface.consumer_usage;
+    }
+    wide_color_support = wide_color_support && swapchain_ext;
 
     AHardwareBuffer_Desc desc = {};
     desc.width = 1;
     desc.height = 1;
     desc.layers = 1;
-    desc.usage = surface.consumer_usage |
-                 AHARDWAREBUFFER_USAGE_GPU_SAMPLED_IMAGE |
+    desc.usage = consumer_usage | AHARDWAREBUFFER_USAGE_GPU_SAMPLED_IMAGE |
                  AHARDWAREBUFFER_USAGE_GPU_FRAMEBUFFER;
 
     // We must support R8G8B8A8
@@ -721,6 +764,10 @@
             VK_FORMAT_R8G8B8A8_SRGB, VK_COLOR_SPACE_DISPLAY_P3_NONLINEAR_EXT});
     }
 
+    // NOTE: Any new formats that are added must be coordinated across different
+    // Android users.  This includes the ANGLE team (a layered implementation of
+    // OpenGL-ES).
+
     desc.format = AHARDWAREBUFFER_FORMAT_R5G6B5_UNORM;
     if (AHardwareBuffer_isSupported(&desc)) {
         all_formats.emplace_back(VkSurfaceFormatKHR{
@@ -753,6 +800,10 @@
         }
     }
 
+    // NOTE: Any new formats that are added must be coordinated across different
+    // Android users.  This includes the ANGLE team (a layered implementation of
+    // OpenGL-ES).
+
     VkResult result = VK_SUCCESS;
     if (formats) {
         uint32_t transfer_count = all_formats.size();
@@ -797,6 +848,12 @@
                         .supportedUsageFlags;
             } break;
 
+            case VK_STRUCTURE_TYPE_SURFACE_PROTECTED_CAPABILITIES_KHR: {
+                VkSurfaceProtectedCapabilitiesKHR* protected_caps =
+                    reinterpret_cast<VkSurfaceProtectedCapabilitiesKHR*>(caps);
+                protected_caps->supportsProtected = VK_TRUE;
+            } break;
+
             default:
                 // Ignore all other extension structs
                 break;
@@ -848,31 +905,51 @@
 
     int err;
     int query_value;
-    ANativeWindow* window = SurfaceFromHandle(surface)->window.get();
-
-    err = window->query(window, NATIVE_WINDOW_MIN_UNDEQUEUED_BUFFERS,
-                        &query_value);
-    if (err != android::OK || query_value < 0) {
-        ALOGE(
-            "NATIVE_WINDOW_MIN_UNDEQUEUED_BUFFERS query failed: %s (%d) "
-            "value=%d",
-            strerror(-err), err, query_value);
-        return VK_ERROR_SURFACE_LOST_KHR;
-    }
-    uint32_t min_undequeued_buffers = static_cast<uint32_t>(query_value);
-
-    err = window->query(window, NATIVE_WINDOW_MAX_BUFFER_COUNT, &query_value);
-    if (err != android::OK || query_value < 0) {
-        ALOGE("NATIVE_WINDOW_MAX_BUFFER_COUNT query failed: %s (%d) value=%d",
-              strerror(-err), err, query_value);
-        return VK_ERROR_SURFACE_LOST_KHR;
-    }
-    uint32_t max_buffer_count = static_cast<uint32_t>(query_value);
-
     std::vector<VkPresentModeKHR> present_modes;
-    if (min_undequeued_buffers + 1 < max_buffer_count)
+    if (surface == VK_NULL_HANDLE) {
+        const InstanceData& instance_data = GetData(pdev);
+        ProcHook::Extension surfaceless = ProcHook::GOOGLE_surfaceless_query;
+        bool surfaceless_enabled =
+            instance_data.hook_extensions.test(surfaceless);
+        if (!surfaceless_enabled) {
+            return VK_ERROR_SURFACE_LOST_KHR;
+        }
+        // Support for VK_GOOGLE_surfaceless_query.  The primary purpose of this
+        // extension for this function is for
+        // VK_PRESENT_MODE_SHARED_DEMAND_REFRESH_KHR and
+        // VK_PRESENT_MODE_SHARED_CONTINUOUS_REFRESH_KHR.  We technically cannot
+        // know if VK_PRESENT_MODE_SHARED_MAILBOX_KHR is supported without a
+        // surface, and that cannot be relied upon.
         present_modes.push_back(VK_PRESENT_MODE_MAILBOX_KHR);
-    present_modes.push_back(VK_PRESENT_MODE_FIFO_KHR);
+        present_modes.push_back(VK_PRESENT_MODE_FIFO_KHR);
+    } else {
+        ANativeWindow* window = SurfaceFromHandle(surface)->window.get();
+
+        err = window->query(window, NATIVE_WINDOW_MIN_UNDEQUEUED_BUFFERS,
+                            &query_value);
+        if (err != android::OK || query_value < 0) {
+            ALOGE(
+                "NATIVE_WINDOW_MIN_UNDEQUEUED_BUFFERS query failed: %s (%d) "
+                "value=%d",
+                strerror(-err), err, query_value);
+            return VK_ERROR_SURFACE_LOST_KHR;
+        }
+        uint32_t min_undequeued_buffers = static_cast<uint32_t>(query_value);
+
+        err =
+            window->query(window, NATIVE_WINDOW_MAX_BUFFER_COUNT, &query_value);
+        if (err != android::OK || query_value < 0) {
+            ALOGE(
+                "NATIVE_WINDOW_MAX_BUFFER_COUNT query failed: %s (%d) value=%d",
+                strerror(-err), err, query_value);
+            return VK_ERROR_SURFACE_LOST_KHR;
+        }
+        uint32_t max_buffer_count = static_cast<uint32_t>(query_value);
+
+        if (min_undequeued_buffers + 1 < max_buffer_count)
+            present_modes.push_back(VK_PRESENT_MODE_MAILBOX_KHR);
+        present_modes.push_back(VK_PRESENT_MODE_FIFO_KHR);
+    }
 
     VkPhysicalDevicePresentationPropertiesANDROID present_properties;
     QueryPresentationProperties(pdev, &present_properties);
diff --git a/vulkan/scripts/driver_generator.py b/vulkan/scripts/driver_generator.py
index 6a73023..af56764 100644
--- a/vulkan/scripts/driver_generator.py
+++ b/vulkan/scripts/driver_generator.py
@@ -27,11 +27,13 @@
     'VK_EXT_hdr_metadata',
     'VK_EXT_swapchain_colorspace',
     'VK_GOOGLE_display_timing',
+    'VK_GOOGLE_surfaceless_query',
     'VK_KHR_android_surface',
     'VK_KHR_get_surface_capabilities2',
     'VK_KHR_incremental_present',
     'VK_KHR_shared_presentable_image',
     'VK_KHR_surface',
+    'VK_KHR_surface_protected_capabilities',
     'VK_KHR_swapchain',
 ]