Merge "Convert certain format types to another buffer format." into sc-dev
diff --git a/cmds/dumpstate/Android.bp b/cmds/dumpstate/Android.bp
index 80d14ac..34e9a85 100644
--- a/cmds/dumpstate/Android.bp
+++ b/cmds/dumpstate/Android.bp
@@ -112,6 +112,7 @@
     ],
     required: [
         "atrace",
+        "dmabuf_dump",
         "ip",
         "iptables",
         "librank",
diff --git a/cmds/dumpstate/dumpstate.cpp b/cmds/dumpstate/dumpstate.cpp
index 4a4a510..990aa53 100644
--- a/cmds/dumpstate/dumpstate.cpp
+++ b/cmds/dumpstate/dumpstate.cpp
@@ -1846,10 +1846,8 @@
     RunCommand("IOTOP", {"iotop", "-n", "1", "-m", "100"});
 
     // Gather shared memory buffer info if the product implements it
-    struct stat st;
-    if (!stat("/product/bin/dmabuf_dump", &st)) {
-        RunCommand("Dmabuf dump", {"/product/bin/dmabuf_dump"});
-    }
+    RunCommand("Dmabuf dump", {"dmabuf_dump"});
+    RunCommand("Dmabuf per-buffer/per-exporter/per-device stats", {"dmabuf_dump", "-b"});
 
     DumpFile("PSI cpu", "/proc/pressure/cpu");
     DumpFile("PSI memory", "/proc/pressure/memory");
diff --git a/cmds/idlcli/Android.bp b/cmds/idlcli/Android.bp
index 643b3ca..72ffc94 100644
--- a/cmds/idlcli/Android.bp
+++ b/cmds/idlcli/Android.bp
@@ -15,7 +15,7 @@
 cc_defaults {
     name: "idlcli-defaults",
     shared_libs: [
-        "android.hardware.vibrator-unstable-ndk_platform",
+        "android.hardware.vibrator-V2-ndk_platform",
         "android.hardware.vibrator@1.0",
         "android.hardware.vibrator@1.1",
         "android.hardware.vibrator@1.2",
diff --git a/cmds/installd/Android.bp b/cmds/installd/Android.bp
index 96875d5..cbe857a 100644
--- a/cmds/installd/Android.bp
+++ b/cmds/installd/Android.bp
@@ -38,6 +38,9 @@
         "libutils",
         "server_configurable_flags",
     ],
+    export_shared_lib_headers: [
+        "libbinder",
+    ],
 
     product_variables: {
         arc: {
diff --git a/cmds/lshal/DebugCommand.cpp b/cmds/lshal/DebugCommand.cpp
index 72958bd..ccf1ab1 100644
--- a/cmds/lshal/DebugCommand.cpp
+++ b/cmds/lshal/DebugCommand.cpp
@@ -28,7 +28,7 @@
 }
 
 std::string DebugCommand::getSimpleDescription() const {
-    return "Debug a specified HAL.";
+    return "Debug a specified HIDL HAL.";
 }
 
 Status DebugCommand::parseArgs(const Arg &arg) {
@@ -78,7 +78,7 @@
             "debug:\n"
             "    lshal debug [-E] <interface> [options [options [...]]] \n"
             "        Print debug information of a specified interface.\n"
-            "        -E: excludes debug output if HAL is actually a subclass.\n"
+            "        -E: excludes debug output if HIDL HAL is actually a subclass.\n"
             "        <interface>: Format is `android.hardware.foo@1.0::IFoo/default`.\n"
             "            If instance name is missing `default` is used.\n"
             "        options: space separated options to IBase::debug.\n";
diff --git a/cmds/lshal/ListCommand.cpp b/cmds/lshal/ListCommand.cpp
index 22268ac..d5110f6 100644
--- a/cmds/lshal/ListCommand.cpp
+++ b/cmds/lshal/ListCommand.cpp
@@ -81,7 +81,7 @@
     return "list";
 }
 std::string ListCommand::getSimpleDescription() const {
-    return "List HALs.";
+    return "List HIDL HALs.";
 }
 
 std::string ListCommand::parseCmdline(pid_t pid) const {
@@ -295,21 +295,21 @@
     }
 
     mServicesTable.setDescription(
-            "| All binderized services (registered with hwservicemanager)");
+            "| All HIDL binderized services (registered with hwservicemanager)");
     mPassthroughRefTable.setDescription(
-            "| All interfaces that getService() has ever returned as a passthrough interface;\n"
+            "| All HIDL interfaces getService() has ever returned as a passthrough interface;\n"
             "| PIDs / processes shown below might be inaccurate because the process\n"
             "| might have relinquished the interface or might have died.\n"
             "| The Server / Server CMD column can be ignored.\n"
             "| The Clients / Clients CMD column shows all process that have ever dlopen'ed \n"
             "| the library and successfully fetched the passthrough implementation.");
     mImplementationsTable.setDescription(
-            "| All available passthrough implementations (all -impl.so files).\n"
+            "| All available HIDL passthrough implementations (all -impl.so files).\n"
             "| These may return subclasses through their respective HIDL_FETCH_I* functions.");
     mManifestHalsTable.setDescription(
-            "| All HALs that are in VINTF manifest.");
+            "| All HIDL HALs that are in VINTF manifest.");
     mLazyHalsTable.setDescription(
-            "| All HALs that are declared in VINTF manifest:\n"
+            "| All HIDL HALs that are declared in VINTF manifest:\n"
             "|    - as hwbinder HALs but are not registered to hwservicemanager, and\n"
             "|    - as hwbinder/passthrough HALs with no implementation.");
 }
@@ -903,11 +903,11 @@
         thiz->mSelectedColumns.push_back(TableColumnType::VINTF);
         return OK;
     }, "print VINTF info. This column contains a comma-separated list of:\n"
