Merge "SF: Dev Options should force client composition for all frames"
diff --git a/PREUPLOAD.cfg b/PREUPLOAD.cfg
index 4f7cdf3..3fa5430 100644
--- a/PREUPLOAD.cfg
+++ b/PREUPLOAD.cfg
@@ -5,6 +5,7 @@
 # Only turn on clang-format check for the following subfolders.
 clang_format = --commit ${PREUPLOAD_COMMIT} --style file --extensions c,h,cc,cpp
                include/input/
+               libs/binder/fuzzer/
                libs/binder/ndk/
                libs/graphicsenv/
                libs/gui/
diff --git a/libs/binder/IServiceManager.cpp b/libs/binder/IServiceManager.cpp
index ee637e2..4bea2179 100644
--- a/libs/binder/IServiceManager.cpp
+++ b/libs/binder/IServiceManager.cpp
@@ -43,6 +43,17 @@
 using AidlServiceManager = android::os::IServiceManager;
 using android::binder::Status;
 
+// libbinder's IServiceManager.h can't rely on the values generated by AIDL
+// because many places use its headers via include_dirs (meaning, without
+// declaring the dependency in the build system). So, for now, we can just check
+// the values here.
+static_assert(AidlServiceManager::DUMP_FLAG_PRIORITY_CRITICAL == IServiceManager::DUMP_FLAG_PRIORITY_CRITICAL);
+static_assert(AidlServiceManager::DUMP_FLAG_PRIORITY_HIGH == IServiceManager::DUMP_FLAG_PRIORITY_HIGH);
+static_assert(AidlServiceManager::DUMP_FLAG_PRIORITY_NORMAL == IServiceManager::DUMP_FLAG_PRIORITY_NORMAL);
+static_assert(AidlServiceManager::DUMP_FLAG_PRIORITY_DEFAULT == IServiceManager::DUMP_FLAG_PRIORITY_DEFAULT);
+static_assert(AidlServiceManager::DUMP_FLAG_PRIORITY_ALL == IServiceManager::DUMP_FLAG_PRIORITY_ALL);
+static_assert(AidlServiceManager::DUMP_FLAG_PROTO == IServiceManager::DUMP_FLAG_PROTO);
+
 sp<IServiceManager> defaultServiceManager()
 {
     static Mutex gDefaultServiceManagerLock;
diff --git a/libs/binder/fuzzer/Android.bp b/libs/binder/fuzzer/Android.bp
index f3e4229..d2f0d37 100644
--- a/libs/binder/fuzzer/Android.bp
+++ b/libs/binder/fuzzer/Android.bp
@@ -1,8 +1,10 @@
 cc_fuzz {
     name: "binder_parcel_fuzzer",
+    defaults: ["libbinder_ndk_host_user"],
     host_supported: true,
     srcs: [
         "binder.cpp",
+        "binder_ndk.cpp",
         "hwbinder.cpp",
         "main.cpp",
         "util.cpp",
@@ -22,10 +24,16 @@
 
     target: {
         android: {
-            shared_libs: ["libbinder"],
+            shared_libs: [
+                "libbinder_ndk",
+                "libbinder",
+            ],
         },
         host: {
-            static_libs: ["libbinder"],
+            static_libs: [
+                "libbinder_ndk",
+                "libbinder",
+            ],
         },
     },
 }
diff --git a/libs/binder/fuzzer/binder.h b/libs/binder/fuzzer/binder.h
index 32dcc79..b224ef4 100644
--- a/libs/binder/fuzzer/binder.h
+++ b/libs/binder/fuzzer/binder.h
@@ -17,6 +17,6 @@
 #include <binder/Parcel.h>
 #include <vector>
 
-#include "parcel.h"
+#include "parcel_fuzzer.h"
 
 extern std::vector<ParcelRead<::android::Parcel>> BINDER_PARCEL_READ_FUNCTIONS;
diff --git a/libs/binder/fuzzer/binder_ndk.cpp b/libs/binder/fuzzer/binder_ndk.cpp
new file mode 100644
index 0000000..29da8f7
--- /dev/null
+++ b/libs/binder/fuzzer/binder_ndk.cpp
@@ -0,0 +1,98 @@
+/*
+ * Copyright (C) 2019 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.
+ */
+#define FUZZ_LOG_TAG "binder_ndk"
+
+#include "binder_ndk.h"
+
+#include <android/binder_parcel_utils.h>
+
+#include "util.h"
+
+// TODO(b/142061461): parent class
+class SomeParcelable {
+public:
+    binder_status_t readFromParcel(const AParcel* parcel) {
+        return AParcel_readInt32(parcel, &mValue);
+    }
+
+private:
+    int32_t mValue = 0;
+};
+
+#define PARCEL_READ(T, FUN)                                              \
+    [](const NdkParcelAdapter& p, uint8_t /*data*/) {                    \
+        FUZZ_LOG() << "about to read " #T " using " #FUN " with status"; \
+        T t{};                                                           \
+        binder_status_t status = FUN(p.aParcel(), &t);                   \
+        FUZZ_LOG() << #T " status: " << status /* << " value: " << t*/;  \
+    }
+
+// clang-format off
+std::vector<ParcelRead<NdkParcelAdapter>> BINDER_NDK_PARCEL_READ_FUNCTIONS{
+        // methods from binder_parcel.h
+        [](const NdkParcelAdapter& p, uint8_t pos) {
+            FUZZ_LOG() << "about to set data position to " << pos;
+            binder_status_t status = AParcel_setDataPosition(p.aParcel(), pos);
+            FUZZ_LOG() << "set data position: " << status;
+        },
+        [](const NdkParcelAdapter& p, uint8_t /*data*/) {
+            FUZZ_LOG() << "about to read status header";
+            ndk::ScopedAStatus t;
+            binder_status_t status = AParcel_readStatusHeader(p.aParcel(), t.getR());
+            FUZZ_LOG() << "read status header: " << status;
+        },
+        PARCEL_READ(int32_t, AParcel_readInt32),
+        PARCEL_READ(uint32_t, AParcel_readUint32),
+        PARCEL_READ(int64_t, AParcel_readInt64),
+        PARCEL_READ(uint64_t, AParcel_readUint64),
+        PARCEL_READ(float, AParcel_readFloat),
+        PARCEL_READ(double, AParcel_readDouble),
+        PARCEL_READ(bool, AParcel_readBool),
+        PARCEL_READ(char16_t, AParcel_readChar),
+        PARCEL_READ(int8_t, AParcel_readByte),
+
+        // methods from binder_parcel_utils.h
+        PARCEL_READ(ndk::SpAIBinder, ndk::AParcel_readNullableStrongBinder),
+        PARCEL_READ(ndk::SpAIBinder, ndk::AParcel_readRequiredStrongBinder),
+        PARCEL_READ(ndk::ScopedFileDescriptor, ndk::AParcel_readNullableParcelFileDescriptor),
+        PARCEL_READ(ndk::ScopedFileDescriptor, ndk::AParcel_readRequiredParcelFileDescriptor),
+        PARCEL_READ(std::string, ndk::AParcel_readString),
+        PARCEL_READ(std::optional<std::string>, ndk::AParcel_readString),
+        // TODO(b/131868573): can force process to allocate arbitrary amount of
+        // memory
+        // PARCEL_READ(std::vector<std::string>, ndk::AParcel_readVector),
+        // PARCEL_READ(std::optional<std::vector<std::optional<std::string>>>,
+        // ndk::AParcel_readVector), PARCEL_READ(std::vector<SomeParcelable>,
+        // ndk::AParcel_readVector), PARCEL_READ(std::vector<int32_t>, ndk::AParcel_readVector),
+        // PARCEL_READ(std::optional<std::vector<int32_t>>, ndk::AParcel_readVector),
+        // PARCEL_READ(std::vector<uint32_t>, ndk::AParcel_readVector),
+        // PARCEL_READ(std::optional<std::vector<uint32_t>>, ndk::AParcel_readVector),
+        // PARCEL_READ(std::vector<int64_t>, ndk::AParcel_readVector),
+        // PARCEL_READ(std::optional<std::vector<int64_t>>, ndk::AParcel_readVector),
+        // PARCEL_READ(std::vector<uint64_t>, ndk::AParcel_readVector),
+        // PARCEL_READ(std::optional<std::vector<uint64_t>>, ndk::AParcel_readVector),
+        // PARCEL_READ(std::vector<float>, ndk::AParcel_readVector),
+        // PARCEL_READ(std::optional<std::vector<float>>, ndk::AParcel_readVector),
+        // PARCEL_READ(std::vector<double>, ndk::AParcel_readVector),
+        // PARCEL_READ(std::optional<std::vector<double>>, ndk::AParcel_readVector),
+        // PARCEL_READ(std::vector<bool>, ndk::AParcel_readVector),
+        // PARCEL_READ(std::optional<std::vector<bool>>, ndk::AParcel_readVector),
+        // PARCEL_READ(std::vector<char16_t>, ndk::AParcel_readVector),
+        // PARCEL_READ(std::optional<std::vector<char16_t>>, ndk::AParcel_readVector),
+        // PARCEL_READ(std::vector<int32_t>, ndk::AParcel_resizeVector),
+        // PARCEL_READ(std::optional<std::vector<int32_t>>, ndk::AParcel_resizeVector),
+};
+// clang-format on
diff --git a/libs/binder/fuzzer/binder_ndk.h b/libs/binder/fuzzer/binder_ndk.h
new file mode 100644
index 0000000..622cafc
--- /dev/null
+++ b/libs/binder/fuzzer/binder_ndk.h
@@ -0,0 +1,46 @@
+/*
+ * Copyright (C) 2019 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 <android/binder_auto_utils.h>
+#include <vector>
+
+#include <android/binder_parcel.h>
+#include "parcel_fuzzer.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/parcel_internal.h"
+
+class NdkParcelAdapter {
+public:
+    NdkParcelAdapter() : mParcel(new AParcel(nullptr /*binder*/)) {}
+
+    const AParcel* aParcel() const { return mParcel.get(); }
+    AParcel* aParcel() { return mParcel.get(); }
+
+    size_t dataSize() const { return aParcel()->get()->dataSize(); }
+    size_t dataAvail() const { return aParcel()->get()->dataAvail(); }
+    size_t dataPosition() const { return aParcel()->get()->dataPosition(); }
+    size_t dataCapacity() const { return aParcel()->get()->dataCapacity(); }
+    android::status_t setData(const uint8_t* buffer, size_t len) {
+        return aParcel()->get()->setData(buffer, len);
+    }
+
+private:
+    ndk::ScopedAParcel mParcel;
+};
+
+extern std::vector<ParcelRead<NdkParcelAdapter>> BINDER_NDK_PARCEL_READ_FUNCTIONS;
diff --git a/libs/binder/fuzzer/hwbinder.h b/libs/binder/fuzzer/hwbinder.h
index 03ab510..a6c66be 100644
--- a/libs/binder/fuzzer/hwbinder.h
+++ b/libs/binder/fuzzer/hwbinder.h
@@ -17,6 +17,6 @@
 #include <hwbinder/Parcel.h>
 #include <vector>
 