-       "    - DM: if the HAL is in the device manifest\n"
-       "    - DC: if the HAL is in the device compatibility matrix\n"
-       "    - FM: if the HAL is in the framework manifest\n"
-       "    - FC: if the HAL is in the framework compatibility matrix\n"
-       "    - X: if the HAL is in none of the above lists"});
+       "    - DM: if the HIDL HAL is in the device manifest\n"
+       "    - DC: if the HIDL HAL is in the device compatibility matrix\n"
+       "    - FM: if the HIDL HAL is in the framework manifest\n"
+       "    - FC: if the HIDL HAL is in the framework compatibility matrix\n"
+       "    - X: if the HIDL HAL is in none of the above lists"});
     mOptions.push_back({'S', "service-status", no_argument, v++, [](ListCommand* thiz, const char*) {
         thiz->mSelectedColumns.push_back(TableColumnType::SERVICE_STATUS);
         return OK;
diff --git a/cmds/lshal/Lshal.cpp b/cmds/lshal/Lshal.cpp
index 99cb93a..bc99f4d 100644
--- a/cmds/lshal/Lshal.cpp
+++ b/cmds/lshal/Lshal.cpp
@@ -59,7 +59,8 @@
 }
 
 void Lshal::usage() {
-    err() << "lshal: List and debug HALs." << std::endl << std::endl
+    err() << "lshal: List and debug HIDL HALs." << std::endl
+          << "   (for AIDL HALs, see `dumpsys`)" << std::endl << std::endl
           << "commands:" << std::endl;
 
     size_t nameMaxLength = 0;
diff --git a/cmds/lshal/WaitCommand.cpp b/cmds/lshal/WaitCommand.cpp
index 65b41b9..437a66a 100644
--- a/cmds/lshal/WaitCommand.cpp
+++ b/cmds/lshal/WaitCommand.cpp
@@ -29,7 +29,7 @@
 }
 
 std::string WaitCommand::getSimpleDescription() const {
-    return "Wait for HAL to start if it is not already started.";
+    return "Wait for HIDL HAL to start if it is not already started.";
 }
 
 Status WaitCommand::parseArgs(const Arg &arg) {
diff --git a/libs/binder/Android.bp b/libs/binder/Android.bp
index 2c0cca1..91033e9 100644
--- a/libs/binder/Android.bp
+++ b/libs/binder/Android.bp
@@ -22,11 +22,13 @@
 
     header_libs: [
         "libbase_headers",
+        "libbinder_headers_platform_shared",
         "libcutils_headers",
         "libutils_headers",
     ],
     export_header_lib_headers: [
         "libbase_headers",
+        "libbinder_headers_platform_shared",
         "libcutils_headers",
         "libutils_headers",
     ],
diff --git a/libs/binder/include/binder/IBinder.h b/libs/binder/include/binder/IBinder.h
index c8fb448..31f63c8 100644
--- a/libs/binder/include/binder/IBinder.h
+++ b/libs/binder/include/binder/IBinder.h
@@ -60,6 +60,15 @@
         EXTENSION_TRANSACTION   = B_PACK_CHARS('_', 'E', 'X', 'T'),
         DEBUG_PID_TRANSACTION   = B_PACK_CHARS('_', 'P', 'I', 'D'),
 
+        // See android.os.IBinder.TWEET_TRANSACTION
+        // Most importantly, messages can be anything not exceeding 130 UTF-8
+        // characters, and callees should exclaim "jolly good message old boy!"
+        TWEET_TRANSACTION       = B_PACK_CHARS('_', 'T', 'W', 'T'),
+
+        // See android.os.IBinder.LIKE_TRANSACTION
+        // Improve binder self-esteem.
+        LIKE_TRANSACTION        = B_PACK_CHARS('_', 'L', 'I', 'K'),
+
         // Corresponds to TF_ONE_WAY -- an asynchronous call.
         FLAG_ONEWAY             = 0x00000001,
 
diff --git a/libs/binder/ndk/Android.bp b/libs/binder/ndk/Android.bp
index 82f3882..d76a1f9 100644
--- a/libs/binder/ndk/Android.bp
+++ b/libs/binder/ndk/Android.bp
@@ -129,6 +129,28 @@
     ],
 }
 
+cc_library_headers {
+    name: "libbinder_headers_platform_shared",
+    export_include_dirs: ["include_cpp"],
+    vendor_available: true,
+    host_supported: true,
+    // TODO(b/153609531): remove when no longer needed.
+    native_bridge_supported: true,
+    target: {
+        darwin: {
+            enabled: false,
+        },
+    },
+    min_sdk_version: "29",
+    apex_available: [
+        "//apex_available:platform",
+        // TODO(b/166468760) remove these three
+        "com.android.media",
+        "com.android.media.swcodec",
+        "test_com.android.media.swcodec",
+    ],
+}
+
 ndk_headers {
     name: "libbinder_ndk_headers",
     from: "include_ndk/android",
diff --git a/libs/binder/ndk/include_cpp/android/binder_to_string.h b/libs/binder/ndk/include_cpp/android/binder_to_string.h
new file mode 100644
index 0000000..bd51b11
--- /dev/null
+++ b/libs/binder/ndk/include_cpp/android/binder_to_string.h
@@ -0,0 +1,184 @@
+/*
+ * 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.
+ */
+
+/**
+ * @addtogroup NdkBinder
+ * @{
+ */
+
+/**
+ * @file binder_to_string.h
+ * @brief Helper for parcelable.
+ */
+
+#pragma once
+
+#include <codecvt>
+#include <locale>
+#include <sstream>
+#include <string>
+#include <type_traits>
+
+#if __has_include(<android/binder_ibinder.h>)
+#include <android/binder_auto_utils.h>
+#include <android/binder_interface_utils.h>
+#include <android/binder_parcelable_utils.h>
+#define HAS_NDK_INTERFACE
+#else
+#include <binder/IBinder.h>
+#include <binder/IInterface.h>
+#include <binder/ParcelFileDescriptor.h>
+#include <binder/ParcelableHolder.h>
+#include <utils/String16.h>
+#include <utils/StrongPointer.h>
+#define HAS_CPP_INTERFACE
+#endif  //_has_include
+
+namespace android {
+namespace internal {
+
+// ToString is a utility to generate string representation for various AIDL-supported types.
+template <typename _T>
+std::string ToString(const _T& t);
+
+namespace details {
+
+// Truthy if _T has toString() method.
+template <typename _T>
+class HasToStringMethod {
+    template <typename _U>
+    static auto _test(int) -> decltype(std::declval<_U>().toString(), std::true_type());
+    template <typename _U>
+    static std::false_type _test(...);
+
+   public:
+    enum { value = decltype(_test<_T>(0))::value };
+};
+
+// Truthy if _T has a overloaded toString(T)
+template <typename _T>
+class HasToStringFunction {
+    template <typename _U>
+    static auto _test(int) -> decltype(toString(std::declval<_U>()), std::true_type());
+    template <typename _U>
+    static std::false_type _test(...);
+
+   public:
+    enum { value = decltype(_test<_T>(0))::value };
+};
+
+// Truthy if _T is like a pointer
+template <typename _T>
+class IsPointerLike {
+    template <typename _U>
+    static auto _test(int) -> decltype(!std::declval<_U>(), *std::declval<_U>(), std::true_type());
+    template <typename _U>
+    static std::false_type _test(...);
+
+   public:
+    enum { value = decltype(_test<_T>(0))::value };
+};
+
+// Truthy if _T is like a container
+template <typename _T>
+class IsIterable {
+    template <typename _U>
+    static auto _test(int)
+            -> decltype(begin(std::declval<_U>()), end(std::declval<_U>()), std::true_type());
+    template <typename _U>
+    static std::false_type _test(...);
+
+   public:
+    enum { value = decltype(_test<_T>(0))::value };
+};
+
+template <typename _T>
+class ToEmptyString {
+    template <typename _U>
+    static std::enable_if_t<
+#ifdef HAS_NDK_INTERFACE
+            std::is_base_of_v<::ndk::ICInterface, _U> || std::is_same_v<::ndk::SpAIBinder, _U> ||
+                    std::is_same_v<::ndk::ScopedFileDescriptor, _U> ||
+                    std::is_same_v<::ndk::AParcelableHolder, _U>
+#else
+            std::is_base_of_v<IInterface, _U> || std::is_same_v<IBinder, _U> ||
+                    std::is_same_v<os::ParcelFileDescriptor, _U> ||
+                    std::is_same_v<os::ParcelableHolder, _U>
+#endif
+            ,
+            std::true_type>
+    _test(int);
+    template <typename _U>
+    static std::false_type _test(...);
+
+   public:
+    enum { value = decltype(_test<_T>(0))::value };
+};
+
+}  // namespace details
+
+template <typename _T>
+std::string ToString(const _T& t) {
+    if constexpr (details::ToEmptyString<_T>::value) {
+        return "";
+    } else if constexpr (std::is_same_v<bool, _T>) {
+        return t ? "true" : "false";
+    } else if constexpr (std::is_same_v<char16_t, _T>) {
+        return std::wstring_convert<std::codecvt_utf8_utf16<char16_t>, char16_t>().to_bytes(t);
+    } else if constexpr (std::is_arithmetic_v<_T>) {
+        return std::to_string(t);
+    } else if constexpr (std::is_same_v<std::string, _T>) {
+        return t;
+#ifdef HAS_CPP_INTERFACE
+    } else if constexpr (std::is_same_v<String16, _T>) {
+        std::stringstream out;
+        out << t;
+        return out.str();
+#endif
+    } else if constexpr (details::HasToStringMethod<_T>::value) {
+        return t.toString();
+    } else if constexpr (details::HasToStringFunction<_T>::value) {
+        return toString(t);
+    } else if constexpr (details::IsIterable<_T>::value) {
+        std::stringstream out;
+        bool first = true;
+        out << "[";
+        for (const auto& e : t) {
+            if (first) {
+                first = false;
+            } else {
+                out << ", ";
+            }
+            // Use explicit type parameter in case deref of iterator has different type
+            // e.g. vector<bool>
+            out << ToString<typename _T::value_type>(e);
+        }
+        out << "]";
+        return out.str();
+    } else if constexpr (details::IsPointerLike<_T>::value) {
+        if (!t) return "(null)";
+        std::stringstream out;
+        out << ToString(*t);
+        return out.str();
+    } else {
+        return "{no toString() implemented}";
+    }
+}
+
+}  // namespace internal
+}  // namespace android
+
+/** @} */
diff --git a/libs/binder/tests/binderLibTest.cpp b/libs/binder/tests/binderLibTest.cpp
index a5261e5..e2193fa 100644
--- a/libs/binder/tests/binderLibTest.cpp
+++ b/libs/binder/tests/binderLibTest.cpp
@@ -21,6 +21,7 @@
 #include <pthread.h>
 #include <stdio.h>
 #include <stdlib.h>
+#include <thread>
 
 #include <gtest/gtest.h>
 
@@ -28,6 +29,7 @@
 #include <binder/IBinder.h>
 #include <binder/IPCThreadState.h>
 #include <binder/IServiceManager.h>
+#include <binder/ParcelRef.h>
 
 #include <private/binder/binder_module.h>
 #include <linux/sched.h>
@@ -916,6 +918,36 @@
     }
 }
 
+TEST_F(BinderLibTest, ParcelAllocatedOnAnotherThread) {
+    sp<IBinder> server = addServer();
+    ASSERT_TRUE(server != nullptr);
+
+    Parcel data;
+    sp<ParcelRef> reply = ParcelRef::create();
+
+    // when we have a Parcel which is deleted on another thread, if it gets
+    // deleted, it will tell the kernel this, and it will drop strong references
+    // to binder, so that we can't BR_ACQUIRE would fail
+    IPCThreadState::self()->createTransactionReference(reply.get());
+    ASSERT_EQ(NO_ERROR, server->transact(BINDER_LIB_TEST_CREATE_BINDER_TRANSACTION,
+                                         data,
+                                         reply.get()));
+
+    // we have sp to binder, but it is not actually acquired by kernel, the
+    // transaction is sitting on an out buffer
+    sp<IBinder> binder = reply->readStrongBinder();
+
+    std::thread([&] {
+        // without the transaction reference, this would cause the Parcel to be
+        // deallocated before the first thread flushes BR_ACQUIRE
+        reply = nullptr;
+        IPCThreadState::self()->flushCommands();
+    }).join();
+
+    ASSERT_NE(nullptr, binder);
+    ASSERT_EQ(NO_ERROR, binder->pingBinder());
+}
+
 TEST_F(BinderLibTest, CheckNoHeaderMappedInUser) {
     status_t ret;
     Parcel data, reply;
diff --git a/libs/gralloc/types/Android.bp b/libs/gralloc/types/Android.bp
index 243d7f1..dd0ae30 100644
--- a/libs/gralloc/types/Android.bp
+++ b/libs/gralloc/types/Android.bp
@@ -43,14 +43,14 @@
     ],
 
     shared_libs: [
-        "android.hardware.graphics.common-unstable-ndk_platform",
+        "android.hardware.graphics.common-V2-ndk_platform",
         "android.hardware.graphics.mapper@4.0",
         "libhidlbase",
         "liblog",
     ],
 
     export_shared_lib_headers: [
-        "android.hardware.graphics.common-unstable-ndk_platform",
+        "android.hardware.graphics.common-V2-ndk_platform",
         "android.hardware.graphics.mapper@4.0",
         "libhidlbase",
     ],