-#include "parcel.h"
+#include "parcel_fuzzer.h"
 
 extern std::vector<ParcelRead<::android::hardware::Parcel>> HWBINDER_PARCEL_READ_FUNCTIONS;
diff --git a/libs/binder/fuzzer/main.cpp b/libs/binder/fuzzer/main.cpp
index 03fde3a..369aa34 100644
--- a/libs/binder/fuzzer/main.cpp
+++ b/libs/binder/fuzzer/main.cpp
@@ -16,6 +16,7 @@
 #define FUZZ_LOG_TAG "main"
 
 #include "binder.h"
+#include "binder_ndk.h"
 #include "hwbinder.h"
 #include "util.h"
 
@@ -50,6 +51,7 @@
     // although they will do completely different things, might as well fuzz both
     doFuzz<::android::hardware::Parcel>(HWBINDER_PARCEL_READ_FUNCTIONS, input, instructions);
     doFuzz<::android::Parcel>(BINDER_PARCEL_READ_FUNCTIONS, input, instructions);
+    doFuzz<NdkParcelAdapter>(BINDER_NDK_PARCEL_READ_FUNCTIONS, input, instructions);
 }
 
 extern "C" int LLVMFuzzerTestOneInput(const uint8_t* data, size_t size) {
diff --git a/libs/binder/fuzzer/parcel.h b/libs/binder/fuzzer/parcel_fuzzer.h
similarity index 99%
rename from libs/binder/fuzzer/parcel.h
rename to libs/binder/fuzzer/parcel_fuzzer.h
index 5f05335..10cf17c 100644
--- a/libs/binder/fuzzer/parcel.h
+++ b/libs/binder/fuzzer/parcel_fuzzer.h
@@ -16,5 +16,3 @@
 
 template <typename P>
 using ParcelRead = std::function<void(const P& p, uint8_t data)>;
-
-
diff --git a/libs/binder/include/binder/IServiceManager.h b/libs/binder/include/binder/IServiceManager.h
index def1bea..cd63a58 100644
--- a/libs/binder/include/binder/IServiceManager.h
+++ b/libs/binder/include/binder/IServiceManager.h
@@ -31,7 +31,7 @@
 public:
     DECLARE_META_INTERFACE(ServiceManager)
     /**
-     * Must match values in IServiceManager.java
+     * Must match values in IServiceManager.aidl
      */
     /* Allows services to dump sections according to priorities. */
     static const int DUMP_FLAG_PRIORITY_CRITICAL = 1 << 0;
diff --git a/libs/binder/ndk/Android.bp b/libs/binder/ndk/Android.bp
index 62a0f9f..22344b6 100644
--- a/libs/binder/ndk/Android.bp
+++ b/libs/binder/ndk/Android.bp
@@ -27,7 +27,7 @@
     },
 }
 
-cc_library_shared {
+cc_library {
     name: "libbinder_ndk",
 
     defaults: ["libbinder_ndk_host_user"],
@@ -69,6 +69,12 @@
     ],
 
     target: {
+        android: {
+            // Only one copy of this library on an Android device
+            static: {
+                enabled: false,
+            },
+        },
         linux: {
             version_script: "libbinder_ndk.map.txt",
         },
diff --git a/libs/vr/libvrflinger/Android.bp b/libs/vr/libvrflinger/Android.bp
index 2053344..04493f0 100644
--- a/libs/vr/libvrflinger/Android.bp
+++ b/libs/vr/libvrflinger/Android.bp
@@ -40,6 +40,7 @@
     "android.hardware.graphics.composer@2.1",
     "android.hardware.graphics.composer@2.2",
     "android.hardware.graphics.composer@2.3",
+    "android.hardware.graphics.composer@2.4",
     "libbinder",
     "libbase",
     "libbufferhubqueue",
diff --git a/services/inputflinger/reader/Android.bp b/services/inputflinger/reader/Android.bp
index a64f4dd..3c16070 100644
--- a/services/inputflinger/reader/Android.bp
+++ b/services/inputflinger/reader/Android.bp
@@ -50,6 +50,7 @@
 
     shared_libs: [
         "libbase",
+        "libcap",
         "libinputflinger_base",
         "libcrypto",
         "libcutils",
diff --git a/services/inputflinger/reader/EventHub.cpp b/services/inputflinger/reader/EventHub.cpp
index efe3809..c8da0ab 100644
--- a/services/inputflinger/reader/EventHub.cpp
+++ b/services/inputflinger/reader/EventHub.cpp
@@ -24,6 +24,7 @@
 #include <stdio.h>
 #include <stdlib.h>
 #include <string.h>
+#include <sys/capability.h>
 #include <sys/epoll.h>
 #include <sys/inotify.h>
 #include <sys/ioctl.h>
@@ -237,6 +238,47 @@
     return !isVirtual && enabled;
 }
 
+/**
+ * Get the capabilities for the current process.
+ * Crashes the system if unable to create / check / destroy the capabilities object.
+ */
+class Capabilities final {
+public:
+    explicit Capabilities() {
+        mCaps = cap_get_proc();
+        LOG_ALWAYS_FATAL_IF(mCaps == nullptr, "Could not get capabilities of the current process");
+    }
+
+    /**
+     * Check whether the current process has a specific capability
+     * in the set of effective capabilities.
+     * Return CAP_SET if the process has the requested capability
+     * Return CAP_CLEAR otherwise.
+     */
+    cap_flag_value_t checkEffectiveCapability(cap_value_t capability) {
+        cap_flag_value_t value;
+        const int result = cap_get_flag(mCaps, capability, CAP_EFFECTIVE, &value);
+        LOG_ALWAYS_FATAL_IF(result == -1, "Could not obtain the requested capability");
+        return value;
+    }
+
+    ~Capabilities() {
+        const int result = cap_free(mCaps);
+        LOG_ALWAYS_FATAL_IF(result == -1, "Could not release the capabilities structure");
+    }
+
+private:
+    cap_t mCaps;
+};
+
+static void ensureProcessCanBlockSuspend() {
+    Capabilities capabilities;
+    const bool canBlockSuspend =
+            capabilities.checkEffectiveCapability(CAP_BLOCK_SUSPEND) == CAP_SET;
+    LOG_ALWAYS_FATAL_IF(!canBlockSuspend,
+                        "Input must be able to block suspend to properly process events");
+}
+
 // --- EventHub ---
 
 const int EventHub::EPOLL_MAX_EVENTS;
@@ -253,6 +295,7 @@
         mPendingEventCount(0),
         mPendingEventIndex(0),
         mPendingINotify(false) {
+    ensureProcessCanBlockSuspend();
     acquire_wake_lock(PARTIAL_WAKE_LOCK, WAKE_LOCK_ID);
 
     mEpollFd = epoll_create1(EPOLL_CLOEXEC);
diff --git a/services/surfaceflinger/Android.bp b/services/surfaceflinger/Android.bp
index b404836..213a62e 100644
--- a/services/surfaceflinger/Android.bp
+++ b/services/surfaceflinger/Android.bp
@@ -29,6 +29,7 @@
         "android.hardware.graphics.composer@2.1",
         "android.hardware.graphics.composer@2.2",
         "android.hardware.graphics.composer@2.3",
+        "android.hardware.graphics.composer@2.4",
         "android.hardware.power@1.0",
         "android.hardware.power@1.3",
         "libbase",
@@ -92,6 +93,7 @@
         "android.hardware.graphics.composer@2.1",
         "android.hardware.graphics.composer@2.2",
         "android.hardware.graphics.composer@2.3",
+        "android.hardware.graphics.composer@2.4",
         "android.hardware.power@1.3",
         "libhidlbase",
     ],
diff --git a/services/surfaceflinger/CompositionEngine/Android.bp b/services/surfaceflinger/CompositionEngine/Android.bp
index 1407ef7..738a2a4 100644
--- a/services/surfaceflinger/CompositionEngine/Android.bp
+++ b/services/surfaceflinger/CompositionEngine/Android.bp
@@ -11,6 +11,7 @@
         "android.hardware.graphics.composer@2.1",
         "android.hardware.graphics.composer@2.2",
         "android.hardware.graphics.composer@2.3",
+        "android.hardware.graphics.composer@2.4",
         "android.hardware.power@1.0",
         "android.hardware.power@1.3",
         "libbase",
diff --git a/services/surfaceflinger/DisplayHardware/ComposerHal.cpp b/services/surfaceflinger/DisplayHardware/ComposerHal.cpp
index e53d099..acddc42 100644
--- a/services/surfaceflinger/DisplayHardware/ComposerHal.cpp
+++ b/services/surfaceflinger/DisplayHardware/ComposerHal.cpp
@@ -17,9 +17,11 @@
 #undef LOG_TAG
 #define LOG_TAG "HwcComposer"
 
-#include <inttypes.h>
 #include <log/log.h>
 
+#include <algorithm>
+#include <cinttypes>
+
 #include "ComposerHal.h"
 
 #include <composer-command-buffer/2.2/ComposerCommandBuffer.h>
@@ -173,7 +175,16 @@
         LOG_ALWAYS_FATAL("failed to get hwcomposer service");
     }
 
-    if (sp<IComposer> composer_2_3 = IComposer::castFrom(mComposer)) {
+    if (sp<IComposer> composer_2_4 = IComposer::castFrom(mComposer)) {
+        composer_2_4->createClient_2_4([&](const auto& tmpError, const auto& tmpClient) {
+            if (tmpError == Error::NONE) {
+                mClient = tmpClient;
+                mClient_2_2 = tmpClient;
+                mClient_2_3 = tmpClient;
+                mClient_2_4 = tmpClient;
+            }
+        });
+    } else if (sp<V2_3::IComposer> composer_2_3 = V2_3::IComposer::castFrom(mComposer)) {
         composer_2_3->createClient_2_3([&](const auto& tmpError, const auto& tmpClient) {
             if (tmpError == Error::NONE) {
                 mClient = tmpClient;
@@ -456,23 +467,6 @@
     return Error::NONE;
 }
 
-Error Composer::getDisplayType(Display display,
-        IComposerClient::DisplayType* outType)
-{
-    Error error = kDefaultError;
-    mClient->getDisplayType(display,
-            [&](const auto& tmpError, const auto& tmpType) {
-                error = tmpError;
-                if (error != Error::NONE) {
-                    return;
-                }
-
-                *outType = tmpType;
-            });
-
-    return error;
-}
-
 Error Composer::getDozeSupport(Display display, bool* outSupport)
 {
     Error error = kDefaultError;
@@ -1113,23 +1107,6 @@
     return error;
 }
 
-Error Composer::getDisplayCapabilities(Display display,
-                                       std::vector<DisplayCapability>* outCapabilities) {
-    if (!mClient_2_3) {
-        return Error::UNSUPPORTED;
-    }
-    Error error = kDefaultError;
-    mClient_2_3->getDisplayCapabilities(display,
-                                        [&](const auto& tmpError, const auto& tmpCapabilities) {
-                                            error = tmpError;
-                                            if (error != Error::NONE) {
-                                                return;
-                                            }
-                                            *outCapabilities = tmpCapabilities;
-                                        });
-    return error;
-}
-
 Error Composer::setDisplayContentSamplingEnabled(Display display, bool enabled,
                                                  uint8_t componentMask, uint64_t maxFrames) {
     if (!mClient_2_3) {
@@ -1187,6 +1164,60 @@
     return mClient_2_3->setDisplayBrightness(display, brightness);
 }
 
+// Composer HAL 2.4
+
+Error Composer::getDisplayCapabilities(Display display,
+                                       std::vector<DisplayCapability>* outCapabilities) {
+    if (!mClient_2_3) {
+        return Error::UNSUPPORTED;
+    }
+
+    Error error = kDefaultError;
+    if (mClient_2_4) {
+        mClient_2_4->getDisplayCapabilities_2_4(display,
+                                                [&](const auto& tmpError, const auto& tmpCaps) {
+                                                    error = tmpError;
+                                                    if (error != Error::NONE) {
+                                                        return;
+                                                    }
+                                                    *outCapabilities = tmpCaps;
+                                                });
+    } else {
+        mClient_2_3
+                ->getDisplayCapabilities(display, [&](const auto& tmpError, const auto& tmpCaps) {
+                    error = tmpError;
+                    if (error != Error::NONE) {
+                        return;
+                    }
+
+                    outCapabilities->resize(tmpCaps.size());
+                    std::transform(tmpCaps.begin(), tmpCaps.end(), outCapabilities->begin(),
+                                   [](auto cap) { return static_cast<DisplayCapability>(cap); });
+                });
+    }
+
+    return error;
+}
+
+Error Composer::getDisplayConnectionType(Display display,
+                                         IComposerClient::DisplayConnectionType* outType) {
+    if (!mClient_2_4) {
+        return Error::UNSUPPORTED;
+    }
+
+    Error error = kDefaultError;
+    mClient_2_4->getDisplayConnectionType(display, [&](const auto& tmpError, const auto& tmpType) {
+        error = tmpError;
+        if (error != Error::NONE) {
+            return;
+        }
+
+        *outType = tmpType;
+    });
+
+    return error;
+}
+
 CommandReader::~CommandReader()
 {
     resetData();
diff --git a/services/surfaceflinger/DisplayHardware/ComposerHal.h b/services/surfaceflinger/DisplayHardware/ComposerHal.h
index 9f6cac2..e743e59 100644
--- a/services/surfaceflinger/DisplayHardware/ComposerHal.h
+++ b/services/surfaceflinger/DisplayHardware/ComposerHal.h
@@ -27,8 +27,8 @@
 #include <android/frameworks/vr/composer/2.0/IVrComposerClient.h>
 #endif // defined(USE_VR_COMPOSER) && USE_VR_COMPOSER
 #include <android/hardware/graphics/common/1.1/types.h>
-#include <android/hardware/graphics/composer/2.3/IComposer.h>
-#include <android/hardware/graphics/composer/2.3/IComposerClient.h>
+#include <android/hardware/graphics/composer/2.4/IComposer.h>
+#include <android/hardware/graphics/composer/2.4/IComposerClient.h>
 #include <composer-command-buffer/2.3/ComposerCommandBuffer.h>
 #include <gui/HdrMetadata.h>
 #include <math/mat4.h>
@@ -49,6 +49,7 @@
 namespace V2_1 = hardware::graphics::composer::V2_1;
 namespace V2_2 = hardware::graphics::composer::V2_2;
 namespace V2_3 = hardware::graphics::composer::V2_3;
+namespace V2_4 = hardware::graphics::composer::V2_4;
 
 using types::V1_0::ColorTransform;
 using types::V1_0::Transform;
@@ -65,8 +66,8 @@
 using V2_1::Layer;
 using V2_3::CommandReaderBase;
 using V2_3::CommandWriterBase;
-using V2_3::IComposer;
-using V2_3::IComposerClient;
+using V2_4::IComposer;
+using V2_4::IComposerClient;
 using DisplayCapability = IComposerClient::DisplayCapability;
 using PerFrameMetadata = IComposerClient::PerFrameMetadata;
 using PerFrameMetadataKey = IComposerClient::PerFrameMetadataKey;
@@ -118,7 +119,6 @@
                                      std::vector<Layer>* outLayers,
                                      std::vector<uint32_t>* outLayerRequestMasks) = 0;
 
-    virtual Error getDisplayType(Display display, IComposerClient::DisplayType* outType) = 0;
     virtual Error getDozeSupport(Display display, bool* outSupport) = 0;
     virtual Error getHdrCapabilities(Display display, std::vector<Hdr>* outTypes,
                                      float* outMaxLuminance, float* outMaxAverageLuminance,
@@ -203,11 +203,15 @@
                                                    uint8_t componentMask, uint64_t maxFrames) = 0;
     virtual Error getDisplayedContentSample(Display display, uint64_t maxFrames, uint64_t timestamp,
                                             DisplayedFrameStats* outStats) = 0;
-    virtual Error getDisplayCapabilities(Display display,
-                                         std::vector<DisplayCapability>* outCapabilities) = 0;
     virtual Error setLayerPerFrameMetadataBlobs(
             Display display, Layer layer, const std::vector<PerFrameMetadataBlob>& metadata) = 0;
     virtual Error setDisplayBrightness(Display display, float brightness) = 0;
+
+    // Composer HAL 2.4
+    virtual Error getDisplayCapabilities(Display display,
+                                         std::vector<DisplayCapability>* outCapabilities) = 0;
+    virtual Error getDisplayConnectionType(Display display,
+                                           IComposerClient::DisplayConnectionType* outType) = 0;
 };
 
 namespace impl {
@@ -334,7 +338,6 @@
                              std::vector<Layer>* outLayers,
                              std::vector<uint32_t>* outLayerRequestMasks) override;
 
-    Error getDisplayType(Display display, IComposerClient::DisplayType* outType) override;
     Error getDozeSupport(Display display, bool* outSupport) override;
     Error getHdrCapabilities(Display display, std::vector<Hdr>* outTypes, float* outMaxLuminance,
                              float* outMaxAverageLuminance, float* outMinLuminance) override;
@@ -414,13 +417,17 @@
                                            uint64_t maxFrames) override;
     Error getDisplayedContentSample(Display display, uint64_t maxFrames, uint64_t timestamp,
                                     DisplayedFrameStats* outStats) override;
-    Error getDisplayCapabilities(Display display,
-                                 std::vector<DisplayCapability>* outCapabilities) override;
     Error setLayerPerFrameMetadataBlobs(
             Display display, Layer layer,
             const std::vector<IComposerClient::PerFrameMetadataBlob>& metadata) override;
     Error setDisplayBrightness(Display display, float brightness) override;
 
+    // Composer HAL 2.4
+    Error getDisplayCapabilities(Display display,
+                                 std::vector<DisplayCapability>* outCapabilities) override;
+    Error getDisplayConnectionType(Display display,
+                                   IComposerClient::DisplayConnectionType* outType) override;
+
 private:
 #if defined(USE_VR_COMPOSER) && USE_VR_COMPOSER
     class CommandWriter : public CommandWriterBase {
@@ -455,7 +462,8 @@
 
     sp<V2_1::IComposerClient> mClient;
     sp<V2_2::IComposerClient> mClient_2_2;
-    sp<IComposerClient> mClient_2_3;
+    sp<V2_3::IComposerClient> mClient_2_3;
+    sp<IComposerClient> mClient_2_4;
 
     // 64KiB minus a small space for metadata such as read/write pointers
     static constexpr size_t kWriterInitialSize =
diff --git a/services/surfaceflinger/DisplayHardware/HWC2.cpp b/services/surfaceflinger/DisplayHardware/HWC2.cpp
index c463c4e..6f7428a 100644
--- a/services/surfaceflinger/DisplayHardware/HWC2.cpp
+++ b/services/surfaceflinger/DisplayHardware/HWC2.cpp
@@ -169,20 +169,8 @@
         }
         mDisplays.erase(displayId);
 
-        DisplayType displayType;
-        auto intError = mComposer->getDisplayType(displayId,
-                reinterpret_cast<Hwc2::IComposerClient::DisplayType *>(
-                        &displayType));
-        auto error = static_cast<Error>(intError);
-        if (error != Error::None) {
-            ALOGE("getDisplayType(%" PRIu64 ") failed: %s (%d). "
-                    "Aborting hotplug attempt.",
-                    displayId, to_string(error).c_str(), intError);
-            return;
-        }
-
         auto newDisplay = std::make_unique<impl::Display>(*mComposer.get(), mCapabilities,
-                                                          displayId, displayType);
+                                                          displayId, DisplayType::Physical);
         newDisplay->setConnected(true);
         mDisplays.emplace(displayId, std::move(newDisplay));
     } else if (connection == Connection::Disconnected) {
diff --git a/services/surfaceflinger/tests/fakehwc/SFFakeHwc_test.cpp b/services/surfaceflinger/tests/fakehwc/SFFakeHwc_test.cpp
index c949d7c..67faa57 100644
--- a/services/surfaceflinger/tests/fakehwc/SFFakeHwc_test.cpp
+++ b/services/surfaceflinger/tests/fakehwc/SFFakeHwc_test.cpp
@@ -127,7 +127,6 @@
 public:
     class MockComposerClient : public FakeComposerClient {
     public:
-        MOCK_METHOD2(getDisplayType, Error(Display display, ComposerClient::DisplayType* outType));
         MOCK_METHOD4(getDisplayAttribute,
                      Error(Display display, Config config, IComposerClient::Attribute attribute,
                            int32_t* outValue));
@@ -176,9 +175,6 @@
     android::hardware::ProcessState::self()->startThreadPool();
     android::ProcessState::self()->startThreadPool();
 
-    EXPECT_CALL(*mMockComposer, getDisplayType(PRIMARY_DISPLAY, _))
-            .WillOnce(DoAll(SetArgPointee<1>(IComposerClient::DisplayType::PHYSICAL),
-                            Return(Error::NONE)));
     // Primary display will be queried twice for all 5 attributes. One
     // set of queries comes from the SurfaceFlinger proper an the
     // other set from the VR composer.
@@ -270,10 +266,6 @@
 TEST_F(DisplayTest, Hotplug) {
     ALOGD("DisplayTest::Hotplug");
 
-    EXPECT_CALL(*mMockComposer, getDisplayType(EXTERNAL_DISPLAY, _))
-            .Times(2)
-            .WillRepeatedly(DoAll(SetArgPointee<1>(IComposerClient::DisplayType::PHYSICAL),
-                                  Return(Error::NONE)));
     // The attribute queries will get done twice. This is for defaults
     EXPECT_CALL(*mMockComposer, getDisplayAttribute(EXTERNAL_DISPLAY, 1, _, _))
             .Times(2 * 3)
@@ -381,10 +373,6 @@
 
     mMockComposer->clearFrames();
 
-    EXPECT_CALL(*mMockComposer, getDisplayType(PRIMARY_DISPLAY, _))
-            .Times(2)
-            .WillRepeatedly(DoAll(SetArgPointee<1>(IComposerClient::DisplayType::PHYSICAL),
-                                  Return(Error::NONE)));
     // The attribute queries will get done twice. This is for defaults
     EXPECT_CALL(*mMockComposer, getDisplayAttribute(PRIMARY_DISPLAY, 1, _, _))
             .Times(2 * 3)
diff --git a/services/surfaceflinger/tests/unittests/DisplayTransactionTest.cpp b/services/surfaceflinger/tests/unittests/DisplayTransactionTest.cpp
index fcce57b..ee1f3aa 100644
--- a/services/surfaceflinger/tests/unittests/DisplayTransactionTest.cpp
+++ b/services/surfaceflinger/tests/unittests/DisplayTransactionTest.cpp
@@ -445,10 +445,6 @@
     }
 
     static void setupHwcHotplugCallExpectations(DisplayTransactionTest* test) {
-        EXPECT_CALL(*test->mComposer, getDisplayType(HWC_DISPLAY_ID, _))
-                .WillOnce(DoAll(SetArgPointee<1>(static_cast<IComposerClient::DisplayType>(
-                                        HWC_DISPLAY_TYPE)),
-                                Return(Error::NONE)));
         EXPECT_CALL(*test->mComposer, setClientTargetSlotCount(_)).WillOnce(Return(Error::NONE));
         EXPECT_CALL(*test->mComposer, getDisplayConfigs(HWC_DISPLAY_ID, _))
                 .WillOnce(DoAll(SetArgPointee<1>(std::vector<unsigned>{HWC_ACTIVE_CONFIG_ID}),
diff --git a/services/surfaceflinger/tests/unittests/mock/DisplayHardware/MockComposer.h b/services/surfaceflinger/tests/unittests/mock/DisplayHardware/MockComposer.h
index 3c7e1da..98c6aa0 100644
--- a/services/surfaceflinger/tests/unittests/mock/DisplayHardware/MockComposer.h
+++ b/services/surfaceflinger/tests/unittests/mock/DisplayHardware/MockComposer.h
@@ -41,7 +41,7 @@
 using android::hardware::graphics::composer::V2_1::IComposer;
 using android::hardware::graphics::composer::V2_1::IComposerCallback;
 using android::hardware::graphics::composer::V2_1::Layer;
-using android::hardware::graphics::composer::V2_3::IComposerClient;
+using android::hardware::graphics::composer::V2_4::IComposerClient;
 
 class Composer : public Hwc2::Composer {
 public:
@@ -71,7 +71,6 @@
     MOCK_METHOD2(getDisplayName, Error(Display, std::string*));
     MOCK_METHOD4(getDisplayRequests,
                  Error(Display, uint32_t*, std::vector<Layer>*, std::vector<uint32_t>*));
-    MOCK_METHOD2(getDisplayType, Error(Display, IComposerClient::DisplayType*));
     MOCK_METHOD2(getDozeSupport, Error(Display, bool*));
     MOCK_METHOD5(getHdrCapabilities, Error(Display, std::vector<Hdr>*, float*, float*, float*));
     MOCK_METHOD1(getPerFrameMetadataKeys,
@@ -118,10 +117,11 @@
     MOCK_METHOD4(setDisplayContentSamplingEnabled, Error(Display, bool, uint8_t, uint64_t));
     MOCK_METHOD4(getDisplayedContentSample,
                  Error(Display, uint64_t, uint64_t, DisplayedFrameStats*));
-    MOCK_METHOD2(getDisplayCapabilities, Error(Display, std::vector<DisplayCapability>*));
     MOCK_METHOD3(setLayerPerFrameMetadataBlobs,
                  Error(Display, Layer, const std::vector<IComposerClient::PerFrameMetadataBlob>&));
     MOCK_METHOD2(setDisplayBrightness, Error(Display, float));
+    MOCK_METHOD2(getDisplayCapabilities, Error(Display, std::vector<DisplayCapability>*));
+    MOCK_METHOD2(getDisplayConnectionType, Error(Display, IComposerClient::DisplayConnectionType*));
 };
 
 } // namespace mock