diff --git a/libs/renderengine/skia/SkiaGLRenderEngine.cpp b/libs/renderengine/skia/SkiaGLRenderEngine.cpp
index 79505ba..dd26b17 100644
--- a/libs/renderengine/skia/SkiaGLRenderEngine.cpp
+++ b/libs/renderengine/skia/SkiaGLRenderEngine.cpp
@@ -33,9 +33,11 @@
 #include <SkRegion.h>
 #include <SkShadowUtils.h>
 #include <SkSurface.h>
+#include <android-base/stringprintf.h>
 #include <gl/GrGLInterface.h>
 #include <sync/sync.h>
 #include <ui/BlurRegion.h>
+#include <ui/DebugUtils.h>
 #include <ui/GraphicBuffer.h>
 #include <utils/Trace.h>
 
@@ -59,6 +61,8 @@
 namespace renderengine {
 namespace skia {
 
+using base::StringAppendF;
+
 static status_t selectConfigForAttribute(EGLDisplay dpy, EGLint const* attrs, EGLint attribute,
                                          EGLint wanted, EGLConfig* outConfig) {
     EGLint numConfigs = -1, n = 0;
@@ -1075,6 +1079,53 @@
     return value;
 }
 
+void SkiaGLRenderEngine::dump(std::string& result) {
+    const gl::GLExtensions& extensions = gl::GLExtensions::getInstance();
+
+    StringAppendF(&result, "\n ------------RE-----------------\n");
+    StringAppendF(&result, "EGL implementation : %s\n", extensions.getEGLVersion());
+    StringAppendF(&result, "%s\n", extensions.getEGLExtensions());
+    StringAppendF(&result, "GLES: %s, %s, %s\n", extensions.getVendor(), extensions.getRenderer(),
+                  extensions.getVersion());
+    StringAppendF(&result, "%s\n", extensions.getExtensions());
+    StringAppendF(&result, "RenderEngine supports protected context: %d\n",
+                  supportsProtectedContent());
+    StringAppendF(&result, "RenderEngine is in protected context: %d\n", mInProtectedContext);
+
+    {
+        std::lock_guard<std::mutex> lock(mRenderingMutex);
+        StringAppendF(&result, "RenderEngine texture cache size: %zu\n", mTextureCache.size());
+        StringAppendF(&result, "Dumping buffer ids...\n");
+        // TODO(178539829): It would be nice to know which layer these are coming from and what
+        // the texture sizes are.
+        for (const auto& [id, unused] : mTextureCache) {
+            StringAppendF(&result, "- 0x%" PRIx64 "\n", id);
+        }
+        StringAppendF(&result, "\n");
+        StringAppendF(&result, "RenderEngine protected texture cache size: %zu\n",
+                      mProtectedTextureCache.size());
+        StringAppendF(&result, "Dumping buffer ids...\n");
+        for (const auto& [id, unused] : mProtectedTextureCache) {
+            StringAppendF(&result, "- 0x%" PRIx64 "\n", id);
+        }
+        StringAppendF(&result, "\n");
+        StringAppendF(&result, "RenderEngine runtime effects: %zu\n", mRuntimeEffects.size());
+        for (const auto& [linearEffect, unused] : mRuntimeEffects) {
+            StringAppendF(&result, "- inputDataspace: %s\n",
+                          dataspaceDetails(
+                                  static_cast<android_dataspace>(linearEffect.inputDataspace))
+                                  .c_str());
+            StringAppendF(&result, "- outputDataspace: %s\n",
+                          dataspaceDetails(
+                                  static_cast<android_dataspace>(linearEffect.outputDataspace))
+                                  .c_str());
+            StringAppendF(&result, "undoPremultipliedAlpha: %s\n",
+                          linearEffect.undoPremultipliedAlpha ? "true" : "false");
+        }
+    }
+    StringAppendF(&result, "\n");
+}
+
 } // namespace skia
 } // namespace renderengine
 } // namespace android
diff --git a/libs/renderengine/skia/SkiaGLRenderEngine.h b/libs/renderengine/skia/SkiaGLRenderEngine.h
index 3294de8..810fc2a 100644
--- a/libs/renderengine/skia/SkiaGLRenderEngine.h
+++ b/libs/renderengine/skia/SkiaGLRenderEngine.h
@@ -63,7 +63,7 @@
     bool useProtectedContext(bool useProtectedContext) override;
 
 protected:
-    void dump(std::string& /*result*/) override{};
+    void dump(std::string& result) override;
     size_t getMaxTextureSize() const override;
     size_t getMaxViewportDims() const override;
 
diff --git a/libs/renderengine/skia/debug/record.sh b/libs/renderengine/skia/debug/record.sh
new file mode 100755
index 0000000..bc406d9
--- /dev/null
+++ b/libs/renderengine/skia/debug/record.sh
@@ -0,0 +1,106 @@
+# This script captures MSKP files from RenderEngine in a connected device.
+# this only functions when RenderEngine uses the Skia backend.
+# it triggers code in SkiaCapture.cpp.
+
+# for a newly flashed device, perform first time steps with
+# record.sh rootandsetup
+
+# record all frames that RenderEngine handles over the span of 2 seconds.
+# record.sh 2000
+
+if [ -z "$1" ]; then
+    printf 'Usage:\n    record.sh rootandsetup\n'
+    printf '    record.sh MILLISECONDS\n\n'
+    exit 1
+elif [ "$1" == "rootandsetup" ]; then
+  # first time use requires these changes
+  adb root
+  adb shell setenforce 0
+  adb shell setprop debug.renderengine.backend "skiagl"
+  adb shell stop
+  adb shell start
+  exit 1;
+fi
+
+# name of the newest file in /data/user/ before starting
+oldname=$(adb shell ls -cr /data/user/ | head -n 1)
+
+# record frames for some number of milliseconds.
+adb shell setprop debug.renderengine.capture_skia_ms $1
+
+# give the device time to both record, and starting writing the file.
+# Total time needed to write the file depends on how much data was recorded.
+# the loop at the end waits for this.
+sleep $(($1 / 1000 + 2));
+
+# There is no guarantee that at least one frame passed through renderengine during that time
+# but as far as I know it always at least writes a 0-byte file with a new name, unless it crashes
+# the process it is recording.
+# /data/user/re_skiacapture_56204430551705.mskp
+
+# list the files here from newest to oldest, keep only the name of the newest.
+name=$(adb shell ls -cr /data/user/ | head -n 1)
+remote_path=/data/user/$name
+
+if [[ $oldname = $name ]]; then
+  echo "No new file written, probably no RenderEngine activity during recording period."
+  exit 1
+fi
+
+# return the size of a file in bytes
+adb_filesize() {
+    adb shell "wc -c \"$1\"" 2> /dev/null | awk '{print $1}'
+}
+
+mskp_size=$(adb_filesize "/data/user/$name")
+if [[ $mskp_size = "0" ]]; then
+  echo "Empty file, probably no RenderEngine activity during recording period."
+  exit 1
+fi
+
+spin() {
+    case "$spin" in
+         1) printf '\b|';;
+         2) printf '\b\\';;
+         3) printf '\b-';;
+         *) printf '\b/';;
+    esac
+    spin=$(( ( ${spin:-0} + 1 ) % 4 ))
+    sleep $1
+}
+
+printf "MSKP captured, Waiting for file serialization to finish.\n"
+
+local_path=~/Downloads/$name
+
+# wait for the file size to stop changing
+
+timeout=$(( $(date +%s) + 300))
+last_size='0' # output of last size check command
+unstable=true # false once the file size stops changing
+counter=0 # used to perform size check only 1/sec though we update spinner 20/sec
+# loop until the file size is unchanged for 1 second.
+while [ $unstable != 0 ] ; do
+    spin 0.05
+    counter=$(( $counter+1 ))
+    if ! (( $counter % 20)) ; then
+        new_size=$(adb_filesize "$remote_path")
+        unstable=$(($new_size != $last_size))
+        last_size=$new_size
+    fi
+    if [ $(date +%s) -gt $timeout ] ; then
+        printf '\bTimed out.\n'
+        exit 3
+    fi
+done
+printf '\b'
+
+printf "MSKP file serialized: %s\n" $(echo $last_size | numfmt --to=iec)
+
+adb pull "$remote_path" "$local_path"
+if ! [ -f "$local_path" ] ; then
+    printf "something went wrong with `adb pull`."
+    exit 4
+fi
+adb shell rm "$remote_path"
+printf 'SKP saved to %s\n\n' "$local_path"
\ No newline at end of file
diff --git a/libs/ui/Android.bp b/libs/ui/Android.bp
index 7c68aaa..714ee3e 100644
--- a/libs/ui/Android.bp
+++ b/libs/ui/Android.bp
@@ -140,7 +140,7 @@
         "android.hardware.graphics.allocator@2.0",
         "android.hardware.graphics.allocator@3.0",
         "android.hardware.graphics.allocator@4.0",
-        "android.hardware.graphics.common-unstable-ndk_platform",
+        "android.hardware.graphics.common-V2-ndk_platform",
         "android.hardware.graphics.common@1.2",
         "android.hardware.graphics.mapper@2.0",
         "android.hardware.graphics.mapper@2.1",
@@ -157,7 +157,7 @@
 
     export_shared_lib_headers: [
         "android.hardware.graphics.common@1.2",
-        "android.hardware.graphics.common-unstable-ndk_platform",
+        "android.hardware.graphics.common-V2-ndk_platform",
         "android.hardware.graphics.mapper@4.0",
         "libgralloctypes",
     ],
diff --git a/libs/ui/PublicFormat.cpp b/libs/ui/PublicFormat.cpp
index a6595cf..78e82da 100644
--- a/libs/ui/PublicFormat.cpp
+++ b/libs/ui/PublicFormat.cpp
@@ -100,6 +100,7 @@
         case HAL_PIXEL_FORMAT_RAW12:
         case HAL_PIXEL_FORMAT_YCbCr_420_888:
         case HAL_PIXEL_FORMAT_YV12:
+        case HAL_PIXEL_FORMAT_YCBCR_P010:
             // Enums overlap in both name and value
             return static_cast<PublicFormat>(format);
         case HAL_PIXEL_FORMAT_RAW16:
diff --git a/libs/ui/include/ui/PublicFormat.h b/libs/ui/include/ui/PublicFormat.h
index 22274a2..aa58805 100644
--- a/libs/ui/include/ui/PublicFormat.h
+++ b/libs/ui/include/ui/PublicFormat.h
@@ -54,6 +54,7 @@
     YV12 = 0x32315659,
     Y8 = 0x20203859,
     Y16 = 0x20363159, // @hide
+    YCBCR_P010 = 0x36,
     DEPTH16 = 0x44363159,
     DEPTH_JPEG = 0x69656963,
     HEIC = 0x48454946,
diff --git a/services/powermanager/Android.bp b/services/powermanager/Android.bp
index b5e6ae9..68f4f28 100644
--- a/services/powermanager/Android.bp
+++ b/services/powermanager/Android.bp
@@ -29,7 +29,7 @@
         "libutils",
         "android.hardware.power@1.0",
         "android.hardware.power@1.1",
-        "android.hardware.power-cpp",
+        "android.hardware.power-V1-cpp",
     ],
 
     cflags: [
diff --git a/services/powermanager/benchmarks/Android.bp b/services/powermanager/benchmarks/Android.bp
index 4c5d508..ad93a65 100644
--- a/services/powermanager/benchmarks/Android.bp
+++ b/services/powermanager/benchmarks/Android.bp
@@ -29,7 +29,7 @@
         "libutils",
         "android.hardware.power@1.0",
         "android.hardware.power@1.1",
-        "android.hardware.power-cpp",
+        "android.hardware.power-V1-cpp",
     ],
     static_libs: [
         "libtestUtil",
diff --git a/services/powermanager/tests/Android.bp b/services/powermanager/tests/Android.bp
index 49abc11..0f5037e 100644
--- a/services/powermanager/tests/Android.bp
+++ b/services/powermanager/tests/Android.bp
@@ -37,7 +37,7 @@
         "libutils",
         "android.hardware.power@1.0",
         "android.hardware.power@1.1",
-        "android.hardware.power-cpp",
+        "android.hardware.power-V1-cpp",
     ],
     static_libs: [
         "libgmock",
diff --git a/services/surfaceflinger/Android.bp b/services/surfaceflinger/Android.bp
index a7cd258..825626a 100644
--- a/services/surfaceflinger/Android.bp
+++ b/services/surfaceflinger/Android.bp
@@ -36,7 +36,7 @@
         "android.hardware.graphics.composer@2.4",
         "android.hardware.power@1.0",
         "android.hardware.power@1.3",
-        "android.hardware.power-cpp",
+        "android.hardware.power-V1-cpp",
         "libbase",
         "libbinder",
         "libcutils",
diff --git a/services/surfaceflinger/Layer.h b/services/surfaceflinger/Layer.h
index 4b40c8e..3930a81 100644
--- a/services/surfaceflinger/Layer.h
+++ b/services/surfaceflinger/Layer.h
@@ -904,7 +904,6 @@
     bool mPendingHWCDestroy{false};
 
     bool backpressureEnabled() { return mDrawingState.flags & layer_state_t::eEnableBackpressure; }
-    bool hasPendingBuffer() { return mCurrentState.buffer != mDrawingState.buffer; };
 
 protected:
     class SyncPoint {
diff --git a/services/surfaceflinger/SurfaceFlinger.cpp b/services/surfaceflinger/SurfaceFlinger.cpp
index e9b5875..cf7d1e1 100644
--- a/services/surfaceflinger/SurfaceFlinger.cpp
+++ b/services/surfaceflinger/SurfaceFlinger.cpp
@@ -3291,66 +3291,75 @@
     // we must keep a copy of the transactions (specifically the composer
     // states) around outside the scope of the lock
     std::vector<const TransactionState> transactions;
+    // Layer handles that have transactions with buffers that are ready to be applied.
+    std::unordered_set<sp<IBinder>, ISurfaceComposer::SpHash<IBinder>> pendingBuffers;
     {
-        Mutex::Autolock _l(mQueueLock);
-        // Collect transactions from pending transaction queue.
-        auto it = mPendingTransactionQueues.begin();
-        while (it != mPendingTransactionQueues.end()) {
-            auto& [applyToken, transactionQueue] = *it;
+        Mutex::Autolock _l(mStateLock);
+        {
+            Mutex::Autolock _l(mQueueLock);
+            // Collect transactions from pending transaction queue.
+            auto it = mPendingTransactionQueues.begin();
+            while (it != mPendingTransactionQueues.end()) {
+                auto& [applyToken, transactionQueue] = *it;
 
-            while (!transactionQueue.empty()) {
-                const auto& transaction = transactionQueue.front();
+                while (!transactionQueue.empty()) {
+                    const auto& transaction = transactionQueue.front();
+                    if (!transactionIsReadyToBeApplied(transaction.isAutoTimestamp,
+                                                       transaction.desiredPresentTime,
+                                                       transaction.states,
+                                                       false /* updateTransactionCounters*/,
+                                                       pendingBuffers)) {
+                        setTransactionFlags(eTransactionFlushNeeded);
+                        break;
+                    }
+                    transactions.push_back(transaction);
+                    transactionQueue.pop();
+                }
+
+                if (transactionQueue.empty()) {
+                    it = mPendingTransactionQueues.erase(it);
+                    mTransactionQueueCV.broadcast();
+                } else {
+                    it = std::next(it, 1);
+                }
+            }
+
+            // Collect transactions from current transaction queue or queue to pending transactions.
+            // Case 1: push to pending when transactionIsReadyToBeApplied is false.
+            // Case 2: push to pending when there exist a pending queue.
+            // Case 3: others are ready to apply.
+            while (!mTransactionQueue.empty()) {
+                const auto& transaction = mTransactionQueue.front();
+                bool pendingTransactions = mPendingTransactionQueues.find(transaction.applyToken) !=
+                        mPendingTransactionQueues.end();
+                // Call transactionIsReadyToBeApplied first in case we need to
+                // incrementPendingBufferCount and keep track of pending buffers
+                // if the transaction contains a buffer.
                 if (!transactionIsReadyToBeApplied(transaction.isAutoTimestamp,
                                                    transaction.desiredPresentTime,
-                                                   transaction.states)) {
-                    setTransactionFlags(eTransactionFlushNeeded);
-                    break;
+                                                   transaction.states,
+                                                   true /* updateTransactionCounters */,
+                                                   pendingBuffers) ||
+                    pendingTransactions) {
+                    mPendingTransactionQueues[transaction.applyToken].push(transaction);
+                } else {
+                    transactions.push_back(transaction);
                 }
-                transactions.push_back(transaction);
-                transactionQueue.pop();
-            }
-
-            if (transactionQueue.empty()) {
-                it = mPendingTransactionQueues.erase(it);
-                mTransactionQueueCV.broadcast();
-            } else {
-                it = std::next(it, 1);
+                mTransactionQueue.pop();
             }
         }
 
-        // Collect transactions from current transaction queue or queue to pending transactions.
-        // Case 1: push to pending when transactionIsReadyToBeApplied is false.
-        // Case 2: push to pending when there exist a pending queue.
-        // Case 3: others are ready to apply.
-        while (!mTransactionQueue.empty()) {
-            const auto& transaction = mTransactionQueue.front();
-            bool pendingTransactions = mPendingTransactionQueues.find(transaction.applyToken) !=
-                    mPendingTransactionQueues.end();
-            // Call transactionIsReadyToBeApplied first in case we need to
-            // incrementPendingBufferCount if the transaction contains a buffer.
-            if (!transactionIsReadyToBeApplied(transaction.isAutoTimestamp,
-                                               transaction.desiredPresentTime, transaction.states,
-                                               true) ||
-                pendingTransactions) {
-                mPendingTransactionQueues[transaction.applyToken].push(transaction);
-            } else {
-                transactions.push_back(transaction);
-            }
-            mTransactionQueue.pop();
+        // Now apply all transactions.
+        for (const auto& transaction : transactions) {
+            applyTransactionState(transaction.frameTimelineInfo, transaction.states,
+                                  transaction.displays, transaction.flags,
+                                  transaction.inputWindowCommands, transaction.desiredPresentTime,
+                                  transaction.isAutoTimestamp, transaction.buffer,
+                                  transaction.postTime, transaction.privileged,
+                                  transaction.hasListenerCallbacks, transaction.listenerCallbacks,
+                                  transaction.originPid, transaction.originUid, transaction.id);
         }
     }
-
-    // Now apply all transactions.
-    Mutex::Autolock _l(mStateLock);
-    for (const auto& transaction : transactions) {
-        applyTransactionState(transaction.frameTimelineInfo, transaction.states,
-                              transaction.displays, transaction.flags,
-                              transaction.inputWindowCommands, transaction.desiredPresentTime,
-                              transaction.isAutoTimestamp, transaction.buffer, transaction.postTime,
-                              transaction.privileged, transaction.hasListenerCallbacks,
-                              transaction.listenerCallbacks, transaction.originPid,
-                              transaction.originUid, transaction.id);
-    }
 }
 
 bool SurfaceFlinger::transactionFlushNeeded() {
@@ -3358,9 +3367,10 @@
     return !mPendingTransactionQueues.empty();
 }
 
-bool SurfaceFlinger::transactionIsReadyToBeApplied(bool isAutoTimestamp, int64_t desiredPresentTime,
-                                                   const Vector<ComposerState>& states,
-                                                   bool updateTransactionCounters) {
+bool SurfaceFlinger::transactionIsReadyToBeApplied(
+        bool isAutoTimestamp, int64_t desiredPresentTime, const Vector<ComposerState>& states,
+        bool updateTransactionCounters,
+        std::unordered_set<sp<IBinder>, ISurfaceComposer::SpHash<IBinder>>& pendingBuffers) {
     const nsecs_t expectedPresentTime = mExpectedPresentTime.load();
     bool ready = true;
     // Do not present if the desiredPresentTime has not passed unless it is more than one second
@@ -3379,7 +3389,6 @@
             ready = false;
         }
 
-        Mutex::Autolock _l(mStateLock);
         sp<Layer> layer = nullptr;
         if (s.surface) {
             layer = fromHandleLocked(s.surface).promote();
@@ -3402,12 +3411,11 @@
 
         // If backpressure is enabled and we already have a buffer to commit, keep the transaction
         // in the queue.
-        bool hasBuffer = s.what & layer_state_t::eBufferChanged ||
-                s.what & layer_state_t::eCachedBufferChanged;
-        if (hasBuffer && layer->backpressureEnabled() && layer->hasPendingBuffer() &&
-            isAutoTimestamp) {
+        const bool hasPendingBuffer = pendingBuffers.find(s.surface) != pendingBuffers.end();
+        if (layer->backpressureEnabled() && hasPendingBuffer && isAutoTimestamp) {
             ready = false;
         }
+        pendingBuffers.insert(s.surface);
     }
     return ready;
 }
diff --git a/services/surfaceflinger/SurfaceFlinger.h b/services/surfaceflinger/SurfaceFlinger.h
index 66fc4f0..400345f 100644
--- a/services/surfaceflinger/SurfaceFlinger.h
+++ b/services/surfaceflinger/SurfaceFlinger.h
@@ -760,9 +760,11 @@
     uint32_t setTransactionFlags(uint32_t flags, TransactionSchedule);
     void commitTransaction() REQUIRES(mStateLock);
     void commitOffscreenLayers();
-    bool transactionIsReadyToBeApplied(bool isAutoTimestamp, int64_t desiredPresentTime,
-                                       const Vector<ComposerState>& states,
-                                       bool updateTransactionCounters = false);
+    bool transactionIsReadyToBeApplied(
+            bool isAutoTimestamp, int64_t desiredPresentTime, const Vector<ComposerState>& states,
+            bool updateTransactionCounters,
+            std::unordered_set<sp<IBinder>, ISurfaceComposer::SpHash<IBinder>>& pendingBuffers)
+            REQUIRES(mStateLock);
     uint32_t setDisplayStateLocked(const DisplayState& s) REQUIRES(mStateLock);
     uint32_t addInputWindowCommands(const InputWindowCommands& inputWindowCommands)
             REQUIRES(mStateLock);
diff --git a/services/surfaceflinger/tests/Android.bp b/services/surfaceflinger/tests/Android.bp
index cfaf229..8142aad 100644
--- a/services/surfaceflinger/tests/Android.bp
+++ b/services/surfaceflinger/tests/Android.bp
@@ -49,7 +49,7 @@
         "android.hardware.graphics.composer@2.1",
     ],
     shared_libs: [
-        "android.hardware.graphics.common-unstable-ndk_platform",
+        "android.hardware.graphics.common-V2-ndk_platform",
         "android.hardware.graphics.common@1.2",
         "libandroid",
         "libbase",
diff --git a/services/surfaceflinger/tests/unittests/Android.bp b/services/surfaceflinger/tests/unittests/Android.bp
index 13b26fc..9b29b70 100644
--- a/services/surfaceflinger/tests/unittests/Android.bp
+++ b/services/surfaceflinger/tests/unittests/Android.bp
@@ -124,7 +124,7 @@
         "android.hardware.graphics.allocator@2.0",
         "android.hardware.graphics.allocator@3.0",
         "android.hardware.graphics.common@1.2",
-        "android.hardware.power-cpp",
+        "android.hardware.power-V1-cpp",
         "libbase",
         "libbinder",
         "libcutils",
diff --git a/services/vibratorservice/Android.bp b/services/vibratorservice/Android.bp
index c18bf18..4f89353 100644
--- a/services/vibratorservice/Android.bp
+++ b/services/vibratorservice/Android.bp
@@ -36,7 +36,7 @@
         "libhidlbase",
         "liblog",
         "libutils",
-        "android.hardware.vibrator-unstable-cpp",
+        "android.hardware.vibrator-V2-cpp",
         "android.hardware.vibrator@1.0",
         "android.hardware.vibrator@1.1",
         "android.hardware.vibrator@1.2",
diff --git a/services/vibratorservice/benchmarks/Android.bp b/services/vibratorservice/benchmarks/Android.bp
index d3130f4..7b4cc19 100644
--- a/services/vibratorservice/benchmarks/Android.bp
+++ b/services/vibratorservice/benchmarks/Android.bp
@@ -23,7 +23,7 @@
         "liblog",
         "libutils",
         "libvibratorservice",
-        "android.hardware.vibrator-unstable-cpp",
+        "android.hardware.vibrator-V2-cpp",
         "android.hardware.vibrator@1.0",
         "android.hardware.vibrator@1.1",
         "android.hardware.vibrator@1.2",
diff --git a/services/vibratorservice/test/Android.bp b/services/vibratorservice/test/Android.bp
index 9af1b7b..ad85990 100644
--- a/services/vibratorservice/test/Android.bp
+++ b/services/vibratorservice/test/Android.bp
@@ -39,7 +39,7 @@
         "liblog",
         "libvibratorservice",
         "libutils",
-        "android.hardware.vibrator-unstable-cpp",
+        "android.hardware.vibrator-V2-cpp",
         "android.hardware.vibrator@1.0",
         "android.hardware.vibrator@1.1",
         "android.hardware.vibrator@1.2",
diff --git a/vulkan/libvulkan/swapchain.cpp b/vulkan/libvulkan/swapchain.cpp
index 48090af..cb845a0 100644
--- a/vulkan/libvulkan/swapchain.cpp
+++ b/vulkan/libvulkan/swapchain.cpp
@@ -606,44 +606,9 @@
 VKAPI_ATTR
 VkResult GetPhysicalDeviceSurfaceSupportKHR(VkPhysicalDevice /*pdev*/,
                                             uint32_t /*queue_family*/,
-                                            VkSurfaceKHR surface_handle,
+                                            VkSurfaceKHR /*surface_handle*/,
                                             VkBool32* supported) {
-    ATRACE_CALL();
-
-    const Surface* surface = SurfaceFromHandle(surface_handle);
-    if (!surface) {
-        return VK_ERROR_SURFACE_LOST_KHR;
-    }
-    const ANativeWindow* window = surface->window.get();
-
-    int query_value;
-    int err = window->query(window, NATIVE_WINDOW_FORMAT, &query_value);
-    if (err != android::OK || query_value < 0) {
-        ALOGE("NATIVE_WINDOW_FORMAT query failed: %s (%d) value=%d",
-              strerror(-err), err, query_value);
-        return VK_ERROR_SURFACE_LOST_KHR;
-    }
-
-    android_pixel_format native_format =
-        static_cast<android_pixel_format>(query_value);
-
-    bool format_supported = false;
-    switch (native_format) {
-        case HAL_PIXEL_FORMAT_RGBA_8888:
-        case HAL_PIXEL_FORMAT_RGB_565:
-        case HAL_PIXEL_FORMAT_RGBA_FP16:
-        case HAL_PIXEL_FORMAT_RGBA_1010102:
-            format_supported = true;
-            break;
-        default:
-            break;
-    }
-
-    *supported = static_cast<VkBool32>(
-        format_supported || (surface->consumer_usage &
-                             (AHARDWAREBUFFER_USAGE_CPU_READ_MASK |
-                              AHARDWAREBUFFER_USAGE_CPU_WRITE_MASK)) == 0);
-
+    *supported = VK_TRUE;
     return VK_SUCCESS;
 }