Merge "camera: Add OisSamples synthetic key"
diff --git a/audio/4.0/IDevice.hal b/audio/4.0/IDevice.hal
index bb58568..7eb03c8 100644
--- a/audio/4.0/IDevice.hal
+++ b/audio/4.0/IDevice.hal
@@ -268,4 +268,16 @@
      */
     getMicrophones()
          generates(Result retval, vec<MicrophoneInfo> microphones);
+
+    /**
+     * Notifies the device module about the connection state of an input/output
+     * device attached to it. Calling this method is equivalent to setting
+     * AUDIO_PARAMETER_DEVICE_[DIS]CONNECT on the legacy HAL.
+     *
+     * @param address audio device specification.
+     * @param connected whether the device is connected.
+     * @return retval operation completion status.
+     */
+    setConnectedState(DeviceAddress address, bool connected)
+            generates (Result retval);
 };
diff --git a/audio/4.0/IPrimaryDevice.hal b/audio/4.0/IPrimaryDevice.hal
index f3d904c..258c28b 100644
--- a/audio/4.0/IPrimaryDevice.hal
+++ b/audio/4.0/IPrimaryDevice.hal
@@ -37,6 +37,17 @@
     setMode(AudioMode mode) generates (Result retval);
 
     /**
+     * Sets the name of the current BT SCO headset. Calling this method
+     * is equivalent to setting legacy "bt_headset_name" parameter.
+     * The BT SCO headset name must only be used for debugging purposes.
+     * Optional method
+     *
+     * @param name the name of the current BT SCO headset (can be empty).
+     * @return retval operation completion status.
+     */
+    setBtScoHeadsetDebugName(string name) generates (Result retval);
+
+    /**
      * Gets whether BT SCO Noise Reduction and Echo Cancellation are enabled.
      * Calling this method is equivalent to getting AUDIO_PARAMETER_KEY_BT_NREC
      * on the legacy HAL.
@@ -76,6 +87,48 @@
      */
     setBtScoWidebandEnabled(bool enabled) generates (Result retval);
 
+    /**
+     * Gets whether BT HFP (Hands-Free Profile) is enabled. Calling this method
+     * is equivalent to getting "hfp_enable" parameter value on the legacy HAL.
+     *
+     * @return retval operation completion status.
+     * @return enabled whether BT HFP is enabled.
+     */
+    getBtHfpEnabled() generates (Result retval, bool enabled);
+
+    /**
+     * Sets whether BT HFP (Hands-Free Profile) is enabled. Calling this method
+     * is equivalent to setting "hfp_enable" parameter on the legacy HAL.
+     * Optional method
+     *
+     * @param enabled whether BT HFP is enabled.
+     * @return retval operation completion status.
+     */
+    setBtHfpEnabled(bool enabled) generates (Result retval);
+
+    /**
+     * Sets the sampling rate of BT HFP (Hands-Free Profile). Calling this
+     * method is equivalent to setting "hfp_set_sampling_rate" parameter
+     * on the legacy HAL.
+     * Optional method
+     *
+     * @param sampleRateHz sample rate in Hz.
+     * @return retval operation completion status.
+     */
+    setBtHfpSampleRate(uint32_t sampleRateHz) generates (Result retval);
+
+    /**
+     * Sets the current output volume Hz for BT HFP (Hands-Free Profile).
+     * Calling this method is equivalent to setting "hfp_volume" parameter value
+     * on the legacy HAL (except that legacy HAL implementations expect
+     * an integer value in the range from 0 to 15.)
+     * Optional method
+     *
+     * @param volume 1.0f means unity, 0.0f is zero.
+     * @return retval operation completion status.
+     */
+    setBtHfpVolume(float volume) generates (Result retval);
+
     enum TtyMode : int32_t {
         OFF,
         VCO,
@@ -121,4 +174,22 @@
      * @return retval operation completion status.
      */
     setHacEnabled(bool enabled) generates (Result retval);
+
+    enum Rotation : int32_t {
+        DEG_0,
+        DEG_90,
+        DEG_180,
+        DEG_270
+    };
+
+    /**
+     * Updates HAL on the current rotation of the device relative to natural
+     * orientation. Calling this method is equivalent to setting legacy
+     * parameter "rotation".
+     *
+     * @param rotation rotation in degrees relative to natural device
+     *     orientation.
+     * @return retval operation completion status.
+     */
+    updateRotation(Rotation rotation) generates (Result retval);
 };
diff --git a/audio/4.0/IStream.hal b/audio/4.0/IStream.hal
index f05d7b0..e7a4b7d 100644
--- a/audio/4.0/IStream.hal
+++ b/audio/4.0/IStream.hal
@@ -175,38 +175,26 @@
     standby() generates (Result retval);
 
     /**
-     * Return the set of device(s) which this stream is connected to.
+     * Return the set of devices which this stream is connected to.
      * Optional method
      *
      * @return retval operation completion status: OK or NOT_SUPPORTED.
-     * @return device set of device(s) which this stream is connected to.
+     * @return device set of devices which this stream is connected to.
      */
-    getDevice() generates (Result retval, bitfield<AudioDevice> device);
+    getDevices() generates (Result retval, vec<DeviceAddress> devices);
 
     /**
-     * Connects the stream to the device.
+     * Connects the stream to one or multiple devices.
      *
      * This method must only be used for HALs that do not support
      * 'IDevice.createAudioPatch' method. Calling this method is
-     * equivalent to setting AUDIO_PARAMETER_STREAM_ROUTING in the legacy HAL
-     * interface.
+     * equivalent to setting AUDIO_PARAMETER_STREAM_ROUTING preceeded
+     * with a device address in the legacy HAL interface.
      *
      * @param address device to connect the stream to.
      * @return retval operation completion status.
      */
-    setDevice(DeviceAddress address) generates (Result retval);
-
-    /**
-     * Notifies the stream about device connection state. Calling this method is
-     * equivalent to setting AUDIO_PARAMETER_DEVICE_[DIS]CONNECT on the legacy
-     * HAL.
-     *
-     * @param address audio device specification.
-     * @param connected whether the device is connected.
-     * @return retval operation completion status.
-     */
-    setConnectedState(DeviceAddress address, bool connected)
-            generates (Result retval);
+    setDevices(vec<DeviceAddress> devices) generates (Result retval);
 
     /**
      * Sets the HW synchronization source. Calling this method is equivalent to
diff --git a/audio/4.0/IStreamOut.hal b/audio/4.0/IStreamOut.hal
index 3aa93fc..65eba60 100644
--- a/audio/4.0/IStreamOut.hal
+++ b/audio/4.0/IStreamOut.hal
@@ -264,4 +264,16 @@
      */
     getPresentationPosition()
             generates (Result retval, uint64_t frames, TimeSpec timeStamp);
+
+    /**
+     * Selects a presentation for decoding from a next generation media stream
+     * (as defined per ETSI TS 103 190-2) and a program within the presentation.
+     * Optional method
+     *
+     * @param presentationId selected audio presentation.
+     * @param programId refinement for the presentation.
+     * @return retval operation completion status.
+     */
+    selectPresentation(int32_t presentationId, int32_t programId)
+            generates (Result retval);
 };
diff --git a/audio/4.0/types.hal b/audio/4.0/types.hal
index 7853f3c..7b2035b 100644
--- a/audio/4.0/types.hal
+++ b/audio/4.0/types.hal
@@ -23,6 +23,10 @@
     NOT_INITIALIZED,
     INVALID_ARGUMENTS,
     INVALID_STATE,
+    /**
+     * Methods marked as "Optional method" must return this result value
+     * if the operation is not supported by HAL.
+     */
     NOT_SUPPORTED
 };
 
diff --git a/audio/common/4.0/types.hal b/audio/common/4.0/types.hal
index d4c6efe..4efdea3 100644
--- a/audio/common/4.0/types.hal
+++ b/audio/common/4.0/types.hal
@@ -485,7 +485,7 @@
 };
 
 @export(name="", value_prefix="AUDIO_DEVICE_")
-enum AudioDevice : uint64_t {
+enum AudioDevice : uint32_t {
     NONE                          = 0x0,
     /** reserved bits */
     BIT_IN                        = 0x80000000,
@@ -530,6 +530,7 @@
     OUT_BUS                       = 0x1000000,
     OUT_PROXY                     = 0x2000000,
     OUT_USB_HEADSET               = 0x4000000,
+    OUT_HEARING_AID               = 0x8000000,
     OUT_ECHO_CANCELLER            = 0x10000000,
     OUT_DEFAULT                   = BIT_DEFAULT,
     // Note that the 2.0 OUT_ALL* have been moved to helper functions
diff --git a/authsecret/1.0/IAuthSecret.hal b/authsecret/1.0/IAuthSecret.hal
index 6b573b3..9a0fd5f 100644
--- a/authsecret/1.0/IAuthSecret.hal
+++ b/authsecret/1.0/IAuthSecret.hal
@@ -42,5 +42,5 @@
      *
      * @param secret blob derived from the primary user's credential.
      */
-    primaryUserCredential(vec<uint8_t> secret);
+    oneway primaryUserCredential(vec<uint8_t> secret);
 };
diff --git a/automotive/evs/1.0/vts/functional/VtsHalEvsV1_0TargetTest.cpp b/automotive/evs/1.0/vts/functional/VtsHalEvsV1_0TargetTest.cpp
index 57050d7..d904ad0 100644
--- a/automotive/evs/1.0/vts/functional/VtsHalEvsV1_0TargetTest.cpp
+++ b/automotive/evs/1.0/vts/functional/VtsHalEvsV1_0TargetTest.cpp
@@ -54,7 +54,7 @@
 #include <android/hardware/automotive/evs/1.0/IEvsDisplay.h>
 
 #include <VtsHalHidlTargetTestBase.h>
-
+#include <VtsHalHidlTargetTestEnvBase.h>
 
 using namespace ::android::hardware::automotive::evs::V1_0;
 using ::android::hardware::Return;
@@ -64,13 +64,28 @@
 using ::android::hardware::hidl_string;
 using ::android::sp;
 
+// Test environment for Evs HIDL HAL.
+class EvsHidlEnvironment : public ::testing::VtsHalHidlTargetTestEnvBase {
+   public:
+    // get the test environment singleton
+    static EvsHidlEnvironment* Instance() {
+        static EvsHidlEnvironment* instance = new EvsHidlEnvironment;
+        return instance;
+    }
+
+    virtual void registerTestServices() override { registerTestService<IEvsEnumerator>(); }
+
+   private:
+    EvsHidlEnvironment() {}
+};
 
 // The main test class for EVS
 class EvsHidlTest : public ::testing::VtsHalHidlTargetTestBase {
 public:
     virtual void SetUp() override {
         // Make sure we can connect to the enumerator
-        pEnumerator = IEvsEnumerator::getService(kEnumeratorName);
+        pEnumerator = getService<IEvsEnumerator>(
+            EvsHidlEnvironment::Instance()->getServiceName<IEvsEnumerator>(kEnumeratorName));
         ASSERT_NE(pEnumerator.get(), nullptr);
     }
 
@@ -480,3 +495,12 @@
     // Explicitly release the display
     pEnumerator->closeDisplay(pDisplay);
 }
+
+int main(int argc, char** argv) {
+    ::testing::AddGlobalTestEnvironment(EvsHidlEnvironment::Instance());
+    ::testing::InitGoogleTest(&argc, argv);
+    EvsHidlEnvironment::Instance()->init(&argc, argv);
+    int status = RUN_ALL_TESTS();
+    ALOGI("Test result = %d", status);
+    return status;
+}
diff --git a/broadcastradio/1.0/vts/functional/Android.bp b/broadcastradio/1.0/vts/functional/Android.bp
index f31a2dc..7040a01 100644
--- a/broadcastradio/1.0/vts/functional/Android.bp
+++ b/broadcastradio/1.0/vts/functional/Android.bp
@@ -18,5 +18,8 @@
     name: "VtsHalBroadcastradioV1_0TargetTest",
     defaults: ["VtsHalTargetTestDefaults"],
     srcs: ["VtsHalBroadcastradioV1_0TargetTest.cpp"],
-    static_libs: ["android.hardware.broadcastradio@1.0"],
+    static_libs: [
+        "android.hardware.broadcastradio@1.0",
+        "android.hardware.broadcastradio@vts-utils-lib",
+    ],
 }
diff --git a/broadcastradio/1.0/vts/functional/VtsHalBroadcastradioV1_0TargetTest.cpp b/broadcastradio/1.0/vts/functional/VtsHalBroadcastradioV1_0TargetTest.cpp
index fd048db..90c8463 100644
--- a/broadcastradio/1.0/vts/functional/VtsHalBroadcastradioV1_0TargetTest.cpp
+++ b/broadcastradio/1.0/vts/functional/VtsHalBroadcastradioV1_0TargetTest.cpp
@@ -22,12 +22,12 @@
 #include <hidl/HidlTransportSupport.h>
 #include <utils/threads.h>
 
-#include <android/hardware/broadcastradio/1.0/IBroadcastRadioFactory.h>
 #include <android/hardware/broadcastradio/1.0/IBroadcastRadio.h>
+#include <android/hardware/broadcastradio/1.0/IBroadcastRadioFactory.h>
 #include <android/hardware/broadcastradio/1.0/ITuner.h>
 #include <android/hardware/broadcastradio/1.0/ITunerCallback.h>
 #include <android/hardware/broadcastradio/1.0/types.h>
-
+#include <broadcastradio-vts-utils/environment-utils.h>
 
 using ::android::sp;
 using ::android::Mutex;
@@ -48,6 +48,7 @@
 using ::android::hardware::broadcastradio::V1_0::MetaData;
 using ::android::hardware::broadcastradio::V1_0::MetadataKey;
 using ::android::hardware::broadcastradio::V1_0::MetadataType;
+using ::android::hardware::broadcastradio::vts::BroadcastRadioHidlEnvironment;
 
 #define RETURN_IF_SKIPPED \
     if (skipped) { \
@@ -55,8 +56,8 @@
         return; \
     }
 
+static BroadcastRadioHidlEnvironment<IBroadcastRadioFactory>* gEnv = nullptr;
 // The main test class for Broadcast Radio HIDL HAL.
-
 class BroadcastRadioHidlTest : public ::testing::VtsHalHidlTargetTestBase,
         public ::testing::WithParamInterface<Class> {
  protected:
@@ -67,7 +68,7 @@
         skipped = false;
 
         sp<IBroadcastRadioFactory> factory =
-              ::testing::VtsHalHidlTargetTestBase::getService<IBroadcastRadioFactory>();
+            getService<IBroadcastRadioFactory>(gEnv->getServiceName<IBroadcastRadioFactory>());
         ASSERT_NE(nullptr, factory.get());
 
         Result connectResult;
@@ -731,8 +732,11 @@
     ::testing::Values(Class::AM_FM, Class::SAT, Class::DT));
 
 int main(int argc, char** argv) {
-  ::testing::InitGoogleTest(&argc, argv);
-  int status = RUN_ALL_TESTS();
-  ALOGI("Test result = %d", status);
-  return status;
+    gEnv = new BroadcastRadioHidlEnvironment<IBroadcastRadioFactory>;
+    ::testing::AddGlobalTestEnvironment(gEnv);
+    ::testing::InitGoogleTest(&argc, argv);
+    gEnv->init(&argc, argv);
+    int status = RUN_ALL_TESTS();
+    ALOGI("Test result = %d", status);
+    return status;
 }
diff --git a/broadcastradio/1.1/vts/functional/VtsHalBroadcastradioV1_1TargetTest.cpp b/broadcastradio/1.1/vts/functional/VtsHalBroadcastradioV1_1TargetTest.cpp
index 823d14c..6687731 100644
--- a/broadcastradio/1.1/vts/functional/VtsHalBroadcastradioV1_1TargetTest.cpp
+++ b/broadcastradio/1.1/vts/functional/VtsHalBroadcastradioV1_1TargetTest.cpp
@@ -25,6 +25,7 @@
 #include <android/hardware/broadcastradio/1.1/types.h>
 #include <broadcastradio-utils-1x/Utils.h>
 #include <broadcastradio-vts-utils/call-barrier.h>
+#include <broadcastradio-vts-utils/environment-utils.h>
 #include <broadcastradio-vts-utils/mock-timeout.h>
 #include <broadcastradio-vts-utils/pointer-utils.h>
 #include <cutils/native_handle.h>
@@ -58,6 +59,7 @@
 using V1_0::MetadataType;
 
 using broadcastradio::vts::clearAndWait;
+using broadcastradio::vts::BroadcastRadioHidlEnvironment;
 
 static constexpr auto kConfigTimeout = 10s;
 static constexpr auto kConnectModuleTimeout = 1s;
@@ -91,6 +93,8 @@
     MOCK_TIMEOUT_METHOD1(currentProgramInfoChanged, Return<void>(const ProgramInfo&));
 };
 
+static BroadcastRadioHidlEnvironment<IBroadcastRadioFactory>* gEnv = nullptr;
+
 class BroadcastRadioHalTest : public ::testing::VtsHalHidlTargetTestBase,
                               public ::testing::WithParamInterface<Class> {
    protected:
@@ -119,7 +123,8 @@
     radioClass = GetParam();
 
     // lookup HIDL service
-    auto factory = getService<IBroadcastRadioFactory>();
+    auto factory =
+        getService<IBroadcastRadioFactory>(gEnv->getServiceName<IBroadcastRadioFactory>());
     ASSERT_NE(nullptr, factory.get());
 
     // connect radio module
@@ -606,8 +611,14 @@
 }  // namespace android
 
 int main(int argc, char** argv) {
-  ::testing::InitGoogleTest(&argc, argv);
-  int status = RUN_ALL_TESTS();
-  ALOGI("Test result = %d", status);
-  return status;
+    using android::hardware::broadcastradio::V1_1::vts::gEnv;
+    using android::hardware::broadcastradio::V1_1::IBroadcastRadioFactory;
+    using android::hardware::broadcastradio::vts::BroadcastRadioHidlEnvironment;
+    gEnv = new BroadcastRadioHidlEnvironment<IBroadcastRadioFactory>;
+    ::testing::AddGlobalTestEnvironment(gEnv);
+    ::testing::InitGoogleTest(&argc, argv);
+    gEnv->init(&argc, argv);
+    int status = RUN_ALL_TESTS();
+    ALOGI("Test result = %d", status);
+    return status;
 }
diff --git a/broadcastradio/2.0/types.hal b/broadcastradio/2.0/types.hal
index 9fd0738..a9b9600 100644
--- a/broadcastradio/2.0/types.hal
+++ b/broadcastradio/2.0/types.hal
@@ -288,6 +288,9 @@
 struct ProgramInfo {
     /**
      * An identifier used to point at the program (primarily to tune to it).
+     *
+     * This field is required - its type field must not be set to
+     * IdentifierType::INVALID.
      */
     ProgramSelector selector;
 
@@ -302,8 +305,9 @@
      * may choose to use DAB technology to make actual tuning. This identifier
      * must reflect that.
      *
-     * This field is optional, but must be set for currently tuned program.
-     * If it's not set, its value must be initialized to all-zeros.
+     * This field is required for currently tuned program only.
+     * For all other items on the program list, its type field must be
+     * initialized to IdentifierType::INVALID.
      *
      * Only primary identifiers for a given radio technology are valid:
      *  - AMFM_FREQUENCY for analog AM/FM;
@@ -326,9 +330,9 @@
      * multiple ensembles. This identifier points to the channel to which the
      * radio hardware is physically tuned to.
      *
-     * This field is optional, but must be set for currently tuned program.
-     * If it's not set, its type field must be initialized to
-     * IdentifierType::INVALID.
+     * This field is required for currently tuned program only.
+     * For all other items on the program list, its type field must be
+     * initialized to IdentifierType::INVALID.
      *
      * Only physical identifiers are valid:
      *  - AMFM_FREQUENCY;
@@ -408,6 +412,8 @@
      * Tuned to a program (not playing a static).
      *
      * It's the same condition that would stop scan() operation.
+     *
+     * By definition, this flag must be set for all items on the program list.
      */
     TUNED = 1 << 4,
 
diff --git a/broadcastradio/2.0/vts/functional/VtsHalBroadcastradioV2_0TargetTest.cpp b/broadcastradio/2.0/vts/functional/VtsHalBroadcastradioV2_0TargetTest.cpp
index 2a5ec8fe..6877f07 100644
--- a/broadcastradio/2.0/vts/functional/VtsHalBroadcastradioV2_0TargetTest.cpp
+++ b/broadcastradio/2.0/vts/functional/VtsHalBroadcastradioV2_0TargetTest.cpp
@@ -26,6 +26,7 @@
 #include <android/hardware/broadcastradio/2.0/types.h>
 #include <broadcastradio-utils-2x/Utils.h>
 #include <broadcastradio-vts-utils/call-barrier.h>
+#include <broadcastradio-vts-utils/environment-utils.h>
 #include <broadcastradio-vts-utils/mock-timeout.h>
 #include <broadcastradio-vts-utils/pointer-utils.h>
 #include <cutils/bitops.h>
@@ -52,6 +53,7 @@
 using testing::Invoke;
 using testing::SaveArg;
 
+using broadcastradio::vts::BroadcastRadioHidlEnvironment;
 using broadcastradio::vts::CallBarrier;
 using broadcastradio::vts::clearAndWait;
 using utils::make_identifier;
@@ -97,6 +99,8 @@
     MOCK_METHOD1(onListUpdated, Return<void>(const hidl_vec<Announcement>&));
 };
 
+static BroadcastRadioHidlEnvironment<IBroadcastRadio>* gEnv = nullptr;
+
 class BroadcastRadioHalTest : public ::testing::VtsHalHidlTargetTestBase {
    protected:
     virtual void SetUp() override;
@@ -171,7 +175,7 @@
     EXPECT_EQ(nullptr, mModule.get()) << "Module is already open";
 
     // lookup HIDL service (radio module)
-    mModule = getService<IBroadcastRadio>();
+    mModule = getService<IBroadcastRadio>(gEnv->getServiceName<IBroadcastRadio>());
     ASSERT_NE(nullptr, mModule.get()) << "Couldn't find broadcast radio HAL implementation";
 
     // get module properties
@@ -804,7 +808,13 @@
 }  // namespace android
 
 int main(int argc, char** argv) {
+    using android::hardware::broadcastradio::V2_0::vts::gEnv;
+    using android::hardware::broadcastradio::V2_0::IBroadcastRadio;
+    using android::hardware::broadcastradio::vts::BroadcastRadioHidlEnvironment;
+    gEnv = new BroadcastRadioHidlEnvironment<IBroadcastRadio>;
+    ::testing::AddGlobalTestEnvironment(gEnv);
     ::testing::InitGoogleTest(&argc, argv);
+    gEnv->init(&argc, argv);
     int status = RUN_ALL_TESTS();
     ALOGI("Test result = %d", status);
     return status;
diff --git a/broadcastradio/common/vts/utils/Android.bp b/broadcastradio/common/vts/utils/Android.bp
index 4ba8a17..d3edc76 100644
--- a/broadcastradio/common/vts/utils/Android.bp
+++ b/broadcastradio/common/vts/utils/Android.bp
@@ -25,4 +25,8 @@
         "-Wextra",
         "-Werror",
     ],
+    static_libs: [
+        "VtsHalHidlTargetTestBase",
+    ],
+    group_static_libs: true,
 }
diff --git a/broadcastradio/common/vts/utils/include/broadcastradio-vts-utils/environment-utils.h b/broadcastradio/common/vts/utils/include/broadcastradio-vts-utils/environment-utils.h
new file mode 100644
index 0000000..274e632
--- /dev/null
+++ b/broadcastradio/common/vts/utils/include/broadcastradio-vts-utils/environment-utils.h
@@ -0,0 +1,41 @@
+/*
+ * Copyright (C) 2018 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.
+ */
+#ifndef ANDROID_HARDWARE_BROADCASTRADIO_VTS_ENVIRONMENT_UTILS
+#define ANDROID_HARDWARE_BROADCASTRADIO_VTS_ENVIRONMENT_UTILS
+
+#include <VtsHalHidlTargetTestEnvBase.h>
+
+namespace android {
+namespace hardware {
+namespace broadcastradio {
+namespace vts {
+
+// Test environment for BroadcastRadio HIDL HAL.
+template <typename... T>
+class BroadcastRadioHidlEnvironment : public ::testing::VtsHalHidlTargetTestEnvBase {
+   public:
+    virtual void registerTestServices() override {
+        using expander = int[];
+        (void)expander{0, (registerTestService<T>(), 0)...};
+    }
+};
+
+}  // namespace vts
+}  // namespace broadcastradio
+}  // namespace hardware
+}  // namespace android
+
+#endif  // ANDROID_HARDWARE_BROADCASTRADIO_VTS_ENVIRONMENT_UTILS
diff --git a/camera/device/3.4/default/CameraDeviceSession.cpp b/camera/device/3.4/default/CameraDeviceSession.cpp
index 771197a..bb4886d 100644
--- a/camera/device/3.4/default/CameraDeviceSession.cpp
+++ b/camera/device/3.4/default/CameraDeviceSession.cpp
@@ -370,7 +370,7 @@
 
         for (size_t i = 0; i < settingsCount; i++) {
             uint64_t settingsSize = request.physicalCameraSettings[i].fmqSettingsSize;
-            const camera_metadata_t *settings;
+            const camera_metadata_t *settings = nullptr;
             if (settingsSize > 0) {
                 physicalFmq.push_back(V3_2::CameraMetadata(settingsSize));
                 bool read = mRequestMetadataQueue->read(physicalFmq[i].data(), settingsSize);
@@ -392,6 +392,13 @@
                 ALOGE("%s: physical camera settings metadata is corrupt!", __FUNCTION__);
                 return Status::ILLEGAL_ARGUMENT;
             }
+
+            if (mFirstRequest && settings == nullptr) {
+                ALOGE("%s: Individual request settings must not be null for first request!",
+                        __FUNCTION__);
+                return Status::ILLEGAL_ARGUMENT;
+            }
+
             physicalCameraIds.push_back(request.physicalCameraSettings[i].physicalCameraId.c_str());
         }
     }
diff --git a/camera/device/3.4/default/ExternalCameraDevice.cpp b/camera/device/3.4/default/ExternalCameraDevice.cpp
index 61b8921..14f82bc 100644
--- a/camera/device/3.4/default/ExternalCameraDevice.cpp
+++ b/camera/device/3.4/default/ExternalCameraDevice.cpp
@@ -131,7 +131,7 @@
 
     session = new ExternalCameraDeviceSession(
             callback, mCfg, mSupportedFormats, mCroppingType,
-            mCameraCharacteristics, std::move(fd));
+            mCameraCharacteristics, mCameraId, std::move(fd));
     if (session == nullptr) {
         ALOGE("%s: camera device session allocation failed", __FUNCTION__);
         mLock.unlock();
@@ -595,16 +595,19 @@
                     ANDROID_SCALER_AVAILABLE_STREAM_CONFIGURATIONS_OUTPUT);
         }
 
-        int64_t min_frame_duration = std::numeric_limits<int64_t>::max();
-        for (const auto& frameRate : supportedFormat.frameRates) {
-            int64_t frame_duration = 1000000000LL / frameRate;
-            if (frame_duration < min_frame_duration) {
-                min_frame_duration = frame_duration;
+        int64_t minFrameDuration = std::numeric_limits<int64_t>::max();
+        for (const auto& fr : supportedFormat.frameRates) {
+            // 1000000000LL < (2^32 - 1) and
+            // fr.durationNumerator is uint32_t, so no overflow here
+            int64_t frameDuration = 1000000000LL * fr.durationNumerator /
+                    fr.durationDenominator;
+            if (frameDuration < minFrameDuration) {
+                minFrameDuration = frameDuration;
             }
-            if (frame_duration > maxFrameDuration) {
-                maxFrameDuration = frame_duration;
+            if (frameDuration > maxFrameDuration) {
+                maxFrameDuration = frameDuration;
             }
-            int32_t frameRateInt = static_cast<int32_t>(frameRate);
+            int32_t frameRateInt = static_cast<int32_t>(fr.getDouble());
             if (minFps > frameRateInt) {
                 minFps = frameRateInt;
             }
@@ -618,7 +621,7 @@
             minFrameDurations.push_back(format);
             minFrameDurations.push_back(supportedFormat.width);
             minFrameDurations.push_back(supportedFormat.height);
-            minFrameDurations.push_back(min_frame_duration);
+            minFrameDurations.push_back(minFrameDuration);
         }
 
         // The stall duration is 0 for non-jpeg formats. For JPEG format, stall
@@ -705,8 +708,10 @@
             ++frameInterval.index) {
         if (frameInterval.type == V4L2_FRMIVAL_TYPE_DISCRETE) {
             if (frameInterval.discrete.numerator != 0) {
-                float framerate = frameInterval.discrete.denominator /
-                        static_cast<float>(frameInterval.discrete.numerator);
+                SupportedV4L2Format::FrameRate fr = {
+                        frameInterval.discrete.numerator,
+                        frameInterval.discrete.denominator};
+                double framerate = fr.getDouble();
                 if (framerate > fpsUpperBound) {
                     continue;
                 }
@@ -717,7 +722,7 @@
                     (frameInterval.pixel_format >> 16) & 0xFF,
                     (frameInterval.pixel_format >> 24) & 0xFF,
                     frameInterval.width, frameInterval.height, framerate);
-                format->frameRates.push_back(framerate);
+                format->frameRates.push_back(fr);
             }
         }
     }
diff --git a/camera/device/3.4/default/ExternalCameraDeviceSession.cpp b/camera/device/3.4/default/ExternalCameraDeviceSession.cpp
index b6728ed..5346f80 100644
--- a/camera/device/3.4/default/ExternalCameraDeviceSession.cpp
+++ b/camera/device/3.4/default/ExternalCameraDeviceSession.cpp
@@ -46,6 +46,21 @@
                                        // bad frames. TODO: develop a better bad frame detection
                                        // method
 
+bool tryLock(Mutex& mutex)
+{
+    static const int kDumpLockRetries = 50;
+    static const int kDumpLockSleep = 60000;
+    bool locked = false;
+    for (int i = 0; i < kDumpLockRetries; ++i) {
+        if (mutex.tryLock() == NO_ERROR) {
+            locked = true;
+            break;
+        }
+        usleep(kDumpLockSleep);
+    }
+    return locked;
+}
+
 } // Anonymous namespace
 
 // Static instances
@@ -59,12 +74,14 @@
         const std::vector<SupportedV4L2Format>& sortedFormats,
         const CroppingType& croppingType,
         const common::V1_0::helper::CameraMetadata& chars,
+        const std::string& cameraId,
         unique_fd v4l2Fd) :
         mCallback(callback),
         mCfg(cfg),
         mCameraCharacteristics(chars),
         mSupportedFormats(sortedFormats),
         mCroppingType(croppingType),
+        mCameraId(cameraId),
         mV4l2Fd(std::move(v4l2Fd)),
         mOutputThread(new OutputThread(this, mCroppingType)),
         mMaxThumbResolution(getMaxThumbResolution()),
@@ -119,8 +136,79 @@
     }
 }
 
-void ExternalCameraDeviceSession::dumpState(const native_handle_t*) {
-    // TODO: b/72261676 dump more runtime information
+
+void ExternalCameraDeviceSession::dumpState(const native_handle_t* handle) {
+    if (handle->numFds != 1 || handle->numInts != 0) {
+        ALOGE("%s: handle must contain 1 FD and 0 integers! Got %d FDs and %d ints",
+                __FUNCTION__, handle->numFds, handle->numInts);
+        return;
+    }
+    int fd = handle->data[0];
+
+    bool intfLocked = tryLock(mInterfaceLock);
+    if (!intfLocked) {
+        dprintf(fd, "!! ExternalCameraDeviceSession interface may be deadlocked !!\n");
+    }
+
+    if (isClosed()) {
+        dprintf(fd, "External camera %s is closed\n", mCameraId.c_str());
+        return;
+    }
+
+    bool streaming = false;
+    size_t v4L2BufferCount = 0;
+    SupportedV4L2Format streamingFmt;
+    std::unordered_set<uint32_t>  inflightFrames;
+    {
+        Mutex::Autolock _l(mLock);
+        bool sessionLocked = tryLock(mLock);
+        if (!sessionLocked) {
+            dprintf(fd, "!! ExternalCameraDeviceSession mLock may be deadlocked !!\n");
+        }
+        streaming = mV4l2Streaming;
+        streamingFmt = mV4l2StreamingFmt;
+        v4L2BufferCount = mV4L2BufferCount;
+        inflightFrames = mInflightFrames;
+        if (sessionLocked) {
+            mLock.unlock();
+        }
+    }
+
+    dprintf(fd, "External camera %s V4L2 FD %d, cropping type %s, %s\n",
+            mCameraId.c_str(), mV4l2Fd.get(),
+            (mCroppingType == VERTICAL) ? "vertical" : "horizontal",
+            streaming ? "streaming" : "not streaming");
+    if (streaming) {
+        // TODO: dump fps later
+        dprintf(fd, "Current V4L2 format %c%c%c%c %dx%d\n",
+                streamingFmt.fourcc & 0xFF,
+                (streamingFmt.fourcc >> 8) & 0xFF,
+                (streamingFmt.fourcc >> 16) & 0xFF,
+                (streamingFmt.fourcc >> 24) & 0xFF,
+                streamingFmt.width, streamingFmt.height);
+
+        size_t numDequeuedV4l2Buffers = 0;
+        {
+            std::lock_guard<std::mutex> lk(mV4l2BufferLock);
+            numDequeuedV4l2Buffers = mNumDequeuedV4l2Buffers;
+        }
+        dprintf(fd, "V4L2 buffer queue size %zu, dequeued %zu\n",
+                v4L2BufferCount, numDequeuedV4l2Buffers);
+    }
+
+    dprintf(fd, "In-flight frames (not sorted):");
+    for (const auto& frameNumber : inflightFrames) {
+        dprintf(fd, "%d, ", frameNumber);
+    }
+    dprintf(fd, "\n");
+    mOutputThread->dump(fd);
+    dprintf(fd, "\n");
+
+    if (intfLocked) {
+        mInterfaceLock.unlock();
+    }
+
+    return;
 }
 
 Return<void> ExternalCameraDeviceSession::constructDefaultRequestSettings(
@@ -270,26 +358,31 @@
 }
 
 Return<Status> ExternalCameraDeviceSession::flush() {
+    Mutex::Autolock _il(mInterfaceLock);
+    Status status = initStatus();
+    if (status != Status::OK) {
+        return status;
+    }
+    mOutputThread->flush();
     return Status::OK;
 }
 
 Return<void> ExternalCameraDeviceSession::close() {
     Mutex::Autolock _il(mInterfaceLock);
-    Mutex::Autolock _l(mLock);
-    if (!mClosed) {
-        // TODO: b/72261676 Cleanup inflight buffers/V4L2 buffer queue
+    bool closed = isClosed();
+    if (!closed) {
+        mOutputThread->flush();
+        mOutputThread->requestExit();
+        mOutputThread->join();
+
+        Mutex::Autolock _l(mLock);
+        // free all buffers
+        for(auto pair : mStreamMap) {
+            cleanupBuffersLocked(/*Stream ID*/pair.first);
+        }
+        v4l2StreamOffLocked();
         ALOGV("%s: closing V4L2 camera FD %d", __FUNCTION__, mV4l2Fd.get());
         mV4l2Fd.reset();
-        mOutputThread->requestExit(); // TODO: join?
-
-        // free all imported buffers
-        for(auto& pair : mCirculatingBuffers) {
-            CirculatingBuffers& buffers = pair.second;
-            for (auto& p2 : buffers) {
-                sHandleImporter.freeBuffer(p2.second);
-            }
-        }
-
         mClosed = true;
     }
     return Void();
@@ -425,25 +518,22 @@
     // TODO: program fps range per capture request here
     //       or limit the set of availableFpsRange
 
-    sp<V4L2Frame> frameIn = dequeueV4l2FrameLocked();
+
+    nsecs_t shutterTs = 0;
+    sp<V4L2Frame> frameIn = dequeueV4l2FrameLocked(&shutterTs);
     if ( frameIn == nullptr) {
         ALOGE("%s: V4L2 deque frame failed!", __FUNCTION__);
         return Status::INTERNAL_ERROR;
     }
-    // TODO: This can probably be replaced by use v4lbuffer timestamp
-    //       if the device supports it
-    nsecs_t shutterTs = systemTime(SYSTEM_TIME_MONOTONIC);
 
-
-    // TODO: reduce object copy in this path
-    HalRequest halReq = {
-            .frameNumber = request.frameNumber,
-            .setting = mLatestReqSetting,
-            .frameIn = frameIn,
-            .shutterTs = shutterTs};
-    halReq.buffers.resize(numOutputBufs);
+    std::shared_ptr<HalRequest> halReq = std::make_shared<HalRequest>();
+    halReq->frameNumber = request.frameNumber;
+    halReq->setting = mLatestReqSetting;
+    halReq->frameIn = frameIn;
+    halReq->shutterTs = shutterTs;
+    halReq->buffers.resize(numOutputBufs);
     for (size_t i = 0; i < numOutputBufs; i++) {
-        HalStreamBuffer& halBuf = halReq.buffers[i];
+        HalStreamBuffer& halBuf = halReq->buffers[i];
         int streamId = halBuf.streamId = request.outputBuffers[i].streamId;
         halBuf.bufferId = request.outputBuffers[i].bufferId;
         const Stream& stream = mStreamMap[streamId];
@@ -455,7 +545,7 @@
         halBuf.acquireFence = allFences[i];
         halBuf.fenceTimeout = false;
     }
-    mInflightFrames.insert(halReq.frameNumber);
+    mInflightFrames.insert(halReq->frameNumber);
     // Send request to OutputThread for the rest of processing
     mOutputThread->submitRequest(halReq);
     mFirstRequest = false;
@@ -481,30 +571,31 @@
 }
 
 //TODO: refactor with processCaptureResult
-Status ExternalCameraDeviceSession::processCaptureRequestError(HalRequest& req) {
+Status ExternalCameraDeviceSession::processCaptureRequestError(
+        const std::shared_ptr<HalRequest>& req) {
     // Return V4L2 buffer to V4L2 buffer queue
-    enqueueV4l2Frame(req.frameIn);
+    enqueueV4l2Frame(req->frameIn);
 
     // NotifyShutter
-    notifyShutter(req.frameNumber, req.shutterTs);
+    notifyShutter(req->frameNumber, req->shutterTs);
 
-    notifyError(/*frameNum*/req.frameNumber, /*stream*/-1, ErrorCode::ERROR_REQUEST);
+    notifyError(/*frameNum*/req->frameNumber, /*stream*/-1, ErrorCode::ERROR_REQUEST);
 
     // Fill output buffers
     hidl_vec<CaptureResult> results;
     results.resize(1);
     CaptureResult& result = results[0];
-    result.frameNumber = req.frameNumber;
+    result.frameNumber = req->frameNumber;
     result.partialResult = 1;
     result.inputBuffer.streamId = -1;
-    result.outputBuffers.resize(req.buffers.size());
-    for (size_t i = 0; i < req.buffers.size(); i++) {
-        result.outputBuffers[i].streamId = req.buffers[i].streamId;
-        result.outputBuffers[i].bufferId = req.buffers[i].bufferId;
+    result.outputBuffers.resize(req->buffers.size());
+    for (size_t i = 0; i < req->buffers.size(); i++) {
+        result.outputBuffers[i].streamId = req->buffers[i].streamId;
+        result.outputBuffers[i].bufferId = req->buffers[i].bufferId;
         result.outputBuffers[i].status = BufferStatus::ERROR;
-        if (req.buffers[i].acquireFence >= 0) {
+        if (req->buffers[i].acquireFence >= 0) {
             native_handle_t* handle = native_handle_create(/*numFds*/1, /*numInts*/0);
-            handle->data[0] = req.buffers[i].acquireFence;
+            handle->data[0] = req->buffers[i].acquireFence;
             result.outputBuffers[i].releaseFence.setTo(handle, /*shouldOwn*/false);
         }
     }
@@ -512,7 +603,7 @@
     // update inflight records
     {
         Mutex::Autolock _l(mLock);
-        mInflightFrames.erase(req.frameNumber);
+        mInflightFrames.erase(req->frameNumber);
     }
 
     // Callback into framework
@@ -521,51 +612,51 @@
     return Status::OK;
 }
 
-Status ExternalCameraDeviceSession::processCaptureResult(HalRequest& req) {
+Status ExternalCameraDeviceSession::processCaptureResult(std::shared_ptr<HalRequest>& req) {
     // Return V4L2 buffer to V4L2 buffer queue
-    enqueueV4l2Frame(req.frameIn);
+    enqueueV4l2Frame(req->frameIn);
 
     // NotifyShutter
-    notifyShutter(req.frameNumber, req.shutterTs);
+    notifyShutter(req->frameNumber, req->shutterTs);
 
     // Fill output buffers
     hidl_vec<CaptureResult> results;
     results.resize(1);
     CaptureResult& result = results[0];
-    result.frameNumber = req.frameNumber;
+    result.frameNumber = req->frameNumber;
     result.partialResult = 1;
     result.inputBuffer.streamId = -1;
-    result.outputBuffers.resize(req.buffers.size());
-    for (size_t i = 0; i < req.buffers.size(); i++) {
-        result.outputBuffers[i].streamId = req.buffers[i].streamId;
-        result.outputBuffers[i].bufferId = req.buffers[i].bufferId;
-        if (req.buffers[i].fenceTimeout) {
+    result.outputBuffers.resize(req->buffers.size());
+    for (size_t i = 0; i < req->buffers.size(); i++) {
+        result.outputBuffers[i].streamId = req->buffers[i].streamId;
+        result.outputBuffers[i].bufferId = req->buffers[i].bufferId;
+        if (req->buffers[i].fenceTimeout) {
             result.outputBuffers[i].status = BufferStatus::ERROR;
             native_handle_t* handle = native_handle_create(/*numFds*/1, /*numInts*/0);
-            handle->data[0] = req.buffers[i].acquireFence;
+            handle->data[0] = req->buffers[i].acquireFence;
             result.outputBuffers[i].releaseFence.setTo(handle, /*shouldOwn*/false);
-            notifyError(req.frameNumber, req.buffers[i].streamId, ErrorCode::ERROR_BUFFER);
+            notifyError(req->frameNumber, req->buffers[i].streamId, ErrorCode::ERROR_BUFFER);
         } else {
             result.outputBuffers[i].status = BufferStatus::OK;
             // TODO: refactor
-            if (req.buffers[i].acquireFence > 0) {
+            if (req->buffers[i].acquireFence > 0) {
                 native_handle_t* handle = native_handle_create(/*numFds*/1, /*numInts*/0);
-                handle->data[0] = req.buffers[i].acquireFence;
+                handle->data[0] = req->buffers[i].acquireFence;
                 result.outputBuffers[i].releaseFence.setTo(handle, /*shouldOwn*/false);
             }
         }
     }
 
     // Fill capture result metadata
-    fillCaptureResult(req.setting, req.shutterTs);
-    const camera_metadata_t *rawResult = req.setting.getAndLock();
+    fillCaptureResult(req->setting, req->shutterTs);
+    const camera_metadata_t *rawResult = req->setting.getAndLock();
     V3_2::implementation::convertToHidl(rawResult, &result.result);
-    req.setting.unlock(rawResult);
+    req->setting.unlock(rawResult);
 
     // update inflight records
     {
         Mutex::Autolock _l(mLock);
-        mInflightFrames.erase(req.frameNumber);
+        mInflightFrames.erase(req->frameNumber);
     }
 
     // Callback into framework
@@ -1296,7 +1387,7 @@
 
 int ExternalCameraDeviceSession::OutputThread::createJpegLocked(
         HalStreamBuffer &halBuf,
-        HalRequest &req)
+        const std::shared_ptr<HalRequest>& req)
 {
     int ret;
     auto lfail = [&](auto... args) {
@@ -1323,17 +1414,17 @@
     int jpegQuality, thumbQuality;
     Size thumbSize;
 
-    if (req.setting.exists(ANDROID_JPEG_QUALITY)) {
+    if (req->setting.exists(ANDROID_JPEG_QUALITY)) {
         camera_metadata_entry entry =
-            req.setting.find(ANDROID_JPEG_QUALITY);
+            req->setting.find(ANDROID_JPEG_QUALITY);
         jpegQuality = entry.data.u8[0];
     } else {
         return lfail("%s: ANDROID_JPEG_QUALITY not set",__FUNCTION__);
     }
 
-    if (req.setting.exists(ANDROID_JPEG_THUMBNAIL_QUALITY)) {
+    if (req->setting.exists(ANDROID_JPEG_THUMBNAIL_QUALITY)) {
         camera_metadata_entry entry =
-            req.setting.find(ANDROID_JPEG_THUMBNAIL_QUALITY);
+            req->setting.find(ANDROID_JPEG_THUMBNAIL_QUALITY);
         thumbQuality = entry.data.u8[0];
     } else {
         return lfail(
@@ -1341,9 +1432,9 @@
             __FUNCTION__);
     }
 
-    if (req.setting.exists(ANDROID_JPEG_THUMBNAIL_SIZE)) {
+    if (req->setting.exists(ANDROID_JPEG_THUMBNAIL_SIZE)) {
         camera_metadata_entry entry =
-            req.setting.find(ANDROID_JPEG_THUMBNAIL_SIZE);
+            req->setting.find(ANDROID_JPEG_THUMBNAIL_SIZE);
         thumbSize = Size { static_cast<uint32_t>(entry.data.i32[0]),
                            static_cast<uint32_t>(entry.data.i32[1])
         };
@@ -1403,7 +1494,7 @@
     /* Combine camera characteristics with request settings to form EXIF
      * metadata */
     common::V1_0::helper::CameraMetadata meta(parent->mCameraCharacteristics);
-    meta.append(req.setting);
+    meta.append(req->setting);
 
     /* Generate EXIF object */
     std::unique_ptr<ExifUtils> utils(ExifUtils::create());
@@ -1467,7 +1558,7 @@
 }
 
 bool ExternalCameraDeviceSession::OutputThread::threadLoop() {
-    HalRequest req;
+    std::shared_ptr<HalRequest> req;
     auto parent = mParent.promote();
     if (parent == nullptr) {
        ALOGE("%s: session has been disconnected!", __FUNCTION__);
@@ -1478,29 +1569,33 @@
     //       regularly to prevent v4l buffer queue filled with stale buffers
     //       when app doesn't program a preveiw request
     waitForNextRequest(&req);
-    if (req.frameIn == nullptr) {
+    if (req == nullptr) {
         // No new request, wait again
         return true;
     }
 
-    if (req.frameIn->mFourcc != V4L2_PIX_FMT_MJPEG) {
-        ALOGE("%s: do not support V4L2 format %c%c%c%c", __FUNCTION__,
-                req.frameIn->mFourcc & 0xFF,
-                (req.frameIn->mFourcc >> 8) & 0xFF,
-                (req.frameIn->mFourcc >> 16) & 0xFF,
-                (req.frameIn->mFourcc >> 24) & 0xFF);
+    auto onDeviceError = [&](auto... args) {
+        ALOGE(args...);
         parent->notifyError(
-                /*frameNum*/req.frameNumber, /*stream*/-1, ErrorCode::ERROR_DEVICE);
+                req->frameNumber, /*stream*/-1, ErrorCode::ERROR_DEVICE);
+        signalRequestDone();
         return false;
+    };
+
+    if (req->frameIn->mFourcc != V4L2_PIX_FMT_MJPEG) {
+        return onDeviceError("%s: do not support V4L2 format %c%c%c%c", __FUNCTION__,
+                req->frameIn->mFourcc & 0xFF,
+                (req->frameIn->mFourcc >> 8) & 0xFF,
+                (req->frameIn->mFourcc >> 16) & 0xFF,
+                (req->frameIn->mFourcc >> 24) & 0xFF);
     }
 
-    std::unique_lock<std::mutex> lk(mLock);
-
+    std::unique_lock<std::mutex> lk(mBufferLock);
     // Convert input V4L2 frame to YU12 of the same size
     // TODO: see if we can save some computation by converting to YV12 here
     uint8_t* inData;
     size_t inDataSize;
-    req.frameIn->map(&inData, &inDataSize);
+    req->frameIn->map(&inData, &inDataSize);
     // TODO: profile
     // TODO: in some special case maybe we can decode jpg directly to gralloc output?
     int res = libyuv::MJPGToI420(
@@ -1520,17 +1615,15 @@
         lk.unlock();
         Status st = parent->processCaptureRequestError(req);
         if (st != Status::OK) {
-            ALOGE("%s: failed to process capture request error!", __FUNCTION__);
-            parent->notifyError(
-                    /*frameNum*/req.frameNumber, /*stream*/-1, ErrorCode::ERROR_DEVICE);
-            return false;
+            return onDeviceError("%s: failed to process capture request error!", __FUNCTION__);
         }
+        signalRequestDone();
         return true;
     }
 
     ALOGV("%s processing new request", __FUNCTION__);
     const int kSyncWaitTimeoutMs = 500;
-    for (auto& halBuf : req.buffers) {
+    for (auto& halBuf : req->buffers) {
         if (halBuf.acquireFence != -1) {
             int ret = sync_wait(halBuf.acquireFence, kSyncWaitTimeoutMs);
             if (ret) {
@@ -1551,15 +1644,9 @@
                 int ret = createJpegLocked(halBuf, req);
 
                 if(ret != 0) {
-                    ALOGE("%s: createJpegLocked failed with %d",
-                          __FUNCTION__, ret);
                     lk.unlock();
-                    parent->notifyError(
-                            /*frameNum*/req.frameNumber,
-                            /*stream*/-1,
-                            ErrorCode::ERROR_DEVICE);
-
-                    return false;
+                    return onDeviceError("%s: createJpegLocked failed with %d",
+                          __FUNCTION__, ret);
                 }
             } break;
             case PixelFormat::YCBCR_420_888:
@@ -1587,21 +1674,15 @@
                         Size { halBuf.width, halBuf.height },
                         &cropAndScaled);
                 if (ret != 0) {
-                    ALOGE("%s: crop and scale failed!", __FUNCTION__);
                     lk.unlock();
-                    parent->notifyError(
-                            /*frameNum*/req.frameNumber, /*stream*/-1, ErrorCode::ERROR_DEVICE);
-                    return false;
+                    return onDeviceError("%s: crop and scale failed!", __FUNCTION__);
                 }
 
                 Size sz {halBuf.width, halBuf.height};
                 ret = formatConvertLocked(cropAndScaled, outLayout, sz, outputFourcc);
                 if (ret != 0) {
-                    ALOGE("%s: format coversion failed!", __FUNCTION__);
                     lk.unlock();
-                    parent->notifyError(
-                            /*frameNum*/req.frameNumber, /*stream*/-1, ErrorCode::ERROR_DEVICE);
-                    return false;
+                    return onDeviceError("%s: format coversion failed!", __FUNCTION__);
                 }
                 int relFence = sHandleImporter.unlock(*(halBuf.bufPtr));
                 if (relFence > 0) {
@@ -1609,11 +1690,8 @@
                 }
             } break;
             default:
-                ALOGE("%s: unknown output format %x", __FUNCTION__, halBuf.format);
                 lk.unlock();
-                parent->notifyError(
-                        /*frameNum*/req.frameNumber, /*stream*/-1, ErrorCode::ERROR_DEVICE);
-                return false;
+                return onDeviceError("%s: unknown output format %x", __FUNCTION__, halBuf.format);
         }
     } // for each buffer
     mScaledYu12Frames.clear();
@@ -1622,18 +1700,16 @@
     lk.unlock();
     Status st = parent->processCaptureResult(req);
     if (st != Status::OK) {
-        ALOGE("%s: failed to process capture result!", __FUNCTION__);
-        parent->notifyError(
-                /*frameNum*/req.frameNumber, /*stream*/-1, ErrorCode::ERROR_DEVICE);
-        return false;
+        return onDeviceError("%s: failed to process capture result!", __FUNCTION__);
     }
+    signalRequestDone();
     return true;
 }
 
 Status ExternalCameraDeviceSession::OutputThread::allocateIntermediateBuffers(
         const Size& v4lSize, const Size& thumbSize,
         const hidl_vec<Stream>& streams) {
-    std::lock_guard<std::mutex> lk(mLock);
+    std::lock_guard<std::mutex> lk(mBufferLock);
     if (mScaledYu12Frames.size() != 0) {
         ALOGE("%s: intermediate buffer pool has %zu inflight buffers! (expect 0)",
                 __FUNCTION__, mScaledYu12Frames.size());
@@ -1704,37 +1780,88 @@
     return Status::OK;
 }
 
-Status ExternalCameraDeviceSession::OutputThread::submitRequest(const HalRequest& req) {
-    std::lock_guard<std::mutex> lk(mLock);
-    // TODO: reduce object copy in this path
+Status ExternalCameraDeviceSession::OutputThread::submitRequest(
+        const std::shared_ptr<HalRequest>& req) {
+    std::unique_lock<std::mutex> lk(mRequestListLock);
     mRequestList.push_back(req);
+    lk.unlock();
     mRequestCond.notify_one();
     return Status::OK;
 }
 
 void ExternalCameraDeviceSession::OutputThread::flush() {
-    std::lock_guard<std::mutex> lk(mLock);
-    // TODO: send buffer/request errors back to framework
+    auto parent = mParent.promote();
+    if (parent == nullptr) {
+       ALOGE("%s: session has been disconnected!", __FUNCTION__);
+       return;
+    }
+
+    std::unique_lock<std::mutex> lk(mRequestListLock);
+    std::list<std::shared_ptr<HalRequest>> reqs = std::move(mRequestList);
     mRequestList.clear();
+    if (mProcessingRequest) {
+        std::chrono::seconds timeout = std::chrono::seconds(kFlushWaitTimeoutSec);
+        auto st = mRequestDoneCond.wait_for(lk, timeout);
+        if (st == std::cv_status::timeout) {
+            ALOGE("%s: wait for inflight request finish timeout!", __FUNCTION__);
+        }
+    }
+
+    lk.unlock();
+    for (const auto& req : reqs) {
+        parent->processCaptureRequestError(req);
+    }
 }
 
-void ExternalCameraDeviceSession::OutputThread::waitForNextRequest(HalRequest* out) {
+void ExternalCameraDeviceSession::OutputThread::waitForNextRequest(
+        std::shared_ptr<HalRequest>* out) {
     if (out == nullptr) {
         ALOGE("%s: out is null", __FUNCTION__);
         return;
     }
 
-    std::unique_lock<std::mutex> lk(mLock);
+    std::unique_lock<std::mutex> lk(mRequestListLock);
+    int waitTimes = 0;
     while (mRequestList.empty()) {
-        std::chrono::seconds timeout = std::chrono::seconds(kReqWaitTimeoutSec);
+        if (exitPending()) {
+            return;
+        }
+        std::chrono::milliseconds timeout = std::chrono::milliseconds(kReqWaitTimeoutMs);
         auto st = mRequestCond.wait_for(lk, timeout);
         if (st == std::cv_status::timeout) {
-            // no new request, return
-            return;
+            waitTimes++;
+            if (waitTimes == kReqWaitTimesMax) {
+                // no new request, return
+                return;
+            }
         }
     }
     *out = mRequestList.front();
     mRequestList.pop_front();
+    mProcessingRequest = true;
+    mProcessingFrameNumer = (*out)->frameNumber;
+}
+
+void ExternalCameraDeviceSession::OutputThread::signalRequestDone() {
+    std::unique_lock<std::mutex> lk(mRequestListLock);
+    mProcessingRequest = false;
+    mProcessingFrameNumer = 0;
+    lk.unlock();
+    mRequestDoneCond.notify_one();
+}
+
+void ExternalCameraDeviceSession::OutputThread::dump(int fd) {
+    std::lock_guard<std::mutex> lk(mRequestListLock);
+    if (mProcessingRequest) {
+        dprintf(fd, "OutputThread processing frame %d\n", mProcessingFrameNumer);
+    } else {
+        dprintf(fd, "OutputThread not processing any frames\n");
+    }
+    dprintf(fd, "OutputThread request list contains frame: ");
+    for (const auto& req : mRequestList) {
+        dprintf(fd, "%d, ", req->frameNumber);
+    }
+    dprintf(fd, "\n");
 }
 
 void ExternalCameraDeviceSession::cleanupBuffersLocked(int id) {
@@ -1893,7 +2020,8 @@
     float fps = 1000.f;
     const float kDefaultFps = 30.f;
     // Try to pick the slowest fps that is at least 30
-    for (const auto& f : v4l2Fmt.frameRates) {
+    for (const auto& fr : v4l2Fmt.frameRates) {
+        double f = fr.getDouble();
         if (maxFps < f) {
             maxFps = f;
         }
@@ -1997,15 +2125,25 @@
     return OK;
 }
 
-sp<V4L2Frame> ExternalCameraDeviceSession::dequeueV4l2FrameLocked() {
+sp<V4L2Frame> ExternalCameraDeviceSession::dequeueV4l2FrameLocked(/*out*/nsecs_t* shutterTs) {
     sp<V4L2Frame> ret = nullptr;
 
+    if (shutterTs == nullptr) {
+        ALOGE("%s: shutterTs must not be null!", __FUNCTION__);
+        return ret;
+    }
+
     {
         std::unique_lock<std::mutex> lk(mV4l2BufferLock);
         if (mNumDequeuedV4l2Buffers == mV4L2BufferCount) {
             std::chrono::seconds timeout = std::chrono::seconds(kBufferWaitTimeoutSec);
             mLock.unlock();
             auto st = mV4L2BufferReturned.wait_for(lk, timeout);
+            // Here we introduce a case where mV4l2BufferLock is acquired before mLock, while
+            // the normal lock acquisition order is reversed, but this is fine because in most of
+            // cases we are protected by mInterfaceLock. The only thread that can compete these
+            // locks are the OutputThread, where we do need to make sure we don't acquire mLock then
+            // mV4l2BufferLock
             mLock.lock();
             if (st == std::cv_status::timeout) {
                 ALOGE("%s: wait for V4L2 buffer return timeout!", __FUNCTION__);
@@ -2032,6 +2170,15 @@
         // TODO: try to dequeue again
     }
 
+    if (buffer.flags & V4L2_BUF_FLAG_TIMESTAMP_MONOTONIC) {
+        // Ideally we should also check for V4L2_BUF_FLAG_TSTAMP_SRC_SOE, but
+        // even V4L2_BUF_FLAG_TSTAMP_SRC_EOF is better than capture a timestamp now
+        *shutterTs = static_cast<nsecs_t>(buffer.timestamp.tv_sec)*1000000000LL +
+                buffer.timestamp.tv_usec * 1000LL;
+    } else {
+        *shutterTs = systemTime(SYSTEM_TIME_MONOTONIC);
+    }
+
     {
         std::lock_guard<std::mutex> lk(mV4l2BufferLock);
         mNumDequeuedV4l2Buffers++;
@@ -2042,22 +2189,27 @@
 }
 
 void ExternalCameraDeviceSession::enqueueV4l2Frame(const sp<V4L2Frame>& frame) {
-    Mutex::Autolock _l(mLock);
-    frame->unmap();
-    v4l2_buffer buffer{};
-    buffer.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
-    buffer.memory = V4L2_MEMORY_MMAP;
-    buffer.index = frame->mBufferIndex;
-    if (TEMP_FAILURE_RETRY(ioctl(mV4l2Fd.get(), VIDIOC_QBUF, &buffer)) < 0) {
-        ALOGE("%s: QBUF index %d fails: %s", __FUNCTION__, frame->mBufferIndex, strerror(errno));
-        return;
+    {
+        // Release mLock before acquiring mV4l2BufferLock to avoid potential
+        // deadlock
+        Mutex::Autolock _l(mLock);
+        frame->unmap();
+        v4l2_buffer buffer{};
+        buffer.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
+        buffer.memory = V4L2_MEMORY_MMAP;
+        buffer.index = frame->mBufferIndex;
+        if (TEMP_FAILURE_RETRY(ioctl(mV4l2Fd.get(), VIDIOC_QBUF, &buffer)) < 0) {
+            ALOGE("%s: QBUF index %d fails: %s", __FUNCTION__,
+                    frame->mBufferIndex, strerror(errno));
+            return;
+        }
     }
 
     {
         std::lock_guard<std::mutex> lk(mV4l2BufferLock);
         mNumDequeuedV4l2Buffers--;
-        mV4L2BufferReturned.notify_one();
     }
+    mV4L2BufferReturned.notify_one();
 }
 
 Status ExternalCameraDeviceSession::configureStreams(
@@ -2335,8 +2487,8 @@
     bool support30Fps = false;
     int32_t maxFps = std::numeric_limits<int32_t>::min();
     for (const auto& supportedFormat : mSupportedFormats) {
-        for (const auto& frameRate : supportedFormat.frameRates) {
-            int32_t framerateInt = static_cast<int32_t>(frameRate);
+        for (const auto& fr : supportedFormat.frameRates) {
+            int32_t framerateInt = static_cast<int32_t>(fr.getDouble());
             if (maxFps < framerateInt) {
                 maxFps = framerateInt;
             }
diff --git a/camera/device/3.4/default/ExternalCameraUtils.cpp b/camera/device/3.4/default/ExternalCameraUtils.cpp
index 80f296c..d28a4dd 100644
--- a/camera/device/3.4/default/ExternalCameraUtils.cpp
+++ b/camera/device/3.4/default/ExternalCameraUtils.cpp
@@ -147,6 +147,10 @@
     return (std::abs(ar1 - ar2) < kAspectRatioMatchThres);
 }
 
+double SupportedV4L2Format::FrameRate::getDouble() const {
+    return durationDenominator / static_cast<double>(durationNumerator);
+}
+
 }  // namespace implementation
 }  // namespace V3_4
 }  // namespace device
@@ -247,7 +251,7 @@
             limit.size = {
                 row->UnsignedAttribute("width", /*Default*/0),
                 row->UnsignedAttribute("height", /*Default*/0)};
-            limit.fpsUpperBound = row->FloatAttribute("fpsBound", /*Default*/1000.0);
+            limit.fpsUpperBound = row->DoubleAttribute("fpsBound", /*Default*/1000.0);
             if (limit.size.width <= prevLimit.size.width ||
                     limit.size.height <= prevLimit.size.height ||
                     limit.fpsUpperBound >= prevLimit.fpsUpperBound) {
diff --git a/camera/device/3.4/default/include/ext_device_v3_4_impl/ExternalCameraDeviceSession.h b/camera/device/3.4/default/include/ext_device_v3_4_impl/ExternalCameraDeviceSession.h
index a7eb121..9c0ad7f 100644
--- a/camera/device/3.4/default/include/ext_device_v3_4_impl/ExternalCameraDeviceSession.h
+++ b/camera/device/3.4/default/include/ext_device_v3_4_impl/ExternalCameraDeviceSession.h
@@ -91,6 +91,7 @@
             const std::vector<SupportedV4L2Format>& sortedFormats,
             const CroppingType& croppingType,
             const common::V1_0::helper::CameraMetadata& chars,
+            const std::string& cameraId,
             unique_fd v4l2Fd);
     virtual ~ExternalCameraDeviceSession();
     // Call by CameraDevice to dump active device states
@@ -180,7 +181,7 @@
     int v4l2StreamOffLocked();
 
     // TODO: change to unique_ptr for better tracking
-    sp<V4L2Frame> dequeueV4l2FrameLocked(); // Called with mLock hold
+    sp<V4L2Frame> dequeueV4l2FrameLocked(/*out*/nsecs_t* shutterTs); // Called with mLock hold
     void enqueueV4l2Frame(const sp<V4L2Frame>&);
 
     // Check if input Stream is one of supported stream setting on this device
@@ -198,8 +199,8 @@
 
     Status processOneCaptureRequest(const CaptureRequest& request);
 
-    Status processCaptureResult(HalRequest&);
-    Status processCaptureRequestError(HalRequest&);
+    Status processCaptureResult(std::shared_ptr<HalRequest>&);
+    Status processCaptureRequestError(const std::shared_ptr<HalRequest>&);
     void notifyShutter(uint32_t frameNumber, nsecs_t shutterTs);
     void notifyError(uint32_t frameNumber, int32_t streamId, ErrorCode ec);
     void invokeProcessCaptureResultCallback(
@@ -219,8 +220,9 @@
         Status allocateIntermediateBuffers(
                 const Size& v4lSize, const Size& thumbSize,
                 const hidl_vec<Stream>& streams);
-        Status submitRequest(const HalRequest&);
+        Status submitRequest(const std::shared_ptr<HalRequest>&);
         void flush();
+        void dump(int fd);
         virtual bool threadLoop() override;
 
     private:
@@ -232,9 +234,13 @@
         static int getCropRect(
                 CroppingType ct, const Size& inSize, const Size& outSize, IMapper::Rect* out);
 
-        static const int kReqWaitTimeoutSec = 3;
+        static const int kFlushWaitTimeoutSec = 3; // 3 sec
+        static const int kReqWaitTimeoutMs = 33;   // 33ms
+        static const int kReqWaitTimesMax = 90;    // 33ms * 90 ~= 3 sec
 
-        void waitForNextRequest(HalRequest* out);
+        void waitForNextRequest(std::shared_ptr<HalRequest>* out);
+        void signalRequestDone();
+
         int cropAndScaleLocked(
                 sp<AllocatedFrame>& in, const Size& outSize,
                 YCbCrLayout* out);
@@ -252,17 +258,24 @@
                 void *out, size_t maxOutSize,
                 size_t &actualCodeSize);
 
-        int createJpegLocked(HalStreamBuffer &halBuf, HalRequest &req);
+        int createJpegLocked(HalStreamBuffer &halBuf, const std::shared_ptr<HalRequest>& req);
 
-        mutable std::mutex mLock;
-        std::condition_variable mRequestCond;
-        wp<ExternalCameraDeviceSession> mParent;
-        CroppingType mCroppingType;
-        std::list<HalRequest> mRequestList;
+        const wp<ExternalCameraDeviceSession> mParent;
+        const CroppingType mCroppingType;
+
+        mutable std::mutex mRequestListLock;      // Protect acccess to mRequestList,
+                                                  // mProcessingRequest and mProcessingFrameNumer
+        std::condition_variable mRequestCond;     // signaled when a new request is submitted
+        std::condition_variable mRequestDoneCond; // signaled when a request is done processing
+        std::list<std::shared_ptr<HalRequest>> mRequestList;
+        bool mProcessingRequest = false;
+        uint32_t mProcessingFrameNumer = 0;
+
         // V4L2 frameIn
         // (MJPG decode)-> mYu12Frame
         // (Scale)-> mScaledYu12Frames
         // (Format convert) -> output gralloc frames
+        mutable std::mutex mBufferLock; // Protect access to intermediate buffers
         sp<AllocatedFrame> mYu12Frame;
         sp<AllocatedFrame> mYu12ThumbFrame;
         std::unordered_map<Size, sp<AllocatedFrame>, SizeHasher> mIntermediateBuffers;
@@ -280,7 +293,9 @@
     const common::V1_0::helper::CameraMetadata mCameraCharacteristics;
     const std::vector<SupportedV4L2Format> mSupportedFormats;
     const CroppingType mCroppingType;
+    const std::string& mCameraId;
     unique_fd mV4l2Fd;
+
     // device is closed either
     //    - closed by user
     //    - init failed
@@ -299,6 +314,7 @@
     std::condition_variable mV4L2BufferReturned;
     size_t mNumDequeuedV4l2Buffers = 0;
 
+    // Not protected by mLock (but might be used when mLock is locked)
     sp<OutputThread> mOutputThread;
 
     // Stream ID -> Camera3Stream cache
diff --git a/camera/device/3.4/default/include/ext_device_v3_4_impl/ExternalCameraUtils.h b/camera/device/3.4/default/include/ext_device_v3_4_impl/ExternalCameraUtils.h
index e56160a..37e7cfb 100644
--- a/camera/device/3.4/default/include/ext_device_v3_4_impl/ExternalCameraUtils.h
+++ b/camera/device/3.4/default/include/ext_device_v3_4_impl/ExternalCameraUtils.h
@@ -73,7 +73,7 @@
 
     struct FpsLimitation {
         Size size;
-        float fpsUpperBound;
+        double fpsUpperBound;
     };
     std::vector<FpsLimitation> fpsLimits;
 
@@ -93,7 +93,12 @@
     uint32_t height;
     uint32_t fourcc;
     // All supported frame rate for this w/h/fourcc combination
-    std::vector<float> frameRates;
+    struct FrameRate {
+        uint32_t durationNumerator;   // frame duration numerator.   Ex: 1
+        uint32_t durationDenominator; // frame duration denominator. Ex: 30
+        double getDouble() const;     // FrameRate in double.        Ex: 30.0
+    };
+    std::vector<FrameRate> frameRates;
 };
 
 // A class provide access to a dequeued V4L2 frame buffer (mostly in MJPG format)
diff --git a/camera/device/3.4/types.hal b/camera/device/3.4/types.hal
index 5681a5c..bf2b3fc 100644
--- a/camera/device/3.4/types.hal
+++ b/camera/device/3.4/types.hal
@@ -177,9 +177,14 @@
 
     /**
      * If fmqSettingsSize is zero, the settings buffer contains the capture and
-     * processing parameters for the physical device with id 'phyCamId'.
-     * In case the individual settings are empty or missing, Hal should fail the
-     * request and return Status::ILLEGAL_ARGUMENT.
+     * processing parameters for the physical device with id 'physicalCameraId'.
+     * As a special case, an empty settings buffer indicates that the
+     * settings are identical to the most-recently submitted capture request.
+     * An empty buffer cannot be used as the first submitted request after
+     * a configureStreams() call.
+     *
+     * This field must be used if fmqSettingsSize is zero. It must not be used
+     * if fmqSettingsSize is non-zero.
      */
     CameraMetadata settings;
 };
diff --git a/camera/provider/2.4/ICameraProvider.hal b/camera/provider/2.4/ICameraProvider.hal
index 3015b7d..abb6366 100644
--- a/camera/provider/2.4/ICameraProvider.hal
+++ b/camera/provider/2.4/ICameraProvider.hal
@@ -35,22 +35,23 @@
  * where
  *   - <major>/<minor> is the provider HAL HIDL version,
  *   - <type> is the type of devices this provider knows about, such as
- *     "internal", "legacy", "usb", or "remote"
+ *     "internal", "legacy", "external", or "remote"
  *   - <instance> is a non-negative integer starting from 0 to disambiguate
  *     between multiple HALs of the same type.
  *
  * The "legacy" type is only used for passthrough legacy HAL mode, and must
  * not be used by a standalone binderized HAL.
  *
- * The device instance names enumerated by the provider must be of the form
+ * The device instance names enumerated by the provider in getCameraIdList() or
+ * ICameraProviderCallback::cameraDeviceStatusChange() must be of the form
  * "device@<major>.<minor>/<type>/<id>" where
  * <major>/<minor> is the HIDL version of the interface. <id> is either a small
  * incrementing integer for "internal" device types, with 0 being the main
  * back-facing camera and 1 being the main front-facing camera, if they exist.
- * Or, for external devices such as type "usb", a unique serial number that can
- * be used to identify the device reliably when it is disconnected and
- * reconnected. Multiple providers may not enumerate the same device ID.
+ * Or, for external devices, a unique serial number (if possible) that can be
+ * used to identify the device reliably when it is disconnected and reconnected.
  *
+ * Multiple providers must not enumerate the same device ID.
  */
 interface ICameraProvider {
 
@@ -97,7 +98,7 @@
     getVendorTags() generates (Status status, vec<VendorTagSection> sections);
 
     /**
-     * getCameraDeviceList:
+     * getCameraIdList:
      *
      * Returns the list of internal camera device interfaces known to this
      * camera provider. These devices can then be accessed via the hardware
diff --git a/camera/provider/2.4/vts/functional/VtsHalCameraProviderV2_4TargetTest.cpp b/camera/provider/2.4/vts/functional/VtsHalCameraProviderV2_4TargetTest.cpp
index 1405ea9..e78dbe8 100644
--- a/camera/provider/2.4/vts/functional/VtsHalCameraProviderV2_4TargetTest.cpp
+++ b/camera/provider/2.4/vts/functional/VtsHalCameraProviderV2_4TargetTest.cpp
@@ -116,6 +116,7 @@
 const int64_t kTorchTimeoutSec = 1;
 const int64_t kEmptyFlushTimeoutMSec = 200;
 const char kDumpOutput[] = "/dev/null";
+const uint32_t kBurstFrameCount = 10;
 
 struct AvailableStream {
     int32_t width;
@@ -655,6 +656,13 @@
     static Status isLogicalMultiCamera(camera_metadata_t *staticMeta);
     static Status getPhysicalCameraIds(camera_metadata_t *staticMeta,
             std::unordered_set<std::string> *physicalIds/*out*/);
+    static Status getSupportedKeys(camera_metadata_t *staticMeta,
+            uint32_t tagId, std::unordered_set<int32_t> *requestIDs/*out*/);
+    static void constructFilteredSettings(const sp<ICameraDeviceSession>& session,
+            const std::unordered_set<int32_t>& availableKeys, RequestTemplate reqTemplate,
+            android::hardware::camera::common::V1_0::helper::CameraMetadata* defaultSettings/*out*/,
+            android::hardware::camera::common::V1_0::helper::CameraMetadata* filteredSettings
+            /*out*/);
     static Status pickConstrainedModeSize(camera_metadata_t *staticMeta,
             AvailableStream &hfrStream);
     static Status isZSLModeAvailable(camera_metadata_t *staticMeta);
@@ -712,6 +720,20 @@
         // return from HAL but framework.
         ::android::Vector<StreamBuffer> resultOutputBuffers;
 
+        InFlightRequest() :
+                shutterTimestamp(0),
+                errorCodeValid(false),
+                errorCode(ErrorCode::ERROR_BUFFER),
+                usePartialResult(false),
+                numPartialResults(0),
+                resultQueue(nullptr),
+                haveResultMetadata(false),
+                numBuffersLeft(0),
+                frameNumber(0),
+                partialResultCount(0),
+                errorStreamId(-1),
+                hasInputBuffer(false) {}
+
         InFlightRequest(ssize_t numBuffers, bool hasInput,
                 bool partialResults, uint32_t partialCount,
                 std::shared_ptr<ResultMetadataQueue> queue = nullptr) :
@@ -2748,42 +2770,23 @@
         castSession(session, deviceVersion, &session3_3, &session3_4);
         ASSERT_NE(session3_4, nullptr);
 
-        const android::hardware::camera::common::V1_0::helper::CameraMetadata staticMeta(
-                staticMetaBuffer);
-        camera_metadata_ro_entry availableSessionKeys = staticMeta.find(
-                ANDROID_REQUEST_AVAILABLE_SESSION_KEYS);
-        if (availableSessionKeys.count == 0) {
+        std::unordered_set<int32_t> availableSessionKeys;
+        auto rc = getSupportedKeys(staticMetaBuffer, ANDROID_REQUEST_AVAILABLE_SESSION_KEYS,
+                &availableSessionKeys);
+        ASSERT_TRUE(Status::OK == rc);
+        if (availableSessionKeys.empty()) {
+            free_camera_metadata(staticMetaBuffer);
             ret = session->close();
             ASSERT_TRUE(ret.isOk());
             continue;
         }
 
         android::hardware::camera::common::V1_0::helper::CameraMetadata previewRequestSettings;
-        ret = session->constructDefaultRequestSettings(RequestTemplate::PREVIEW,
-                [&previewRequestSettings] (auto status, const auto& req) mutable {
-                    ASSERT_EQ(Status::OK, status);
-
-                    const camera_metadata_t *metadata = reinterpret_cast<const camera_metadata_t*> (
-                            req.data());
-                    size_t expectedSize = req.size();
-                    int result = validate_camera_metadata_structure(metadata, &expectedSize);
-                    ASSERT_TRUE((result == 0) || (result == CAMERA_METADATA_VALIDATION_SHIFTED));
-
-                    size_t entryCount = get_camera_metadata_entry_count(metadata);
-                    ASSERT_GT(entryCount, 0u);
-                    previewRequestSettings = metadata;
-                    });
-        ASSERT_TRUE(ret.isOk());
-        const android::hardware::camera::common::V1_0::helper::CameraMetadata &constSettings =
-            previewRequestSettings;
         android::hardware::camera::common::V1_0::helper::CameraMetadata sessionParams;
-        for (size_t i = 0; i < availableSessionKeys.count; i++) {
-            camera_metadata_ro_entry entry = constSettings.find(availableSessionKeys.data.i32[i]);
-            if (entry.count > 0) {
-                sessionParams.update(entry);
-            }
-        }
+        constructFilteredSettings(session, availableSessionKeys, RequestTemplate::PREVIEW,
+                &previewRequestSettings, &sessionParams);
         if (sessionParams.isEmpty()) {
+            free_camera_metadata(staticMetaBuffer);
             ret = session->close();
             ASSERT_TRUE(ret.isOk());
             continue;
@@ -2817,7 +2820,7 @@
                 });
         ASSERT_TRUE(ret.isOk());
 
-        sessionParams.unlock(sessionParamsBuffer);
+        free_camera_metadata(staticMetaBuffer);
         ret = session->close();
         ASSERT_TRUE(ret.isOk());
     }
@@ -3350,6 +3353,8 @@
         if (deviceVersion < CAMERA_DEVICE_API_VERSION_3_4) {
             continue;
         }
+        std::string version, deviceId;
+        ASSERT_TRUE(::matchDeviceName(name, mProviderType, &version, &deviceId));
         camera_metadata_t* staticMeta;
         Return<void> ret;
         sp<ICameraDeviceSession> session;
@@ -3357,6 +3362,7 @@
 
         Status rc = isLogicalMultiCamera(staticMeta);
         if (Status::METHOD_NOT_SUPPORTED == rc) {
+            free_camera_metadata(staticMeta);
             ret = session->close();
             ASSERT_TRUE(ret.isOk());
             continue;
@@ -3366,13 +3372,45 @@
         ASSERT_TRUE(Status::OK == rc);
         ASSERT_TRUE(physicalIds.size() > 1);
 
+        std::unordered_set<int32_t> physicalRequestKeyIDs;
+        rc = getSupportedKeys(staticMeta,
+                ANDROID_REQUEST_AVAILABLE_PHYSICAL_CAMERA_REQUEST_KEYS, &physicalRequestKeyIDs);
+        ASSERT_TRUE(Status::OK == rc);
+        if (physicalRequestKeyIDs.empty()) {
+            free_camera_metadata(staticMeta);
+            ret = session->close();
+            ASSERT_TRUE(ret.isOk());
+            // The logical camera doesn't support any individual physical requests.
+            continue;
+        }
+
+        android::hardware::camera::common::V1_0::helper::CameraMetadata defaultPreviewSettings;
+        android::hardware::camera::common::V1_0::helper::CameraMetadata filteredSettings;
+        constructFilteredSettings(session, physicalRequestKeyIDs, RequestTemplate::PREVIEW,
+                &defaultPreviewSettings, &filteredSettings);
+        if (filteredSettings.isEmpty()) {
+            // No physical device settings in default request.
+            free_camera_metadata(staticMeta);
+            ret = session->close();
+            ASSERT_TRUE(ret.isOk());
+            continue;
+        }
+
+        const camera_metadata_t *settingsBuffer = defaultPreviewSettings.getAndLock();
+        settings.setToExternal(
+                reinterpret_cast<uint8_t *> (const_cast<camera_metadata_t *> (settingsBuffer)),
+                get_camera_metadata_size(settingsBuffer));
+
         free_camera_metadata(staticMeta);
         ret = session->close();
         ASSERT_TRUE(ret.isOk());
 
-        // Leave only 2 physical devices in the id set.
-        auto it = physicalIds.begin(); it++; it++;
-        physicalIds.erase(it, physicalIds.end());
+        auto it = physicalIds.begin();
+        string physicalDeviceId = *it;
+        // Leave only the first physical device in the id set and insert the logical device.
+        physicalIds.erase(++it, physicalIds.end());
+        physicalIds.emplace(deviceId);
+        ASSERT_EQ(physicalIds.size(), 2u);
 
         V3_4::HalStreamConfiguration halStreamConfig;
         bool supportsPartialResults = false;
@@ -3400,38 +3438,34 @@
                 });
         ASSERT_TRUE(resultQueueRet.isOk());
 
-        InFlightRequest inflightReq = {static_cast<ssize_t> (physicalIds.size()), false,
+        InFlightRequest inflightReq = {static_cast<ssize_t> (halStreamConfig.streams.size()), false,
             supportsPartialResults, partialResultCount, resultQueue};
 
-        RequestTemplate reqTemplate = RequestTemplate::PREVIEW;
-        ret = session3_4->constructDefaultRequestSettings(reqTemplate,
-                                                       [&](auto status, const auto& req) {
-                                                           ASSERT_EQ(Status::OK, status);
-                                                           settings = req;
-                                                       });
-        ASSERT_TRUE(ret.isOk());
-        ASSERT_TRUE(settings.size() > 0);
-
         std::vector<sp<GraphicBuffer>> graphicBuffers;
-        graphicBuffers.reserve(physicalIds.size());
+        graphicBuffers.reserve(halStreamConfig.streams.size());
         ::android::hardware::hidl_vec<StreamBuffer> outputBuffers;
-        outputBuffers.resize(physicalIds.size());
-        hidl_vec<V3_4::PhysicalCameraSetting> camSettings;
-        camSettings.resize(physicalIds.size());
+        outputBuffers.resize(halStreamConfig.streams.size());
         size_t k = 0;
-        for (const auto physicalIdIt : physicalIds) {
+        for (const auto& halStream : halStreamConfig.streams) {
             sp<GraphicBuffer> gb = new GraphicBuffer(previewStream.width, previewStream.height,
-                    static_cast<int32_t>(halStreamConfig.streams[k].v3_3.v3_2.overrideFormat), 1,
+                    static_cast<int32_t>(halStream.v3_3.v3_2.overrideFormat), 1,
                     android_convertGralloc1To0Usage(
-                        halStreamConfig.streams[k].v3_3.v3_2.producerUsage,
-                        halStreamConfig.streams[k].v3_3.v3_2.consumerUsage));
+                        halStream.v3_3.v3_2.producerUsage, halStream.v3_3.v3_2.consumerUsage));
             ASSERT_NE(nullptr, gb.get());
-            outputBuffers[k] = {halStreamConfig.streams[k].v3_3.v3_2.id, bufferId,
-                hidl_handle(gb->getNativeBuffer()->handle), BufferStatus::OK, nullptr, nullptr};
             graphicBuffers.push_back(gb);
-            camSettings[k] = {0, hidl_string(physicalIdIt), settings};
+            outputBuffers[k] = {halStream.v3_3.v3_2.id, bufferId,
+                hidl_handle(gb->getNativeBuffer()->handle), BufferStatus::OK, nullptr, nullptr};
+            bufferId++;
             k++;
         }
+        hidl_vec<V3_4::PhysicalCameraSetting> camSettings(1);
+        const camera_metadata_t *filteredSettingsBuffer = filteredSettings.getAndLock();
+        camSettings[0].settings.setToExternal(
+                reinterpret_cast<uint8_t *> (const_cast<camera_metadata_t *> (
+                        filteredSettingsBuffer)),
+                get_camera_metadata_size(filteredSettingsBuffer));
+        camSettings[0].fmqSettingsSize = 0;
+        camSettings[0].physicalCameraId = physicalDeviceId;
 
         StreamBuffer emptyInputBuffer = {-1, 0, nullptr, BufferStatus::ERROR, nullptr, nullptr};
         V3_4::CaptureRequest request = {{frameNumber, 0 /* fmqSettingsSize */, settings,
@@ -3468,24 +3502,49 @@
 
             ASSERT_FALSE(inflightReq.errorCodeValid);
             ASSERT_NE(inflightReq.resultOutputBuffers.size(), 0u);
+
+            request.v3_2.frameNumber++;
+            // Empty settings should be supported after the first call
+            // for repeating requests.
+            request.v3_2.settings.setToExternal(nullptr, 0, true);
+            request.physicalCameraSettings[0].settings.setToExternal(nullptr, 0, true);
+            // The buffer has been registered to HAL by bufferId, so per
+            // API contract we should send a null handle for this buffer
+            request.v3_2.outputBuffers[0].buffer = nullptr;
+            mInflightMap.clear();
+            inflightReq = {static_cast<ssize_t> (physicalIds.size()), false,
+                supportsPartialResults, partialResultCount, resultQueue};
+            mInflightMap.add(request.v3_2.frameNumber, &inflightReq);
         }
 
-        // Empty physical camera settings should fail process requests
-        camSettings[1].settings = emptySettings;
-        frameNumber++;
-        request = {{frameNumber, 0 /* fmqSettingsSize */, settings,
-            emptyInputBuffer, outputBuffers}, camSettings};
         returnStatus = session3_4->processCaptureRequest_3_4(
             {request}, cachesToRemove, [&stat, &numRequestProcessed](auto s, uint32_t n) {
                 stat = s;
                 numRequestProcessed = n;
             });
         ASSERT_TRUE(returnStatus.isOk());
-        ASSERT_EQ(Status::ILLEGAL_ARGUMENT, stat);
+        ASSERT_EQ(Status::OK, stat);
+        ASSERT_EQ(numRequestProcessed, 1u);
+
+        {
+            std::unique_lock<std::mutex> l(mLock);
+            while (!inflightReq.errorCodeValid &&
+                    ((0 < inflightReq.numBuffersLeft) ||
+                     (!inflightReq.haveResultMetadata))) {
+                auto timeout = std::chrono::system_clock::now() +
+                    std::chrono::seconds(kStreamBufferTimeoutSec);
+                ASSERT_NE(std::cv_status::timeout,
+                        mResultCondition.wait_until(l, timeout));
+            }
+
+            ASSERT_FALSE(inflightReq.errorCodeValid);
+            ASSERT_NE(inflightReq.resultOutputBuffers.size(), 0u);
+        }
 
         // Invalid physical camera id should fail process requests
-        camSettings[1].physicalCameraId = invalidPhysicalId;
-        camSettings[1].settings = settings;
+        frameNumber++;
+        camSettings[0].physicalCameraId = invalidPhysicalId;
+        camSettings[0].settings = settings;
         request = {{frameNumber, 0 /* fmqSettingsSize */, settings,
             emptyInputBuffer, outputBuffers}, camSettings};
         returnStatus = session3_4->processCaptureRequest_3_4(
@@ -3496,11 +3555,158 @@
         ASSERT_TRUE(returnStatus.isOk());
         ASSERT_EQ(Status::ILLEGAL_ARGUMENT, stat);
 
+        defaultPreviewSettings.unlock(settingsBuffer);
+        filteredSettings.unlock(filteredSettingsBuffer);
         ret = session3_4->close();
         ASSERT_TRUE(ret.isOk());
     }
 }
 
+// Generate and verify a burst containing alternating sensor sensitivity values
+TEST_F(CameraHidlTest, processCaptureRequestBurstISO) {
+    hidl_vec<hidl_string> cameraDeviceNames = getCameraDeviceNames(mProvider);
+    AvailableStream previewThreshold = {kMaxPreviewWidth, kMaxPreviewHeight,
+                                        static_cast<int32_t>(PixelFormat::IMPLEMENTATION_DEFINED)};
+    uint64_t bufferId = 1;
+    uint32_t frameNumber = 1;
+    ::android::hardware::hidl_vec<uint8_t> settings;
+
+    for (const auto& name : cameraDeviceNames) {
+        int deviceVersion = getCameraDeviceVersion(name, mProviderType);
+        if (deviceVersion == CAMERA_DEVICE_API_VERSION_1_0) {
+            continue;
+        } else if (deviceVersion <= 0) {
+            ALOGE("%s: Unsupported device version %d", __func__, deviceVersion);
+            ADD_FAILURE();
+            return;
+        }
+        camera_metadata_t* staticMetaBuffer;
+        Return<void> ret;
+        sp<ICameraDeviceSession> session;
+        openEmptyDeviceSession(name, mProvider, &session /*out*/, &staticMetaBuffer /*out*/);
+        ::android::hardware::camera::common::V1_0::helper::CameraMetadata staticMeta(
+                staticMetaBuffer);
+
+        camera_metadata_entry_t hwLevel = staticMeta.find(ANDROID_INFO_SUPPORTED_HARDWARE_LEVEL);
+        ASSERT_TRUE(0 < hwLevel.count);
+        if (ANDROID_INFO_SUPPORTED_HARDWARE_LEVEL_LIMITED == hwLevel.data.u8[0]) {
+            //Limited devices can skip this test
+            ret = session->close();
+            ASSERT_TRUE(ret.isOk());
+            continue;
+        }
+
+        camera_metadata_entry_t isoRange = staticMeta.find(ANDROID_SENSOR_INFO_SENSITIVITY_RANGE);
+        ASSERT_EQ(isoRange.count, 2u);
+
+        ret = session->close();
+        ASSERT_TRUE(ret.isOk());
+
+        bool supportsPartialResults = false;
+        uint32_t partialResultCount = 0;
+        V3_2::Stream previewStream;
+        HalStreamConfiguration halStreamConfig;
+        configurePreviewStream(name, deviceVersion, mProvider, &previewThreshold,
+                &session /*out*/, &previewStream /*out*/, &halStreamConfig /*out*/,
+                &supportsPartialResults /*out*/, &partialResultCount /*out*/);
+        std::shared_ptr<ResultMetadataQueue> resultQueue;
+
+        auto resultQueueRet = session->getCaptureResultMetadataQueue(
+            [&resultQueue](const auto& descriptor) {
+                resultQueue = std::make_shared<ResultMetadataQueue>(descriptor);
+                if (!resultQueue->isValid() || resultQueue->availableToWrite() <= 0) {
+                    ALOGE("%s: HAL returns empty result metadata fmq,"
+                            " not use it", __func__);
+                    resultQueue = nullptr;
+                    // Don't use the queue onwards.
+                }
+            });
+        ASSERT_TRUE(resultQueueRet.isOk());
+        ASSERT_NE(nullptr, resultQueue);
+
+        ret = session->constructDefaultRequestSettings(RequestTemplate::PREVIEW,
+            [&](auto status, const auto& req) {
+                ASSERT_EQ(Status::OK, status);
+                settings = req; });
+        ASSERT_TRUE(ret.isOk());
+
+        ::android::hardware::camera::common::V1_0::helper::CameraMetadata requestMeta;
+        StreamBuffer emptyInputBuffer = {-1, 0, nullptr, BufferStatus::ERROR, nullptr, nullptr};
+        sp<GraphicBuffer> buffers[kBurstFrameCount];
+        StreamBuffer outputBuffers[kBurstFrameCount];
+        CaptureRequest requests[kBurstFrameCount];
+        InFlightRequest inflightReqs[kBurstFrameCount];
+        int32_t isoValues[kBurstFrameCount];
+        hidl_vec<uint8_t> requestSettings[kBurstFrameCount];
+        for (uint32_t i = 0; i < kBurstFrameCount; i++) {
+            std::unique_lock<std::mutex> l(mLock);
+
+            isoValues[i] = ((i % 2) == 0) ? isoRange.data.i32[0] : isoRange.data.i32[1];
+            buffers[i] = new GraphicBuffer( previewStream.width, previewStream.height,
+                static_cast<int32_t>(halStreamConfig.streams[0].overrideFormat), 1,
+                android_convertGralloc1To0Usage( halStreamConfig.streams[0].producerUsage,
+                    halStreamConfig.streams[0].consumerUsage));
+            ASSERT_NE(nullptr, buffers[i].get());
+
+            outputBuffers[i] = {halStreamConfig.streams[0].id, bufferId + i,
+                hidl_handle( buffers[i]->getNativeBuffer()->handle), BufferStatus::OK, nullptr,
+                nullptr};
+            requestMeta.append(reinterpret_cast<camera_metadata_t *> (settings.data()));
+
+            // Disable all 3A routines
+            uint8_t mode = static_cast<uint8_t>(ANDROID_CONTROL_MODE_OFF);
+            ASSERT_EQ(::android::OK, requestMeta.update(ANDROID_CONTROL_MODE, &mode, 1));
+            ASSERT_EQ(::android::OK, requestMeta.update(ANDROID_SENSOR_SENSITIVITY, &isoValues[i],
+                        1));
+            camera_metadata_t *metaBuffer = requestMeta.release();
+            requestSettings[i].setToExternal(reinterpret_cast<uint8_t *> (metaBuffer),
+                    get_camera_metadata_size(metaBuffer), true);
+
+            requests[i] = {frameNumber + i, 0 /* fmqSettingsSize */, requestSettings[i],
+                emptyInputBuffer, {outputBuffers[i]}};
+
+            inflightReqs[i] = {1, false, supportsPartialResults, partialResultCount, resultQueue};
+            mInflightMap.add(frameNumber + i, &inflightReqs[i]);
+        }
+
+        Status status = Status::INTERNAL_ERROR;
+        uint32_t numRequestProcessed = 0;
+        hidl_vec<BufferCache> cachesToRemove;
+        hidl_vec<CaptureRequest> burstRequest;
+        burstRequest.setToExternal(requests, kBurstFrameCount);
+        Return<void> returnStatus = session->processCaptureRequest(burstRequest, cachesToRemove,
+                [&status, &numRequestProcessed] (auto s, uint32_t n) {
+                    status = s;
+                    numRequestProcessed = n;
+                });
+        ASSERT_TRUE(returnStatus.isOk());
+        ASSERT_EQ(Status::OK, status);
+        ASSERT_EQ(numRequestProcessed, kBurstFrameCount);
+
+        for (size_t i = 0; i < kBurstFrameCount; i++) {
+            std::unique_lock<std::mutex> l(mLock);
+            while (!inflightReqs[i].errorCodeValid && ((0 < inflightReqs[i].numBuffersLeft) ||
+                            (!inflightReqs[i].haveResultMetadata))) {
+                auto timeout = std::chrono::system_clock::now() +
+                        std::chrono::seconds(kStreamBufferTimeoutSec);
+                ASSERT_NE(std::cv_status::timeout, mResultCondition.wait_until(l, timeout));
+            }
+
+            ASSERT_FALSE(inflightReqs[i].errorCodeValid);
+            ASSERT_NE(inflightReqs[i].resultOutputBuffers.size(), 0u);
+            ASSERT_EQ(previewStream.id, inflightReqs[i].resultOutputBuffers[0].streamId);
+            ASSERT_FALSE(inflightReqs[i].collectedResult.isEmpty());
+            ASSERT_TRUE(inflightReqs[i].collectedResult.exists(ANDROID_SENSOR_SENSITIVITY));
+            camera_metadata_entry_t isoResult = inflightReqs[i].collectedResult.find(
+                    ANDROID_SENSOR_SENSITIVITY);
+            ASSERT_TRUE(isoResult.data.i32[0] == isoValues[i]);
+        }
+
+        ret = session->close();
+        ASSERT_TRUE(ret.isOk());
+    }
+}
+
 // Test whether an incorrect capture request with missing settings will
 // be reported correctly.
 TEST_F(CameraHidlTest, processCaptureRequestInvalidSinglePreview) {
@@ -3901,6 +4107,56 @@
     return Status::OK;
 }
 
+// Generate a set of suported camera key ids.
+Status CameraHidlTest::getSupportedKeys(camera_metadata_t *staticMeta,
+        uint32_t tagId, std::unordered_set<int32_t> *requestIDs) {
+    if ((nullptr == staticMeta) || (nullptr == requestIDs)) {
+        return Status::ILLEGAL_ARGUMENT;
+    }
+
+    camera_metadata_ro_entry entry;
+    int rc = find_camera_metadata_ro_entry(staticMeta, tagId, &entry);
+    if ((0 != rc) || (entry.count == 0)) {
+        return Status::OK;
+    }
+
+    requestIDs->insert(entry.data.i32, entry.data.i32 + entry.count);
+
+    return Status::OK;
+}
+
+void CameraHidlTest::constructFilteredSettings(const sp<ICameraDeviceSession>& session,
+        const std::unordered_set<int32_t>& availableKeys, RequestTemplate reqTemplate,
+        android::hardware::camera::common::V1_0::helper::CameraMetadata* defaultSettings,
+        android::hardware::camera::common::V1_0::helper::CameraMetadata* filteredSettings) {
+    ASSERT_NE(defaultSettings, nullptr);
+    ASSERT_NE(filteredSettings, nullptr);
+
+    auto ret = session->constructDefaultRequestSettings(reqTemplate,
+            [&defaultSettings] (auto status, const auto& req) mutable {
+                ASSERT_EQ(Status::OK, status);
+
+                const camera_metadata_t *metadata = reinterpret_cast<const camera_metadata_t*> (
+                        req.data());
+                size_t expectedSize = req.size();
+                int result = validate_camera_metadata_structure(metadata, &expectedSize);
+                ASSERT_TRUE((result == 0) || (result == CAMERA_METADATA_VALIDATION_SHIFTED));
+
+                size_t entryCount = get_camera_metadata_entry_count(metadata);
+                ASSERT_GT(entryCount, 0u);
+                *defaultSettings = metadata;
+                });
+    ASSERT_TRUE(ret.isOk());
+    const android::hardware::camera::common::V1_0::helper::CameraMetadata &constSettings =
+        *defaultSettings;
+    for (const auto& keyIt : availableKeys) {
+        camera_metadata_ro_entry entry = constSettings.find(keyIt);
+        if (entry.count > 0) {
+            filteredSettings->update(entry);
+        }
+    }
+}
+
 // Check if constrained mode is supported by using the static
 // camera characteristics.
 Status CameraHidlTest::isConstrainedModeAvailable(camera_metadata_t *staticMeta) {
diff --git a/cas/1.0/vts/functional/Android.bp b/cas/1.0/vts/functional/Android.bp
index e1e09e9..0db9bb0 100644
--- a/cas/1.0/vts/functional/Android.bp
+++ b/cas/1.0/vts/functional/Android.bp
@@ -23,6 +23,7 @@
         "android.hardware.cas.native@1.0",
         "android.hidl.allocator@1.0",
         "android.hidl.memory@1.0",
+        "libhidlallocatorutils",
         "libhidlmemory",
     ],
     shared_libs: [
diff --git a/cas/1.0/vts/functional/VtsHalCasV1_0TargetTest.cpp b/cas/1.0/vts/functional/VtsHalCasV1_0TargetTest.cpp
index 053d37a..14b8bbd 100644
--- a/cas/1.0/vts/functional/VtsHalCasV1_0TargetTest.cpp
+++ b/cas/1.0/vts/functional/VtsHalCasV1_0TargetTest.cpp
@@ -30,6 +30,7 @@
 #include <hidl/HidlSupport.h>
 #include <hidl/HidlTransportSupport.h>
 #include <hidl/Status.h>
+#include <hidlmemory/FrameworkUtils.h>
 #include <utils/Condition.h>
 #include <utils/Mutex.h>
 
@@ -53,6 +54,7 @@
 using android::hardware::cas::V1_0::ICas;
 using android::hardware::cas::V1_0::ICasListener;
 using android::hardware::cas::V1_0::IDescramblerBase;
+using android::hardware::cas::V1_0::Status;
 using android::hardware::cas::native::V1_0::IDescrambler;
 using android::hardware::cas::native::V1_0::SubSample;
 using android::hardware::cas::native::V1_0::SharedBuffer;
@@ -61,13 +63,12 @@
 using android::hardware::cas::native::V1_0::ScramblingControl;
 using android::hardware::cas::V1_0::IMediaCasService;
 using android::hardware::cas::V1_0::HidlCasPluginDescriptor;
-using android::hardware::Void;
+using android::hardware::fromHeap;
 using android::hardware::hidl_vec;
 using android::hardware::hidl_string;
-using android::hardware::hidl_handle;
-using android::hardware::hidl_memory;
+using android::hardware::HidlMemory;
 using android::hardware::Return;
-using android::hardware::cas::V1_0::Status;
+using android::hardware::Void;
 using android::IMemory;
 using android::IMemoryHeap;
 using android::MemoryDealer;
@@ -315,7 +316,7 @@
     }
     *inMemory = mem;
 
-    // build hidl_memory from memory heap
+    // build HidlMemory from memory heap
     ssize_t offset;
     size_t size;
     sp<IMemoryHeap> heap = mem->getMemory(&offset, &size);
@@ -324,18 +325,14 @@
         return ::testing::AssertionFailure();
     }
 
-    native_handle_t* nativeHandle = native_handle_create(1, 0);
-    if (!nativeHandle) {
-        ALOGE("failed to create native handle!");
-        return ::testing::AssertionFailure();
-    }
-    nativeHandle->data[0] = heap->getHeapID();
-
     uint8_t* ipBuffer = static_cast<uint8_t*>(static_cast<void*>(mem->pointer()));
     memcpy(ipBuffer, kInBinaryBuffer, sizeof(kInBinaryBuffer));
 
+    // hidlMemory is not to be passed out of scope!
+    sp<HidlMemory> hidlMemory = fromHeap(heap);
+
     SharedBuffer srcBuffer = {
-            .heapBase = hidl_memory("ashmem", hidl_handle(nativeHandle), heap->getSize()),
+            .heapBase = *hidlMemory,
             .offset = (uint64_t) offset,
             .size = (uint64_t) size
     };
@@ -380,7 +377,7 @@
         return ::testing::AssertionFailure();
     }
 
-    // build hidl_memory from memory heap
+    // build HidlMemory from memory heap
     ssize_t offset;
     size_t size;
     sp<IMemoryHeap> heap = mem->getMemory(&offset, &size);
@@ -389,15 +386,11 @@
         return ::testing::AssertionFailure();
     }
 
-    native_handle_t* nativeHandle = native_handle_create(1, 0);
-    if (!nativeHandle) {
-        ALOGE("failed to create native handle!");
-        return ::testing::AssertionFailure();
-    }
-    nativeHandle->data[0] = heap->getHeapID();
+    // hidlMemory is not to be passed out of scope!
+    sp<HidlMemory> hidlMemory = fromHeap(heap);
 
     SharedBuffer srcBuffer = {
-            .heapBase = hidl_memory("ashmem", hidl_handle(nativeHandle), heap->getSize()),
+            .heapBase = *hidlMemory,
             .offset = (uint64_t) offset + params.imemOffset,
             .size = (uint64_t) params.imemSize,
     };
diff --git a/confirmationui/1.0/vts/OWNERS b/confirmationui/1.0/vts/OWNERS
new file mode 100644
index 0000000..e7aa8b4
--- /dev/null
+++ b/confirmationui/1.0/vts/OWNERS
@@ -0,0 +1,3 @@
+jdanis@google.com
+swillden@google.com
+yim@google.com
diff --git a/confirmationui/1.0/vts/functional/Android.bp b/confirmationui/1.0/vts/functional/Android.bp
new file mode 100644
index 0000000..823e035
--- /dev/null
+++ b/confirmationui/1.0/vts/functional/Android.bp
@@ -0,0 +1,30 @@
+//
+// Copyright (C) 2018 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.
+//
+
+cc_test {
+    name: "VtsHalConfirmationUIV1_0TargetTest",
+    defaults: ["VtsHalTargetTestDefaults"],
+    srcs: [
+        "VtsHalConfirmationUIV1_0TargetTest.cpp",
+    ],
+    static_libs: [
+        "android.hardware.confirmationui@1.0",
+        "android.hardware.keymaster@4.0",
+        "libcrypto",
+        "libcn-cbor",
+        "android.hardware.confirmationui-support-lib",
+    ],
+}
diff --git a/confirmationui/1.0/vts/functional/VtsHalConfirmationUIV1_0TargetTest.cpp b/confirmationui/1.0/vts/functional/VtsHalConfirmationUIV1_0TargetTest.cpp
new file mode 100644
index 0000000..463bb40
--- /dev/null
+++ b/confirmationui/1.0/vts/functional/VtsHalConfirmationUIV1_0TargetTest.cpp
@@ -0,0 +1,428 @@
+/*
+ * Copyright (C) 2018 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 LOG_TAG "ConfirmationIOHidlHalTest"
+#include <cutils/log.h>
+
+#include <algorithm>
+#include <iostream>
+#include <memory>
+
+#include <android/hardware/confirmationui/1.0/IConfirmationResultCallback.h>
+#include <android/hardware/confirmationui/1.0/IConfirmationUI.h>
+#include <android/hardware/confirmationui/1.0/types.h>
+#include <android/hardware/confirmationui/support/confirmationui_utils.h>
+
+#include <VtsHalHidlTargetCallbackBase.h>
+#include <VtsHalHidlTargetTestBase.h>
+
+#include <openssl/hmac.h>
+#include <openssl/sha.h>
+
+#include <cn-cbor/cn-cbor.h>
+
+using ::android::sp;
+
+using ::std::string;
+
+namespace android {
+namespace hardware {
+
+namespace confirmationui {
+namespace V1_0 {
+
+namespace test {
+namespace {
+class HMacImplementation {
+   public:
+    static support::NullOr<support::array<uint8_t, 32>> hmac256(
+        const uint8_t key[32], std::initializer_list<support::ByteBufferProxy> buffers) {
+        HMAC_CTX hmacCtx;
+        HMAC_CTX_init(&hmacCtx);
+        if (!HMAC_Init_ex(&hmacCtx, key, 32, EVP_sha256(), nullptr)) {
+            return {};
+        }
+        for (auto& buffer : buffers) {
+            if (!HMAC_Update(&hmacCtx, buffer.data(), buffer.size())) {
+                return {};
+            }
+        }
+        support::array<uint8_t, 32> result;
+        if (!HMAC_Final(&hmacCtx, result.data(), nullptr)) {
+            return {};
+        }
+        return result;
+    }
+};
+
+using HMacer = support::HMac<HMacImplementation>;
+
+constexpr uint8_t testKeyByte = static_cast<uint8_t>(TestKeyBits::BYTE);
+
+template <typename... Data>
+hidl_vec<uint8_t> testHMAC(const Data&... data) {
+    constexpr uint8_t testKey[32] = {testKeyByte, testKeyByte, testKeyByte, testKeyByte,
+                                     testKeyByte, testKeyByte, testKeyByte, testKeyByte,
+                                     testKeyByte, testKeyByte, testKeyByte, testKeyByte,
+                                     testKeyByte, testKeyByte, testKeyByte, testKeyByte};
+    constexpr uint8_t hmac_size_bytes = sizeof testKey;
+
+    auto hmac = HMacer::hmac256(testKey, data...);
+    if (!hmac.isOk()) {
+        EXPECT_TRUE(false) << "Failed to compute test hmac.  This is a self-test error.";
+        return {};
+    }
+    hidl_vec<uint8_t> result(hmac_size_bytes);
+    copy(hmac.value().data(), hmac.value().data() + hmac_size_bytes, result.data());
+    return result;
+}
+
+using ::android::hardware::keymaster::V4_0::HardwareAuthToken;
+using ::android::hardware::keymaster::V4_0::HardwareAuthenticatorType;
+
+template <typename T>
+auto toBytes(const T& v) -> const uint8_t (&)[sizeof(T)] {
+    return *reinterpret_cast<const uint8_t(*)[sizeof(T)]>(&v);
+}
+
+HardwareAuthToken makeTestToken(const TestModeCommands command, uint64_t timestamp = 0) {
+    HardwareAuthToken auth_token;
+    auth_token.challenge = static_cast<uint64_t>(command);
+    auth_token.userId = 0;
+    auth_token.authenticatorId = 0;
+    auth_token.authenticatorType = HardwareAuthenticatorType::NONE;
+    auth_token.timestamp = timestamp;
+
+    // Canonical form  of auth-token v0
+    // version (1 byte)
+    // challenge (8 bytes)
+    // user_id (8 bytes)
+    // authenticator_id (8 bytes)
+    // authenticator_type (4 bytes)
+    // timestamp (8 bytes)
+    // total 37 bytes
+    auth_token.mac = testHMAC("\0",
+                              toBytes(auth_token.challenge),                         //
+                              toBytes(auth_token.userId),                            //
+                              toBytes(auth_token.authenticatorId),                   //
+                              toBytes(support::hton(auth_token.authenticatorType)),  //
+                              toBytes(support::hton(auth_token.timestamp)));         //
+
+    return auth_token;
+}
+
+#define DEBUG_CONFRIMATIONUI_UTILS_TEST
+
+#ifdef DEBUG_CONFRIMATIONUI_UTILS_TEST
+std::ostream& hexdump(std::ostream& out, const uint8_t* data, size_t size) {
+    for (size_t i = 0; i < size; ++i) {
+        uint8_t byte = data[i];
+        out << std::hex << std::setw(2) << std::setfill('0') << (unsigned)byte;
+        switch (i & 0xf) {
+            case 0xf:
+                out << "\n";
+                break;
+            case 7:
+                out << "  ";
+                break;
+            default:
+                out << " ";
+                break;
+        }
+    }
+    return out;
+}
+#endif
+
+constexpr char hex_value[256] = {0, 0,  0,  0,  0,  0,  0,  0, 0, 0, 0, 0, 0, 0, 0, 0,  //
+                                 0, 0,  0,  0,  0,  0,  0,  0, 0, 0, 0, 0, 0, 0, 0, 0,  //
+                                 0, 0,  0,  0,  0,  0,  0,  0, 0, 0, 0, 0, 0, 0, 0, 0,  //
+                                 0, 1,  2,  3,  4,  5,  6,  7, 8, 9, 0, 0, 0, 0, 0, 0,  // '0'..'9'
+                                 0, 10, 11, 12, 13, 14, 15, 0, 0, 0, 0, 0, 0, 0, 0, 0,  // 'A'..'F'
+                                 0, 0,  0,  0,  0,  0,  0,  0, 0, 0, 0, 0, 0, 0, 0, 0,  //
+                                 0, 10, 11, 12, 13, 14, 15, 0, 0, 0, 0, 0, 0, 0, 0, 0,  // 'a'..'f'
+                                 0, 0,  0,  0,  0,  0,  0,  0, 0, 0, 0, 0, 0, 0, 0, 0,  //
+                                 0, 0,  0,  0,  0,  0,  0,  0, 0, 0, 0, 0, 0, 0, 0, 0,  //
+                                 0, 0,  0,  0,  0,  0,  0,  0, 0, 0, 0, 0, 0, 0, 0, 0,  //
+                                 0, 0,  0,  0,  0,  0,  0,  0, 0, 0, 0, 0, 0, 0, 0, 0,  //
+                                 0, 0,  0,  0,  0,  0,  0,  0, 0, 0, 0, 0, 0, 0, 0, 0,  //
+                                 0, 0,  0,  0,  0,  0,  0,  0, 0, 0, 0, 0, 0, 0, 0, 0,  //
+                                 0, 0,  0,  0,  0,  0,  0,  0, 0, 0, 0, 0, 0, 0, 0, 0,  //
+                                 0, 0,  0,  0,  0,  0,  0,  0, 0, 0, 0, 0, 0, 0, 0, 0,  //
+                                 0, 0,  0,  0,  0,  0,  0,  0, 0, 0, 0, 0, 0, 0, 0, 0};
+
+std::string hex2str(std::string a) {
+    std::string b;
+    size_t num = a.size() / 2;
+    b.resize(num);
+    for (size_t i = 0; i < num; i++) {
+        b[i] = (hex_value[a[i * 2] & 0xFF] << 4) + (hex_value[a[i * 2 + 1] & 0xFF]);
+    }
+    return b;
+}
+
+}  // namespace
+
+class ConfirmationArgs {
+   public:
+    ResponseCode error_;
+    hidl_vec<uint8_t> formattedMessage_;
+    hidl_vec<uint8_t> confirmationToken_;
+    bool verifyConfirmationToken() {
+        static constexpr char confirmationPrefix[] = "confirmation token";
+        EXPECT_EQ(32U, confirmationToken_.size());
+        return 32U == confirmationToken_.size() &&
+               !memcmp(confirmationToken_.data(),
+                       testHMAC(confirmationPrefix, formattedMessage_).data(), 32);
+    }
+};
+
+class ConfirmationTestCallback : public ::testing::VtsHalHidlTargetCallbackBase<ConfirmationArgs>,
+                                 public IConfirmationResultCallback {
+   public:
+    Return<void> result(ResponseCode error, const hidl_vec<uint8_t>& formattedMessage,
+                        const hidl_vec<uint8_t>& confirmationToken) override {
+        ConfirmationArgs args;
+        args.error_ = error;
+        args.formattedMessage_ = formattedMessage;
+        args.confirmationToken_ = confirmationToken;
+        NotifyFromCallback(args);
+        return Void();
+    }
+};
+
+class ConfirmationUIHidlEnvironment : public ::testing::VtsHalHidlTargetTestEnvBase {
+   public:
+    // get the test environment singleton
+    static ConfirmationUIHidlEnvironment* Instance() {
+        static ConfirmationUIHidlEnvironment* instance = new ConfirmationUIHidlEnvironment;
+        return instance;
+    }
+
+    void registerTestServices() override { registerTestService<IConfirmationUI>(); }
+
+   private:
+    ConfirmationUIHidlEnvironment(){};
+
+    GTEST_DISALLOW_COPY_AND_ASSIGN_(ConfirmationUIHidlEnvironment);
+};
+
+class ConfirmationUIHidlTest : public ::testing::VtsHalHidlTargetTestBase {
+   public:
+    void TearDown() override { confirmator().abort(); }
+
+    static void SetUpTestCase() {
+        string service_name =
+            ConfirmationUIHidlEnvironment::Instance()->getServiceName<IConfirmationUI>();
+        confirmator_ = IConfirmationUI::getService(service_name);
+        ASSERT_NE(nullptr, confirmator_.get());
+    }
+
+    static void TearDownTestCase() { confirmator_.clear(); }
+
+    static IConfirmationUI& confirmator() { return *confirmator_; }
+
+   private:
+    static sp<IConfirmationUI> confirmator_;
+};
+
+sp<IConfirmationUI> ConfirmationUIHidlTest::confirmator_;
+
+#define ASSERT_HAL_CALL(expected, call)                               \
+    {                                                                 \
+        auto result = call;                                           \
+        ASSERT_TRUE(result.isOk());                                   \
+        ASSERT_EQ(expected, static_cast<decltype(expected)>(result)); \
+    }
+
+struct CnCborDeleter {
+    void operator()(cn_cbor* ptr) { cn_cbor_free(ptr); }
+};
+
+typedef std::unique_ptr<cn_cbor, CnCborDeleter> CnCborPtr;
+
+// Simulates the User taping Ok
+TEST_F(ConfirmationUIHidlTest, UserOkTest) {
+    static constexpr char test_prompt[] = "Me first, gimme gimme!";
+    static constexpr uint8_t test_extra[] = {0x1, 0x2, 0x3};
+    sp<ConfirmationTestCallback> conf_cb = new ConfirmationTestCallback;
+    hidl_string prompt_text(test_prompt);
+    hidl_vec<uint8_t> extra(test_extra, test_extra + 3);
+    ASSERT_HAL_CALL(ResponseCode::OK,
+                    confirmator().promptUserConfirmation(conf_cb, prompt_text, extra, "en", {}));
+
+    ASSERT_HAL_CALL(ResponseCode::OK, confirmator().deliverSecureInputEvent(
+                                          makeTestToken(TestModeCommands::OK_EVENT)));
+
+    auto result = conf_cb->WaitForCallback();
+    ASSERT_EQ(ResponseCode::OK, result.args->error_);
+
+    ASSERT_TRUE(result.args->verifyConfirmationToken());
+
+    cn_cbor_errback cn_cbor_error;
+    auto parsed_message =
+        CnCborPtr(cn_cbor_decode(result.args->formattedMessage_.data(),
+                                 result.args->formattedMessage_.size(), &cn_cbor_error));
+    // is parsable CBOR
+    ASSERT_TRUE(parsed_message.get());
+    // is a map
+    ASSERT_EQ(CN_CBOR_MAP, parsed_message->type);
+
+    // the message must have exactly 2 key value pairs.
+    // cn_cbor holds 2*<no_of_pairs> in the length field
+    ASSERT_EQ(4, parsed_message->length);
+    // map has key "prompt"
+    auto prompt = cn_cbor_mapget_string(parsed_message.get(), "prompt");
+    ASSERT_TRUE(prompt);
+    ASSERT_EQ(CN_CBOR_TEXT, prompt->type);
+    ASSERT_EQ(22, prompt->length);
+    ASSERT_EQ(0, memcmp(test_prompt, prompt->v.str, 22));
+    // map has key "extra"
+    auto extra_out = cn_cbor_mapget_string(parsed_message.get(), "extra");
+    ASSERT_TRUE(extra_out);
+    ASSERT_EQ(CN_CBOR_BYTES, extra_out->type);
+    ASSERT_EQ(3, extra_out->length);
+    ASSERT_EQ(0, memcmp(test_extra, extra_out->v.bytes, 3));
+}
+
+// Initiates a confirmation prompt with a message that is too long
+TEST_F(ConfirmationUIHidlTest, MessageTooLongTest) {
+    static constexpr uint8_t test_extra[static_cast<uint32_t>(MessageSize::MAX)] = {};
+    static constexpr char test_prompt[] = "D\'oh!";
+    sp<ConfirmationTestCallback> conf_cb = new ConfirmationTestCallback;
+    hidl_string prompt_text(test_prompt);
+    hidl_vec<uint8_t> extra(test_extra, test_extra + sizeof(test_extra));
+    ASSERT_HAL_CALL(ResponseCode::UIErrorMessageTooLong,
+                    confirmator().promptUserConfirmation(conf_cb, prompt_text, extra, "en", {}));
+}
+
+// If the message gets very long some HAL implementations might fail even before the message
+// reaches the trusted app implementation. But the HAL must still diagnose the correct error.
+TEST_F(ConfirmationUIHidlTest, MessageWayTooLongTest) {
+    static constexpr uint8_t test_extra[static_cast<uint32_t>(MessageSize::MAX) * 10] = {};
+    static constexpr char test_prompt[] = "D\'oh!";
+    sp<ConfirmationTestCallback> conf_cb = new ConfirmationTestCallback;
+    hidl_string prompt_text(test_prompt);
+    hidl_vec<uint8_t> extra(test_extra, test_extra + sizeof(test_extra));
+    ASSERT_HAL_CALL(ResponseCode::UIErrorMessageTooLong,
+                    confirmator().promptUserConfirmation(conf_cb, prompt_text, extra, "en", {}));
+}
+
+// Simulates the User tapping the Cancel
+TEST_F(ConfirmationUIHidlTest, UserCancelTest) {
+    static constexpr char test_prompt[] = "Me first, gimme gimme!";
+    static constexpr uint8_t test_extra[] = {0x1, 0x2, 0x3};
+    sp<ConfirmationTestCallback> conf_cb = new ConfirmationTestCallback;
+    hidl_string prompt_text(test_prompt);
+    hidl_vec<uint8_t> extra(test_extra, test_extra + 3);
+    ASSERT_HAL_CALL(ResponseCode::OK,
+                    confirmator().promptUserConfirmation(conf_cb, prompt_text, extra, "en", {}));
+
+    ASSERT_HAL_CALL(ResponseCode::OK, confirmator().deliverSecureInputEvent(
+                                          makeTestToken(TestModeCommands::CANCEL_EVENT)));
+
+    auto result = conf_cb->WaitForCallback();
+    ASSERT_EQ(ResponseCode::Canceled, result.args->error_);
+
+    ASSERT_EQ(0U, result.args->confirmationToken_.size());
+    ASSERT_EQ(0U, result.args->formattedMessage_.size());
+}
+
+// Simulates the framework candelling an ongoing prompt
+TEST_F(ConfirmationUIHidlTest, AbortTest) {
+    static constexpr char test_prompt[] = "Me first, gimme gimme!";
+    static constexpr uint8_t test_extra[] = {0x1, 0x2, 0x3};
+    sp<ConfirmationTestCallback> conf_cb = new ConfirmationTestCallback;
+    hidl_string prompt_text(test_prompt);
+    hidl_vec<uint8_t> extra(test_extra, test_extra + 3);
+    ASSERT_HAL_CALL(ResponseCode::OK,
+                    confirmator().promptUserConfirmation(conf_cb, prompt_text, extra, "en", {}));
+
+    confirmator().abort();
+
+    auto result = conf_cb->WaitForCallback();
+    ASSERT_EQ(ResponseCode::Aborted, result.args->error_);
+    ASSERT_EQ(0U, result.args->confirmationToken_.size());
+    ASSERT_EQ(0U, result.args->formattedMessage_.size());
+}
+
+// Passing malformed UTF-8 to the confirmation UI
+// This test passes a string that ends in the middle of a multibyte character
+TEST_F(ConfirmationUIHidlTest, MalformedUTF8Test1) {
+    static constexpr char test_prompt[] = {char(0xc0), 0};
+    static constexpr uint8_t test_extra[] = {0x1, 0x2, 0x3};
+    sp<ConfirmationTestCallback> conf_cb = new ConfirmationTestCallback;
+    hidl_string prompt_text(test_prompt);
+    hidl_vec<uint8_t> extra(test_extra, test_extra + 3);
+    ASSERT_HAL_CALL(ResponseCode::UIErrorMalformedUTF8Encoding,
+                    confirmator().promptUserConfirmation(conf_cb, prompt_text, extra, "en", {}));
+}
+
+// Passing malformed UTF-8 to the confirmation UI
+// This test passes a string with a 5-byte character.
+TEST_F(ConfirmationUIHidlTest, MalformedUTF8Test2) {
+    static constexpr char test_prompt[] = {char(0xf8), char(0x82), char(0x82),
+                                           char(0x82), char(0x82), 0};
+    static constexpr uint8_t test_extra[] = {0x1, 0x2, 0x3};
+    sp<ConfirmationTestCallback> conf_cb = new ConfirmationTestCallback;
+    hidl_string prompt_text(test_prompt);
+    hidl_vec<uint8_t> extra(test_extra, test_extra + 3);
+    ASSERT_HAL_CALL(ResponseCode::UIErrorMalformedUTF8Encoding,
+                    confirmator().promptUserConfirmation(conf_cb, prompt_text, extra, "en", {}));
+}
+
+// Passing malformed UTF-8 to the confirmation UI
+// This test passes a string with a 2-byte character followed by a stray non UTF-8 character.
+TEST_F(ConfirmationUIHidlTest, MalformedUTF8Test3) {
+    static constexpr char test_prompt[] = {char(0xc0), char(0x82), char(0x83), 0};
+    static constexpr uint8_t test_extra[] = {0x1, 0x2, 0x3};
+    sp<ConfirmationTestCallback> conf_cb = new ConfirmationTestCallback;
+    hidl_string prompt_text(test_prompt);
+    hidl_vec<uint8_t> extra(test_extra, test_extra + 3);
+    ASSERT_HAL_CALL(ResponseCode::UIErrorMalformedUTF8Encoding,
+                    confirmator().promptUserConfirmation(conf_cb, prompt_text, extra, "en", {}));
+}
+
+// Test the implementation of HMAC SHA 256 against a golden blob.
+TEST(ConfirmationUITestSelfTest, HMAC256SelfTest) {
+    const char key_str[32] = "keykeykeykeykeykeykeykeykeykeyk";
+    const uint8_t(&key)[32] = *reinterpret_cast<const uint8_t(*)[32]>(key_str);
+    auto expected = hex2str("2377fbcaa7fb3f6c20cfa1d9ebc60e9922cf58c909e25e300f3cb57f7805c886");
+    auto result = HMacer::hmac256(key, "value1", "value2", "value3");
+
+#ifdef DEBUG_CONFRIMATIONUI_UTILS_TEST
+    hexdump(std::cout, reinterpret_cast<const uint8_t*>(expected.data()), 32) << std::endl;
+    hexdump(std::cout, result.value().data(), 32) << std::endl;
+#endif
+
+    support::ByteBufferProxy expected_bytes(expected);
+    ASSERT_TRUE(result.isOk());
+    ASSERT_EQ(expected, result.value());
+}
+
+}  // namespace test
+}  // namespace V1_0
+}  // namespace confirmationui
+}  // namespace hardware
+}  // namespace android
+
+int main(int argc, char** argv) {
+    ::testing::InitGoogleTest(&argc, argv);
+    std::vector<std::string> positional_args;
+    int status = RUN_ALL_TESTS();
+    ALOGI("Test result = %d", status);
+    return status;
+}
diff --git a/contexthub/1.0/vts/functional/VtsHalContexthubV1_0TargetTest.cpp b/contexthub/1.0/vts/functional/VtsHalContexthubV1_0TargetTest.cpp
index 5672824..7492152 100644
--- a/contexthub/1.0/vts/functional/VtsHalContexthubV1_0TargetTest.cpp
+++ b/contexthub/1.0/vts/functional/VtsHalContexthubV1_0TargetTest.cpp
@@ -17,6 +17,7 @@
 #define LOG_TAG "contexthub_hidl_hal_test"
 
 #include <VtsHalHidlTargetTestBase.h>
+#include <VtsHalHidlTargetTestEnvBase.h>
 #include <android-base/logging.h>
 #include <android/hardware/contexthub/1.0/IContexthub.h>
 #include <android/hardware/contexthub/1.0/IContexthubCallback.h>
@@ -92,12 +93,27 @@
   return hubIds;
 }
 
+// Test environment for Contexthub HIDL HAL.
+class ContexthubHidlEnvironment : public ::testing::VtsHalHidlTargetTestEnvBase {
+ public:
+  // get the test environment singleton
+  static ContexthubHidlEnvironment* Instance() {
+    static ContexthubHidlEnvironment* instance = new ContexthubHidlEnvironment;
+    return instance;
+  }
+
+  virtual void registerTestServices() override { registerTestService<IContexthub>(); }
+ private:
+  ContexthubHidlEnvironment() {}
+};
+
 // Base test fixture that initializes the HAL and makes the context hub API
 // handle available
 class ContexthubHidlTestBase : public ::testing::VtsHalHidlTargetTestBase {
  public:
   virtual void SetUp() override {
-    hubApi = ::testing::VtsHalHidlTargetTestBase::getService<IContexthub>();
+    hubApi = ::testing::VtsHalHidlTargetTestBase::getService<IContexthub>(
+        ContexthubHidlEnvironment::Instance()->getServiceName<IContexthub>());
     ASSERT_NE(hubApi, nullptr);
 
     // getHubs() must be called at least once for proper initialization of the
@@ -381,7 +397,11 @@
 } // anonymous namespace
 
 int main(int argc, char **argv) {
+  ::testing::AddGlobalTestEnvironment(ContexthubHidlEnvironment::Instance());
   ::testing::InitGoogleTest(&argc, argv);
-  return RUN_ALL_TESTS();
+  ContexthubHidlEnvironment::Instance()->init(&argc, argv);
+  int status = RUN_ALL_TESTS();
+  ALOGI ("Test result = %d", status);
+  return status;
 }
 
diff --git a/current.txt b/current.txt
index a5ab307..05660a8 100644
--- a/current.txt
+++ b/current.txt
@@ -251,8 +251,10 @@
 
 # ABI preserving changes to HALs during Android P
 cf72ff5a52bfa4d08e9e1000cf3ab5952a2d280c7f13cdad5ab7905c08050766 android.hardware.camera.metadata@3.2::types
+7b4723305354193b889a24153e1292fec62d5a5127bdfba08a5a27440f092de9 android.hardware.camera.provider@2.4::ICameraProvider
 6fa9804a17a8bb7923a56bd10493a5483c20007e4c9026fd04287bee7c945a8c android.hardware.gnss@1.0::IGnssCallback
 fb92e2b40f8e9d494e8fd3b4ac18499a3216342e7cff160714c3bbf3660b6e79 android.hardware.gnss@1.0::IGnssConfiguration
 251594ea9b27447bfa005ebd806e58fb0ae4aad84a69938129c9800ec0c64eda android.hardware.gnss@1.0::IGnssMeasurementCallback
 4e7169919d24fbe5573e5bcd683d0bd7abf553a4e6c34c41f9dfc1e12050db07 android.hardware.gnss@1.0::IGnssNavigationMessageCallback
+0e6e80ddd5c312726e20b003af438325a2d7c305a60a8c8d8e229df2306d50df android.hardware.radio@1.0::types
 b280c4704dfcc548a9bf127b59b7c3578f460c50cce70a06b66fe0df8b27cff0 android.hardware.wifi@1.0::types
diff --git a/drm/1.0/vts/functional/drm_hal_vendor_test.cpp b/drm/1.0/vts/functional/drm_hal_vendor_test.cpp
index 47c6950..d03b2af 100644
--- a/drm/1.0/vts/functional/drm_hal_vendor_test.cpp
+++ b/drm/1.0/vts/functional/drm_hal_vendor_test.cpp
@@ -97,6 +97,27 @@
 
 static drm_vts::VendorModules* gVendorModules = nullptr;
 
+// Test environment for drm
+class DrmHidlEnvironment : public ::testing::VtsHalHidlTargetTestEnvBase {
+   public:
+    // get the test environment singleton
+    static DrmHidlEnvironment* Instance() {
+        static DrmHidlEnvironment* instance = new DrmHidlEnvironment;
+        return instance;
+    }
+
+    void registerTestServices() override {
+        registerTestService<ICryptoFactory>();
+        registerTestService<IDrmFactory>();
+        setServiceCombMode(::testing::HalServiceCombMode::NO_COMBINATION);
+    }
+
+   private:
+    DrmHidlEnvironment() {}
+
+    GTEST_DISALLOW_COPY_AND_ASSIGN_(DrmHidlEnvironment);
+};
+
 class DrmHalVendorFactoryTest : public testing::TestWithParam<std::string> {
    public:
     DrmHalVendorFactoryTest()
@@ -1598,6 +1619,10 @@
         std::cerr << "WARNING: No vendor modules found in " << kModulePath <<
                 ", all vendor tests will be skipped" << std::endl;
     }
+    ::testing::AddGlobalTestEnvironment(DrmHidlEnvironment::Instance());
     ::testing::InitGoogleTest(&argc, argv);
-    return RUN_ALL_TESTS();
+    DrmHidlEnvironment::Instance()->init(&argc, argv);
+    int status = RUN_ALL_TESTS();
+    ALOGI("Test result = %d", status);
+    return status;
 }
diff --git a/drm/1.1/vts/functional/drm_hal_clearkey_test.cpp b/drm/1.1/vts/functional/drm_hal_clearkey_test.cpp
index a8ed0e5..061f2cd 100644
--- a/drm/1.1/vts/functional/drm_hal_clearkey_test.cpp
+++ b/drm/1.1/vts/functional/drm_hal_clearkey_test.cpp
@@ -106,6 +106,12 @@
 
     virtual void HidlTearDown() override { ALOGI("TearDown DrmHidlEnvironment"); }
 
+    void registerTestServices() override {
+        registerTestService<ICryptoFactory>();
+        registerTestService<IDrmFactory>();
+        setServiceCombMode(::testing::HalServiceCombMode::NO_COMBINATION);
+    }
+
    private:
     DrmHidlEnvironment() {}
 
diff --git a/gnss/1.1/Android.bp b/gnss/1.1/Android.bp
index 417b4f5..4ae4439 100644
--- a/gnss/1.1/Android.bp
+++ b/gnss/1.1/Android.bp
@@ -11,6 +11,7 @@
         "IGnssCallback.hal",
         "IGnssConfiguration.hal",
         "IGnssMeasurement.hal",
+        "IGnssMeasurementCallback.hal",
     ],
     interfaces: [
         "android.hardware.gnss@1.0",
diff --git a/gnss/1.1/IGnssMeasurement.hal b/gnss/1.1/IGnssMeasurement.hal
index 75df5a8..cd83ae3 100644
--- a/gnss/1.1/IGnssMeasurement.hal
+++ b/gnss/1.1/IGnssMeasurement.hal
@@ -17,7 +17,7 @@
 package android.hardware.gnss@1.1;
 
 import @1.0::IGnssMeasurement;
-import @1.0::IGnssMeasurementCallback;
+import IGnssMeasurementCallback;
 
 /**
  * Extended interface for GNSS Measurements support.
diff --git a/gnss/1.1/IGnssMeasurementCallback.hal b/gnss/1.1/IGnssMeasurementCallback.hal
new file mode 100644
index 0000000..5a60a56
--- /dev/null
+++ b/gnss/1.1/IGnssMeasurementCallback.hal
@@ -0,0 +1,80 @@
+/*
+ * Copyright (C) 2018 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.
+ */
+
+package android.hardware.gnss@1.1;
+
+import @1.0::IGnssMeasurementCallback;
+
+/** The callback interface to report measurements from the HAL. */
+interface IGnssMeasurementCallback extends @1.0::IGnssMeasurementCallback {
+    /**
+     * Flags indicating the Accumulated Delta Range's states.
+     */
+    enum GnssAccumulatedDeltaRangeState
+            : @1.0::IGnssMeasurementCallback.GnssAccumulatedDeltaRangeState {
+        ADR_STATE_HALF_CYCLE_RESOLVED = 1 << 3, // Carrier-phase half-cycle ambiguity resolved
+    };
+
+    /**
+     * Extends a GNSS Measurement, adding the new enum.
+     */
+    struct GnssMeasurement {
+        /**
+         * GNSS measurement information for a single satellite and frequency, as in the 1.0
+         * version of the HAL.
+         *
+         * In this version of the HAL, these fields of the
+         * @1.0::IGnssMeasurementCallback.GnssMeasurement v1_0 struct are deprecated, and
+         * are no longer used by the framework:
+         *   carrierCycles
+         *   carrierPhase
+         *   carrierPhaseUncertainty
+         *
+         * Similar information about carrier phase signal tracking is still reported in these
+         * fields of @1.0::IGnssMeasurementCallback.GnssMeasurement v1_0:
+         *   accumulatedDeltaRangeM
+         *   accumulatedDeltaRangeUncertaintyM
+         */
+        @1.0::IGnssMeasurementCallback.GnssMeasurement v1_0;
+
+        /**
+         * Provides the state of Accumulated Delta Range values, including additional information
+         * beyond version 1.0 of the HAL.  See GnssAccumulatedDeltaRangeState.
+         *
+         * In this (1.1) version of the HAL, this value is used by the framework, not the
+         * value provided by v1_0.accumulatedDeltaRangeState.
+         */
+        bitfield<GnssAccumulatedDeltaRangeState> accumulatedDeltaRangeState;
+    };
+
+    /**
+     * Complete set of GNSS Measurement data, same as 1.0 with additional enum in measurements.
+     */
+    struct GnssData {
+        /** The full set of satellite measurement observations. */
+        vec<GnssMeasurement> measurements;
+
+        /** The GNSS clock time reading. */
+        GnssClock clock;
+    };
+
+    /**
+     * Callback for the hal to pass a GnssData structure back to the client.
+     *
+     * @param data Contains a reading of GNSS measurements.
+     */
+    gnssMeasurementCb(GnssData data);
+};
diff --git a/gnss/1.1/vts/functional/gnss_hal_test_cases.cpp b/gnss/1.1/vts/functional/gnss_hal_test_cases.cpp
index 264a11d..a0a1c73 100644
--- a/gnss/1.1/vts/functional/gnss_hal_test_cases.cpp
+++ b/gnss/1.1/vts/functional/gnss_hal_test_cases.cpp
@@ -396,6 +396,10 @@
 
     ASSERT_TRUE(result.isOk());
     EXPECT_TRUE(result);
+
+    auto resultVoid = gnss_hal_->deleteAidingData(IGnss::GnssAidingData::DELETE_ALL);
+
+    ASSERT_TRUE(resultVoid.isOk());
 }
 
 /*
diff --git a/graphics/composer/2.1/default/Android.bp b/graphics/composer/2.1/default/Android.bp
index b46a1de..2de1e3c 100644
--- a/graphics/composer/2.1/default/Android.bp
+++ b/graphics/composer/2.1/default/Android.bp
@@ -1,34 +1,12 @@
-cc_library_static {
-    name: "libhwcomposer-client",
-    vendor_available: true,
-    defaults: ["hidl_defaults"],
-    export_include_dirs: ["."],
-    srcs: ["ComposerClient.cpp"],
-    shared_libs: [
-        "android.hardware.graphics.composer@2.1",
-        "android.hardware.graphics.mapper@2.0",
-        "libbase",
-        "libcutils",
-        "libfmq",
-        "libhardware",
-        "libhidlbase",
-        "libhidltransport",
-        "liblog",
-        "libsync",
-        "libutils",
-    ],
-    header_libs: [
-        "android.hardware.graphics.composer@2.1-command-buffer",
-    ],
-}
-
 cc_library_shared {
     name: "android.hardware.graphics.composer@2.1-impl",
     defaults: ["hidl_defaults"],
-    proprietary: true,
+    vendor: true,
     relative_install_path: "hw",
-    srcs: ["Hwc.cpp"],
-    static_libs: ["libhwcomposer-client"],
+    srcs: ["passthrough.cpp"],
+    header_libs: [
+        "android.hardware.graphics.composer@2.1-passthrough",
+    ],
     shared_libs: [
         "android.hardware.graphics.composer@2.1",
         "android.hardware.graphics.mapper@2.0",
@@ -44,26 +22,21 @@
         "libhwc2on1adapter",
         "libhwc2onfbadapter",
     ],
-    header_libs: [
-        "android.hardware.graphics.composer@2.1-command-buffer",
+    cflags: [
+        "-DLOG_TAG=\"ComposerHal\""
     ],
 }
 
 cc_binary {
     name: "android.hardware.graphics.composer@2.1-service",
     defaults: ["hidl_defaults"],
-    proprietary: true,
+    vendor: true,
     relative_install_path: "hw",
     srcs: ["service.cpp"],
     init_rc: ["android.hardware.graphics.composer@2.1-service.rc"],
-    static_libs: ["libhwcomposer-client"],
     shared_libs: [
         "android.hardware.graphics.composer@2.1",
-        "libbase",
         "libbinder",
-        "libcutils",
-        "libfmq",
-        "libhardware",
         "libhidlbase",
         "libhidltransport",
         "liblog",
diff --git a/graphics/composer/2.1/default/ComposerBase.h b/graphics/composer/2.1/default/ComposerBase.h
deleted file mode 100644
index e1c9d33..0000000
--- a/graphics/composer/2.1/default/ComposerBase.h
+++ /dev/null
@@ -1,132 +0,0 @@
-/*
- * Copyright 2017 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.
- */
-
-#ifndef ANDROID_HARDWARE_GRAPHICS_COMPOSER_V2_1_COMPOSER_BASE_H
-#define ANDROID_HARDWARE_GRAPHICS_COMPOSER_V2_1_COMPOSER_BASE_H
-
-#include <android/hardware/graphics/composer/2.1/IComposer.h>
-#include <hardware/hwcomposer2.h>
-
-namespace android {
-namespace hardware {
-namespace graphics {
-namespace composer {
-namespace V2_1 {
-namespace implementation {
-
-using android::hardware::graphics::common::V1_0::PixelFormat;
-using android::hardware::graphics::common::V1_0::Transform;
-using android::hardware::graphics::common::V1_0::Dataspace;
-using android::hardware::graphics::common::V1_0::ColorMode;
-using android::hardware::graphics::common::V1_0::ColorTransform;
-using android::hardware::graphics::common::V1_0::Hdr;
-
-class ComposerBase {
-public:
-    virtual ~ComposerBase() {};
-
-    virtual bool hasCapability(hwc2_capability_t capability) = 0;
-
-    virtual void removeClient() = 0;
-    virtual void enableCallback(bool enable) = 0;
-    virtual uint32_t getMaxVirtualDisplayCount() = 0;
-    virtual Error createVirtualDisplay(uint32_t width, uint32_t height,
-        PixelFormat* format, Display* outDisplay) = 0;
-    virtual Error destroyVirtualDisplay(Display display) = 0;
-    virtual Error createLayer(Display display, Layer* outLayer) = 0;
-    virtual Error destroyLayer(Display display, Layer layer) = 0;
-
-    virtual Error getActiveConfig(Display display, Config* outConfig) = 0;
-    virtual Error getClientTargetSupport(Display display,
-            uint32_t width, uint32_t height,
-            PixelFormat format, Dataspace dataspace) = 0;
-    virtual Error getColorModes(Display display,
-            hidl_vec<ColorMode>* outModes) = 0;
-    virtual Error getDisplayAttribute(Display display, Config config,
-            IComposerClient::Attribute attribute, int32_t* outValue) = 0;
-    virtual Error getDisplayConfigs(Display display,
-            hidl_vec<Config>* outConfigs) = 0;
-    virtual Error getDisplayName(Display display, hidl_string* outName) = 0;
-    virtual Error getDisplayType(Display display,
-            IComposerClient::DisplayType* outType) = 0;
-    virtual Error getDozeSupport(Display display, bool* outSupport) = 0;
-    virtual Error getHdrCapabilities(Display display, hidl_vec<Hdr>* outTypes,
-            float* outMaxLuminance, float* outMaxAverageLuminance,
-            float* outMinLuminance) = 0;
-
-    virtual Error setActiveConfig(Display display, Config config) = 0;
-    virtual Error setColorMode(Display display, ColorMode mode) = 0;
-    virtual Error setPowerMode(Display display,
-            IComposerClient::PowerMode mode) = 0;
-    virtual Error setVsyncEnabled(Display display,
-            IComposerClient::Vsync enabled) = 0;
-
-    virtual Error setColorTransform(Display display, const float* matrix,
-            int32_t hint) = 0;
-    virtual Error setClientTarget(Display display, buffer_handle_t target,
-            int32_t acquireFence, int32_t dataspace,
-            const std::vector<hwc_rect_t>& damage) = 0;
-    virtual Error setOutputBuffer(Display display, buffer_handle_t buffer,
-            int32_t releaseFence) = 0;
-    virtual Error validateDisplay(Display display,
-            std::vector<Layer>* outChangedLayers,
-            std::vector<IComposerClient::Composition>* outCompositionTypes,
-            uint32_t* outDisplayRequestMask,
-            std::vector<Layer>* outRequestedLayers,
-            std::vector<uint32_t>* outRequestMasks) = 0;
-    virtual Error acceptDisplayChanges(Display display) = 0;
-    virtual Error presentDisplay(Display display, int32_t* outPresentFence,
-            std::vector<Layer>* outLayers,
-            std::vector<int32_t>* outReleaseFences) = 0;
-
-    virtual Error setLayerCursorPosition(Display display, Layer layer,
-            int32_t x, int32_t y) = 0;
-    virtual Error setLayerBuffer(Display display, Layer layer,
-            buffer_handle_t buffer, int32_t acquireFence) = 0;
-    virtual Error setLayerSurfaceDamage(Display display, Layer layer,
-            const std::vector<hwc_rect_t>& damage) = 0;
-    virtual Error setLayerBlendMode(Display display, Layer layer,
-            int32_t mode) = 0;
-    virtual Error setLayerColor(Display display, Layer layer,
-            IComposerClient::Color color) = 0;
-    virtual Error setLayerCompositionType(Display display, Layer layer,
-            int32_t type) = 0;
-    virtual Error setLayerDataspace(Display display, Layer layer,
-            int32_t dataspace) = 0;
-    virtual Error setLayerDisplayFrame(Display display, Layer layer,
-            const hwc_rect_t& frame) = 0;
-    virtual Error setLayerPlaneAlpha(Display display, Layer layer,
-            float alpha) = 0;
-    virtual Error setLayerSidebandStream(Display display, Layer layer,
-            buffer_handle_t stream) = 0;
-    virtual Error setLayerSourceCrop(Display display, Layer layer,
-            const hwc_frect_t& crop) = 0;
-    virtual Error setLayerTransform(Display display, Layer layer,
-            int32_t transform) = 0;
-    virtual Error setLayerVisibleRegion(Display display, Layer layer,
-            const std::vector<hwc_rect_t>& visible) = 0;
-    virtual Error setLayerZOrder(Display display, Layer layer,
-            uint32_t z) = 0;
-};
-
-}  // namespace implementation
-}  // namespace V2_1
-}  // namespace composer
-}  // namespace graphics
-}  // namespace hardware
-}  // namespace android
-
-#endif  // ANDROID_HARDWARE_GRAPHICS_COMPOSER_V2_1_COMPOSER_BASE_H
diff --git a/graphics/composer/2.1/default/ComposerClient.cpp b/graphics/composer/2.1/default/ComposerClient.cpp
deleted file mode 100644
index 0fcb9de..0000000
--- a/graphics/composer/2.1/default/ComposerClient.cpp
+++ /dev/null
@@ -1,1205 +0,0 @@
-/*
- * Copyright 2016 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 LOG_TAG "HwcPassthrough"
-
-#include <android/hardware/graphics/mapper/2.0/IMapper.h>
-#include <log/log.h>
-
-#include "ComposerBase.h"
-#include "ComposerClient.h"
-
-namespace android {
-namespace hardware {
-namespace graphics {
-namespace composer {
-namespace V2_1 {
-namespace implementation {
-
-namespace {
-
-using MapperError = android::hardware::graphics::mapper::V2_0::Error;
-using android::hardware::graphics::mapper::V2_0::IMapper;
-
-class HandleImporter {
-public:
-    bool initialize()
-    {
-        // allow only one client
-        if (mInitialized) {
-            return false;
-        }
-
-        mMapper = IMapper::getService();
-
-        mInitialized = true;
-        return true;
-    }
-
-    void cleanup()
-    {
-        mMapper.clear();
-        mInitialized = false;
-    }
-
-    // In IComposer, any buffer_handle_t is owned by the caller and we need to
-    // make a clone for hwcomposer2.  We also need to translate empty handle
-    // to nullptr.  This function does that, in-place.
-    bool importBuffer(buffer_handle_t& handle)
-    {
-        if (!handle) {
-            return true;
-        }
-
-        if (!handle->numFds && !handle->numInts) {
-            handle = nullptr;
-            return true;
-        }
-
-        MapperError error;
-        buffer_handle_t importedHandle;
-        mMapper->importBuffer(
-            hidl_handle(handle),
-            [&](const auto& tmpError, const auto& tmpBufferHandle) {
-                error = tmpError;
-                importedHandle = static_cast<buffer_handle_t>(tmpBufferHandle);
-            });
-        if (error != MapperError::NONE) {
-            return false;
-        }
-
-        handle = importedHandle;
-
-        return true;
-    }
-
-    void freeBuffer(buffer_handle_t handle)
-    {
-        if (!handle) {
-            return;
-        }
-
-        mMapper->freeBuffer(const_cast<native_handle_t*>(handle));
-    }
-
-private:
- bool mInitialized = false;
- sp<IMapper> mMapper;
-};
-
-HandleImporter sHandleImporter;
-
-} // anonymous namespace
-
-BufferCacheEntry::BufferCacheEntry()
-    : mHandle(nullptr)
-{
-}
-
-BufferCacheEntry::BufferCacheEntry(BufferCacheEntry&& other)
-{
-    mHandle = other.mHandle;
-    other.mHandle = nullptr;
-}
-
-BufferCacheEntry& BufferCacheEntry::operator=(buffer_handle_t handle)
-{
-    clear();
-    mHandle = handle;
-    return *this;
-}
-
-BufferCacheEntry::~BufferCacheEntry()
-{
-    clear();
-}
-
-void BufferCacheEntry::clear()
-{
-    if (mHandle) {
-        sHandleImporter.freeBuffer(mHandle);
-    }
-}
-
-ComposerClient::ComposerClient(ComposerBase& hal)
-    : mHal(hal), mWriter(kWriterInitialSize)
-{
-}
-
-ComposerClient::~ComposerClient()
-{
-    // We want to call hwc2_close here (and move hwc2_open to the
-    // constructor), with the assumption that hwc2_close would
-    //
-    //  - clean up all resources owned by the client
-    //  - make sure all displays are blank (since there is no layer)
-    //
-    // But since SF used to crash at this point, different hwcomposer2
-    // implementations behave differently on hwc2_close.  Our only portable
-    // choice really is to abort().  But that is not an option anymore
-    // because we might also have VTS or VR as clients that can come and go.
-    //
-    // Below we manually clean all resources (layers and virtual
-    // displays), and perform a presentDisplay afterwards.
-    ALOGW("destroying composer client");
-
-    mHal.enableCallback(false);
-
-    // no need to grab the mutex as any in-flight hwbinder call would have
-    // kept the client alive
-    for (const auto& dpy : mDisplayData) {
-        ALOGW("destroying client resources for display %" PRIu64, dpy.first);
-
-        for (const auto& ly : dpy.second.Layers) {
-            mHal.destroyLayer(dpy.first, ly.first);
-        }
-
-        if (dpy.second.IsVirtual) {
-            mHal.destroyVirtualDisplay(dpy.first);
-        } else {
-            ALOGW("performing a final presentDisplay");
-
-            std::vector<Layer> changedLayers;
-            std::vector<IComposerClient::Composition> compositionTypes;
-            uint32_t displayRequestMask = 0;
-            std::vector<Layer> requestedLayers;
-            std::vector<uint32_t> requestMasks;
-            mHal.validateDisplay(dpy.first, &changedLayers, &compositionTypes,
-                    &displayRequestMask, &requestedLayers, &requestMasks);
-
-            mHal.acceptDisplayChanges(dpy.first);
-
-            int32_t presentFence = -1;
-            std::vector<Layer> releasedLayers;
-            std::vector<int32_t> releaseFences;
-            mHal.presentDisplay(dpy.first, &presentFence, &releasedLayers, &releaseFences);
-            if (presentFence >= 0) {
-                close(presentFence);
-            }
-            for (auto fence : releaseFences) {
-                if (fence >= 0) {
-                    close(fence);
-                }
-            }
-        }
-    }
-
-    mDisplayData.clear();
-
-    sHandleImporter.cleanup();
-
-    mHal.removeClient();
-
-    ALOGW("removed composer client");
-}
-
-void ComposerClient::initialize()
-{
-    mReader = createCommandReader();
-    if (!sHandleImporter.initialize()) {
-        LOG_ALWAYS_FATAL("failed to initialize handle importer");
-    }
-}
-
-void ComposerClient::onHotplug(Display display,
-        IComposerCallback::Connection connected)
-{
-    {
-        std::lock_guard<std::mutex> lock(mDisplayDataMutex);
-
-        if (connected == IComposerCallback::Connection::CONNECTED) {
-            mDisplayData.emplace(display, DisplayData(false));
-        } else if (connected == IComposerCallback::Connection::DISCONNECTED) {
-            mDisplayData.erase(display);
-        }
-    }
-
-    auto ret = mCallback->onHotplug(display, connected);
-    ALOGE_IF(!ret.isOk(), "failed to send onHotplug: %s",
-            ret.description().c_str());
-}
-
-void ComposerClient::onRefresh(Display display)
-{
-    auto ret = mCallback->onRefresh(display);
-    ALOGE_IF(!ret.isOk(), "failed to send onRefresh: %s",
-            ret.description().c_str());
-}
-
-void ComposerClient::onVsync(Display display, int64_t timestamp)
-{
-    auto ret = mCallback->onVsync(display, timestamp);
-    ALOGE_IF(!ret.isOk(), "failed to send onVsync: %s",
-            ret.description().c_str());
-}
-
-Return<void> ComposerClient::registerCallback(
-        const sp<IComposerCallback>& callback)
-{
-    // no locking as we require this function to be called only once
-    mCallback = callback;
-    mHal.enableCallback(callback != nullptr);
-
-    return Void();
-}
-
-Return<uint32_t> ComposerClient::getMaxVirtualDisplayCount()
-{
-    return mHal.getMaxVirtualDisplayCount();
-}
-
-Return<void> ComposerClient::createVirtualDisplay(uint32_t width,
-        uint32_t height, PixelFormat formatHint, uint32_t outputBufferSlotCount,
-        createVirtualDisplay_cb hidl_cb)
-{
-    Display display = 0;
-    Error err = mHal.createVirtualDisplay(width, height,
-            &formatHint, &display);
-    if (err == Error::NONE) {
-        std::lock_guard<std::mutex> lock(mDisplayDataMutex);
-
-        auto dpy = mDisplayData.emplace(display, DisplayData(true)).first;
-        dpy->second.OutputBuffers.resize(outputBufferSlotCount);
-    }
-
-    hidl_cb(err, display, formatHint);
-    return Void();
-}
-
-Return<Error> ComposerClient::destroyVirtualDisplay(Display display)
-{
-    Error err = mHal.destroyVirtualDisplay(display);
-    if (err == Error::NONE) {
-        std::lock_guard<std::mutex> lock(mDisplayDataMutex);
-
-        mDisplayData.erase(display);
-    }
-
-    return err;
-}
-
-Return<void> ComposerClient::createLayer(Display display,
-        uint32_t bufferSlotCount, createLayer_cb hidl_cb)
-{
-    Layer layer = 0;
-    Error err = mHal.createLayer(display, &layer);
-    if (err == Error::NONE) {
-        std::lock_guard<std::mutex> lock(mDisplayDataMutex);
-        auto dpy = mDisplayData.find(display);
-        // The display entry may have already been removed by onHotplug.
-        if (dpy != mDisplayData.end()) {
-            auto ly = dpy->second.Layers.emplace(layer, LayerBuffers()).first;
-            ly->second.Buffers.resize(bufferSlotCount);
-        } else {
-            err = Error::BAD_DISPLAY;
-            // Note: We do not destroy the layer on this error as the hotplug
-            // disconnect invalidates the display id. The implementation should
-            // ensure all layers for the display are destroyed.
-        }
-    }
-
-    hidl_cb(err, layer);
-    return Void();
-}
-
-Return<Error> ComposerClient::destroyLayer(Display display, Layer layer)
-{
-    Error err = mHal.destroyLayer(display, layer);
-    if (err == Error::NONE) {
-        std::lock_guard<std::mutex> lock(mDisplayDataMutex);
-
-        auto dpy = mDisplayData.find(display);
-        // The display entry may have already been removed by onHotplug.
-        if (dpy != mDisplayData.end()) {
-            dpy->second.Layers.erase(layer);
-        }
-    }
-
-    return err;
-}
-
-Return<void> ComposerClient::getActiveConfig(Display display,
-        getActiveConfig_cb hidl_cb)
-{
-    Config config = 0;
-    Error err = mHal.getActiveConfig(display, &config);
-
-    hidl_cb(err, config);
-    return Void();
-}
-
-Return<Error> ComposerClient::getClientTargetSupport(Display display,
-        uint32_t width, uint32_t height,
-        PixelFormat format, Dataspace dataspace)
-{
-    Error err = mHal.getClientTargetSupport(display,
-            width, height, format, dataspace);
-    return err;
-}
-
-Return<void> ComposerClient::getColorModes(Display display,
-          getColorModes_cb hidl_cb)
-{
-    hidl_vec<ColorMode> modes;
-    Error err = mHal.getColorModes(display, &modes);
-
-    hidl_cb(err, modes);
-    return Void();
-}
-
-Return<void> ComposerClient::getDisplayAttribute(Display display,
-        Config config, Attribute attribute,
-        getDisplayAttribute_cb hidl_cb)
-{
-    int32_t value = 0;
-    Error err = mHal.getDisplayAttribute(display, config, attribute, &value);
-
-    hidl_cb(err, value);
-    return Void();
-}
-
-Return<void> ComposerClient::getDisplayConfigs(Display display,
-        getDisplayConfigs_cb hidl_cb)
-{
-    hidl_vec<Config> configs;
-    Error err = mHal.getDisplayConfigs(display, &configs);
-
-    hidl_cb(err, configs);
-    return Void();
-}
-
-Return<void> ComposerClient::getDisplayName(Display display,
-        getDisplayName_cb hidl_cb)
-{
-    hidl_string name;
-    Error err = mHal.getDisplayName(display, &name);
-
-    hidl_cb(err, name);
-    return Void();
-}
-
-Return<void> ComposerClient::getDisplayType(Display display,
-        getDisplayType_cb hidl_cb)
-{
-    DisplayType type = DisplayType::INVALID;
-    Error err = mHal.getDisplayType(display, &type);
-
-    hidl_cb(err, type);
-    return Void();
-}
-
-Return<void> ComposerClient::getDozeSupport(Display display,
-        getDozeSupport_cb hidl_cb)
-{
-    bool support = false;
-    Error err = mHal.getDozeSupport(display, &support);
-
-    hidl_cb(err, support);
-    return Void();
-}
-
-Return<void> ComposerClient::getHdrCapabilities(Display display,
-        getHdrCapabilities_cb hidl_cb)
-{
-    hidl_vec<Hdr> types;
-    float max_lumi = 0.0f;
-    float max_avg_lumi = 0.0f;
-    float min_lumi = 0.0f;
-    Error err = mHal.getHdrCapabilities(display, &types,
-            &max_lumi, &max_avg_lumi, &min_lumi);
-
-    hidl_cb(err, types, max_lumi, max_avg_lumi, min_lumi);
-    return Void();
-}
-
-Return<Error> ComposerClient::setClientTargetSlotCount(Display display,
-        uint32_t clientTargetSlotCount)
-{
-    std::lock_guard<std::mutex> lock(mDisplayDataMutex);
-
-    auto dpy = mDisplayData.find(display);
-    if (dpy == mDisplayData.end()) {
-        return Error::BAD_DISPLAY;
-    }
-
-    dpy->second.ClientTargets.resize(clientTargetSlotCount);
-
-    return Error::NONE;
-}
-
-Return<Error> ComposerClient::setActiveConfig(Display display, Config config)
-{
-    Error err = mHal.setActiveConfig(display, config);
-    return err;
-}
-
-Return<Error> ComposerClient::setColorMode(Display display, ColorMode mode)
-{
-    Error err = mHal.setColorMode(display, mode);
-    return err;
-}
-
-Return<Error> ComposerClient::setPowerMode(Display display, PowerMode mode)
-{
-    Error err = mHal.setPowerMode(display, mode);
-    return err;
-}
-
-Return<Error> ComposerClient::setVsyncEnabled(Display display, Vsync enabled)
-{
-    Error err = mHal.setVsyncEnabled(display, enabled);
-    return err;
-}
-
-Return<Error> ComposerClient::setInputCommandQueue(
-        const MQDescriptorSync<uint32_t>& descriptor)
-{
-    std::lock_guard<std::mutex> lock(mCommandMutex);
-    return mReader->setMQDescriptor(descriptor) ?
-        Error::NONE : Error::NO_RESOURCES;
-}
-
-Return<void> ComposerClient::getOutputCommandQueue(
-        getOutputCommandQueue_cb hidl_cb)
-{
-    // no locking as we require this function to be called inside
-    // executeCommands_cb
-
-    auto outDescriptor = mWriter.getMQDescriptor();
-    if (outDescriptor) {
-        hidl_cb(Error::NONE, *outDescriptor);
-    } else {
-        hidl_cb(Error::NO_RESOURCES, CommandQueueType::Descriptor());
-    }
-
-    return Void();
-}
-
-Return<void> ComposerClient::executeCommands(uint32_t inLength,
-        const hidl_vec<hidl_handle>& inHandles,
-        executeCommands_cb hidl_cb)
-{
-    std::lock_guard<std::mutex> lock(mCommandMutex);
-
-    bool outChanged = false;
-    uint32_t outLength = 0;
-    hidl_vec<hidl_handle> outHandles;
-
-    if (!mReader->readQueue(inLength, inHandles)) {
-        hidl_cb(Error::BAD_PARAMETER, outChanged, outLength, outHandles);
-        return Void();
-    }
-
-    Error err = mReader->parse();
-    if (err == Error::NONE &&
-            !mWriter.writeQueue(&outChanged, &outLength, &outHandles)) {
-        err = Error::NO_RESOURCES;
-    }
-
-    hidl_cb(err, outChanged, outLength, outHandles);
-
-    mReader->reset();
-    mWriter.reset();
-
-    return Void();
-}
-
-std::unique_ptr<ComposerClient::CommandReader>
-ComposerClient::createCommandReader()
-{
-    return std::unique_ptr<ComposerClient::CommandReader>(
-        new CommandReader(*this));
-}
-
-ComposerClient::CommandReader::CommandReader(ComposerClient& client)
-    : mClient(client), mHal(client.mHal), mWriter(client.mWriter)
-{
-}
-
-ComposerClient::CommandReader::~CommandReader()
-{
-}
-
-Error ComposerClient::CommandReader::parse()
-{
-    IComposerClient::Command command;
-    uint16_t length = 0;
-
-    while (!isEmpty()) {
-        if (!beginCommand(&command, &length)) {
-            break;
-        }
-
-        bool parsed = parseCommand(command, length);
-        endCommand();
-
-        if (!parsed) {
-            ALOGE("failed to parse command 0x%x, length %" PRIu16,
-                    command, length);
-            break;
-        }
-    }
-
-    return (isEmpty()) ? Error::NONE : Error::BAD_PARAMETER;
-}
-
-bool ComposerClient::CommandReader::parseCommand(
-        IComposerClient::Command command, uint16_t length) {
-    switch (command) {
-    case IComposerClient::Command::SELECT_DISPLAY:
-        return parseSelectDisplay(length);
-    case IComposerClient::Command::SELECT_LAYER:
-        return parseSelectLayer(length);
-    case IComposerClient::Command::SET_COLOR_TRANSFORM:
-        return parseSetColorTransform(length);
-    case IComposerClient::Command::SET_CLIENT_TARGET:
-        return parseSetClientTarget(length);
-    case IComposerClient::Command::SET_OUTPUT_BUFFER:
-        return parseSetOutputBuffer(length);
-    case IComposerClient::Command::VALIDATE_DISPLAY:
-        return parseValidateDisplay(length);
-    case IComposerClient::Command::PRESENT_OR_VALIDATE_DISPLAY:
-        return parsePresentOrValidateDisplay(length);
-    case IComposerClient::Command::ACCEPT_DISPLAY_CHANGES:
-        return parseAcceptDisplayChanges(length);
-    case IComposerClient::Command::PRESENT_DISPLAY:
-        return parsePresentDisplay(length);
-    case IComposerClient::Command::SET_LAYER_CURSOR_POSITION:
-        return parseSetLayerCursorPosition(length);
-    case IComposerClient::Command::SET_LAYER_BUFFER:
-        return parseSetLayerBuffer(length);
-    case IComposerClient::Command::SET_LAYER_SURFACE_DAMAGE:
-        return parseSetLayerSurfaceDamage(length);
-    case IComposerClient::Command::SET_LAYER_BLEND_MODE:
-        return parseSetLayerBlendMode(length);
-    case IComposerClient::Command::SET_LAYER_COLOR:
-        return parseSetLayerColor(length);
-    case IComposerClient::Command::SET_LAYER_COMPOSITION_TYPE:
-        return parseSetLayerCompositionType(length);
-    case IComposerClient::Command::SET_LAYER_DATASPACE:
-        return parseSetLayerDataspace(length);
-    case IComposerClient::Command::SET_LAYER_DISPLAY_FRAME:
-        return parseSetLayerDisplayFrame(length);
-    case IComposerClient::Command::SET_LAYER_PLANE_ALPHA:
-        return parseSetLayerPlaneAlpha(length);
-    case IComposerClient::Command::SET_LAYER_SIDEBAND_STREAM:
-        return parseSetLayerSidebandStream(length);
-    case IComposerClient::Command::SET_LAYER_SOURCE_CROP:
-        return parseSetLayerSourceCrop(length);
-    case IComposerClient::Command::SET_LAYER_TRANSFORM:
-        return parseSetLayerTransform(length);
-    case IComposerClient::Command::SET_LAYER_VISIBLE_REGION:
-        return parseSetLayerVisibleRegion(length);
-    case IComposerClient::Command::SET_LAYER_Z_ORDER:
-        return parseSetLayerZOrder(length);
-    default:
-        return false;
-    }
-}
-
-bool ComposerClient::CommandReader::parseSelectDisplay(uint16_t length)
-{
-    if (length != CommandWriterBase::kSelectDisplayLength) {
-        return false;
-    }
-
-    mDisplay = read64();
-    mWriter.selectDisplay(mDisplay);
-
-    return true;
-}
-
-bool ComposerClient::CommandReader::parseSelectLayer(uint16_t length)
-{
-    if (length != CommandWriterBase::kSelectLayerLength) {
-        return false;
-    }
-
-    mLayer = read64();
-
-    return true;
-}
-
-bool ComposerClient::CommandReader::parseSetColorTransform(uint16_t length)
-{
-    if (length != CommandWriterBase::kSetColorTransformLength) {
-        return false;
-    }
-
-    float matrix[16];
-    for (int i = 0; i < 16; i++) {
-        matrix[i] = readFloat();
-    }
-    auto transform = readSigned();
-
-    auto err = mHal.setColorTransform(mDisplay, matrix, transform);
-    if (err != Error::NONE) {
-        mWriter.setError(getCommandLoc(), err);
-    }
-
-    return true;
-}
-
-bool ComposerClient::CommandReader::parseSetClientTarget(uint16_t length)
-{
-    // 4 parameters followed by N rectangles
-    if ((length - 4) % 4 != 0) {
-        return false;
-    }
-
-    bool useCache = false;
-    auto slot = read();
-    auto clientTarget = readHandle(&useCache);
-    auto fence = readFence();
-    auto dataspace = readSigned();
-    auto damage = readRegion((length - 4) / 4);
-    bool closeFence = true;
-
-    auto err = lookupBuffer(BufferCache::CLIENT_TARGETS,
-            slot, useCache, clientTarget, &clientTarget);
-    if (err == Error::NONE) {
-        err = mHal.setClientTarget(mDisplay, clientTarget, fence,
-                dataspace, damage);
-        auto updateBufErr = updateBuffer(BufferCache::CLIENT_TARGETS, slot,
-                useCache, clientTarget);
-        if (err == Error::NONE) {
-            closeFence = false;
-            err = updateBufErr;
-        }
-    }
-    if (closeFence) {
-        close(fence);
-    }
-    if (err != Error::NONE) {
-        mWriter.setError(getCommandLoc(), err);
-    }
-
-    return true;
-}
-
-bool ComposerClient::CommandReader::parseSetOutputBuffer(uint16_t length)
-{
-    if (length != CommandWriterBase::kSetOutputBufferLength) {
-        return false;
-    }
-
-    bool useCache = false;
-    auto slot = read();
-    auto outputBuffer = readHandle(&useCache);
-    auto fence = readFence();
-    bool closeFence = true;
-
-    auto err = lookupBuffer(BufferCache::OUTPUT_BUFFERS,
-            slot, useCache, outputBuffer, &outputBuffer);
-    if (err == Error::NONE) {
-        err = mHal.setOutputBuffer(mDisplay, outputBuffer, fence);
-        auto updateBufErr = updateBuffer(BufferCache::OUTPUT_BUFFERS,
-                slot, useCache, outputBuffer);
-        if (err == Error::NONE) {
-            closeFence = false;
-            err = updateBufErr;
-        }
-    }
-    if (closeFence) {
-        close(fence);
-    }
-    if (err != Error::NONE) {
-        mWriter.setError(getCommandLoc(), err);
-    }
-
-    return true;
-}
-
-bool ComposerClient::CommandReader::parseValidateDisplay(uint16_t length)
-{
-    if (length != CommandWriterBase::kValidateDisplayLength) {
-        return false;
-    }
-
-    std::vector<Layer> changedLayers;
-    std::vector<IComposerClient::Composition> compositionTypes;
-    uint32_t displayRequestMask = 0x0;
-    std::vector<Layer> requestedLayers;
-    std::vector<uint32_t> requestMasks;
-
-    auto err = mHal.validateDisplay(mDisplay, &changedLayers,
-            &compositionTypes, &displayRequestMask,
-            &requestedLayers, &requestMasks);
-    if (err == Error::NONE) {
-        mWriter.setChangedCompositionTypes(changedLayers,
-                compositionTypes);
-        mWriter.setDisplayRequests(displayRequestMask,
-                requestedLayers, requestMasks);
-    } else {
-        mWriter.setError(getCommandLoc(), err);
-    }
-
-    return true;
-}
-
-bool ComposerClient::CommandReader::parsePresentOrValidateDisplay(uint16_t length)
-{
-    if (length != CommandWriterBase::kPresentOrValidateDisplayLength) {
-        return false;
-    }
-
-    // First try to Present as is.
-    if (mHal.hasCapability(HWC2_CAPABILITY_SKIP_VALIDATE)) {
-        int presentFence = -1;
-        std::vector<Layer> layers;
-        std::vector<int> fences;
-        auto err = mHal.presentDisplay(mDisplay, &presentFence, &layers, &fences);
-        if (err == Error::NONE) {
-            mWriter.setPresentOrValidateResult(1);
-            mWriter.setPresentFence(presentFence);
-            mWriter.setReleaseFences(layers, fences);
-            return true;
-        }
-    }
-
-    // Present has failed. We need to fallback to validate
-    std::vector<Layer> changedLayers;
-    std::vector<IComposerClient::Composition> compositionTypes;
-    uint32_t displayRequestMask = 0x0;
-    std::vector<Layer> requestedLayers;
-    std::vector<uint32_t> requestMasks;
-
-    auto err = mHal.validateDisplay(mDisplay, &changedLayers, &compositionTypes,
-                                    &displayRequestMask, &requestedLayers, &requestMasks);
-    if (err == Error::NONE) {
-        mWriter.setPresentOrValidateResult(0);
-        mWriter.setChangedCompositionTypes(changedLayers,
-                                           compositionTypes);
-        mWriter.setDisplayRequests(displayRequestMask,
-                                   requestedLayers, requestMasks);
-    } else {
-        mWriter.setError(getCommandLoc(), err);
-    }
-
-    return true;
-}
-
-bool ComposerClient::CommandReader::parseAcceptDisplayChanges(uint16_t length)
-{
-    if (length != CommandWriterBase::kAcceptDisplayChangesLength) {
-        return false;
-    }
-
-    auto err = mHal.acceptDisplayChanges(mDisplay);
-    if (err != Error::NONE) {
-        mWriter.setError(getCommandLoc(), err);
-    }
-
-    return true;
-}
-
-bool ComposerClient::CommandReader::parsePresentDisplay(uint16_t length)
-{
-    if (length != CommandWriterBase::kPresentDisplayLength) {
-        return false;
-    }
-
-    int presentFence = -1;
-    std::vector<Layer> layers;
-    std::vector<int> fences;
-    auto err = mHal.presentDisplay(mDisplay, &presentFence, &layers, &fences);
-    if (err == Error::NONE) {
-        mWriter.setPresentFence(presentFence);
-        mWriter.setReleaseFences(layers, fences);
-    } else {
-        mWriter.setError(getCommandLoc(), err);
-    }
-
-    return true;
-}
-
-bool ComposerClient::CommandReader::parseSetLayerCursorPosition(uint16_t length)
-{
-    if (length != CommandWriterBase::kSetLayerCursorPositionLength) {
-        return false;
-    }
-
-    auto err = mHal.setLayerCursorPosition(mDisplay, mLayer,
-            readSigned(), readSigned());
-    if (err != Error::NONE) {
-        mWriter.setError(getCommandLoc(), err);
-    }
-
-    return true;
-}
-
-bool ComposerClient::CommandReader::parseSetLayerBuffer(uint16_t length)
-{
-    if (length != CommandWriterBase::kSetLayerBufferLength) {
-        return false;
-    }
-
-    bool useCache = false;
-    auto slot = read();
-    auto buffer = readHandle(&useCache);
-    auto fence = readFence();
-    bool closeFence = true;
-
-    auto err = lookupBuffer(BufferCache::LAYER_BUFFERS,
-            slot, useCache, buffer, &buffer);
-    if (err == Error::NONE) {
-        err = mHal.setLayerBuffer(mDisplay, mLayer, buffer, fence);
-        auto updateBufErr = updateBuffer(BufferCache::LAYER_BUFFERS, slot,
-                useCache, buffer);
-        if (err == Error::NONE) {
-            closeFence = false;
-            err = updateBufErr;
-        }
-    }
-    if (closeFence) {
-        close(fence);
-    }
-    if (err != Error::NONE) {
-        mWriter.setError(getCommandLoc(), err);
-    }
-
-    return true;
-}
-
-bool ComposerClient::CommandReader::parseSetLayerSurfaceDamage(uint16_t length)
-{
-    // N rectangles
-    if (length % 4 != 0) {
-        return false;
-    }
-
-    auto damage = readRegion(length / 4);
-    auto err = mHal.setLayerSurfaceDamage(mDisplay, mLayer, damage);
-    if (err != Error::NONE) {
-        mWriter.setError(getCommandLoc(), err);
-    }
-
-    return true;
-}
-
-bool ComposerClient::CommandReader::parseSetLayerBlendMode(uint16_t length)
-{
-    if (length != CommandWriterBase::kSetLayerBlendModeLength) {
-        return false;
-    }
-
-    auto err = mHal.setLayerBlendMode(mDisplay, mLayer, readSigned());
-    if (err != Error::NONE) {
-        mWriter.setError(getCommandLoc(), err);
-    }
-
-    return true;
-}
-
-bool ComposerClient::CommandReader::parseSetLayerColor(uint16_t length)
-{
-    if (length != CommandWriterBase::kSetLayerColorLength) {
-        return false;
-    }
-
-    auto err = mHal.setLayerColor(mDisplay, mLayer, readColor());
-    if (err != Error::NONE) {
-        mWriter.setError(getCommandLoc(), err);
-    }
-
-    return true;
-}
-
-bool ComposerClient::CommandReader::parseSetLayerCompositionType(
-        uint16_t length)
-{
-    if (length != CommandWriterBase::kSetLayerCompositionTypeLength) {
-        return false;
-    }
-
-    auto err = mHal.setLayerCompositionType(mDisplay, mLayer, readSigned());
-    if (err != Error::NONE) {
-        mWriter.setError(getCommandLoc(), err);
-    }
-
-    return true;
-}
-
-bool ComposerClient::CommandReader::parseSetLayerDataspace(uint16_t length)
-{
-    if (length != CommandWriterBase::kSetLayerDataspaceLength) {
-        return false;
-    }
-
-    auto err = mHal.setLayerDataspace(mDisplay, mLayer, readSigned());
-    if (err != Error::NONE) {
-        mWriter.setError(getCommandLoc(), err);
-    }
-
-    return true;
-}
-
-bool ComposerClient::CommandReader::parseSetLayerDisplayFrame(uint16_t length)
-{
-    if (length != CommandWriterBase::kSetLayerDisplayFrameLength) {
-        return false;
-    }
-
-    auto err = mHal.setLayerDisplayFrame(mDisplay, mLayer, readRect());
-    if (err != Error::NONE) {
-        mWriter.setError(getCommandLoc(), err);
-    }
-
-    return true;
-}
-
-bool ComposerClient::CommandReader::parseSetLayerPlaneAlpha(uint16_t length)
-{
-    if (length != CommandWriterBase::kSetLayerPlaneAlphaLength) {
-        return false;
-    }
-
-    auto err = mHal.setLayerPlaneAlpha(mDisplay, mLayer, readFloat());
-    if (err != Error::NONE) {
-        mWriter.setError(getCommandLoc(), err);
-    }
-
-    return true;
-}
-
-bool ComposerClient::CommandReader::parseSetLayerSidebandStream(uint16_t length)
-{
-    if (length != CommandWriterBase::kSetLayerSidebandStreamLength) {
-        return false;
-    }
-
-    auto stream = readHandle();
-
-    auto err = lookupLayerSidebandStream(stream, &stream);
-    if (err == Error::NONE) {
-        err = mHal.setLayerSidebandStream(mDisplay, mLayer, stream);
-        auto updateErr = updateLayerSidebandStream(stream);
-        if (err == Error::NONE) {
-            err = updateErr;
-        }
-    }
-    if (err != Error::NONE) {
-        mWriter.setError(getCommandLoc(), err);
-    }
-
-    return true;
-}
-
-bool ComposerClient::CommandReader::parseSetLayerSourceCrop(uint16_t length)
-{
-    if (length != CommandWriterBase::kSetLayerSourceCropLength) {
-        return false;
-    }
-
-    auto err = mHal.setLayerSourceCrop(mDisplay, mLayer, readFRect());
-    if (err != Error::NONE) {
-        mWriter.setError(getCommandLoc(), err);
-    }
-
-    return true;
-}
-
-bool ComposerClient::CommandReader::parseSetLayerTransform(uint16_t length)
-{
-    if (length != CommandWriterBase::kSetLayerTransformLength) {
-        return false;
-    }
-
-    auto err = mHal.setLayerTransform(mDisplay, mLayer, readSigned());
-    if (err != Error::NONE) {
-        mWriter.setError(getCommandLoc(), err);
-    }
-
-    return true;
-}
-
-bool ComposerClient::CommandReader::parseSetLayerVisibleRegion(uint16_t length)
-{
-    // N rectangles
-    if (length % 4 != 0) {
-        return false;
-    }
-
-    auto region = readRegion(length / 4);
-    auto err = mHal.setLayerVisibleRegion(mDisplay, mLayer, region);
-    if (err != Error::NONE) {
-        mWriter.setError(getCommandLoc(), err);
-    }
-
-    return true;
-}
-
-bool ComposerClient::CommandReader::parseSetLayerZOrder(uint16_t length)
-{
-    if (length != CommandWriterBase::kSetLayerZOrderLength) {
-        return false;
-    }
-
-    auto err = mHal.setLayerZOrder(mDisplay, mLayer, read());
-    if (err != Error::NONE) {
-        mWriter.setError(getCommandLoc(), err);
-    }
-
-    return true;
-}
-
-hwc_rect_t ComposerClient::CommandReader::readRect()
-{
-    return hwc_rect_t{
-        readSigned(),
-        readSigned(),
-        readSigned(),
-        readSigned(),
-    };
-}
-
-std::vector<hwc_rect_t> ComposerClient::CommandReader::readRegion(size_t count)
-{
-    std::vector<hwc_rect_t> region;
-    region.reserve(count);
-    while (count > 0) {
-        region.emplace_back(readRect());
-        count--;
-    }
-
-    return region;
-}
-
-hwc_frect_t ComposerClient::CommandReader::readFRect()
-{
-    return hwc_frect_t{
-        readFloat(),
-        readFloat(),
-        readFloat(),
-        readFloat(),
-    };
-}
-
-Error ComposerClient::CommandReader::lookupBufferCacheEntryLocked(
-        BufferCache cache, uint32_t slot, BufferCacheEntry** outEntry)
-{
-    auto dpy = mClient.mDisplayData.find(mDisplay);
-    if (dpy == mClient.mDisplayData.end()) {
-        return Error::BAD_DISPLAY;
-    }
-
-    BufferCacheEntry* entry = nullptr;
-    switch (cache) {
-    case BufferCache::CLIENT_TARGETS:
-        if (slot < dpy->second.ClientTargets.size()) {
-            entry = &dpy->second.ClientTargets[slot];
-        }
-        break;
-    case BufferCache::OUTPUT_BUFFERS:
-        if (slot < dpy->second.OutputBuffers.size()) {
-            entry = &dpy->second.OutputBuffers[slot];
-        }
-        break;
-    case BufferCache::LAYER_BUFFERS:
-        {
-            auto ly = dpy->second.Layers.find(mLayer);
-            if (ly == dpy->second.Layers.end()) {
-                return Error::BAD_LAYER;
-            }
-            if (slot < ly->second.Buffers.size()) {
-                entry = &ly->second.Buffers[slot];
-            }
-        }
-        break;
-    case BufferCache::LAYER_SIDEBAND_STREAMS:
-        {
-            auto ly = dpy->second.Layers.find(mLayer);
-            if (ly == dpy->second.Layers.end()) {
-                return Error::BAD_LAYER;
-            }
-            if (slot == 0) {
-                entry = &ly->second.SidebandStream;
-            }
-        }
-        break;
-    default:
-        break;
-    }
-
-    if (!entry) {
-        ALOGW("invalid buffer slot %" PRIu32, slot);
-        return Error::BAD_PARAMETER;
-    }
-
-    *outEntry = entry;
-
-    return Error::NONE;
-}
-
-Error ComposerClient::CommandReader::lookupBuffer(BufferCache cache,
-        uint32_t slot, bool useCache, buffer_handle_t handle,
-        buffer_handle_t* outHandle)
-{
-    if (useCache) {
-        std::lock_guard<std::mutex> lock(mClient.mDisplayDataMutex);
-
-        BufferCacheEntry* entry;
-        Error error = lookupBufferCacheEntryLocked(cache, slot, &entry);
-        if (error != Error::NONE) {
-            return error;
-        }
-
-        // input handle is ignored
-        *outHandle = entry->getHandle();
-    } else if (cache == BufferCache::LAYER_SIDEBAND_STREAMS) {
-        if (handle) {
-            *outHandle = native_handle_clone(handle);
-            if (*outHandle == nullptr) {
-                return Error::NO_RESOURCES;
-            }
-        }
-    } else {
-        if (!sHandleImporter.importBuffer(handle)) {
-            return Error::NO_RESOURCES;
-        }
-
-        *outHandle = handle;
-    }
-
-    return Error::NONE;
-}
-
-Error ComposerClient::CommandReader::updateBuffer(BufferCache cache,
-        uint32_t slot, bool useCache, buffer_handle_t handle)
-{
-    // handle was looked up from cache
-    if (useCache) {
-        return Error::NONE;
-    }
-
-    std::lock_guard<std::mutex> lock(mClient.mDisplayDataMutex);
-
-    BufferCacheEntry* entry = nullptr;
-    Error error = lookupBufferCacheEntryLocked(cache, slot, &entry);
-    if (error != Error::NONE) {
-      return error;
-    }
-
-    *entry = handle;
-    return Error::NONE;
-}
-
-} // namespace implementation
-} // namespace V2_1
-} // namespace composer
-} // namespace graphics
-} // namespace hardware
-} // namespace android
diff --git a/graphics/composer/2.1/default/ComposerClient.h b/graphics/composer/2.1/default/ComposerClient.h
deleted file mode 100644
index 104ed5a..0000000
--- a/graphics/composer/2.1/default/ComposerClient.h
+++ /dev/null
@@ -1,225 +0,0 @@
-/*
- * Copyright 2016 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.
- */
-
-#ifndef ANDROID_HARDWARE_GRAPHICS_COMPOSER_V2_1_COMPOSER_CLIENT_H
-#define ANDROID_HARDWARE_GRAPHICS_COMPOSER_V2_1_COMPOSER_CLIENT_H
-
-#include <mutex>
-#include <unordered_map>
-#include <vector>
-
-#include <composer-command-buffer/2.1/ComposerCommandBuffer.h>
-#include <hardware/hwcomposer2.h>
-#include "ComposerBase.h"
-
-namespace android {
-namespace hardware {
-namespace graphics {
-namespace composer {
-namespace V2_1 {
-namespace implementation {
-
-class BufferCacheEntry {
-public:
-    BufferCacheEntry();
-    BufferCacheEntry(BufferCacheEntry&& other);
-
-    BufferCacheEntry(const BufferCacheEntry& other) = delete;
-    BufferCacheEntry& operator=(const BufferCacheEntry& other) = delete;
-
-    BufferCacheEntry& operator=(buffer_handle_t handle);
-    ~BufferCacheEntry();
-
-    buffer_handle_t getHandle() const { return mHandle; }
-
-private:
-    void clear();
-
-    buffer_handle_t mHandle;
-};
-
-class ComposerClient : public IComposerClient {
-public:
-    ComposerClient(ComposerBase& hal);
-    virtual ~ComposerClient();
-
-    void initialize();
-
-    void onHotplug(Display display, IComposerCallback::Connection connected);
-    void onRefresh(Display display);
-    void onVsync(Display display, int64_t timestamp);
-
-    // IComposerClient interface
-    Return<void> registerCallback(
-            const sp<IComposerCallback>& callback) override;
-    Return<uint32_t> getMaxVirtualDisplayCount() override;
-    Return<void> createVirtualDisplay(uint32_t width, uint32_t height,
-            PixelFormat formatHint, uint32_t outputBufferSlotCount,
-            createVirtualDisplay_cb hidl_cb) override;
-    Return<Error> destroyVirtualDisplay(Display display) override;
-    Return<void> createLayer(Display display, uint32_t bufferSlotCount,
-            createLayer_cb hidl_cb) override;
-    Return<Error> destroyLayer(Display display, Layer layer) override;
-    Return<void> getActiveConfig(Display display,
-            getActiveConfig_cb hidl_cb) override;
-    Return<Error> getClientTargetSupport(Display display,
-            uint32_t width, uint32_t height,
-            PixelFormat format, Dataspace dataspace) override;
-    Return<void> getColorModes(Display display,
-            getColorModes_cb hidl_cb) override;
-    Return<void> getDisplayAttribute(Display display,
-            Config config, Attribute attribute,
-            getDisplayAttribute_cb hidl_cb) override;
-    Return<void> getDisplayConfigs(Display display,
-            getDisplayConfigs_cb hidl_cb) override;
-    Return<void> getDisplayName(Display display,
-            getDisplayName_cb hidl_cb) override;
-    Return<void> getDisplayType(Display display,
-            getDisplayType_cb hidl_cb) override;
-    Return<void> getDozeSupport(Display display,
-            getDozeSupport_cb hidl_cb) override;
-    Return<void> getHdrCapabilities(Display display,
-            getHdrCapabilities_cb hidl_cb) override;
-    Return<Error> setActiveConfig(Display display, Config config) override;
-    Return<Error> setColorMode(Display display, ColorMode mode) override;
-    Return<Error> setPowerMode(Display display, PowerMode mode) override;
-    Return<Error> setVsyncEnabled(Display display, Vsync enabled) override;
-    Return<Error> setClientTargetSlotCount(Display display,
-            uint32_t clientTargetSlotCount) override;
-    Return<Error> setInputCommandQueue(
-            const MQDescriptorSync<uint32_t>& descriptor) override;
-    Return<void> getOutputCommandQueue(
-            getOutputCommandQueue_cb hidl_cb) override;
-    Return<void> executeCommands(uint32_t inLength,
-            const hidl_vec<hidl_handle>& inHandles,
-            executeCommands_cb hidl_cb) override;
-
-protected:
-    struct LayerBuffers {
-        std::vector<BufferCacheEntry> Buffers;
-        // the handle is a sideband stream handle, not a buffer handle
-        BufferCacheEntry SidebandStream;
-    };
-
-    struct DisplayData {
-        bool IsVirtual;
-
-        std::vector<BufferCacheEntry> ClientTargets;
-        std::vector<BufferCacheEntry> OutputBuffers;
-
-        std::unordered_map<Layer, LayerBuffers> Layers;
-
-        DisplayData(bool isVirtual) : IsVirtual(isVirtual) {}
-    };
-
-    class CommandReader : public CommandReaderBase {
-    public:
-        CommandReader(ComposerClient& client);
-        virtual ~CommandReader();
-
-        Error parse();
-
-    protected:
-        virtual bool parseCommand(IComposerClient::Command command,
-                uint16_t length);
-
-        bool parseSelectDisplay(uint16_t length);
-        bool parseSelectLayer(uint16_t length);
-        bool parseSetColorTransform(uint16_t length);
-        bool parseSetClientTarget(uint16_t length);
-        bool parseSetOutputBuffer(uint16_t length);
-        bool parseValidateDisplay(uint16_t length);
-        bool parsePresentOrValidateDisplay(uint16_t length);
-        bool parseAcceptDisplayChanges(uint16_t length);
-        bool parsePresentDisplay(uint16_t length);
-        bool parseSetLayerCursorPosition(uint16_t length);
-        bool parseSetLayerBuffer(uint16_t length);
-        bool parseSetLayerSurfaceDamage(uint16_t length);
-        bool parseSetLayerBlendMode(uint16_t length);
-        bool parseSetLayerColor(uint16_t length);
-        bool parseSetLayerCompositionType(uint16_t length);
-        bool parseSetLayerDataspace(uint16_t length);
-        bool parseSetLayerDisplayFrame(uint16_t length);
-        bool parseSetLayerPlaneAlpha(uint16_t length);
-        bool parseSetLayerSidebandStream(uint16_t length);
-        bool parseSetLayerSourceCrop(uint16_t length);
-        bool parseSetLayerTransform(uint16_t length);
-        bool parseSetLayerVisibleRegion(uint16_t length);
-        bool parseSetLayerZOrder(uint16_t length);
-
-        hwc_rect_t readRect();
-        std::vector<hwc_rect_t> readRegion(size_t count);
-        hwc_frect_t readFRect();
-
-        enum class BufferCache {
-            CLIENT_TARGETS,
-            OUTPUT_BUFFERS,
-            LAYER_BUFFERS,
-            LAYER_SIDEBAND_STREAMS,
-        };
-        Error lookupBufferCacheEntryLocked(BufferCache cache, uint32_t slot,
-                BufferCacheEntry** outEntry);
-        Error lookupBuffer(BufferCache cache, uint32_t slot,
-                bool useCache, buffer_handle_t handle,
-                buffer_handle_t* outHandle);
-        Error updateBuffer(BufferCache cache, uint32_t slot,
-                bool useCache, buffer_handle_t handle);
-
-        Error lookupLayerSidebandStream(buffer_handle_t handle,
-                buffer_handle_t* outHandle)
-        {
-            return lookupBuffer(BufferCache::LAYER_SIDEBAND_STREAMS,
-                    0, false, handle, outHandle);
-        }
-        Error updateLayerSidebandStream(buffer_handle_t handle)
-        {
-            return updateBuffer(BufferCache::LAYER_SIDEBAND_STREAMS,
-                    0, false, handle);
-        }
-
-        ComposerClient& mClient;
-        ComposerBase& mHal;
-        CommandWriterBase& mWriter;
-
-        Display mDisplay;
-        Layer mLayer;
-    };
-
-    virtual std::unique_ptr<CommandReader> createCommandReader();
-
-    ComposerBase& mHal;
-
-    // 64KiB minus a small space for metadata such as read/write pointers
-    static constexpr size_t kWriterInitialSize =
-        64 * 1024 / sizeof(uint32_t) - 16;
-    std::mutex mCommandMutex;
-    std::unique_ptr<CommandReader> mReader;
-    CommandWriterBase mWriter;
-
-    sp<IComposerCallback> mCallback;
-
-    std::mutex mDisplayDataMutex;
-    std::unordered_map<Display, DisplayData> mDisplayData;
-};
-
-} // namespace implementation
-} // namespace V2_1
-} // namespace composer
-} // namespace graphics
-} // namespace hardware
-} // namespace android
-
-#endif  // ANDROID_HARDWARE_GRAPHICS_COMPOSER_V2_1_COMPOSER_CLIENT_H
diff --git a/graphics/composer/2.1/default/Hwc.cpp b/graphics/composer/2.1/default/Hwc.cpp
deleted file mode 100644
index cb393ec..0000000
--- a/graphics/composer/2.1/default/Hwc.cpp
+++ /dev/null
@@ -1,817 +0,0 @@
-/*
- * Copyright 2016 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 LOG_TAG "HwcPassthrough"
-
-#include "Hwc.h"
-
-#include <chrono>
-#include <type_traits>
-#include <log/log.h>
-
-#include "ComposerClient.h"
-#include "hardware/fb.h"
-#include "hardware/hwcomposer.h"
-#include "hwc2on1adapter/HWC2On1Adapter.h"
-#include "hwc2onfbadapter/HWC2OnFbAdapter.h"
-
-using namespace std::chrono_literals;
-
-namespace android {
-namespace hardware {
-namespace graphics {
-namespace composer {
-namespace V2_1 {
-namespace implementation {
-
-HwcHal::HwcHal(const hw_module_t* module)
-    : mDevice(nullptr), mDispatch(), mMustValidateDisplay(true), mAdapter() {
-    uint32_t majorVersion;
-    if (module->id && strcmp(module->id, GRALLOC_HARDWARE_MODULE_ID) == 0) {
-        majorVersion = initWithFb(module);
-    } else {
-        majorVersion = initWithHwc(module);
-    }
-
-    initCapabilities();
-    if (majorVersion >= 2 && hasCapability(HWC2_CAPABILITY_PRESENT_FENCE_IS_NOT_RELIABLE)) {
-        ALOGE("Present fence must be reliable from HWC2 on.");
-        abort();
-    }
-
-    initDispatch();
-}
-
-HwcHal::~HwcHal()
-{
-    hwc2_close(mDevice);
-}
-
-uint32_t HwcHal::initWithHwc(const hw_module_t* module)
-{
-    // Determine what kind of module is available (HWC2 vs HWC1.X).
-    hw_device_t* device = nullptr;
-    int error = module->methods->open(module, HWC_HARDWARE_COMPOSER, &device);
-    if (error != 0) {
-        ALOGE("Failed to open HWC device (%s), aborting", strerror(-error));
-        abort();
-    }
-    uint32_t majorVersion = (device->version >> 24) & 0xF;
-
-    // If we don't have a HWC2, we need to wrap whatever we have in an adapter.
-    if (majorVersion != 2) {
-        uint32_t minorVersion = device->version & HARDWARE_API_VERSION_2_MAJ_MIN_MASK;
-        minorVersion = (minorVersion >> 16) & 0xF;
-        ALOGI("Found HWC implementation v%d.%d", majorVersion, minorVersion);
-        if (minorVersion < 1) {
-            ALOGE("Cannot adapt to HWC version %d.%d. Minimum supported is 1.1",
-                  majorVersion, minorVersion);
-            abort();
-        }
-        mAdapter = std::make_unique<HWC2On1Adapter>(
-                reinterpret_cast<hwc_composer_device_1*>(device));
-
-        // Place the adapter in front of the device module.
-        mDevice = mAdapter.get();
-    } else {
-        mDevice = reinterpret_cast<hwc2_device_t*>(device);
-    }
-
-    return majorVersion;
-}
-
-uint32_t HwcHal::initWithFb(const hw_module_t* module)
-{
-    framebuffer_device_t* fb_device;
-    int error = framebuffer_open(module, &fb_device);
-    if (error != 0) {
-        ALOGE("Failed to open FB device (%s), aborting", strerror(-error));
-        abort();
-    }
-
-    mFbAdapter = std::make_unique<HWC2OnFbAdapter>(fb_device);
-    mDevice = mFbAdapter.get();
-
-    return 0;
-}
-
-void HwcHal::initCapabilities()
-{
-    uint32_t count = 0;
-    mDevice->getCapabilities(mDevice, &count, nullptr);
-
-    std::vector<int32_t> caps(count);
-    mDevice->getCapabilities(mDevice, &count, caps.data());
-    caps.resize(count);
-
-    mCapabilities.reserve(count);
-    for (auto cap : caps) {
-        mCapabilities.insert(static_cast<hwc2_capability_t>(cap));
-    }
-}
-
-template<typename T>
-void HwcHal::initDispatch(hwc2_function_descriptor_t desc, T* outPfn)
-{
-    auto pfn = mDevice->getFunction(mDevice, desc);
-    if (!pfn) {
-        LOG_ALWAYS_FATAL("failed to get hwcomposer2 function %d", desc);
-    }
-
-    *outPfn = reinterpret_cast<T>(pfn);
-}
-
-void HwcHal::initDispatch()
-{
-    initDispatch(HWC2_FUNCTION_ACCEPT_DISPLAY_CHANGES,
-            &mDispatch.acceptDisplayChanges);
-    initDispatch(HWC2_FUNCTION_CREATE_LAYER, &mDispatch.createLayer);
-    initDispatch(HWC2_FUNCTION_CREATE_VIRTUAL_DISPLAY,
-            &mDispatch.createVirtualDisplay);
-    initDispatch(HWC2_FUNCTION_DESTROY_LAYER, &mDispatch.destroyLayer);
-    initDispatch(HWC2_FUNCTION_DESTROY_VIRTUAL_DISPLAY,
-            &mDispatch.destroyVirtualDisplay);
-    initDispatch(HWC2_FUNCTION_DUMP, &mDispatch.dump);
-    initDispatch(HWC2_FUNCTION_GET_ACTIVE_CONFIG, &mDispatch.getActiveConfig);
-    initDispatch(HWC2_FUNCTION_GET_CHANGED_COMPOSITION_TYPES,
-            &mDispatch.getChangedCompositionTypes);
-    initDispatch(HWC2_FUNCTION_GET_CLIENT_TARGET_SUPPORT,
-            &mDispatch.getClientTargetSupport);
-    initDispatch(HWC2_FUNCTION_GET_COLOR_MODES, &mDispatch.getColorModes);
-    initDispatch(HWC2_FUNCTION_GET_DISPLAY_ATTRIBUTE,
-            &mDispatch.getDisplayAttribute);
-    initDispatch(HWC2_FUNCTION_GET_DISPLAY_CONFIGS,
-            &mDispatch.getDisplayConfigs);
-    initDispatch(HWC2_FUNCTION_GET_DISPLAY_NAME, &mDispatch.getDisplayName);
-    initDispatch(HWC2_FUNCTION_GET_DISPLAY_REQUESTS,
-            &mDispatch.getDisplayRequests);
-    initDispatch(HWC2_FUNCTION_GET_DISPLAY_TYPE, &mDispatch.getDisplayType);
-    initDispatch(HWC2_FUNCTION_GET_DOZE_SUPPORT, &mDispatch.getDozeSupport);
-    initDispatch(HWC2_FUNCTION_GET_HDR_CAPABILITIES,
-            &mDispatch.getHdrCapabilities);
-    initDispatch(HWC2_FUNCTION_GET_MAX_VIRTUAL_DISPLAY_COUNT,
-            &mDispatch.getMaxVirtualDisplayCount);
-    initDispatch(HWC2_FUNCTION_GET_RELEASE_FENCES,
-            &mDispatch.getReleaseFences);
-    initDispatch(HWC2_FUNCTION_PRESENT_DISPLAY, &mDispatch.presentDisplay);
-    initDispatch(HWC2_FUNCTION_REGISTER_CALLBACK,
-            &mDispatch.registerCallback);
-    initDispatch(HWC2_FUNCTION_SET_ACTIVE_CONFIG, &mDispatch.setActiveConfig);
-    initDispatch(HWC2_FUNCTION_SET_CLIENT_TARGET, &mDispatch.setClientTarget);
-    initDispatch(HWC2_FUNCTION_SET_COLOR_MODE, &mDispatch.setColorMode);
-    initDispatch(HWC2_FUNCTION_SET_COLOR_TRANSFORM,
-            &mDispatch.setColorTransform);
-    initDispatch(HWC2_FUNCTION_SET_CURSOR_POSITION,
-            &mDispatch.setCursorPosition);
-    initDispatch(HWC2_FUNCTION_SET_LAYER_BLEND_MODE,
-            &mDispatch.setLayerBlendMode);
-    initDispatch(HWC2_FUNCTION_SET_LAYER_BUFFER, &mDispatch.setLayerBuffer);
-    initDispatch(HWC2_FUNCTION_SET_LAYER_COLOR, &mDispatch.setLayerColor);
-    initDispatch(HWC2_FUNCTION_SET_LAYER_COMPOSITION_TYPE,
-            &mDispatch.setLayerCompositionType);
-    initDispatch(HWC2_FUNCTION_SET_LAYER_DATASPACE,
-            &mDispatch.setLayerDataspace);
-    initDispatch(HWC2_FUNCTION_SET_LAYER_DISPLAY_FRAME,
-            &mDispatch.setLayerDisplayFrame);
-    initDispatch(HWC2_FUNCTION_SET_LAYER_PLANE_ALPHA,
-            &mDispatch.setLayerPlaneAlpha);
-
-    if (hasCapability(HWC2_CAPABILITY_SIDEBAND_STREAM)) {
-        initDispatch(HWC2_FUNCTION_SET_LAYER_SIDEBAND_STREAM,
-                &mDispatch.setLayerSidebandStream);
-    }
-
-    initDispatch(HWC2_FUNCTION_SET_LAYER_SOURCE_CROP,
-            &mDispatch.setLayerSourceCrop);
-    initDispatch(HWC2_FUNCTION_SET_LAYER_SURFACE_DAMAGE,
-            &mDispatch.setLayerSurfaceDamage);
-    initDispatch(HWC2_FUNCTION_SET_LAYER_TRANSFORM,
-            &mDispatch.setLayerTransform);
-    initDispatch(HWC2_FUNCTION_SET_LAYER_VISIBLE_REGION,
-            &mDispatch.setLayerVisibleRegion);
-    initDispatch(HWC2_FUNCTION_SET_LAYER_Z_ORDER, &mDispatch.setLayerZOrder);
-    initDispatch(HWC2_FUNCTION_SET_OUTPUT_BUFFER, &mDispatch.setOutputBuffer);
-    initDispatch(HWC2_FUNCTION_SET_POWER_MODE, &mDispatch.setPowerMode);
-    initDispatch(HWC2_FUNCTION_SET_VSYNC_ENABLED, &mDispatch.setVsyncEnabled);
-    initDispatch(HWC2_FUNCTION_VALIDATE_DISPLAY, &mDispatch.validateDisplay);
-}
-
-bool HwcHal::hasCapability(hwc2_capability_t capability) {
-    return (mCapabilities.count(capability) > 0);
-}
-
-Return<void> HwcHal::getCapabilities(getCapabilities_cb hidl_cb)
-{
-    std::vector<Capability> caps;
-    caps.reserve(mCapabilities.size());
-    for (auto cap : mCapabilities) {
-        switch (cap) {
-            case HWC2_CAPABILITY_SIDEBAND_STREAM:
-            case HWC2_CAPABILITY_SKIP_CLIENT_COLOR_TRANSFORM:
-            case HWC2_CAPABILITY_PRESENT_FENCE_IS_NOT_RELIABLE:
-                caps.push_back(static_cast<Capability>(cap));
-                break;
-            default:
-                // not all HWC2 caps are defined in HIDL
-                break;
-        }
-    }
-
-    hidl_vec<Capability> caps_reply;
-    caps_reply.setToExternal(caps.data(), caps.size());
-    hidl_cb(caps_reply);
-
-    return Void();
-}
-
-Return<void> HwcHal::dumpDebugInfo(dumpDebugInfo_cb hidl_cb)
-{
-    uint32_t len = 0;
-    mDispatch.dump(mDevice, &len, nullptr);
-
-    std::vector<char> buf(len + 1);
-    mDispatch.dump(mDevice, &len, buf.data());
-    buf.resize(len + 1);
-    buf[len] = '\0';
-
-    hidl_string buf_reply;
-    buf_reply.setToExternal(buf.data(), len);
-    hidl_cb(buf_reply);
-
-    return Void();
-}
-
-Return<void> HwcHal::createClient(createClient_cb hidl_cb)
-{
-    Error err = Error::NONE;
-    sp<ComposerClient> client;
-
-    {
-        std::unique_lock<std::mutex> lock(mClientMutex);
-
-        if (mClient != nullptr) {
-            // In surface flinger we delete a composer client on one thread and
-            // then create a new client on another thread. Although surface
-            // flinger ensures the calls are made in that sequence (destroy and
-            // then create), sometimes the calls land in the composer service
-            // inverted (create and then destroy). Wait for a brief period to
-            // see if the existing client is destroyed.
-            ALOGI("HwcHal::createClient: Client already exists. Waiting for"
-                    " it to be destroyed.");
-            mClientDestroyedWait.wait_for(lock, 1s,
-                    [this] { return mClient == nullptr; });
-            std::string doneMsg = mClient == nullptr ?
-                    "Existing client was destroyed." :
-                    "Existing client was never destroyed!";
-            ALOGI("HwcHal::createClient: Done waiting. %s", doneMsg.c_str());
-        }
-
-        // only one client is allowed
-        if (mClient == nullptr) {
-            client = new ComposerClient(*this);
-            client->initialize();
-            mClient = client;
-        } else {
-            err = Error::NO_RESOURCES;
-        }
-    }
-
-    hidl_cb(err, client);
-
-    return Void();
-}
-
-sp<ComposerClient> HwcHal::getClient()
-{
-    std::lock_guard<std::mutex> lock(mClientMutex);
-    return (mClient != nullptr) ? mClient.promote() : nullptr;
-}
-
-void HwcHal::removeClient()
-{
-    std::lock_guard<std::mutex> lock(mClientMutex);
-    mClient = nullptr;
-    mClientDestroyedWait.notify_all();
-}
-
-void HwcHal::hotplugHook(hwc2_callback_data_t callbackData,
-        hwc2_display_t display, int32_t connected)
-{
-    auto hal = reinterpret_cast<HwcHal*>(callbackData);
-    auto client = hal->getClient();
-    if (client != nullptr) {
-        client->onHotplug(display,
-                static_cast<IComposerCallback::Connection>(connected));
-    }
-}
-
-void HwcHal::refreshHook(hwc2_callback_data_t callbackData,
-        hwc2_display_t display)
-{
-    auto hal = reinterpret_cast<HwcHal*>(callbackData);
-    hal->mMustValidateDisplay = true;
-
-    auto client = hal->getClient();
-    if (client != nullptr) {
-        client->onRefresh(display);
-    }
-}
-
-void HwcHal::vsyncHook(hwc2_callback_data_t callbackData,
-        hwc2_display_t display, int64_t timestamp)
-{
-    auto hal = reinterpret_cast<HwcHal*>(callbackData);
-    auto client = hal->getClient();
-    if (client != nullptr) {
-        client->onVsync(display, timestamp);
-    }
-}
-
-void HwcHal::enableCallback(bool enable)
-{
-    if (enable) {
-        mMustValidateDisplay = true;
-
-        mDispatch.registerCallback(mDevice, HWC2_CALLBACK_HOTPLUG, this,
-                reinterpret_cast<hwc2_function_pointer_t>(hotplugHook));
-        mDispatch.registerCallback(mDevice, HWC2_CALLBACK_REFRESH, this,
-                reinterpret_cast<hwc2_function_pointer_t>(refreshHook));
-        mDispatch.registerCallback(mDevice, HWC2_CALLBACK_VSYNC, this,
-                reinterpret_cast<hwc2_function_pointer_t>(vsyncHook));
-    } else {
-        mDispatch.registerCallback(mDevice, HWC2_CALLBACK_HOTPLUG, this,
-                nullptr);
-        mDispatch.registerCallback(mDevice, HWC2_CALLBACK_REFRESH, this,
-                nullptr);
-        mDispatch.registerCallback(mDevice, HWC2_CALLBACK_VSYNC, this,
-                nullptr);
-    }
-}
-
-uint32_t HwcHal::getMaxVirtualDisplayCount()
-{
-    return mDispatch.getMaxVirtualDisplayCount(mDevice);
-}
-
-Error HwcHal::createVirtualDisplay(uint32_t width, uint32_t height,
-    PixelFormat* format, Display* outDisplay)
-{
-    int32_t hwc_format = static_cast<int32_t>(*format);
-    int32_t err = mDispatch.createVirtualDisplay(mDevice, width, height,
-            &hwc_format, outDisplay);
-    *format = static_cast<PixelFormat>(hwc_format);
-
-    return static_cast<Error>(err);
-}
-
-Error HwcHal::destroyVirtualDisplay(Display display)
-{
-    int32_t err = mDispatch.destroyVirtualDisplay(mDevice, display);
-    return static_cast<Error>(err);
-}
-
-Error HwcHal::createLayer(Display display, Layer* outLayer)
-{
-    int32_t err = mDispatch.createLayer(mDevice, display, outLayer);
-    return static_cast<Error>(err);
-}
-
-Error HwcHal::destroyLayer(Display display, Layer layer)
-{
-    int32_t err = mDispatch.destroyLayer(mDevice, display, layer);
-    return static_cast<Error>(err);
-}
-
-Error HwcHal::getActiveConfig(Display display, Config* outConfig)
-{
-    int32_t err = mDispatch.getActiveConfig(mDevice, display, outConfig);
-    return static_cast<Error>(err);
-}
-
-Error HwcHal::getClientTargetSupport(Display display,
-        uint32_t width, uint32_t height,
-        PixelFormat format, Dataspace dataspace)
-{
-    int32_t err = mDispatch.getClientTargetSupport(mDevice, display,
-            width, height, static_cast<int32_t>(format),
-            static_cast<int32_t>(dataspace));
-    return static_cast<Error>(err);
-}
-
-Error HwcHal::getColorModes(Display display, hidl_vec<ColorMode>* outModes)
-{
-    uint32_t count = 0;
-    int32_t err = mDispatch.getColorModes(mDevice, display, &count, nullptr);
-    if (err != HWC2_ERROR_NONE) {
-        return static_cast<Error>(err);
-    }
-
-    outModes->resize(count);
-    err = mDispatch.getColorModes(mDevice, display, &count,
-            reinterpret_cast<std::underlying_type<ColorMode>::type*>(
-                outModes->data()));
-    if (err != HWC2_ERROR_NONE) {
-        *outModes = hidl_vec<ColorMode>();
-        return static_cast<Error>(err);
-    }
-
-    return Error::NONE;
-}
-
-Error HwcHal::getDisplayAttribute(Display display, Config config,
-        IComposerClient::Attribute attribute, int32_t* outValue)
-{
-    int32_t err = mDispatch.getDisplayAttribute(mDevice, display, config,
-            static_cast<int32_t>(attribute), outValue);
-    return static_cast<Error>(err);
-}
-
-Error HwcHal::getDisplayConfigs(Display display, hidl_vec<Config>* outConfigs)
-{
-    uint32_t count = 0;
-    int32_t err = mDispatch.getDisplayConfigs(mDevice, display,
-            &count, nullptr);
-    if (err != HWC2_ERROR_NONE) {
-        return static_cast<Error>(err);
-    }
-
-    outConfigs->resize(count);
-    err = mDispatch.getDisplayConfigs(mDevice, display,
-            &count, outConfigs->data());
-    if (err != HWC2_ERROR_NONE) {
-        *outConfigs = hidl_vec<Config>();
-        return static_cast<Error>(err);
-    }
-
-    return Error::NONE;
-}
-
-Error HwcHal::getDisplayName(Display display, hidl_string* outName)
-{
-    uint32_t count = 0;
-    int32_t err = mDispatch.getDisplayName(mDevice, display, &count, nullptr);
-    if (err != HWC2_ERROR_NONE) {
-        return static_cast<Error>(err);
-    }
-
-    std::vector<char> buf(count + 1);
-    err = mDispatch.getDisplayName(mDevice, display, &count, buf.data());
-    if (err != HWC2_ERROR_NONE) {
-        return static_cast<Error>(err);
-    }
-    buf.resize(count + 1);
-    buf[count] = '\0';
-
-    *outName = buf.data();
-
-    return Error::NONE;
-}
-
-Error HwcHal::getDisplayType(Display display,
-        IComposerClient::DisplayType* outType)
-{
-    int32_t hwc_type = HWC2_DISPLAY_TYPE_INVALID;
-    int32_t err = mDispatch.getDisplayType(mDevice, display, &hwc_type);
-    *outType = static_cast<IComposerClient::DisplayType>(hwc_type);
-
-    return static_cast<Error>(err);
-}
-
-Error HwcHal::getDozeSupport(Display display, bool* outSupport)
-{
-    int32_t hwc_support = 0;
-    int32_t err = mDispatch.getDozeSupport(mDevice, display, &hwc_support);
-    *outSupport = hwc_support;
-
-    return static_cast<Error>(err);
-}
-
-Error HwcHal::getHdrCapabilities(Display display, hidl_vec<Hdr>* outTypes,
-        float* outMaxLuminance, float* outMaxAverageLuminance,
-        float* outMinLuminance)
-{
-    uint32_t count = 0;
-    int32_t err = mDispatch.getHdrCapabilities(mDevice, display, &count,
-            nullptr, outMaxLuminance, outMaxAverageLuminance,
-            outMinLuminance);
-    if (err != HWC2_ERROR_NONE) {
-        return static_cast<Error>(err);
-    }
-
-    outTypes->resize(count);
-    err = mDispatch.getHdrCapabilities(mDevice, display, &count,
-            reinterpret_cast<std::underlying_type<Hdr>::type*>(
-                outTypes->data()), outMaxLuminance,
-            outMaxAverageLuminance, outMinLuminance);
-    if (err != HWC2_ERROR_NONE) {
-        *outTypes = hidl_vec<Hdr>();
-        return static_cast<Error>(err);
-    }
-
-    return Error::NONE;
-}
-
-Error HwcHal::setActiveConfig(Display display, Config config)
-{
-    int32_t err = mDispatch.setActiveConfig(mDevice, display, config);
-    return static_cast<Error>(err);
-}
-
-Error HwcHal::setColorMode(Display display, ColorMode mode)
-{
-    int32_t err = mDispatch.setColorMode(mDevice, display,
-            static_cast<int32_t>(mode));
-    return static_cast<Error>(err);
-}
-
-Error HwcHal::setPowerMode(Display display, IComposerClient::PowerMode mode)
-{
-    int32_t err = mDispatch.setPowerMode(mDevice, display,
-            static_cast<int32_t>(mode));
-    return static_cast<Error>(err);
-}
-
-Error HwcHal::setVsyncEnabled(Display display, IComposerClient::Vsync enabled)
-{
-    int32_t err = mDispatch.setVsyncEnabled(mDevice, display,
-            static_cast<int32_t>(enabled));
-    return static_cast<Error>(err);
-}
-
-Error HwcHal::setColorTransform(Display display, const float* matrix,
-        int32_t hint)
-{
-    int32_t err = mDispatch.setColorTransform(mDevice, display, matrix, hint);
-    return static_cast<Error>(err);
-}
-
-Error HwcHal::setClientTarget(Display display, buffer_handle_t target,
-        int32_t acquireFence, int32_t dataspace,
-        const std::vector<hwc_rect_t>& damage)
-{
-    hwc_region region = { damage.size(), damage.data() };
-    int32_t err = mDispatch.setClientTarget(mDevice, display, target,
-            acquireFence, dataspace, region);
-    return static_cast<Error>(err);
-}
-
-Error HwcHal::setOutputBuffer(Display display, buffer_handle_t buffer,
-        int32_t releaseFence)
-{
-    int32_t err = mDispatch.setOutputBuffer(mDevice, display, buffer,
-            releaseFence);
-    // unlike in setClientTarget, releaseFence is owned by us
-    if (err == HWC2_ERROR_NONE && releaseFence >= 0) {
-        close(releaseFence);
-    }
-
-    return static_cast<Error>(err);
-}
-
-Error HwcHal::validateDisplay(Display display,
-        std::vector<Layer>* outChangedLayers,
-        std::vector<IComposerClient::Composition>* outCompositionTypes,
-        uint32_t* outDisplayRequestMask,
-        std::vector<Layer>* outRequestedLayers,
-        std::vector<uint32_t>* outRequestMasks)
-{
-    uint32_t types_count = 0;
-    uint32_t reqs_count = 0;
-    int32_t err = mDispatch.validateDisplay(mDevice, display,
-            &types_count, &reqs_count);
-    mMustValidateDisplay = false;
-
-    if (err != HWC2_ERROR_NONE && err != HWC2_ERROR_HAS_CHANGES) {
-        return static_cast<Error>(err);
-    }
-
-    err = mDispatch.getChangedCompositionTypes(mDevice, display,
-            &types_count, nullptr, nullptr);
-    if (err != HWC2_ERROR_NONE) {
-        return static_cast<Error>(err);
-    }
-
-    outChangedLayers->resize(types_count);
-    outCompositionTypes->resize(types_count);
-    err = mDispatch.getChangedCompositionTypes(mDevice, display,
-            &types_count, outChangedLayers->data(),
-            reinterpret_cast<
-            std::underlying_type<IComposerClient::Composition>::type*>(
-                outCompositionTypes->data()));
-    if (err != HWC2_ERROR_NONE) {
-        outChangedLayers->clear();
-        outCompositionTypes->clear();
-        return static_cast<Error>(err);
-    }
-
-    int32_t display_reqs = 0;
-    err = mDispatch.getDisplayRequests(mDevice, display, &display_reqs,
-            &reqs_count, nullptr, nullptr);
-    if (err != HWC2_ERROR_NONE) {
-        outChangedLayers->clear();
-        outCompositionTypes->clear();
-        return static_cast<Error>(err);
-    }
-
-    outRequestedLayers->resize(reqs_count);
-    outRequestMasks->resize(reqs_count);
-    err = mDispatch.getDisplayRequests(mDevice, display, &display_reqs,
-            &reqs_count, outRequestedLayers->data(),
-            reinterpret_cast<int32_t*>(outRequestMasks->data()));
-    if (err != HWC2_ERROR_NONE) {
-        outChangedLayers->clear();
-        outCompositionTypes->clear();
-
-        outRequestedLayers->clear();
-        outRequestMasks->clear();
-        return static_cast<Error>(err);
-    }
-
-    *outDisplayRequestMask = display_reqs;
-
-    return static_cast<Error>(err);
-}
-
-Error HwcHal::acceptDisplayChanges(Display display)
-{
-    int32_t err = mDispatch.acceptDisplayChanges(mDevice, display);
-    return static_cast<Error>(err);
-}
-
-Error HwcHal::presentDisplay(Display display, int32_t* outPresentFence,
-        std::vector<Layer>* outLayers, std::vector<int32_t>* outReleaseFences)
-{
-    if (mMustValidateDisplay) {
-        return Error::NOT_VALIDATED;
-    }
-
-    *outPresentFence = -1;
-    int32_t err = mDispatch.presentDisplay(mDevice, display, outPresentFence);
-    if (err != HWC2_ERROR_NONE) {
-        return static_cast<Error>(err);
-    }
-
-    uint32_t count = 0;
-    err = mDispatch.getReleaseFences(mDevice, display, &count,
-            nullptr, nullptr);
-    if (err != HWC2_ERROR_NONE) {
-        ALOGW("failed to get release fences");
-        return Error::NONE;
-    }
-
-    outLayers->resize(count);
-    outReleaseFences->resize(count);
-    err = mDispatch.getReleaseFences(mDevice, display, &count,
-            outLayers->data(), outReleaseFences->data());
-    if (err != HWC2_ERROR_NONE) {
-        ALOGW("failed to get release fences");
-        outLayers->clear();
-        outReleaseFences->clear();
-        return Error::NONE;
-    }
-
-    return static_cast<Error>(err);
-}
-
-Error HwcHal::setLayerCursorPosition(Display display, Layer layer,
-        int32_t x, int32_t y)
-{
-    int32_t err = mDispatch.setCursorPosition(mDevice, display, layer, x, y);
-    return static_cast<Error>(err);
-}
-
-Error HwcHal::setLayerBuffer(Display display, Layer layer,
-        buffer_handle_t buffer, int32_t acquireFence)
-{
-    int32_t err = mDispatch.setLayerBuffer(mDevice, display, layer,
-            buffer, acquireFence);
-    return static_cast<Error>(err);
-}
-
-Error HwcHal::setLayerSurfaceDamage(Display display, Layer layer,
-        const std::vector<hwc_rect_t>& damage)
-{
-    hwc_region region = { damage.size(), damage.data() };
-    int32_t err = mDispatch.setLayerSurfaceDamage(mDevice, display, layer,
-            region);
-    return static_cast<Error>(err);
-}
-
-Error HwcHal::setLayerBlendMode(Display display, Layer layer, int32_t mode)
-{
-    int32_t err = mDispatch.setLayerBlendMode(mDevice, display, layer, mode);
-    return static_cast<Error>(err);
-}
-
-Error HwcHal::setLayerColor(Display display, Layer layer,
-        IComposerClient::Color color)
-{
-    hwc_color_t hwc_color{color.r, color.g, color.b, color.a};
-    int32_t err = mDispatch.setLayerColor(mDevice, display, layer, hwc_color);
-    return static_cast<Error>(err);
-}
-
-Error HwcHal::setLayerCompositionType(Display display, Layer layer,
-        int32_t type)
-{
-    int32_t err = mDispatch.setLayerCompositionType(mDevice, display, layer,
-            type);
-    return static_cast<Error>(err);
-}
-
-Error HwcHal::setLayerDataspace(Display display, Layer layer,
-        int32_t dataspace)
-{
-    int32_t err = mDispatch.setLayerDataspace(mDevice, display, layer,
-            dataspace);
-    return static_cast<Error>(err);
-}
-
-Error HwcHal::setLayerDisplayFrame(Display display, Layer layer,
-        const hwc_rect_t& frame)
-{
-    int32_t err = mDispatch.setLayerDisplayFrame(mDevice, display, layer,
-            frame);
-    return static_cast<Error>(err);
-}
-
-Error HwcHal::setLayerPlaneAlpha(Display display, Layer layer, float alpha)
-{
-    int32_t err = mDispatch.setLayerPlaneAlpha(mDevice, display, layer,
-            alpha);
-    return static_cast<Error>(err);
-}
-
-Error HwcHal::setLayerSidebandStream(Display display, Layer layer,
-        buffer_handle_t stream)
-{
-    int32_t err = mDispatch.setLayerSidebandStream(mDevice, display, layer,
-            stream);
-    return static_cast<Error>(err);
-}
-
-Error HwcHal::setLayerSourceCrop(Display display, Layer layer,
-        const hwc_frect_t& crop)
-{
-    int32_t err = mDispatch.setLayerSourceCrop(mDevice, display, layer, crop);
-    return static_cast<Error>(err);
-}
-
-Error HwcHal::setLayerTransform(Display display, Layer layer,
-        int32_t transform)
-{
-    int32_t err = mDispatch.setLayerTransform(mDevice, display, layer,
-            transform);
-    return static_cast<Error>(err);
-}
-
-Error HwcHal::setLayerVisibleRegion(Display display, Layer layer,
-        const std::vector<hwc_rect_t>& visible)
-{
-    hwc_region_t region = { visible.size(), visible.data() };
-    int32_t err = mDispatch.setLayerVisibleRegion(mDevice, display, layer,
-            region);
-    return static_cast<Error>(err);
-}
-
-Error HwcHal::setLayerZOrder(Display display, Layer layer, uint32_t z)
-{
-    int32_t err = mDispatch.setLayerZOrder(mDevice, display, layer, z);
-    return static_cast<Error>(err);
-}
-
-IComposer* HIDL_FETCH_IComposer(const char*)
-{
-    const hw_module_t* module = nullptr;
-    int err = hw_get_module(HWC_HARDWARE_MODULE_ID, &module);
-    if (err) {
-        ALOGI("falling back to FB HAL");
-        err = hw_get_module(GRALLOC_HARDWARE_MODULE_ID, &module);
-    }
-    if (err) {
-        ALOGE("failed to get hwcomposer or fb module");
-        return nullptr;
-    }
-
-    return new HwcHal(module);
-}
-
-} // namespace implementation
-} // namespace V2_1
-} // namespace composer
-} // namespace graphics
-} // namespace hardware
-} // namespace android
diff --git a/graphics/composer/2.1/default/Hwc.h b/graphics/composer/2.1/default/Hwc.h
deleted file mode 100644
index e3f5ce6..0000000
--- a/graphics/composer/2.1/default/Hwc.h
+++ /dev/null
@@ -1,242 +0,0 @@
-/*
- * Copyright 2016 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.
- */
-
-#ifndef ANDROID_HARDWARE_GRAPHICS_COMPOSER_V2_1_HWC_H
-#define ANDROID_HARDWARE_GRAPHICS_COMPOSER_V2_1_HWC_H
-
-#include <atomic>
-#include <condition_variable>
-#include <memory>
-#include <mutex>
-#include <unordered_set>
-#include <vector>
-
-#include <android/hardware/graphics/composer/2.1/IComposer.h>
-#define HWC2_INCLUDE_STRINGIFICATION
-#define HWC2_USE_CPP11
-#include <hardware/hwcomposer2.h>
-#undef HWC2_INCLUDE_STRINGIFICATION
-#undef HWC2_USE_CPP11
-#include "ComposerBase.h"
-
-namespace android {
-    class HWC2On1Adapter;
-    class HWC2OnFbAdapter;
-}
-
-namespace android {
-namespace hardware {
-namespace graphics {
-namespace composer {
-namespace V2_1 {
-namespace implementation {
-
-using android::hardware::graphics::common::V1_0::PixelFormat;
-using android::hardware::graphics::common::V1_0::Transform;
-using android::hardware::graphics::common::V1_0::Dataspace;
-using android::hardware::graphics::common::V1_0::ColorMode;
-using android::hardware::graphics::common::V1_0::ColorTransform;
-using android::hardware::graphics::common::V1_0::Hdr;
-
-class ComposerClient;
-
-class HwcHal : public IComposer, public ComposerBase {
-public:
-    HwcHal(const hw_module_t* module);
-    virtual ~HwcHal();
-
-    // IComposer interface
-    Return<void> getCapabilities(getCapabilities_cb hidl_cb) override;
-    Return<void> dumpDebugInfo(dumpDebugInfo_cb hidl_cb) override;
-    Return<void> createClient(createClient_cb hidl_cb) override;
-
-    // ComposerBase interface
-    bool hasCapability(hwc2_capability_t capability) override;
-    void removeClient() override;
-    void enableCallback(bool enable) override;
-    uint32_t getMaxVirtualDisplayCount() override;
-    Error createVirtualDisplay(uint32_t width, uint32_t height,
-        PixelFormat* format, Display* outDisplay) override;
-    Error destroyVirtualDisplay(Display display) override;
-
-    Error createLayer(Display display, Layer* outLayer) override;
-    Error destroyLayer(Display display, Layer layer) override;
-
-    Error getActiveConfig(Display display, Config* outConfig) override;
-    Error getClientTargetSupport(Display display,
-            uint32_t width, uint32_t height,
-            PixelFormat format, Dataspace dataspace) override;
-    Error getColorModes(Display display,
-            hidl_vec<ColorMode>* outModes) override;
-    Error getDisplayAttribute(Display display, Config config,
-            IComposerClient::Attribute attribute, int32_t* outValue) override;
-    Error getDisplayConfigs(Display display,
-            hidl_vec<Config>* outConfigs) override;
-    Error getDisplayName(Display display, hidl_string* outName) override;
-    Error getDisplayType(Display display,
-            IComposerClient::DisplayType* outType) override;
-    Error getDozeSupport(Display display, bool* outSupport) override;
-    Error getHdrCapabilities(Display display, hidl_vec<Hdr>* outTypes,
-            float* outMaxLuminance, float* outMaxAverageLuminance,
-            float* outMinLuminance) override;
-
-    Error setActiveConfig(Display display, Config config) override;
-    Error setColorMode(Display display, ColorMode mode) override;
-    Error setPowerMode(Display display,
-            IComposerClient::PowerMode mode) override;
-    Error setVsyncEnabled(Display display,
-            IComposerClient::Vsync enabled) override;
-
-    Error setColorTransform(Display display, const float* matrix,
-            int32_t hint) override;
-    Error setClientTarget(Display display, buffer_handle_t target,
-            int32_t acquireFence, int32_t dataspace,
-            const std::vector<hwc_rect_t>& damage) override;
-    Error setOutputBuffer(Display display, buffer_handle_t buffer,
-            int32_t releaseFence) override;
-    Error validateDisplay(Display display,
-            std::vector<Layer>* outChangedLayers,
-            std::vector<IComposerClient::Composition>* outCompositionTypes,
-            uint32_t* outDisplayRequestMask,
-            std::vector<Layer>* outRequestedLayers,
-            std::vector<uint32_t>* outRequestMasks) override;
-    Error acceptDisplayChanges(Display display) override;
-    Error presentDisplay(Display display, int32_t* outPresentFence,
-            std::vector<Layer>* outLayers,
-            std::vector<int32_t>* outReleaseFences) override;
-
-    Error setLayerCursorPosition(Display display, Layer layer,
-            int32_t x, int32_t y) override;
-    Error setLayerBuffer(Display display, Layer layer,
-            buffer_handle_t buffer, int32_t acquireFence) override;
-    Error setLayerSurfaceDamage(Display display, Layer layer,
-            const std::vector<hwc_rect_t>& damage) override;
-    Error setLayerBlendMode(Display display, Layer layer,
-            int32_t mode) override;
-    Error setLayerColor(Display display, Layer layer,
-            IComposerClient::Color color) override;
-    Error setLayerCompositionType(Display display, Layer layer,
-            int32_t type) override;
-    Error setLayerDataspace(Display display, Layer layer,
-            int32_t dataspace) override;
-    Error setLayerDisplayFrame(Display display, Layer layer,
-            const hwc_rect_t& frame) override;
-    Error setLayerPlaneAlpha(Display display, Layer layer,
-            float alpha) override;
-    Error setLayerSidebandStream(Display display, Layer layer,
-            buffer_handle_t stream) override;
-    Error setLayerSourceCrop(Display display, Layer layer,
-            const hwc_frect_t& crop) override;
-    Error setLayerTransform(Display display, Layer layer,
-            int32_t transform) override;
-    Error setLayerVisibleRegion(Display display, Layer layer,
-            const std::vector<hwc_rect_t>& visible) override;
-    Error setLayerZOrder(Display display, Layer layer, uint32_t z) override;
-
-private:
-    uint32_t initWithHwc(const hw_module_t* module);
-    uint32_t initWithFb(const hw_module_t* module);
-
-    void initCapabilities();
-
-    template<typename T>
-    void initDispatch(hwc2_function_descriptor_t desc, T* outPfn);
-    void initDispatch();
-
-    sp<ComposerClient> getClient();
-
-    static void hotplugHook(hwc2_callback_data_t callbackData,
-        hwc2_display_t display, int32_t connected);
-    static void refreshHook(hwc2_callback_data_t callbackData,
-        hwc2_display_t display);
-    static void vsyncHook(hwc2_callback_data_t callbackData,
-        hwc2_display_t display, int64_t timestamp);
-
-    hwc2_device_t* mDevice;
-
-    std::unordered_set<hwc2_capability_t> mCapabilities;
-
-    struct {
-        HWC2_PFN_ACCEPT_DISPLAY_CHANGES acceptDisplayChanges;
-        HWC2_PFN_CREATE_LAYER createLayer;
-        HWC2_PFN_CREATE_VIRTUAL_DISPLAY createVirtualDisplay;
-        HWC2_PFN_DESTROY_LAYER destroyLayer;
-        HWC2_PFN_DESTROY_VIRTUAL_DISPLAY destroyVirtualDisplay;
-        HWC2_PFN_DUMP dump;
-        HWC2_PFN_GET_ACTIVE_CONFIG getActiveConfig;
-        HWC2_PFN_GET_CHANGED_COMPOSITION_TYPES getChangedCompositionTypes;
-        HWC2_PFN_GET_CLIENT_TARGET_SUPPORT getClientTargetSupport;
-        HWC2_PFN_GET_COLOR_MODES getColorModes;
-        HWC2_PFN_GET_DISPLAY_ATTRIBUTE getDisplayAttribute;
-        HWC2_PFN_GET_DISPLAY_CONFIGS getDisplayConfigs;
-        HWC2_PFN_GET_DISPLAY_NAME getDisplayName;
-        HWC2_PFN_GET_DISPLAY_REQUESTS getDisplayRequests;
-        HWC2_PFN_GET_DISPLAY_TYPE getDisplayType;
-        HWC2_PFN_GET_DOZE_SUPPORT getDozeSupport;
-        HWC2_PFN_GET_HDR_CAPABILITIES getHdrCapabilities;
-        HWC2_PFN_GET_MAX_VIRTUAL_DISPLAY_COUNT getMaxVirtualDisplayCount;
-        HWC2_PFN_GET_RELEASE_FENCES getReleaseFences;
-        HWC2_PFN_PRESENT_DISPLAY presentDisplay;
-        HWC2_PFN_REGISTER_CALLBACK registerCallback;
-        HWC2_PFN_SET_ACTIVE_CONFIG setActiveConfig;
-        HWC2_PFN_SET_CLIENT_TARGET setClientTarget;
-        HWC2_PFN_SET_COLOR_MODE setColorMode;
-        HWC2_PFN_SET_COLOR_TRANSFORM setColorTransform;
-        HWC2_PFN_SET_CURSOR_POSITION setCursorPosition;
-        HWC2_PFN_SET_LAYER_BLEND_MODE setLayerBlendMode;
-        HWC2_PFN_SET_LAYER_BUFFER setLayerBuffer;
-        HWC2_PFN_SET_LAYER_COLOR setLayerColor;
-        HWC2_PFN_SET_LAYER_COMPOSITION_TYPE setLayerCompositionType;
-        HWC2_PFN_SET_LAYER_DATASPACE setLayerDataspace;
-        HWC2_PFN_SET_LAYER_DISPLAY_FRAME setLayerDisplayFrame;
-        HWC2_PFN_SET_LAYER_PLANE_ALPHA setLayerPlaneAlpha;
-        HWC2_PFN_SET_LAYER_SIDEBAND_STREAM setLayerSidebandStream;
-        HWC2_PFN_SET_LAYER_SOURCE_CROP setLayerSourceCrop;
-        HWC2_PFN_SET_LAYER_SURFACE_DAMAGE setLayerSurfaceDamage;
-        HWC2_PFN_SET_LAYER_TRANSFORM setLayerTransform;
-        HWC2_PFN_SET_LAYER_VISIBLE_REGION setLayerVisibleRegion;
-        HWC2_PFN_SET_LAYER_Z_ORDER setLayerZOrder;
-        HWC2_PFN_SET_OUTPUT_BUFFER setOutputBuffer;
-        HWC2_PFN_SET_POWER_MODE setPowerMode;
-        HWC2_PFN_SET_VSYNC_ENABLED setVsyncEnabled;
-        HWC2_PFN_VALIDATE_DISPLAY validateDisplay;
-    } mDispatch;
-
-    std::mutex mClientMutex;
-    std::condition_variable mClientDestroyedWait;
-    wp<ComposerClient> mClient;
-
-    std::atomic<bool> mMustValidateDisplay;
-
-    // If the HWC implementation version is < 2.0, use an adapter to interface
-    // between HWC 2.0 <-> HWC 1.X.
-    std::unique_ptr<HWC2On1Adapter> mAdapter;
-
-    // If there is no HWC implementation, use an adapter to interface between
-    // HWC 2.0 <-> FB HAL.
-    std::unique_ptr<HWC2OnFbAdapter> mFbAdapter;
-};
-
-extern "C" IComposer* HIDL_FETCH_IComposer(const char* name);
-
-} // namespace implementation
-} // namespace V2_1
-} // namespace composer
-} // namespace graphics
-} // namespace hardware
-} // namespace android
-
-#endif  // ANDROID_HARDWARE_GRAPHICS_COMPOSER_V2_1_HWC_H
diff --git a/graphics/composer/2.1/default/passthrough.cpp b/graphics/composer/2.1/default/passthrough.cpp
new file mode 100644
index 0000000..ef7ed7c
--- /dev/null
+++ b/graphics/composer/2.1/default/passthrough.cpp
@@ -0,0 +1,25 @@
+/*
+ * Copyright 2016 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/hardware/graphics/composer/2.1/IComposer.h>
+#include <composer-passthrough/2.1/HwcLoader.h>
+
+using android::hardware::graphics::composer::V2_1::IComposer;
+using android::hardware::graphics::composer::V2_1::passthrough::HwcLoader;
+
+extern "C" IComposer* HIDL_FETCH_IComposer(const char* /* name */) {
+    return HwcLoader::load();
+}
diff --git a/graphics/composer/2.1/utils/command-buffer/Android.bp b/graphics/composer/2.1/utils/command-buffer/Android.bp
index e8d41c2..140d9bb 100644
--- a/graphics/composer/2.1/utils/command-buffer/Android.bp
+++ b/graphics/composer/2.1/utils/command-buffer/Android.bp
@@ -2,6 +2,15 @@
     name: "android.hardware.graphics.composer@2.1-command-buffer",
     defaults: ["hidl_defaults"],
     vendor_available: true,
-    shared_libs: ["android.hardware.graphics.composer@2.1"],
+    shared_libs: [
+        "android.hardware.graphics.composer@2.1",
+        "libfmq",
+        "libsync",
+    ],
+    export_shared_lib_headers: [
+        "android.hardware.graphics.composer@2.1",
+        "libfmq",
+        "libsync",
+    ],
     export_include_dirs: ["include"],
 }
diff --git a/graphics/composer/2.1/utils/hal/Android.bp b/graphics/composer/2.1/utils/hal/Android.bp
new file mode 100644
index 0000000..f24e768
--- /dev/null
+++ b/graphics/composer/2.1/utils/hal/Android.bp
@@ -0,0 +1,37 @@
+//
+// Copyright (C) 2018 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.
+
+cc_library_headers {
+    name: "android.hardware.graphics.composer@2.1-hal",
+    defaults: ["hidl_defaults"],
+    vendor_available: true,
+    shared_libs: [
+        "android.hardware.graphics.composer@2.1",
+        "android.hardware.graphics.mapper@2.0",
+        "libhardware", // TODO remove hwcomposer2.h dependency
+    ],
+    export_shared_lib_headers: [
+        "android.hardware.graphics.composer@2.1",
+        "android.hardware.graphics.mapper@2.0",
+        "libhardware",
+    ],
+    header_libs: [
+        "android.hardware.graphics.composer@2.1-command-buffer",
+    ],
+    export_header_lib_headers: [
+        "android.hardware.graphics.composer@2.1-command-buffer",
+    ],
+    export_include_dirs: ["include"],
+}
diff --git a/graphics/composer/2.1/utils/hal/include/composer-hal/2.1/Composer.h b/graphics/composer/2.1/utils/hal/include/composer-hal/2.1/Composer.h
new file mode 100644
index 0000000..581dc96
--- /dev/null
+++ b/graphics/composer/2.1/utils/hal/include/composer-hal/2.1/Composer.h
@@ -0,0 +1,157 @@
+/*
+ * Copyright 2016 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
+
+#ifndef LOG_TAG
+#warning "Composer.h included without LOG_TAG"
+#endif
+
+#include <array>
+#include <chrono>
+#include <condition_variable>
+#include <memory>
+#include <mutex>
+#include <vector>
+
+#include <android/hardware/graphics/composer/2.1/IComposer.h>
+#include <android/hardware/graphics/composer/2.1/IComposerClient.h>
+#include <composer-hal/2.1/ComposerClient.h>
+#include <composer-hal/2.1/ComposerHal.h>
+
+namespace android {
+namespace hardware {
+namespace graphics {
+namespace composer {
+namespace V2_1 {
+namespace hal {
+
+namespace detail {
+
+// ComposerImpl implements V2_*::IComposer on top of V2_*::ComposerHal
+template <typename Interface, typename Hal>
+class ComposerImpl : public Interface {
+   public:
+    static std::unique_ptr<ComposerImpl> create(std::unique_ptr<Hal> hal) {
+        return std::make_unique<ComposerImpl>(std::move(hal));
+    }
+
+    ComposerImpl(std::unique_ptr<Hal> hal) : mHal(std::move(hal)) {}
+
+    // IComposer 2.1 interface
+
+    Return<void> getCapabilities(IComposer::getCapabilities_cb hidl_cb) override {
+        const std::array<IComposer::Capability, 3> all_caps = {{
+            IComposer::Capability::SIDEBAND_STREAM,
+            IComposer::Capability::SKIP_CLIENT_COLOR_TRANSFORM,
+            IComposer::Capability::PRESENT_FENCE_IS_NOT_RELIABLE,
+        }};
+
+        std::vector<IComposer::Capability> caps;
+        for (auto cap : all_caps) {
+            if (mHal->hasCapability(static_cast<hwc2_capability_t>(cap))) {
+                caps.push_back(cap);
+            }
+        }
+
+        hidl_vec<IComposer::Capability> caps_reply;
+        caps_reply.setToExternal(caps.data(), caps.size());
+        hidl_cb(caps_reply);
+        return Void();
+    }
+
+    Return<void> dumpDebugInfo(IComposer::dumpDebugInfo_cb hidl_cb) override {
+        hidl_cb(mHal->dumpDebugInfo());
+        return Void();
+    }
+
+    Return<void> createClient(IComposer::createClient_cb hidl_cb) override {
+        std::unique_lock<std::mutex> lock(mClientMutex);
+        if (!waitForClientDestroyedLocked(lock)) {
+            hidl_cb(Error::NO_RESOURCES, nullptr);
+            return Void();
+        }
+
+        sp<IComposerClient> client = createClient();
+        if (!client) {
+            hidl_cb(Error::NO_RESOURCES, nullptr);
+            return Void();
+        }
+
+        mClient = client;
+        hidl_cb(Error::NONE, client);
+        return Void();
+    }
+
+   protected:
+    bool waitForClientDestroyedLocked(std::unique_lock<std::mutex>& lock) {
+        if (mClient != nullptr) {
+            using namespace std::chrono_literals;
+
+            // In surface flinger we delete a composer client on one thread and
+            // then create a new client on another thread. Although surface
+            // flinger ensures the calls are made in that sequence (destroy and
+            // then create), sometimes the calls land in the composer service
+            // inverted (create and then destroy). Wait for a brief period to
+            // see if the existing client is destroyed.
+            ALOGD("waiting for previous client to be destroyed");
+            mClientDestroyedCondition.wait_for(
+                lock, 1s, [this]() -> bool { return mClient.promote() == nullptr; });
+            if (mClient.promote() != nullptr) {
+                ALOGD("previous client was not destroyed");
+            } else {
+                mClient.clear();
+            }
+        }
+
+        return mClient == nullptr;
+    }
+
+    void onClientDestroyed() {
+        std::lock_guard<std::mutex> lock(mClientMutex);
+        mClient.clear();
+        mClientDestroyedCondition.notify_all();
+    }
+
+    virtual IComposerClient* createClient() {
+        auto client = ComposerClient::create(mHal.get());
+        if (!client) {
+            return nullptr;
+        }
+
+        auto clientDestroyed = [this]() { onClientDestroyed(); };
+        client->setOnClientDestroyed(clientDestroyed);
+
+        return client.release();
+    }
+
+    const std::unique_ptr<Hal> mHal;
+
+    std::mutex mClientMutex;
+    wp<IComposerClient> mClient;
+    std::condition_variable mClientDestroyedCondition;
+};
+
+}  // namespace detail
+
+using Composer = detail::ComposerImpl<IComposer, ComposerHal>;
+
+}  // namespace hal
+}  // namespace V2_1
+}  // namespace composer
+}  // namespace graphics
+}  // namespace hardware
+}  // namespace android
diff --git a/graphics/composer/2.1/utils/hal/include/composer-hal/2.1/ComposerClient.h b/graphics/composer/2.1/utils/hal/include/composer-hal/2.1/ComposerClient.h
new file mode 100644
index 0000000..86525b8
--- /dev/null
+++ b/graphics/composer/2.1/utils/hal/include/composer-hal/2.1/ComposerClient.h
@@ -0,0 +1,396 @@
+/*
+ * Copyright 2018 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
+
+#ifndef LOG_TAG
+#warning "ComposerClient.h included without LOG_TAG"
+#endif
+
+#include <memory>
+#include <mutex>
+#include <vector>
+
+#include <android/hardware/graphics/composer/2.1/IComposerClient.h>
+#include <composer-hal/2.1/ComposerCommandEngine.h>
+#include <composer-hal/2.1/ComposerHal.h>
+#include <composer-hal/2.1/ComposerResources.h>
+#include <log/log.h>
+
+namespace android {
+namespace hardware {
+namespace graphics {
+namespace composer {
+namespace V2_1 {
+namespace hal {
+
+namespace detail {
+
+// ComposerClientImpl implements V2_*::IComposerClient on top of V2_*::ComposerHal
+template <typename Interface, typename Hal>
+class ComposerClientImpl : public Interface {
+   public:
+    static std::unique_ptr<ComposerClientImpl> create(Hal* hal) {
+        auto client = std::make_unique<ComposerClientImpl>(hal);
+        return client->init() ? std::move(client) : nullptr;
+    }
+
+    ComposerClientImpl(Hal* hal) : mHal(hal) {}
+
+    virtual ~ComposerClientImpl() {
+        // not initialized
+        if (!mCommandEngine) {
+            return;
+        }
+
+        ALOGD("destroying composer client");
+
+        mHal->unregisterEventCallback();
+        destroyResources();
+        if (mOnClientDestroyed) {
+            mOnClientDestroyed();
+        }
+
+        ALOGD("removed composer client");
+    }
+
+    bool init() {
+        mResources = createResources();
+        if (!mResources) {
+            ALOGE("failed to create composer resources");
+            return false;
+        }
+
+        mCommandEngine = createCommandEngine();
+
+        return true;
+    }
+
+    void setOnClientDestroyed(std::function<void()> onClientDestroyed) {
+        mOnClientDestroyed = onClientDestroyed;
+    }
+
+    // IComposerClient 2.1 interface
+
+    class HalEventCallback : public Hal::EventCallback {
+       public:
+        HalEventCallback(const sp<IComposerCallback> callback, ComposerResources* resources)
+            : mCallback(callback), mResources(resources) {}
+
+        void onHotplug(Display display, IComposerCallback::Connection connected) {
+            if (connected == IComposerCallback::Connection::CONNECTED) {
+                mResources->addPhysicalDisplay(display);
+            } else if (connected == IComposerCallback::Connection::DISCONNECTED) {
+                mResources->removeDisplay(display);
+            }
+
+            auto ret = mCallback->onHotplug(display, connected);
+            ALOGE_IF(!ret.isOk(), "failed to send onHotplug: %s", ret.description().c_str());
+        }
+
+        void onRefresh(Display display) {
+            auto ret = mCallback->onRefresh(display);
+            ALOGE_IF(!ret.isOk(), "failed to send onRefresh: %s", ret.description().c_str());
+        }
+
+        void onVsync(Display display, int64_t timestamp) {
+            auto ret = mCallback->onVsync(display, timestamp);
+            ALOGE_IF(!ret.isOk(), "failed to send onVsync: %s", ret.description().c_str());
+        }
+
+       protected:
+        const sp<IComposerCallback> mCallback;
+        ComposerResources* const mResources;
+    };
+
+    Return<void> registerCallback(const sp<IComposerCallback>& callback) override {
+        // no locking as we require this function to be called only once
+        mHalEventCallback = std::make_unique<HalEventCallback>(callback, mResources.get());
+        mHal->registerEventCallback(mHalEventCallback.get());
+        return Void();
+    }
+
+    Return<uint32_t> getMaxVirtualDisplayCount() override {
+        return mHal->getMaxVirtualDisplayCount();
+    }
+
+    Return<void> createVirtualDisplay(uint32_t width, uint32_t height, PixelFormat formatHint,
+                                      uint32_t outputBufferSlotCount,
+                                      IComposerClient::createVirtualDisplay_cb hidl_cb) override {
+        Display display = 0;
+        Error err = mHal->createVirtualDisplay(width, height, &formatHint, &display);
+        if (err == Error::NONE) {
+            mResources->addVirtualDisplay(display, outputBufferSlotCount);
+        }
+
+        hidl_cb(err, display, formatHint);
+        return Void();
+    }
+
+    Return<Error> destroyVirtualDisplay(Display display) override {
+        Error err = mHal->destroyVirtualDisplay(display);
+        if (err == Error::NONE) {
+            mResources->removeDisplay(display);
+        }
+
+        return err;
+    }
+
+    Return<void> createLayer(Display display, uint32_t bufferSlotCount,
+                             IComposerClient::createLayer_cb hidl_cb) override {
+        Layer layer = 0;
+        Error err = mHal->createLayer(display, &layer);
+        if (err == Error::NONE) {
+            err = mResources->addLayer(display, layer, bufferSlotCount);
+            if (err != Error::NONE) {
+                // The display entry may have already been removed by onHotplug.
+                // Note: We do not destroy the layer on this error as the hotplug
+                // disconnect invalidates the display id. The implementation should
+                // ensure all layers for the display are destroyed.
+                layer = 0;
+            }
+        }
+
+        hidl_cb(err, layer);
+        return Void();
+    }
+
+    Return<Error> destroyLayer(Display display, Layer layer) override {
+        Error err = mHal->destroyLayer(display, layer);
+        if (err == Error::NONE) {
+            mResources->removeLayer(display, layer);
+        }
+
+        return err;
+    }
+
+    Return<void> getActiveConfig(Display display,
+                                 IComposerClient::getActiveConfig_cb hidl_cb) override {
+        Config config = 0;
+        Error err = mHal->getActiveConfig(display, &config);
+        hidl_cb(err, config);
+        return Void();
+    }
+
+    Return<Error> getClientTargetSupport(Display display, uint32_t width, uint32_t height,
+                                         PixelFormat format, Dataspace dataspace) override {
+        Error err = mHal->getClientTargetSupport(display, width, height, format, dataspace);
+        return err;
+    }
+
+    Return<void> getColorModes(Display display,
+                               IComposerClient::getColorModes_cb hidl_cb) override {
+        hidl_vec<ColorMode> modes;
+        Error err = mHal->getColorModes(display, &modes);
+        hidl_cb(err, modes);
+        return Void();
+    }
+
+    Return<void> getDisplayAttribute(Display display, Config config,
+                                     IComposerClient::Attribute attribute,
+                                     IComposerClient::getDisplayAttribute_cb hidl_cb) override {
+        int32_t value = 0;
+        Error err = mHal->getDisplayAttribute(display, config, attribute, &value);
+        hidl_cb(err, value);
+        return Void();
+    }
+
+    Return<void> getDisplayConfigs(Display display,
+                                   IComposerClient::getDisplayConfigs_cb hidl_cb) override {
+        hidl_vec<Config> configs;
+        Error err = mHal->getDisplayConfigs(display, &configs);
+        hidl_cb(err, configs);
+        return Void();
+    }
+
+    Return<void> getDisplayName(Display display,
+                                IComposerClient::getDisplayName_cb hidl_cb) override {
+        hidl_string name;
+        Error err = mHal->getDisplayName(display, &name);
+        hidl_cb(err, name);
+        return Void();
+    }
+
+    Return<void> getDisplayType(Display display,
+                                IComposerClient::getDisplayType_cb hidl_cb) override {
+        IComposerClient::DisplayType type = IComposerClient::DisplayType::INVALID;
+        Error err = mHal->getDisplayType(display, &type);
+        hidl_cb(err, type);
+        return Void();
+    }
+
+    Return<void> getDozeSupport(Display display,
+                                IComposerClient::getDozeSupport_cb hidl_cb) override {
+        bool support = false;
+        Error err = mHal->getDozeSupport(display, &support);
+        hidl_cb(err, support);
+        return Void();
+    }
+
+    Return<void> getHdrCapabilities(Display display,
+                                    IComposerClient::getHdrCapabilities_cb hidl_cb) override {
+        hidl_vec<Hdr> types;
+        float max_lumi = 0.0f;
+        float max_avg_lumi = 0.0f;
+        float min_lumi = 0.0f;
+        Error err = mHal->getHdrCapabilities(display, &types, &max_lumi, &max_avg_lumi, &min_lumi);
+        hidl_cb(err, types, max_lumi, max_avg_lumi, min_lumi);
+        return Void();
+    }
+
+    Return<Error> setActiveConfig(Display display, Config config) override {
+        Error err = mHal->setActiveConfig(display, config);
+        return err;
+    }
+
+    Return<Error> setColorMode(Display display, ColorMode mode) override {
+        Error err = mHal->setColorMode(display, mode);
+        return err;
+    }
+
+    Return<Error> setPowerMode(Display display, IComposerClient::PowerMode mode) override {
+        Error err = mHal->setPowerMode(display, mode);
+        return err;
+    }
+
+    Return<Error> setVsyncEnabled(Display display, IComposerClient::Vsync enabled) override {
+        Error err = mHal->setVsyncEnabled(display, enabled);
+        return err;
+    }
+
+    Return<Error> setClientTargetSlotCount(Display display,
+                                           uint32_t clientTargetSlotCount) override {
+        return mResources->setDisplayClientTargetCacheSize(display, clientTargetSlotCount);
+    }
+
+    Return<Error> setInputCommandQueue(const MQDescriptorSync<uint32_t>& descriptor) override {
+        std::lock_guard<std::mutex> lock(mCommandEngineMutex);
+        return mCommandEngine->setInputMQDescriptor(descriptor) ? Error::NONE : Error::NO_RESOURCES;
+    }
+
+    Return<void> getOutputCommandQueue(IComposerClient::getOutputCommandQueue_cb hidl_cb) override {
+        // no locking as we require this function to be called inside
+        // executeCommands_cb
+        auto outDescriptor = mCommandEngine->getOutputMQDescriptor();
+        if (outDescriptor) {
+            hidl_cb(Error::NONE, *outDescriptor);
+        } else {
+            hidl_cb(Error::NO_RESOURCES, CommandQueueType::Descriptor());
+        }
+
+        return Void();
+    }
+
+    Return<void> executeCommands(uint32_t inLength, const hidl_vec<hidl_handle>& inHandles,
+                                 IComposerClient::executeCommands_cb hidl_cb) override {
+        std::lock_guard<std::mutex> lock(mCommandEngineMutex);
+        bool outChanged = false;
+        uint32_t outLength = 0;
+        hidl_vec<hidl_handle> outHandles;
+        Error error =
+            mCommandEngine->execute(inLength, inHandles, &outChanged, &outLength, &outHandles);
+
+        hidl_cb(error, outChanged, outLength, outHandles);
+
+        mCommandEngine->reset();
+
+        return Void();
+    }
+
+   protected:
+    virtual std::unique_ptr<ComposerResources> createResources() {
+        return ComposerResources::create();
+    }
+
+    virtual std::unique_ptr<ComposerCommandEngine> createCommandEngine() {
+        return std::make_unique<ComposerCommandEngine>(mHal, mResources.get());
+    }
+
+    void destroyResources() {
+        // We want to call hwc2_close here (and move hwc2_open to the
+        // constructor), with the assumption that hwc2_close would
+        //
+        //  - clean up all resources owned by the client
+        //  - make sure all displays are blank (since there is no layer)
+        //
+        // But since SF used to crash at this point, different hwcomposer2
+        // implementations behave differently on hwc2_close.  Our only portable
+        // choice really is to abort().  But that is not an option anymore
+        // because we might also have VTS or VR as clients that can come and go.
+        //
+        // Below we manually clean all resources (layers and virtual
+        // displays), and perform a presentDisplay afterwards.
+        mResources->clear([this](Display display, bool isVirtual, const std::vector<Layer> layers) {
+            ALOGW("destroying client resources for display %" PRIu64, display);
+
+            for (auto layer : layers) {
+                mHal->destroyLayer(display, layer);
+            }
+
+            if (isVirtual) {
+                mHal->destroyVirtualDisplay(display);
+            } else {
+                ALOGW("performing a final presentDisplay");
+
+                std::vector<Layer> changedLayers;
+                std::vector<IComposerClient::Composition> compositionTypes;
+                uint32_t displayRequestMask = 0;
+                std::vector<Layer> requestedLayers;
+                std::vector<uint32_t> requestMasks;
+                mHal->validateDisplay(display, &changedLayers, &compositionTypes,
+                                      &displayRequestMask, &requestedLayers, &requestMasks);
+
+                mHal->acceptDisplayChanges(display);
+
+                int32_t presentFence = -1;
+                std::vector<Layer> releasedLayers;
+                std::vector<int32_t> releaseFences;
+                mHal->presentDisplay(display, &presentFence, &releasedLayers, &releaseFences);
+                if (presentFence >= 0) {
+                    close(presentFence);
+                }
+                for (auto fence : releaseFences) {
+                    if (fence >= 0) {
+                        close(fence);
+                    }
+                }
+            }
+        });
+
+        mResources.reset();
+    }
+
+    Hal* const mHal;
+
+    std::unique_ptr<ComposerResources> mResources;
+
+    std::mutex mCommandEngineMutex;
+    std::unique_ptr<ComposerCommandEngine> mCommandEngine;
+
+    std::function<void()> mOnClientDestroyed;
+    std::unique_ptr<HalEventCallback> mHalEventCallback;
+};
+
+}  // namespace detail
+
+using ComposerClient = detail::ComposerClientImpl<IComposerClient, ComposerHal>;
+
+}  // namespace hal
+}  // namespace V2_1
+}  // namespace composer
+}  // namespace graphics
+}  // namespace hardware
+}  // namespace android
diff --git a/graphics/composer/2.1/utils/hal/include/composer-hal/2.1/ComposerCommandEngine.h b/graphics/composer/2.1/utils/hal/include/composer-hal/2.1/ComposerCommandEngine.h
new file mode 100644
index 0000000..36aa64e
--- /dev/null
+++ b/graphics/composer/2.1/utils/hal/include/composer-hal/2.1/ComposerCommandEngine.h
@@ -0,0 +1,594 @@
+/*
+ * Copyright 2018 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
+
+#ifndef LOG_TAG
+#warning "ComposerCommandEngine.h included without LOG_TAG"
+#endif
+
+#include <vector>
+
+#include <composer-command-buffer/2.1/ComposerCommandBuffer.h>
+#include <composer-hal/2.1/ComposerHal.h>
+#include <composer-hal/2.1/ComposerResources.h>
+// TODO remove hwcomposer_defs.h dependency
+#include <hardware/hwcomposer_defs.h>
+#include <log/log.h>
+
+namespace android {
+namespace hardware {
+namespace graphics {
+namespace composer {
+namespace V2_1 {
+namespace hal {
+
+// TODO own a CommandReaderBase rather than subclassing
+class ComposerCommandEngine : protected CommandReaderBase {
+   public:
+    ComposerCommandEngine(ComposerHal* hal, ComposerResources* resources)
+        : mHal(hal), mResources(resources) {}
+
+    virtual ~ComposerCommandEngine() = default;
+
+    bool setInputMQDescriptor(const MQDescriptorSync<uint32_t>& descriptor) {
+        return setMQDescriptor(descriptor);
+    }
+
+    Error execute(uint32_t inLength, const hidl_vec<hidl_handle>& inHandles, bool* outQueueChanged,
+                  uint32_t* outCommandLength, hidl_vec<hidl_handle>* outCommandHandles) {
+        if (!readQueue(inLength, inHandles)) {
+            return Error::BAD_PARAMETER;
+        }
+
+        IComposerClient::Command command;
+        uint16_t length = 0;
+        while (!isEmpty()) {
+            if (!beginCommand(&command, &length)) {
+                break;
+            }
+
+            bool parsed = executeCommand(command, length);
+            endCommand();
+
+            if (!parsed) {
+                ALOGE("failed to parse command 0x%x, length %" PRIu16, command, length);
+                break;
+            }
+        }
+
+        if (!isEmpty()) {
+            return Error::BAD_PARAMETER;
+        }
+
+        return mWriter.writeQueue(outQueueChanged, outCommandLength, outCommandHandles)
+                   ? Error::NONE
+                   : Error::NO_RESOURCES;
+    }
+
+    const MQDescriptorSync<uint32_t>* getOutputMQDescriptor() { return mWriter.getMQDescriptor(); }
+
+    void reset() {
+        CommandReaderBase::reset();
+        mWriter.reset();
+    }
+
+   protected:
+    virtual bool executeCommand(IComposerClient::Command command, uint16_t length) {
+        switch (command) {
+            case IComposerClient::Command::SELECT_DISPLAY:
+                return executeSelectDisplay(length);
+            case IComposerClient::Command::SELECT_LAYER:
+                return executeSelectLayer(length);
+            case IComposerClient::Command::SET_COLOR_TRANSFORM:
+                return executeSetColorTransform(length);
+            case IComposerClient::Command::SET_CLIENT_TARGET:
+                return executeSetClientTarget(length);
+            case IComposerClient::Command::SET_OUTPUT_BUFFER:
+                return executeSetOutputBuffer(length);
+            case IComposerClient::Command::VALIDATE_DISPLAY:
+                return executeValidateDisplay(length);
+            case IComposerClient::Command::PRESENT_OR_VALIDATE_DISPLAY:
+                return executePresentOrValidateDisplay(length);
+            case IComposerClient::Command::ACCEPT_DISPLAY_CHANGES:
+                return executeAcceptDisplayChanges(length);
+            case IComposerClient::Command::PRESENT_DISPLAY:
+                return executePresentDisplay(length);
+            case IComposerClient::Command::SET_LAYER_CURSOR_POSITION:
+                return executeSetLayerCursorPosition(length);
+            case IComposerClient::Command::SET_LAYER_BUFFER:
+                return executeSetLayerBuffer(length);
+            case IComposerClient::Command::SET_LAYER_SURFACE_DAMAGE:
+                return executeSetLayerSurfaceDamage(length);
+            case IComposerClient::Command::SET_LAYER_BLEND_MODE:
+                return executeSetLayerBlendMode(length);
+            case IComposerClient::Command::SET_LAYER_COLOR:
+                return executeSetLayerColor(length);
+            case IComposerClient::Command::SET_LAYER_COMPOSITION_TYPE:
+                return executeSetLayerCompositionType(length);
+            case IComposerClient::Command::SET_LAYER_DATASPACE:
+                return executeSetLayerDataspace(length);
+            case IComposerClient::Command::SET_LAYER_DISPLAY_FRAME:
+                return executeSetLayerDisplayFrame(length);
+            case IComposerClient::Command::SET_LAYER_PLANE_ALPHA:
+                return executeSetLayerPlaneAlpha(length);
+            case IComposerClient::Command::SET_LAYER_SIDEBAND_STREAM:
+                return executeSetLayerSidebandStream(length);
+            case IComposerClient::Command::SET_LAYER_SOURCE_CROP:
+                return executeSetLayerSourceCrop(length);
+            case IComposerClient::Command::SET_LAYER_TRANSFORM:
+                return executeSetLayerTransform(length);
+            case IComposerClient::Command::SET_LAYER_VISIBLE_REGION:
+                return executeSetLayerVisibleRegion(length);
+            case IComposerClient::Command::SET_LAYER_Z_ORDER:
+                return executeSetLayerZOrder(length);
+            default:
+                return false;
+        }
+    }
+
+    bool executeSelectDisplay(uint16_t length) {
+        if (length != CommandWriterBase::kSelectDisplayLength) {
+            return false;
+        }
+
+        mCurrentDisplay = read64();
+        mWriter.selectDisplay(mCurrentDisplay);
+
+        return true;
+    }
+
+    bool executeSelectLayer(uint16_t length) {
+        if (length != CommandWriterBase::kSelectLayerLength) {
+            return false;
+        }
+
+        mCurrentLayer = read64();
+
+        return true;
+    }
+
+    bool executeSetColorTransform(uint16_t length) {
+        if (length != CommandWriterBase::kSetColorTransformLength) {
+            return false;
+        }
+
+        float matrix[16];
+        for (int i = 0; i < 16; i++) {
+            matrix[i] = readFloat();
+        }
+        auto transform = readSigned();
+
+        auto err = mHal->setColorTransform(mCurrentDisplay, matrix, transform);
+        if (err != Error::NONE) {
+            mWriter.setError(getCommandLoc(), err);
+        }
+
+        return true;
+    }
+
+    bool executeSetClientTarget(uint16_t length) {
+        // 4 parameters followed by N rectangles
+        if ((length - 4) % 4 != 0) {
+            return false;
+        }
+
+        bool useCache = false;
+        auto slot = read();
+        auto rawHandle = readHandle(&useCache);
+        auto fence = readFence();
+        auto dataspace = readSigned();
+        auto damage = readRegion((length - 4) / 4);
+        bool closeFence = true;
+
+        const native_handle_t* clientTarget;
+        ComposerResources::ReplacedBufferHandle replacedClientTarget;
+        auto err = mResources->getDisplayClientTarget(mCurrentDisplay, slot, useCache, rawHandle,
+                                                      &clientTarget, &replacedClientTarget);
+        if (err == Error::NONE) {
+            err = mHal->setClientTarget(mCurrentDisplay, clientTarget, fence, dataspace, damage);
+            if (err == Error::NONE) {
+                closeFence = false;
+            }
+        }
+        if (closeFence) {
+            close(fence);
+        }
+        if (err != Error::NONE) {
+            mWriter.setError(getCommandLoc(), err);
+        }
+
+        return true;
+    }
+
+    bool executeSetOutputBuffer(uint16_t length) {
+        if (length != CommandWriterBase::kSetOutputBufferLength) {
+            return false;
+        }
+
+        bool useCache = false;
+        auto slot = read();
+        auto rawhandle = readHandle(&useCache);
+        auto fence = readFence();
+        bool closeFence = true;
+
+        const native_handle_t* outputBuffer;
+        ComposerResources::ReplacedBufferHandle replacedOutputBuffer;
+        auto err = mResources->getDisplayOutputBuffer(mCurrentDisplay, slot, useCache, rawhandle,
+                                                      &outputBuffer, &replacedOutputBuffer);
+        if (err == Error::NONE) {
+            err = mHal->setOutputBuffer(mCurrentDisplay, outputBuffer, fence);
+            if (err == Error::NONE) {
+                closeFence = false;
+            }
+        }
+        if (closeFence) {
+            close(fence);
+        }
+        if (err != Error::NONE) {
+            mWriter.setError(getCommandLoc(), err);
+        }
+
+        return true;
+    }
+
+    bool executeValidateDisplay(uint16_t length) {
+        if (length != CommandWriterBase::kValidateDisplayLength) {
+            return false;
+        }
+
+        std::vector<Layer> changedLayers;
+        std::vector<IComposerClient::Composition> compositionTypes;
+        uint32_t displayRequestMask = 0x0;
+        std::vector<Layer> requestedLayers;
+        std::vector<uint32_t> requestMasks;
+
+        auto err = mHal->validateDisplay(mCurrentDisplay, &changedLayers, &compositionTypes,
+                                         &displayRequestMask, &requestedLayers, &requestMasks);
+        if (err == Error::NONE) {
+            mWriter.setChangedCompositionTypes(changedLayers, compositionTypes);
+            mWriter.setDisplayRequests(displayRequestMask, requestedLayers, requestMasks);
+        } else {
+            mWriter.setError(getCommandLoc(), err);
+        }
+
+        return true;
+    }
+
+    bool executePresentOrValidateDisplay(uint16_t length) {
+        if (length != CommandWriterBase::kPresentOrValidateDisplayLength) {
+            return false;
+        }
+
+        // First try to Present as is.
+        if (mHal->hasCapability(HWC2_CAPABILITY_SKIP_VALIDATE)) {
+            int presentFence = -1;
+            std::vector<Layer> layers;
+            std::vector<int> fences;
+            auto err = mHal->presentDisplay(mCurrentDisplay, &presentFence, &layers, &fences);
+            if (err == Error::NONE) {
+                mWriter.setPresentOrValidateResult(1);
+                mWriter.setPresentFence(presentFence);
+                mWriter.setReleaseFences(layers, fences);
+                return true;
+            }
+        }
+
+        // Present has failed. We need to fallback to validate
+        std::vector<Layer> changedLayers;
+        std::vector<IComposerClient::Composition> compositionTypes;
+        uint32_t displayRequestMask = 0x0;
+        std::vector<Layer> requestedLayers;
+        std::vector<uint32_t> requestMasks;
+
+        auto err = mHal->validateDisplay(mCurrentDisplay, &changedLayers, &compositionTypes,
+                                         &displayRequestMask, &requestedLayers, &requestMasks);
+        if (err == Error::NONE) {
+            mWriter.setPresentOrValidateResult(0);
+            mWriter.setChangedCompositionTypes(changedLayers, compositionTypes);
+            mWriter.setDisplayRequests(displayRequestMask, requestedLayers, requestMasks);
+        } else {
+            mWriter.setError(getCommandLoc(), err);
+        }
+
+        return true;
+    }
+
+    bool executeAcceptDisplayChanges(uint16_t length) {
+        if (length != CommandWriterBase::kAcceptDisplayChangesLength) {
+            return false;
+        }
+
+        auto err = mHal->acceptDisplayChanges(mCurrentDisplay);
+        if (err != Error::NONE) {
+            mWriter.setError(getCommandLoc(), err);
+        }
+
+        return true;
+    }
+
+    bool executePresentDisplay(uint16_t length) {
+        if (length != CommandWriterBase::kPresentDisplayLength) {
+            return false;
+        }
+
+        int presentFence = -1;
+        std::vector<Layer> layers;
+        std::vector<int> fences;
+        auto err = mHal->presentDisplay(mCurrentDisplay, &presentFence, &layers, &fences);
+        if (err == Error::NONE) {
+            mWriter.setPresentFence(presentFence);
+            mWriter.setReleaseFences(layers, fences);
+        } else {
+            mWriter.setError(getCommandLoc(), err);
+        }
+
+        return true;
+    }
+
+    bool executeSetLayerCursorPosition(uint16_t length) {
+        if (length != CommandWriterBase::kSetLayerCursorPositionLength) {
+            return false;
+        }
+
+        auto err = mHal->setLayerCursorPosition(mCurrentDisplay, mCurrentLayer, readSigned(),
+                                                readSigned());
+        if (err != Error::NONE) {
+            mWriter.setError(getCommandLoc(), err);
+        }
+
+        return true;
+    }
+
+    bool executeSetLayerBuffer(uint16_t length) {
+        if (length != CommandWriterBase::kSetLayerBufferLength) {
+            return false;
+        }
+
+        bool useCache = false;
+        auto slot = read();
+        auto rawHandle = readHandle(&useCache);
+        auto fence = readFence();
+        bool closeFence = true;
+
+        const native_handle_t* buffer;
+        ComposerResources::ReplacedBufferHandle replacedBuffer;
+        auto err = mResources->getLayerBuffer(mCurrentDisplay, mCurrentLayer, slot, useCache,
+                                              rawHandle, &buffer, &replacedBuffer);
+        if (err == Error::NONE) {
+            err = mHal->setLayerBuffer(mCurrentDisplay, mCurrentLayer, buffer, fence);
+            if (err == Error::NONE) {
+                closeFence = false;
+            }
+        }
+        if (closeFence) {
+            close(fence);
+        }
+        if (err != Error::NONE) {
+            mWriter.setError(getCommandLoc(), err);
+        }
+
+        return true;
+    }
+
+    bool executeSetLayerSurfaceDamage(uint16_t length) {
+        // N rectangles
+        if (length % 4 != 0) {
+            return false;
+        }
+
+        auto damage = readRegion(length / 4);
+        auto err = mHal->setLayerSurfaceDamage(mCurrentDisplay, mCurrentLayer, damage);
+        if (err != Error::NONE) {
+            mWriter.setError(getCommandLoc(), err);
+        }
+
+        return true;
+    }
+
+    bool executeSetLayerBlendMode(uint16_t length) {
+        if (length != CommandWriterBase::kSetLayerBlendModeLength) {
+            return false;
+        }
+
+        auto err = mHal->setLayerBlendMode(mCurrentDisplay, mCurrentLayer, readSigned());
+        if (err != Error::NONE) {
+            mWriter.setError(getCommandLoc(), err);
+        }
+
+        return true;
+    }
+
+    bool executeSetLayerColor(uint16_t length) {
+        if (length != CommandWriterBase::kSetLayerColorLength) {
+            return false;
+        }
+
+        auto err = mHal->setLayerColor(mCurrentDisplay, mCurrentLayer, readColor());
+        if (err != Error::NONE) {
+            mWriter.setError(getCommandLoc(), err);
+        }
+
+        return true;
+    }
+
+    bool executeSetLayerCompositionType(uint16_t length) {
+        if (length != CommandWriterBase::kSetLayerCompositionTypeLength) {
+            return false;
+        }
+
+        auto err = mHal->setLayerCompositionType(mCurrentDisplay, mCurrentLayer, readSigned());
+        if (err != Error::NONE) {
+            mWriter.setError(getCommandLoc(), err);
+        }
+
+        return true;
+    }
+
+    bool executeSetLayerDataspace(uint16_t length) {
+        if (length != CommandWriterBase::kSetLayerDataspaceLength) {
+            return false;
+        }
+
+        auto err = mHal->setLayerDataspace(mCurrentDisplay, mCurrentLayer, readSigned());
+        if (err != Error::NONE) {
+            mWriter.setError(getCommandLoc(), err);
+        }
+
+        return true;
+    }
+
+    bool executeSetLayerDisplayFrame(uint16_t length) {
+        if (length != CommandWriterBase::kSetLayerDisplayFrameLength) {
+            return false;
+        }
+
+        auto err = mHal->setLayerDisplayFrame(mCurrentDisplay, mCurrentLayer, readRect());
+        if (err != Error::NONE) {
+            mWriter.setError(getCommandLoc(), err);
+        }
+
+        return true;
+    }
+
+    bool executeSetLayerPlaneAlpha(uint16_t length) {
+        if (length != CommandWriterBase::kSetLayerPlaneAlphaLength) {
+            return false;
+        }
+
+        auto err = mHal->setLayerPlaneAlpha(mCurrentDisplay, mCurrentLayer, readFloat());
+        if (err != Error::NONE) {
+            mWriter.setError(getCommandLoc(), err);
+        }
+
+        return true;
+    }
+
+    bool executeSetLayerSidebandStream(uint16_t length) {
+        if (length != CommandWriterBase::kSetLayerSidebandStreamLength) {
+            return false;
+        }
+
+        auto rawHandle = readHandle();
+
+        const native_handle_t* stream;
+        ComposerResources::ReplacedStreamHandle replacedStream;
+        auto err = mResources->getLayerSidebandStream(mCurrentDisplay, mCurrentLayer, rawHandle,
+                                                      &stream, &replacedStream);
+        if (err == Error::NONE) {
+            err = mHal->setLayerSidebandStream(mCurrentDisplay, mCurrentLayer, stream);
+        }
+        if (err != Error::NONE) {
+            mWriter.setError(getCommandLoc(), err);
+        }
+
+        return true;
+    }
+
+    bool executeSetLayerSourceCrop(uint16_t length) {
+        if (length != CommandWriterBase::kSetLayerSourceCropLength) {
+            return false;
+        }
+
+        auto err = mHal->setLayerSourceCrop(mCurrentDisplay, mCurrentLayer, readFRect());
+        if (err != Error::NONE) {
+            mWriter.setError(getCommandLoc(), err);
+        }
+
+        return true;
+    }
+
+    bool executeSetLayerTransform(uint16_t length) {
+        if (length != CommandWriterBase::kSetLayerTransformLength) {
+            return false;
+        }
+
+        auto err = mHal->setLayerTransform(mCurrentDisplay, mCurrentLayer, readSigned());
+        if (err != Error::NONE) {
+            mWriter.setError(getCommandLoc(), err);
+        }
+
+        return true;
+    }
+
+    bool executeSetLayerVisibleRegion(uint16_t length) {
+        // N rectangles
+        if (length % 4 != 0) {
+            return false;
+        }
+
+        auto region = readRegion(length / 4);
+        auto err = mHal->setLayerVisibleRegion(mCurrentDisplay, mCurrentLayer, region);
+        if (err != Error::NONE) {
+            mWriter.setError(getCommandLoc(), err);
+        }
+
+        return true;
+    }
+
+    bool executeSetLayerZOrder(uint16_t length) {
+        if (length != CommandWriterBase::kSetLayerZOrderLength) {
+            return false;
+        }
+
+        auto err = mHal->setLayerZOrder(mCurrentDisplay, mCurrentLayer, read());
+        if (err != Error::NONE) {
+            mWriter.setError(getCommandLoc(), err);
+        }
+
+        return true;
+    }
+
+    hwc_rect_t readRect() {
+        return hwc_rect_t{
+            readSigned(), readSigned(), readSigned(), readSigned(),
+        };
+    }
+
+    std::vector<hwc_rect_t> readRegion(size_t count) {
+        std::vector<hwc_rect_t> region;
+        region.reserve(count);
+        while (count > 0) {
+            region.emplace_back(readRect());
+            count--;
+        }
+
+        return region;
+    }
+
+    hwc_frect_t readFRect() {
+        return hwc_frect_t{
+            readFloat(), readFloat(), readFloat(), readFloat(),
+        };
+    }
+
+    ComposerHal* mHal;
+    ComposerResources* mResources;
+
+    // 64KiB minus a small space for metadata such as read/write pointers
+    static constexpr size_t kWriterInitialSize = 64 * 1024 / sizeof(uint32_t) - 16;
+    CommandWriterBase mWriter{kWriterInitialSize};
+
+    Display mCurrentDisplay = 0;
+    Layer mCurrentLayer = 0;
+};
+
+}  // namespace hal
+}  // namespace V2_1
+}  // namespace composer
+}  // namespace graphics
+}  // namespace hardware
+}  // namespace android
diff --git a/graphics/composer/2.1/utils/hal/include/composer-hal/2.1/ComposerHal.h b/graphics/composer/2.1/utils/hal/include/composer-hal/2.1/ComposerHal.h
new file mode 100644
index 0000000..c9793fd
--- /dev/null
+++ b/graphics/composer/2.1/utils/hal/include/composer-hal/2.1/ComposerHal.h
@@ -0,0 +1,137 @@
+/*
+ * Copyright 2018 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 <string>
+#include <vector>
+
+#include <android/hardware/graphics/composer/2.1/IComposer.h>
+#include <android/hardware/graphics/composer/2.1/IComposerClient.h>
+
+// TODO remove hwcomposer2.h dependency
+#define HWC2_INCLUDE_STRINGIFICATION
+#define HWC2_USE_CPP11
+#include <hardware/hwcomposer2.h>
+#undef HWC2_INCLUDE_STRINGIFICATION
+#undef HWC2_USE_CPP11
+
+namespace android {
+namespace hardware {
+namespace graphics {
+namespace composer {
+namespace V2_1 {
+namespace hal {
+
+using common::V1_0::ColorMode;
+using common::V1_0::ColorTransform;
+using common::V1_0::Dataspace;
+using common::V1_0::Hdr;
+using common::V1_0::PixelFormat;
+using common::V1_0::Transform;
+
+class ComposerHal {
+   public:
+    virtual ~ComposerHal() = default;
+
+    virtual bool hasCapability(hwc2_capability_t capability) = 0;
+
+    // dump the debug information
+    virtual std::string dumpDebugInfo() = 0;
+
+    class EventCallback {
+       public:
+        virtual ~EventCallback() = default;
+        virtual void onHotplug(Display display, IComposerCallback::Connection connected) = 0;
+        virtual void onRefresh(Display display) = 0;
+        virtual void onVsync(Display display, int64_t timestamp) = 0;
+    };
+
+    // Register the event callback object.  The event callback object is valid
+    // until it is unregistered.  A hotplug event must be generated for each
+    // connected physical display, before or after this function returns.
+    virtual void registerEventCallback(EventCallback* callback) = 0;
+
+    // Unregister the event callback object.  It must block if there is any
+    // callback in-flight.
+    virtual void unregisterEventCallback() = 0;
+
+    virtual uint32_t getMaxVirtualDisplayCount() = 0;
+    virtual Error createVirtualDisplay(uint32_t width, uint32_t height, PixelFormat* format,
+                                       Display* outDisplay) = 0;
+    virtual Error destroyVirtualDisplay(Display display) = 0;
+    virtual Error createLayer(Display display, Layer* outLayer) = 0;
+    virtual Error destroyLayer(Display display, Layer layer) = 0;
+
+    virtual Error getActiveConfig(Display display, Config* outConfig) = 0;
+    virtual Error getClientTargetSupport(Display display, uint32_t width, uint32_t height,
+                                         PixelFormat format, Dataspace dataspace) = 0;
+    virtual Error getColorModes(Display display, hidl_vec<ColorMode>* outModes) = 0;
+    virtual Error getDisplayAttribute(Display display, Config config,
+                                      IComposerClient::Attribute attribute, int32_t* outValue) = 0;
+    virtual Error getDisplayConfigs(Display display, hidl_vec<Config>* outConfigs) = 0;
+    virtual Error getDisplayName(Display display, hidl_string* outName) = 0;
+    virtual Error getDisplayType(Display display, IComposerClient::DisplayType* outType) = 0;
+    virtual Error getDozeSupport(Display display, bool* outSupport) = 0;
+    virtual Error getHdrCapabilities(Display display, hidl_vec<Hdr>* outTypes,
+                                     float* outMaxLuminance, float* outMaxAverageLuminance,
+                                     float* outMinLuminance) = 0;
+
+    virtual Error setActiveConfig(Display display, Config config) = 0;
+    virtual Error setColorMode(Display display, ColorMode mode) = 0;
+    virtual Error setPowerMode(Display display, IComposerClient::PowerMode mode) = 0;
+    virtual Error setVsyncEnabled(Display display, IComposerClient::Vsync enabled) = 0;
+
+    virtual Error setColorTransform(Display display, const float* matrix, int32_t hint) = 0;
+    virtual Error setClientTarget(Display display, buffer_handle_t target, int32_t acquireFence,
+                                  int32_t dataspace, const std::vector<hwc_rect_t>& damage) = 0;
+    virtual Error setOutputBuffer(Display display, buffer_handle_t buffer,
+                                  int32_t releaseFence) = 0;
+    virtual Error validateDisplay(Display display, std::vector<Layer>* outChangedLayers,
+                                  std::vector<IComposerClient::Composition>* outCompositionTypes,
+                                  uint32_t* outDisplayRequestMask,
+                                  std::vector<Layer>* outRequestedLayers,
+                                  std::vector<uint32_t>* outRequestMasks) = 0;
+    virtual Error acceptDisplayChanges(Display display) = 0;
+    virtual Error presentDisplay(Display display, int32_t* outPresentFence,
+                                 std::vector<Layer>* outLayers,
+                                 std::vector<int32_t>* outReleaseFences) = 0;
+
+    virtual Error setLayerCursorPosition(Display display, Layer layer, int32_t x, int32_t y) = 0;
+    virtual Error setLayerBuffer(Display display, Layer layer, buffer_handle_t buffer,
+                                 int32_t acquireFence) = 0;
+    virtual Error setLayerSurfaceDamage(Display display, Layer layer,
+                                        const std::vector<hwc_rect_t>& damage) = 0;
+    virtual Error setLayerBlendMode(Display display, Layer layer, int32_t mode) = 0;
+    virtual Error setLayerColor(Display display, Layer layer, IComposerClient::Color color) = 0;
+    virtual Error setLayerCompositionType(Display display, Layer layer, int32_t type) = 0;
+    virtual Error setLayerDataspace(Display display, Layer layer, int32_t dataspace) = 0;
+    virtual Error setLayerDisplayFrame(Display display, Layer layer, const hwc_rect_t& frame) = 0;
+    virtual Error setLayerPlaneAlpha(Display display, Layer layer, float alpha) = 0;
+    virtual Error setLayerSidebandStream(Display display, Layer layer, buffer_handle_t stream) = 0;
+    virtual Error setLayerSourceCrop(Display display, Layer layer, const hwc_frect_t& crop) = 0;
+    virtual Error setLayerTransform(Display display, Layer layer, int32_t transform) = 0;
+    virtual Error setLayerVisibleRegion(Display display, Layer layer,
+                                        const std::vector<hwc_rect_t>& visible) = 0;
+    virtual Error setLayerZOrder(Display display, Layer layer, uint32_t z) = 0;
+};
+
+}  // namespace hal
+}  // namespace V2_1
+}  // namespace composer
+}  // namespace graphics
+}  // namespace hardware
+}  // namespace android
diff --git a/graphics/composer/2.1/utils/hal/include/composer-hal/2.1/ComposerResources.h b/graphics/composer/2.1/utils/hal/include/composer-hal/2.1/ComposerResources.h
new file mode 100644
index 0000000..7bb3692
--- /dev/null
+++ b/graphics/composer/2.1/utils/hal/include/composer-hal/2.1/ComposerResources.h
@@ -0,0 +1,536 @@
+/*
+ * Copyright 2018 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
+
+#ifndef LOG_TAG
+#warning "ComposerResources.h included without LOG_TAG"
+#endif
+
+#include <memory>
+#include <mutex>
+#include <unordered_map>
+#include <vector>
+
+#include <android/hardware/graphics/mapper/2.0/IMapper.h>
+#include <log/log.h>
+
+namespace android {
+namespace hardware {
+namespace graphics {
+namespace composer {
+namespace V2_1 {
+namespace hal {
+
+// wrapper for IMapper to import buffers and sideband streams
+class ComposerHandleImporter {
+   public:
+    bool init() {
+        mMapper = mapper::V2_0::IMapper::getService();
+        ALOGE_IF(!mMapper, "failed to get mapper service");
+        return mMapper != nullptr;
+    }
+
+    Error importBuffer(const native_handle_t* rawHandle, const native_handle_t** outBufferHandle) {
+        if (!rawHandle || (!rawHandle->numFds && !rawHandle->numInts)) {
+            *outBufferHandle = nullptr;
+            return Error::NONE;
+        }
+
+        mapper::V2_0::Error error;
+        const native_handle_t* bufferHandle;
+        mMapper->importBuffer(rawHandle, [&](const auto& tmpError, const auto& tmpBufferHandle) {
+            error = tmpError;
+            bufferHandle = static_cast<const native_handle_t*>(tmpBufferHandle);
+        });
+        if (error != mapper::V2_0::Error::NONE) {
+            return Error::NO_RESOURCES;
+        }
+
+        *outBufferHandle = bufferHandle;
+        return Error::NONE;
+    }
+
+    void freeBuffer(const native_handle_t* bufferHandle) {
+        if (bufferHandle) {
+            mMapper->freeBuffer(static_cast<void*>(const_cast<native_handle_t*>(bufferHandle)));
+        }
+    }
+
+    Error importStream(const native_handle_t* rawHandle, const native_handle_t** outStreamHandle) {
+        const native_handle_t* streamHandle = nullptr;
+        if (rawHandle) {
+            streamHandle = native_handle_clone(rawHandle);
+            if (!streamHandle) {
+                return Error::NO_RESOURCES;
+            }
+        }
+
+        *outStreamHandle = streamHandle;
+        return Error::NONE;
+    }
+
+    void freeStream(const native_handle_t* streamHandle) {
+        if (streamHandle) {
+            native_handle_close(streamHandle);
+            native_handle_delete(const_cast<native_handle_t*>(streamHandle));
+        }
+    }
+
+   private:
+    sp<mapper::V2_0::IMapper> mMapper;
+};
+
+class ComposerHandleCache {
+   public:
+    enum class HandleType {
+        INVALID,
+        BUFFER,
+        STREAM,
+    };
+
+    ComposerHandleCache(ComposerHandleImporter& importer, HandleType type, uint32_t cacheSize)
+        : mImporter(importer), mHandleType(type), mHandles(cacheSize, nullptr) {}
+
+    // must be initialized later with initCache
+    ComposerHandleCache(ComposerHandleImporter& importer) : mImporter(importer) {}
+
+    ~ComposerHandleCache() {
+        switch (mHandleType) {
+            case HandleType::BUFFER:
+                for (auto handle : mHandles) {
+                    mImporter.freeBuffer(handle);
+                }
+                break;
+            case HandleType::STREAM:
+                for (auto handle : mHandles) {
+                    mImporter.freeStream(handle);
+                }
+                break;
+            default:
+                break;
+        }
+    }
+
+    ComposerHandleCache(const ComposerHandleCache&) = delete;
+    ComposerHandleCache& operator=(const ComposerHandleCache&) = delete;
+
+    bool initCache(HandleType type, uint32_t cacheSize) {
+        // already initialized
+        if (mHandleType != HandleType::INVALID) {
+            return false;
+        }
+
+        mHandleType = type;
+        mHandles.resize(cacheSize, nullptr);
+
+        return true;
+    }
+
+    Error lookupCache(uint32_t slot, const native_handle_t** outHandle) {
+        if (slot < mHandles.size()) {
+            *outHandle = mHandles[slot];
+            return Error::NONE;
+        } else {
+            return Error::BAD_PARAMETER;
+        }
+    }
+
+    Error updateCache(uint32_t slot, const native_handle_t* handle,
+                      const native_handle** outReplacedHandle) {
+        if (slot < mHandles.size()) {
+            auto& cachedHandle = mHandles[slot];
+            *outReplacedHandle = cachedHandle;
+            cachedHandle = handle;
+            return Error::NONE;
+        } else {
+            return Error::BAD_PARAMETER;
+        }
+    }
+
+    // when fromCache is true, look up in the cache; otherwise, update the cache
+    Error getHandle(uint32_t slot, bool fromCache, const native_handle_t* inHandle,
+                    const native_handle_t** outHandle, const native_handle** outReplacedHandle) {
+        if (fromCache) {
+            *outReplacedHandle = nullptr;
+            return lookupCache(slot, outHandle);
+        } else {
+            *outHandle = inHandle;
+            return updateCache(slot, inHandle, outReplacedHandle);
+        }
+    }
+
+   private:
+    ComposerHandleImporter& mImporter;
+    HandleType mHandleType = HandleType::INVALID;
+    std::vector<const native_handle_t*> mHandles;
+};
+
+// layer resource
+class ComposerLayerResource {
+   public:
+    ComposerLayerResource(ComposerHandleImporter& importer, uint32_t bufferCacheSize)
+        : mBufferCache(importer, ComposerHandleCache::HandleType::BUFFER, bufferCacheSize),
+          mSidebandStreamCache(importer, ComposerHandleCache::HandleType::STREAM, 1) {}
+
+    Error getBuffer(uint32_t slot, bool fromCache, const native_handle_t* inHandle,
+                    const native_handle_t** outHandle, const native_handle** outReplacedHandle) {
+        return mBufferCache.getHandle(slot, fromCache, inHandle, outHandle, outReplacedHandle);
+    }
+
+    Error getSidebandStream(uint32_t slot, bool fromCache, const native_handle_t* inHandle,
+                            const native_handle_t** outHandle,
+                            const native_handle** outReplacedHandle) {
+        return mSidebandStreamCache.getHandle(slot, fromCache, inHandle, outHandle,
+                                              outReplacedHandle);
+    }
+
+   protected:
+    ComposerHandleCache mBufferCache;
+    ComposerHandleCache mSidebandStreamCache;
+};
+
+// display resource
+class ComposerDisplayResource {
+   public:
+    enum class DisplayType {
+        PHYSICAL,
+        VIRTUAL,
+    };
+
+    ComposerDisplayResource(DisplayType type, ComposerHandleImporter& importer,
+                            uint32_t outputBufferCacheSize)
+        : mType(type),
+          mClientTargetCache(importer),
+          mOutputBufferCache(importer, ComposerHandleCache::HandleType::BUFFER,
+                             outputBufferCacheSize) {}
+
+    bool initClientTargetCache(uint32_t cacheSize) {
+        return mClientTargetCache.initCache(ComposerHandleCache::HandleType::BUFFER, cacheSize);
+    }
+
+    bool isVirtual() const { return mType == DisplayType::VIRTUAL; }
+
+    Error getClientTarget(uint32_t slot, bool fromCache, const native_handle_t* inHandle,
+                          const native_handle_t** outHandle,
+                          const native_handle** outReplacedHandle) {
+        return mClientTargetCache.getHandle(slot, fromCache, inHandle, outHandle,
+                                            outReplacedHandle);
+    }
+
+    Error getOutputBuffer(uint32_t slot, bool fromCache, const native_handle_t* inHandle,
+                          const native_handle_t** outHandle,
+                          const native_handle** outReplacedHandle) {
+        return mOutputBufferCache.getHandle(slot, fromCache, inHandle, outHandle,
+                                            outReplacedHandle);
+    }
+
+    bool addLayer(Layer layer, std::unique_ptr<ComposerLayerResource> layerResource) {
+        auto result = mLayerResources.emplace(layer, std::move(layerResource));
+        return result.second;
+    }
+
+    bool removeLayer(Layer layer) { return mLayerResources.erase(layer) > 0; }
+
+    ComposerLayerResource* findLayerResource(Layer layer) {
+        auto layerIter = mLayerResources.find(layer);
+        if (layerIter == mLayerResources.end()) {
+            return nullptr;
+        }
+
+        return layerIter->second.get();
+    }
+
+    std::vector<Layer> getLayers() const {
+        std::vector<Layer> layers;
+        layers.reserve(mLayerResources.size());
+        for (const auto& layerKey : mLayerResources) {
+            layers.push_back(layerKey.first);
+        }
+        return layers;
+    }
+
+   protected:
+    const DisplayType mType;
+    ComposerHandleCache mClientTargetCache;
+    ComposerHandleCache mOutputBufferCache;
+
+    std::unordered_map<Layer, std::unique_ptr<ComposerLayerResource>> mLayerResources;
+};
+
+class ComposerResources {
+   private:
+    template <bool isBuffer>
+    class ReplacedHandle;
+
+   public:
+    static std::unique_ptr<ComposerResources> create() {
+        auto resources = std::make_unique<ComposerResources>();
+        return resources->init() ? std::move(resources) : nullptr;
+    }
+
+    ComposerResources() = default;
+    virtual ~ComposerResources() = default;
+
+    bool init() { return mImporter.init(); }
+
+    using RemoveDisplay =
+        std::function<void(Display display, bool isVirtual, const std::vector<Layer>& layers)>;
+    void clear(RemoveDisplay removeDisplay) {
+        std::lock_guard<std::mutex> lock(mDisplayResourcesMutex);
+        for (const auto& displayKey : mDisplayResources) {
+            Display display = displayKey.first;
+            const ComposerDisplayResource& displayResource = *displayKey.second;
+            removeDisplay(display, displayResource.isVirtual(), displayResource.getLayers());
+        }
+        mDisplayResources.clear();
+    }
+
+    Error addPhysicalDisplay(Display display) {
+        auto displayResource =
+            createDisplayResource(ComposerDisplayResource::DisplayType::PHYSICAL, 0);
+
+        std::lock_guard<std::mutex> lock(mDisplayResourcesMutex);
+        auto result = mDisplayResources.emplace(display, std::move(displayResource));
+        return result.second ? Error::NONE : Error::BAD_DISPLAY;
+    }
+
+    Error addVirtualDisplay(Display display, uint32_t outputBufferCacheSize) {
+        auto displayResource = createDisplayResource(ComposerDisplayResource::DisplayType::VIRTUAL,
+                                                     outputBufferCacheSize);
+
+        std::lock_guard<std::mutex> lock(mDisplayResourcesMutex);
+        auto result = mDisplayResources.emplace(display, std::move(displayResource));
+        return result.second ? Error::NONE : Error::BAD_DISPLAY;
+    }
+
+    Error removeDisplay(Display display) {
+        std::lock_guard<std::mutex> lock(mDisplayResourcesMutex);
+        return mDisplayResources.erase(display) > 0 ? Error::NONE : Error::BAD_DISPLAY;
+    }
+
+    Error setDisplayClientTargetCacheSize(Display display, uint32_t clientTargetCacheSize) {
+        std::lock_guard<std::mutex> lock(mDisplayResourcesMutex);
+        ComposerDisplayResource* displayResource = findDisplayResourceLocked(display);
+        if (!displayResource) {
+            return Error::BAD_DISPLAY;
+        }
+
+        return displayResource->initClientTargetCache(clientTargetCacheSize) ? Error::NONE
+                                                                             : Error::BAD_PARAMETER;
+    }
+
+    Error addLayer(Display display, Layer layer, uint32_t bufferCacheSize) {
+        auto layerResource = createLayerResource(bufferCacheSize);
+
+        std::lock_guard<std::mutex> lock(mDisplayResourcesMutex);
+        ComposerDisplayResource* displayResource = findDisplayResourceLocked(display);
+        if (!displayResource) {
+            return Error::BAD_DISPLAY;
+        }
+
+        return displayResource->addLayer(layer, std::move(layerResource)) ? Error::NONE
+                                                                          : Error::BAD_LAYER;
+    }
+
+    Error removeLayer(Display display, Layer layer) {
+        std::lock_guard<std::mutex> lock(mDisplayResourcesMutex);
+        ComposerDisplayResource* displayResource = findDisplayResourceLocked(display);
+        if (!displayResource) {
+            return Error::BAD_DISPLAY;
+        }
+
+        return displayResource->removeLayer(layer) ? Error::NONE : Error::BAD_LAYER;
+    }
+
+    using ReplacedBufferHandle = ReplacedHandle<true>;
+    using ReplacedStreamHandle = ReplacedHandle<false>;
+
+    Error getDisplayClientTarget(Display display, uint32_t slot, bool fromCache,
+                                 const native_handle_t* rawHandle,
+                                 const native_handle_t** outBufferHandle,
+                                 ReplacedBufferHandle* outReplacedBuffer) {
+        return getHandle<Cache::CLIENT_TARGET>(display, 0, slot, fromCache, rawHandle,
+                                               outBufferHandle, outReplacedBuffer);
+    }
+
+    Error getDisplayOutputBuffer(Display display, uint32_t slot, bool fromCache,
+                                 const native_handle_t* rawHandle,
+                                 const native_handle_t** outBufferHandle,
+                                 ReplacedBufferHandle* outReplacedBuffer) {
+        return getHandle<Cache::OUTPUT_BUFFER>(display, 0, slot, fromCache, rawHandle,
+                                               outBufferHandle, outReplacedBuffer);
+    }
+
+    Error getLayerBuffer(Display display, Layer layer, uint32_t slot, bool fromCache,
+                         const native_handle_t* rawHandle, const native_handle_t** outBufferHandle,
+                         ReplacedBufferHandle* outReplacedBuffer) {
+        return getHandle<Cache::LAYER_BUFFER>(display, layer, slot, fromCache, rawHandle,
+                                              outBufferHandle, outReplacedBuffer);
+    }
+
+    Error getLayerSidebandStream(Display display, Layer layer, const native_handle_t* rawHandle,
+                                 const native_handle_t** outStreamHandle,
+                                 ReplacedStreamHandle* outReplacedStream) {
+        return getHandle<Cache::LAYER_SIDEBAND_STREAM>(display, layer, 0, false, rawHandle,
+                                                       outStreamHandle, outReplacedStream);
+    }
+
+   protected:
+    virtual std::unique_ptr<ComposerDisplayResource> createDisplayResource(
+        ComposerDisplayResource::DisplayType type, uint32_t outputBufferCacheSize) {
+        return std::make_unique<ComposerDisplayResource>(type, mImporter, outputBufferCacheSize);
+    }
+
+    virtual std::unique_ptr<ComposerLayerResource> createLayerResource(uint32_t bufferCacheSize) {
+        return std::make_unique<ComposerLayerResource>(mImporter, bufferCacheSize);
+    }
+
+    ComposerDisplayResource* findDisplayResourceLocked(Display display) {
+        auto iter = mDisplayResources.find(display);
+        if (iter == mDisplayResources.end()) {
+            return nullptr;
+        }
+        return iter->second.get();
+    }
+
+    ComposerHandleImporter mImporter;
+
+    std::mutex mDisplayResourcesMutex;
+    std::unordered_map<Display, std::unique_ptr<ComposerDisplayResource>> mDisplayResources;
+
+   private:
+    enum class Cache {
+        CLIENT_TARGET,
+        OUTPUT_BUFFER,
+        LAYER_BUFFER,
+        LAYER_SIDEBAND_STREAM,
+    };
+
+    // When a buffer in the cache is replaced by a new one, we must keep it
+    // alive until it has been replaced in ComposerHal.
+    template <bool isBuffer>
+    class ReplacedHandle {
+       public:
+        ReplacedHandle() = default;
+        ReplacedHandle(const ReplacedHandle&) = delete;
+        ReplacedHandle& operator=(const ReplacedHandle&) = delete;
+
+        ~ReplacedHandle() { reset(); }
+
+        void reset(ComposerHandleImporter* importer = nullptr,
+                   const native_handle_t* handle = nullptr) {
+            if (mHandle) {
+                if (isBuffer) {
+                    mImporter->freeBuffer(mHandle);
+                } else {
+                    mImporter->freeStream(mHandle);
+                }
+            }
+
+            mImporter = importer;
+            mHandle = handle;
+        }
+
+       private:
+        ComposerHandleImporter* mImporter = nullptr;
+        const native_handle_t* mHandle = nullptr;
+    };
+
+    template <Cache cache, bool isBuffer>
+    Error getHandle(Display display, Layer layer, uint32_t slot, bool fromCache,
+                    const native_handle_t* rawHandle, const native_handle_t** outHandle,
+                    ReplacedHandle<isBuffer>* outReplacedHandle) {
+        Error error;
+
+        // import the raw handle (or ignore raw handle when fromCache is true)
+        const native_handle_t* importedHandle = nullptr;
+        if (!fromCache) {
+            error = (isBuffer) ? mImporter.importBuffer(rawHandle, &importedHandle)
+                               : mImporter.importStream(rawHandle, &importedHandle);
+            if (error != Error::NONE) {
+                return error;
+            }
+        }
+
+        std::lock_guard<std::mutex> lock(mDisplayResourcesMutex);
+
+        // find display/layer resource
+        const bool needLayerResource =
+            (cache == Cache::LAYER_BUFFER || cache == Cache::LAYER_SIDEBAND_STREAM);
+        ComposerDisplayResource* displayResource = findDisplayResourceLocked(display);
+        ComposerLayerResource* layerResource = (displayResource && needLayerResource)
+                                                   ? displayResource->findLayerResource(layer)
+                                                   : nullptr;
+
+        // lookup or update cache
+        const native_handle_t* replacedHandle = nullptr;
+        if (displayResource && (!needLayerResource || layerResource)) {
+            switch (cache) {
+                case Cache::CLIENT_TARGET:
+                    error = displayResource->getClientTarget(slot, fromCache, importedHandle,
+                                                             outHandle, &replacedHandle);
+                    break;
+                case Cache::OUTPUT_BUFFER:
+                    error = displayResource->getOutputBuffer(slot, fromCache, importedHandle,
+                                                             outHandle, &replacedHandle);
+                    break;
+                case Cache::LAYER_BUFFER:
+                    error = layerResource->getBuffer(slot, fromCache, importedHandle, outHandle,
+                                                     &replacedHandle);
+                    break;
+                case Cache::LAYER_SIDEBAND_STREAM:
+                    error = layerResource->getSidebandStream(slot, fromCache, importedHandle,
+                                                             outHandle, &replacedHandle);
+                    break;
+                default:
+                    error = Error::BAD_PARAMETER;
+                    break;
+            }
+
+            if (error != Error::NONE) {
+                ALOGW("invalid cache %d slot %d", int(cache), int(slot));
+            }
+        } else if (!displayResource) {
+            error = Error::BAD_DISPLAY;
+        } else {
+            error = Error::BAD_LAYER;
+        }
+
+        // clean up on errors
+        if (error != Error::NONE) {
+            if (!fromCache) {
+                if (isBuffer) {
+                    mImporter.freeBuffer(importedHandle);
+                } else {
+                    mImporter.freeStream(importedHandle);
+                }
+            }
+            return error;
+        }
+
+        outReplacedHandle->reset(&mImporter, replacedHandle);
+
+        return Error::NONE;
+    }
+};
+
+}  // namespace hal
+}  // namespace V2_1
+}  // namespace composer
+}  // namespace graphics
+}  // namespace hardware
+}  // namespace android
diff --git a/graphics/composer/2.1/utils/hwc2on1adapter/Android.bp b/graphics/composer/2.1/utils/hwc2on1adapter/Android.bp
new file mode 100644
index 0000000..420a1f6
--- /dev/null
+++ b/graphics/composer/2.1/utils/hwc2on1adapter/Android.bp
@@ -0,0 +1,76 @@
+// Copyright 2010 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.
+
+cc_library_shared {
+    name: "libhwc2on1adapter",
+    vendor: true,
+
+    clang: true,
+    cflags: [
+        "-Wall",
+        "-Werror",
+        "-Wno-user-defined-warnings",
+    ],
+    cppflags: [
+        "-Weverything",
+        "-Wunused",
+        "-Wunreachable-code",
+
+        // The static constructors and destructors in this library have not been noted to
+        // introduce significant overheads
+        "-Wno-exit-time-destructors",
+        "-Wno-global-constructors",
+
+        // We only care about compiling as C++14
+        "-Wno-c++98-compat-pedantic",
+
+        // android/sensors.h uses nested anonymous unions and anonymous structs
+        "-Wno-nested-anon-types",
+        "-Wno-gnu-anonymous-struct",
+
+        // Don't warn about struct padding
+        "-Wno-padded",
+
+        // hwcomposer2.h features switch covering all cases.
+        "-Wno-covered-switch-default",
+
+        // hwcomposer.h features zero size array.
+        "-Wno-zero-length-array",
+
+        // Disabling warning specific to hwc2on1adapter code
+        "-Wno-double-promotion",
+        "-Wno-sign-conversion",
+        "-Wno-switch-enum",
+        "-Wno-float-equal",
+        "-Wno-shorten-64-to-32",
+        "-Wno-sign-compare",
+        "-Wno-missing-prototypes",
+    ],
+
+    srcs: [
+        "HWC2On1Adapter.cpp",
+        "MiniFence.cpp",
+    ],
+
+    shared_libs: [
+        "libutils",
+        "libcutils",
+        "liblog",
+        "libhardware",
+    ],
+
+    export_include_dirs: ["include"],
+
+    export_shared_lib_headers: ["libutils"],
+}
diff --git a/graphics/composer/2.1/utils/hwc2on1adapter/CleanSpec.mk b/graphics/composer/2.1/utils/hwc2on1adapter/CleanSpec.mk
new file mode 100644
index 0000000..7fc2216
--- /dev/null
+++ b/graphics/composer/2.1/utils/hwc2on1adapter/CleanSpec.mk
@@ -0,0 +1,52 @@
+# Copyright (C) 2017 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.
+#
+
+# If you don't need to do a full clean build but would like to touch
+# a file or delete some intermediate files, add a clean step to the end
+# of the list.  These steps will only be run once, if they haven't been
+# run before.
+#
+# E.g.:
+#     $(call add-clean-step, touch -c external/sqlite/sqlite3.h)
+#     $(call add-clean-step, rm -rf $(PRODUCT_OUT)/obj/STATIC_LIBRARIES/libz_intermediates)
+#
+# Always use "touch -c" and "rm -f" or "rm -rf" to gracefully deal with
+# files that are missing or have been moved.
+#
+# Use $(PRODUCT_OUT) to get to the "out/target/product/blah/" directory.
+# Use $(OUT_DIR) to refer to the "out" directory.
+#
+# If you need to re-do something that's already mentioned, just copy
+# the command and add it to the bottom of the list.  E.g., if a change
+# that you made last week required touching a file and a change you
+# made today requires touching the same file, just copy the old
+# touch step and add it to the end of the list.
+#
+# ************************************************
+# NEWER CLEAN STEPS MUST BE AT THE END OF THE LIST
+# ************************************************
+
+# For example:
+#$(call add-clean-step, rm -rf $(OUT_DIR)/target/common/obj/APPS/AndroidTests_intermediates)
+#$(call add-clean-step, rm -rf $(OUT_DIR)/target/common/obj/JAVA_LIBRARIES/core_intermediates)
+#$(call add-clean-step, find $(OUT_DIR) -type f -name "IGTalkSession*" -print0 | xargs -0 rm -f)
+#$(call add-clean-step, rm -rf $(PRODUCT_OUT)/data/*)
+
+# ************************************************
+# NEWER CLEAN STEPS MUST BE AT THE END OF THE LIST
+# ************************************************
+$(call add-clean-step, rm -rf $(PRODUCT_OUT)/obj/SHARED_LIBRARIES/libhwc2on1adapter_intermediates)
+$(call add-clean-step, rm -rf $(PRODUCT_OUT)/system/lib/libhwc2on1adapter.so)
+$(call add-clean-step, rm -rf $(PRODUCT_OUT)/system/lib64/libhwc2on1adapter.so)
diff --git a/graphics/composer/2.1/utils/hwc2on1adapter/HWC2On1Adapter.cpp b/graphics/composer/2.1/utils/hwc2on1adapter/HWC2On1Adapter.cpp
new file mode 100644
index 0000000..77f06bb
--- /dev/null
+++ b/graphics/composer/2.1/utils/hwc2on1adapter/HWC2On1Adapter.cpp
@@ -0,0 +1,2637 @@
+/*
+ * Copyright 2015 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 "hwc2on1adapter/HWC2On1Adapter.h"
+
+//#define LOG_NDEBUG 0
+
+#undef LOG_TAG
+#define LOG_TAG "HWC2On1Adapter"
+#define ATRACE_TAG ATRACE_TAG_GRAPHICS
+
+
+#include <inttypes.h>
+
+#include <chrono>
+#include <cstdlib>
+#include <sstream>
+
+#include <hardware/hwcomposer.h>
+#include <log/log.h>
+#include <utils/Trace.h>
+
+using namespace std::chrono_literals;
+
+static uint8_t getMinorVersion(struct hwc_composer_device_1* device)
+{
+    auto version = device->common.version & HARDWARE_API_VERSION_2_MAJ_MIN_MASK;
+    return (version >> 16) & 0xF;
+}
+
+template <typename PFN, typename T>
+static hwc2_function_pointer_t asFP(T function)
+{
+    static_assert(std::is_same<PFN, T>::value, "Incompatible function pointer");
+    return reinterpret_cast<hwc2_function_pointer_t>(function);
+}
+
+using namespace HWC2;
+
+static constexpr Attribute ColorMode = static_cast<Attribute>(6);
+
+namespace android {
+
+class HWC2On1Adapter::Callbacks : public hwc_procs_t {
+    public:
+        explicit Callbacks(HWC2On1Adapter& adapter) : mAdapter(adapter) {
+            invalidate = &invalidateHook;
+            vsync = &vsyncHook;
+            hotplug = &hotplugHook;
+        }
+
+        static void invalidateHook(const hwc_procs_t* procs) {
+            auto callbacks = static_cast<const Callbacks*>(procs);
+            callbacks->mAdapter.hwc1Invalidate();
+        }
+
+        static void vsyncHook(const hwc_procs_t* procs, int display,
+                int64_t timestamp) {
+            auto callbacks = static_cast<const Callbacks*>(procs);
+            callbacks->mAdapter.hwc1Vsync(display, timestamp);
+        }
+
+        static void hotplugHook(const hwc_procs_t* procs, int display,
+                int connected) {
+            auto callbacks = static_cast<const Callbacks*>(procs);
+            callbacks->mAdapter.hwc1Hotplug(display, connected);
+        }
+
+    private:
+        HWC2On1Adapter& mAdapter;
+};
+
+static int closeHook(hw_device_t* /*device*/)
+{
+    // Do nothing, since the real work is done in the class destructor, but we
+    // need to provide a valid function pointer for hwc2_close to call
+    return 0;
+}
+
+HWC2On1Adapter::HWC2On1Adapter(hwc_composer_device_1_t* hwc1Device)
+  : mDumpString(),
+    mHwc1Device(hwc1Device),
+    mHwc1MinorVersion(getMinorVersion(hwc1Device)),
+    mHwc1SupportsVirtualDisplays(false),
+    mHwc1SupportsBackgroundColor(false),
+    mHwc1Callbacks(std::make_unique<Callbacks>(*this)),
+    mCapabilities(),
+    mLayers(),
+    mHwc1VirtualDisplay(),
+    mStateMutex(),
+    mCallbacks(),
+    mHasPendingInvalidate(false),
+    mPendingVsyncs(),
+    mPendingHotplugs(),
+    mDisplays(),
+    mHwc1DisplayMap()
+{
+    common.close = closeHook;
+    getCapabilities = getCapabilitiesHook;
+    getFunction = getFunctionHook;
+    populateCapabilities();
+    populatePrimary();
+    mHwc1Device->registerProcs(mHwc1Device,
+            static_cast<const hwc_procs_t*>(mHwc1Callbacks.get()));
+}
+
+HWC2On1Adapter::~HWC2On1Adapter() {
+    hwc_close_1(mHwc1Device);
+}
+
+void HWC2On1Adapter::doGetCapabilities(uint32_t* outCount,
+        int32_t* outCapabilities) {
+    if (outCapabilities == nullptr) {
+        *outCount = mCapabilities.size();
+        return;
+    }
+
+    auto capabilityIter = mCapabilities.cbegin();
+    for (size_t written = 0; written < *outCount; ++written) {
+        if (capabilityIter == mCapabilities.cend()) {
+            return;
+        }
+        outCapabilities[written] = static_cast<int32_t>(*capabilityIter);
+        ++capabilityIter;
+    }
+}
+
+hwc2_function_pointer_t HWC2On1Adapter::doGetFunction(
+        FunctionDescriptor descriptor) {
+    switch (descriptor) {
+        // Device functions
+        case FunctionDescriptor::CreateVirtualDisplay:
+            return asFP<HWC2_PFN_CREATE_VIRTUAL_DISPLAY>(
+                    createVirtualDisplayHook);
+        case FunctionDescriptor::DestroyVirtualDisplay:
+            return asFP<HWC2_PFN_DESTROY_VIRTUAL_DISPLAY>(
+                    destroyVirtualDisplayHook);
+        case FunctionDescriptor::Dump:
+            return asFP<HWC2_PFN_DUMP>(dumpHook);
+        case FunctionDescriptor::GetMaxVirtualDisplayCount:
+            return asFP<HWC2_PFN_GET_MAX_VIRTUAL_DISPLAY_COUNT>(
+                    getMaxVirtualDisplayCountHook);
+        case FunctionDescriptor::RegisterCallback:
+            return asFP<HWC2_PFN_REGISTER_CALLBACK>(registerCallbackHook);
+
+        // Display functions
+        case FunctionDescriptor::AcceptDisplayChanges:
+            return asFP<HWC2_PFN_ACCEPT_DISPLAY_CHANGES>(
+                    displayHook<decltype(&Display::acceptChanges),
+                    &Display::acceptChanges>);
+        case FunctionDescriptor::CreateLayer:
+            return asFP<HWC2_PFN_CREATE_LAYER>(
+                    displayHook<decltype(&Display::createLayer),
+                    &Display::createLayer, hwc2_layer_t*>);
+        case FunctionDescriptor::DestroyLayer:
+            return asFP<HWC2_PFN_DESTROY_LAYER>(
+                    displayHook<decltype(&Display::destroyLayer),
+                    &Display::destroyLayer, hwc2_layer_t>);
+        case FunctionDescriptor::GetActiveConfig:
+            return asFP<HWC2_PFN_GET_ACTIVE_CONFIG>(
+                    displayHook<decltype(&Display::getActiveConfig),
+                    &Display::getActiveConfig, hwc2_config_t*>);
+        case FunctionDescriptor::GetChangedCompositionTypes:
+            return asFP<HWC2_PFN_GET_CHANGED_COMPOSITION_TYPES>(
+                    displayHook<decltype(&Display::getChangedCompositionTypes),
+                    &Display::getChangedCompositionTypes, uint32_t*,
+                    hwc2_layer_t*, int32_t*>);
+        case FunctionDescriptor::GetColorModes:
+            return asFP<HWC2_PFN_GET_COLOR_MODES>(
+                    displayHook<decltype(&Display::getColorModes),
+                    &Display::getColorModes, uint32_t*, int32_t*>);
+        case FunctionDescriptor::GetDisplayAttribute:
+            return asFP<HWC2_PFN_GET_DISPLAY_ATTRIBUTE>(
+                    getDisplayAttributeHook);
+        case FunctionDescriptor::GetDisplayConfigs:
+            return asFP<HWC2_PFN_GET_DISPLAY_CONFIGS>(
+                    displayHook<decltype(&Display::getConfigs),
+                    &Display::getConfigs, uint32_t*, hwc2_config_t*>);
+        case FunctionDescriptor::GetDisplayName:
+            return asFP<HWC2_PFN_GET_DISPLAY_NAME>(
+                    displayHook<decltype(&Display::getName),
+                    &Display::getName, uint32_t*, char*>);
+        case FunctionDescriptor::GetDisplayRequests:
+            return asFP<HWC2_PFN_GET_DISPLAY_REQUESTS>(
+                    displayHook<decltype(&Display::getRequests),
+                    &Display::getRequests, int32_t*, uint32_t*, hwc2_layer_t*,
+                    int32_t*>);
+        case FunctionDescriptor::GetDisplayType:
+            return asFP<HWC2_PFN_GET_DISPLAY_TYPE>(
+                    displayHook<decltype(&Display::getType),
+                    &Display::getType, int32_t*>);
+        case FunctionDescriptor::GetDozeSupport:
+            return asFP<HWC2_PFN_GET_DOZE_SUPPORT>(
+                    displayHook<decltype(&Display::getDozeSupport),
+                    &Display::getDozeSupport, int32_t*>);
+        case FunctionDescriptor::GetHdrCapabilities:
+            return asFP<HWC2_PFN_GET_HDR_CAPABILITIES>(
+                    displayHook<decltype(&Display::getHdrCapabilities),
+                    &Display::getHdrCapabilities, uint32_t*, int32_t*, float*,
+                    float*, float*>);
+        case FunctionDescriptor::GetReleaseFences:
+            return asFP<HWC2_PFN_GET_RELEASE_FENCES>(
+                    displayHook<decltype(&Display::getReleaseFences),
+                    &Display::getReleaseFences, uint32_t*, hwc2_layer_t*,
+                    int32_t*>);
+        case FunctionDescriptor::PresentDisplay:
+            return asFP<HWC2_PFN_PRESENT_DISPLAY>(
+                    displayHook<decltype(&Display::present),
+                    &Display::present, int32_t*>);
+        case FunctionDescriptor::SetActiveConfig:
+            return asFP<HWC2_PFN_SET_ACTIVE_CONFIG>(
+                    displayHook<decltype(&Display::setActiveConfig),
+                    &Display::setActiveConfig, hwc2_config_t>);
+        case FunctionDescriptor::SetClientTarget:
+            return asFP<HWC2_PFN_SET_CLIENT_TARGET>(
+                    displayHook<decltype(&Display::setClientTarget),
+                    &Display::setClientTarget, buffer_handle_t, int32_t,
+                    int32_t, hwc_region_t>);
+        case FunctionDescriptor::SetColorMode:
+            return asFP<HWC2_PFN_SET_COLOR_MODE>(setColorModeHook);
+        case FunctionDescriptor::SetColorTransform:
+            return asFP<HWC2_PFN_SET_COLOR_TRANSFORM>(setColorTransformHook);
+        case FunctionDescriptor::SetOutputBuffer:
+            return asFP<HWC2_PFN_SET_OUTPUT_BUFFER>(
+                    displayHook<decltype(&Display::setOutputBuffer),
+                    &Display::setOutputBuffer, buffer_handle_t, int32_t>);
+        case FunctionDescriptor::SetPowerMode:
+            return asFP<HWC2_PFN_SET_POWER_MODE>(setPowerModeHook);
+        case FunctionDescriptor::SetVsyncEnabled:
+            return asFP<HWC2_PFN_SET_VSYNC_ENABLED>(setVsyncEnabledHook);
+        case FunctionDescriptor::ValidateDisplay:
+            return asFP<HWC2_PFN_VALIDATE_DISPLAY>(
+                    displayHook<decltype(&Display::validate),
+                    &Display::validate, uint32_t*, uint32_t*>);
+        case FunctionDescriptor::GetClientTargetSupport:
+            return asFP<HWC2_PFN_GET_CLIENT_TARGET_SUPPORT>(
+                    displayHook<decltype(&Display::getClientTargetSupport),
+                    &Display::getClientTargetSupport, uint32_t, uint32_t,
+                                                      int32_t, int32_t>);
+
+        // Layer functions
+        case FunctionDescriptor::SetCursorPosition:
+            return asFP<HWC2_PFN_SET_CURSOR_POSITION>(
+                    layerHook<decltype(&Layer::setCursorPosition),
+                    &Layer::setCursorPosition, int32_t, int32_t>);
+        case FunctionDescriptor::SetLayerBuffer:
+            return asFP<HWC2_PFN_SET_LAYER_BUFFER>(
+                    layerHook<decltype(&Layer::setBuffer), &Layer::setBuffer,
+                    buffer_handle_t, int32_t>);
+        case FunctionDescriptor::SetLayerSurfaceDamage:
+            return asFP<HWC2_PFN_SET_LAYER_SURFACE_DAMAGE>(
+                    layerHook<decltype(&Layer::setSurfaceDamage),
+                    &Layer::setSurfaceDamage, hwc_region_t>);
+
+        // Layer state functions
+        case FunctionDescriptor::SetLayerBlendMode:
+            return asFP<HWC2_PFN_SET_LAYER_BLEND_MODE>(
+                    setLayerBlendModeHook);
+        case FunctionDescriptor::SetLayerColor:
+            return asFP<HWC2_PFN_SET_LAYER_COLOR>(
+                    layerHook<decltype(&Layer::setColor), &Layer::setColor,
+                    hwc_color_t>);
+        case FunctionDescriptor::SetLayerCompositionType:
+            return asFP<HWC2_PFN_SET_LAYER_COMPOSITION_TYPE>(
+                    setLayerCompositionTypeHook);
+        case FunctionDescriptor::SetLayerDataspace:
+            return asFP<HWC2_PFN_SET_LAYER_DATASPACE>(setLayerDataspaceHook);
+        case FunctionDescriptor::SetLayerDisplayFrame:
+            return asFP<HWC2_PFN_SET_LAYER_DISPLAY_FRAME>(
+                    layerHook<decltype(&Layer::setDisplayFrame),
+                    &Layer::setDisplayFrame, hwc_rect_t>);
+        case FunctionDescriptor::SetLayerPlaneAlpha:
+            return asFP<HWC2_PFN_SET_LAYER_PLANE_ALPHA>(
+                    layerHook<decltype(&Layer::setPlaneAlpha),
+                    &Layer::setPlaneAlpha, float>);
+        case FunctionDescriptor::SetLayerSidebandStream:
+            return asFP<HWC2_PFN_SET_LAYER_SIDEBAND_STREAM>(
+                    layerHook<decltype(&Layer::setSidebandStream),
+                    &Layer::setSidebandStream, const native_handle_t*>);
+        case FunctionDescriptor::SetLayerSourceCrop:
+            return asFP<HWC2_PFN_SET_LAYER_SOURCE_CROP>(
+                    layerHook<decltype(&Layer::setSourceCrop),
+                    &Layer::setSourceCrop, hwc_frect_t>);
+        case FunctionDescriptor::SetLayerTransform:
+            return asFP<HWC2_PFN_SET_LAYER_TRANSFORM>(setLayerTransformHook);
+        case FunctionDescriptor::SetLayerVisibleRegion:
+            return asFP<HWC2_PFN_SET_LAYER_VISIBLE_REGION>(
+                    layerHook<decltype(&Layer::setVisibleRegion),
+                    &Layer::setVisibleRegion, hwc_region_t>);
+        case FunctionDescriptor::SetLayerZOrder:
+            return asFP<HWC2_PFN_SET_LAYER_Z_ORDER>(setLayerZOrderHook);
+
+        default:
+            ALOGE("doGetFunction: Unknown function descriptor: %d (%s)",
+                    static_cast<int32_t>(descriptor),
+                    to_string(descriptor).c_str());
+            return nullptr;
+    }
+}
+
+// Device functions
+
+Error HWC2On1Adapter::createVirtualDisplay(uint32_t width,
+        uint32_t height, hwc2_display_t* outDisplay) {
+    std::unique_lock<std::recursive_timed_mutex> lock(mStateMutex);
+
+    if (mHwc1VirtualDisplay) {
+        // We have already allocated our only HWC1 virtual display
+        ALOGE("createVirtualDisplay: HWC1 virtual display already allocated");
+        return Error::NoResources;
+    }
+
+    mHwc1VirtualDisplay = std::make_shared<HWC2On1Adapter::Display>(*this,
+            HWC2::DisplayType::Virtual);
+    mHwc1VirtualDisplay->populateConfigs(width, height);
+    const auto displayId = mHwc1VirtualDisplay->getId();
+    mHwc1DisplayMap[HWC_DISPLAY_VIRTUAL] = displayId;
+    mHwc1VirtualDisplay->setHwc1Id(HWC_DISPLAY_VIRTUAL);
+    mDisplays.emplace(displayId, mHwc1VirtualDisplay);
+    *outDisplay = displayId;
+
+    return Error::None;
+}
+
+Error HWC2On1Adapter::destroyVirtualDisplay(hwc2_display_t displayId) {
+    std::unique_lock<std::recursive_timed_mutex> lock(mStateMutex);
+
+    if (!mHwc1VirtualDisplay || (mHwc1VirtualDisplay->getId() != displayId)) {
+        return Error::BadDisplay;
+    }
+
+    mHwc1VirtualDisplay.reset();
+    mHwc1DisplayMap.erase(HWC_DISPLAY_VIRTUAL);
+    mDisplays.erase(displayId);
+
+    return Error::None;
+}
+
+void HWC2On1Adapter::dump(uint32_t* outSize, char* outBuffer) {
+    if (outBuffer != nullptr) {
+        auto copiedBytes = mDumpString.copy(outBuffer, *outSize);
+        *outSize = static_cast<uint32_t>(copiedBytes);
+        return;
+    }
+
+    std::stringstream output;
+
+    output << "-- HWC2On1Adapter --\n";
+
+    output << "Adapting to a HWC 1." << static_cast<int>(mHwc1MinorVersion) <<
+            " device\n";
+
+    // Attempt to acquire the lock for 1 second, but proceed without the lock
+    // after that, so we can still get some information if we're deadlocked
+    std::unique_lock<std::recursive_timed_mutex> lock(mStateMutex,
+            std::defer_lock);
+    lock.try_lock_for(1s);
+
+    if (mCapabilities.empty()) {
+        output << "Capabilities: None\n";
+    } else {
+        output << "Capabilities:\n";
+        for (auto capability : mCapabilities) {
+            output << "  " << to_string(capability) << '\n';
+        }
+    }
+
+    output << "Displays:\n";
+    for (const auto& element : mDisplays) {
+        const auto& display = element.second;
+        output << display->dump();
+    }
+    output << '\n';
+
+    // Release the lock before calling into HWC1, and since we no longer require
+    // mutual exclusion to access mCapabilities or mDisplays
+    lock.unlock();
+
+    if (mHwc1Device->dump) {
+        output << "HWC1 dump:\n";
+        std::vector<char> hwc1Dump(4096);
+        // Call with size - 1 to preserve a null character at the end
+        mHwc1Device->dump(mHwc1Device, hwc1Dump.data(),
+                static_cast<int>(hwc1Dump.size() - 1));
+        output << hwc1Dump.data();
+    }
+
+    mDumpString = output.str();
+    *outSize = static_cast<uint32_t>(mDumpString.size());
+}
+
+uint32_t HWC2On1Adapter::getMaxVirtualDisplayCount() {
+    return mHwc1SupportsVirtualDisplays ? 1 : 0;
+}
+
+static bool isValid(Callback descriptor) {
+    switch (descriptor) {
+        case Callback::Hotplug: // Fall-through
+        case Callback::Refresh: // Fall-through
+        case Callback::Vsync: return true;
+        default: return false;
+    }
+}
+
+Error HWC2On1Adapter::registerCallback(Callback descriptor,
+        hwc2_callback_data_t callbackData, hwc2_function_pointer_t pointer) {
+    if (!isValid(descriptor)) {
+        return Error::BadParameter;
+    }
+
+    ALOGV("registerCallback(%s, %p, %p)", to_string(descriptor).c_str(),
+            callbackData, pointer);
+
+    std::unique_lock<std::recursive_timed_mutex> lock(mStateMutex);
+
+    if (pointer != nullptr) {
+        mCallbacks[descriptor] = {callbackData, pointer};
+    } else {
+        ALOGI("unregisterCallback(%s)", to_string(descriptor).c_str());
+        mCallbacks.erase(descriptor);
+        return Error::None;
+    }
+
+    bool hasPendingInvalidate = false;
+    std::vector<hwc2_display_t> displayIds;
+    std::vector<std::pair<hwc2_display_t, int64_t>> pendingVsyncs;
+    std::vector<std::pair<hwc2_display_t, int>> pendingHotplugs;
+
+    if (descriptor == Callback::Refresh) {
+        hasPendingInvalidate = mHasPendingInvalidate;
+        if (hasPendingInvalidate) {
+            for (auto& displayPair : mDisplays) {
+                displayIds.emplace_back(displayPair.first);
+            }
+        }
+        mHasPendingInvalidate = false;
+    } else if (descriptor == Callback::Vsync) {
+        for (auto pending : mPendingVsyncs) {
+            auto hwc1DisplayId = pending.first;
+            if (mHwc1DisplayMap.count(hwc1DisplayId) == 0) {
+                ALOGE("hwc1Vsync: Couldn't find display for HWC1 id %d",
+                        hwc1DisplayId);
+                continue;
+            }
+            auto displayId = mHwc1DisplayMap[hwc1DisplayId];
+            auto timestamp = pending.second;
+            pendingVsyncs.emplace_back(displayId, timestamp);
+        }
+        mPendingVsyncs.clear();
+    } else if (descriptor == Callback::Hotplug) {
+        // Hotplug the primary display
+        pendingHotplugs.emplace_back(mHwc1DisplayMap[HWC_DISPLAY_PRIMARY],
+                static_cast<int32_t>(Connection::Connected));
+
+        for (auto pending : mPendingHotplugs) {
+            auto hwc1DisplayId = pending.first;
+            if (mHwc1DisplayMap.count(hwc1DisplayId) == 0) {
+                ALOGE("hwc1Hotplug: Couldn't find display for HWC1 id %d",
+                        hwc1DisplayId);
+                continue;
+            }
+            auto displayId = mHwc1DisplayMap[hwc1DisplayId];
+            auto connected = pending.second;
+            pendingHotplugs.emplace_back(displayId, connected);
+        }
+    }
+
+    // Call pending callbacks without the state lock held
+    lock.unlock();
+
+    if (hasPendingInvalidate) {
+        auto refresh = reinterpret_cast<HWC2_PFN_REFRESH>(pointer);
+        for (auto displayId : displayIds) {
+            refresh(callbackData, displayId);
+        }
+    }
+    if (!pendingVsyncs.empty()) {
+        auto vsync = reinterpret_cast<HWC2_PFN_VSYNC>(pointer);
+        for (auto& pendingVsync : pendingVsyncs) {
+            vsync(callbackData, pendingVsync.first, pendingVsync.second);
+        }
+    }
+    if (!pendingHotplugs.empty()) {
+        auto hotplug = reinterpret_cast<HWC2_PFN_HOTPLUG>(pointer);
+        for (auto& pendingHotplug : pendingHotplugs) {
+            hotplug(callbackData, pendingHotplug.first, pendingHotplug.second);
+        }
+    }
+    return Error::None;
+}
+
+// Display functions
+
+std::atomic<hwc2_display_t> HWC2On1Adapter::Display::sNextId(1);
+
+HWC2On1Adapter::Display::Display(HWC2On1Adapter& device, HWC2::DisplayType type)
+  : mId(sNextId++),
+    mDevice(device),
+    mStateMutex(),
+    mHwc1RequestedContents(nullptr),
+    mRetireFence(),
+    mChanges(),
+    mHwc1Id(-1),
+    mConfigs(),
+    mActiveConfig(nullptr),
+    mActiveColorMode(static_cast<android_color_mode_t>(-1)),
+    mName(),
+    mType(type),
+    mPowerMode(PowerMode::Off),
+    mVsyncEnabled(Vsync::Invalid),
+    mClientTarget(),
+    mOutputBuffer(),
+    mHasColorTransform(false),
+    mLayers(),
+    mHwc1LayerMap(),
+    mNumAvailableRects(0),
+    mNextAvailableRect(nullptr),
+    mGeometryChanged(false)
+    {}
+
+Error HWC2On1Adapter::Display::acceptChanges() {
+    std::unique_lock<std::recursive_mutex> lock(mStateMutex);
+
+    if (!mChanges) {
+        ALOGV("[%" PRIu64 "] acceptChanges failed, not validated", mId);
+        return Error::NotValidated;
+    }
+
+    ALOGV("[%" PRIu64 "] acceptChanges", mId);
+
+    for (auto& change : mChanges->getTypeChanges()) {
+        auto layerId = change.first;
+        auto type = change.second;
+        if (mDevice.mLayers.count(layerId) == 0) {
+            // This should never happen but somehow does.
+            ALOGW("Cannot accept change for unknown layer (%" PRIu64 ")",
+                  layerId);
+            continue;
+        }
+        auto layer = mDevice.mLayers[layerId];
+        layer->setCompositionType(type);
+    }
+
+    mChanges->clearTypeChanges();
+
+    return Error::None;
+}
+
+Error HWC2On1Adapter::Display::createLayer(hwc2_layer_t* outLayerId) {
+    std::unique_lock<std::recursive_mutex> lock(mStateMutex);
+
+    auto layer = *mLayers.emplace(std::make_shared<Layer>(*this));
+    mDevice.mLayers.emplace(std::make_pair(layer->getId(), layer));
+    *outLayerId = layer->getId();
+    ALOGV("[%" PRIu64 "] created layer %" PRIu64, mId, *outLayerId);
+    markGeometryChanged();
+    return Error::None;
+}
+
+Error HWC2On1Adapter::Display::destroyLayer(hwc2_layer_t layerId) {
+    std::unique_lock<std::recursive_mutex> lock(mStateMutex);
+
+    const auto mapLayer = mDevice.mLayers.find(layerId);
+    if (mapLayer == mDevice.mLayers.end()) {
+        ALOGV("[%" PRIu64 "] destroyLayer(%" PRIu64 ") failed: no such layer",
+                mId, layerId);
+        return Error::BadLayer;
+    }
+    const auto layer = mapLayer->second;
+    mDevice.mLayers.erase(mapLayer);
+    const auto zRange = mLayers.equal_range(layer);
+    for (auto current = zRange.first; current != zRange.second; ++current) {
+        if (**current == *layer) {
+            current = mLayers.erase(current);
+            break;
+        }
+    }
+    ALOGV("[%" PRIu64 "] destroyed layer %" PRIu64, mId, layerId);
+    markGeometryChanged();
+    return Error::None;
+}
+
+Error HWC2On1Adapter::Display::getActiveConfig(hwc2_config_t* outConfig) {
+    std::unique_lock<std::recursive_mutex> lock(mStateMutex);
+
+    if (!mActiveConfig) {
+        ALOGV("[%" PRIu64 "] getActiveConfig --> %s", mId,
+                to_string(Error::BadConfig).c_str());
+        return Error::BadConfig;
+    }
+    auto configId = mActiveConfig->getId();
+    ALOGV("[%" PRIu64 "] getActiveConfig --> %u", mId, configId);
+    *outConfig = configId;
+    return Error::None;
+}
+
+Error HWC2On1Adapter::Display::getAttribute(hwc2_config_t configId,
+        Attribute attribute, int32_t* outValue) {
+    std::unique_lock<std::recursive_mutex> lock(mStateMutex);
+
+    if (configId > mConfigs.size() || !mConfigs[configId]->isOnDisplay(*this)) {
+        ALOGV("[%" PRIu64 "] getAttribute failed: bad config (%u)", mId,
+                configId);
+        return Error::BadConfig;
+    }
+    *outValue = mConfigs[configId]->getAttribute(attribute);
+    ALOGV("[%" PRIu64 "] getAttribute(%u, %s) --> %d", mId, configId,
+            to_string(attribute).c_str(), *outValue);
+    return Error::None;
+}
+
+Error HWC2On1Adapter::Display::getChangedCompositionTypes(
+        uint32_t* outNumElements, hwc2_layer_t* outLayers, int32_t* outTypes) {
+    std::unique_lock<std::recursive_mutex> lock(mStateMutex);
+
+    if (!mChanges) {
+        ALOGE("[%" PRIu64 "] getChangedCompositionTypes failed: not validated",
+                mId);
+        return Error::NotValidated;
+    }
+
+    if ((outLayers == nullptr) || (outTypes == nullptr)) {
+        *outNumElements = mChanges->getTypeChanges().size();
+        return Error::None;
+    }
+
+    uint32_t numWritten = 0;
+    for (const auto& element : mChanges->getTypeChanges()) {
+        if (numWritten == *outNumElements) {
+            break;
+        }
+        auto layerId = element.first;
+        auto intType = static_cast<int32_t>(element.second);
+        ALOGV("Adding %" PRIu64 " %s", layerId,
+                to_string(element.second).c_str());
+        outLayers[numWritten] = layerId;
+        outTypes[numWritten] = intType;
+        ++numWritten;
+    }
+    *outNumElements = numWritten;
+
+    return Error::None;
+}
+
+Error HWC2On1Adapter::Display::getColorModes(uint32_t* outNumModes,
+        int32_t* outModes) {
+    std::unique_lock<std::recursive_mutex> lock(mStateMutex);
+
+    if (!outModes) {
+        *outNumModes = mColorModes.size();
+        return Error::None;
+    }
+    uint32_t numModes = std::min(*outNumModes,
+            static_cast<uint32_t>(mColorModes.size()));
+    std::copy_n(mColorModes.cbegin(), numModes, outModes);
+    *outNumModes = numModes;
+    return Error::None;
+}
+
+Error HWC2On1Adapter::Display::getConfigs(uint32_t* outNumConfigs,
+        hwc2_config_t* outConfigs) {
+    std::unique_lock<std::recursive_mutex> lock(mStateMutex);
+
+    if (!outConfigs) {
+        *outNumConfigs = mConfigs.size();
+        return Error::None;
+    }
+    uint32_t numWritten = 0;
+    for (const auto& config : mConfigs) {
+        if (numWritten == *outNumConfigs) {
+            break;
+        }
+        outConfigs[numWritten] = config->getId();
+        ++numWritten;
+    }
+    *outNumConfigs = numWritten;
+    return Error::None;
+}
+
+Error HWC2On1Adapter::Display::getDozeSupport(int32_t* outSupport) {
+    std::unique_lock<std::recursive_mutex> lock(mStateMutex);
+
+    if (mDevice.mHwc1MinorVersion < 4 || mHwc1Id != 0) {
+        *outSupport = 0;
+    } else {
+        *outSupport = 1;
+    }
+    return Error::None;
+}
+
+Error HWC2On1Adapter::Display::getHdrCapabilities(uint32_t* outNumTypes,
+        int32_t* /*outTypes*/, float* /*outMaxLuminance*/,
+        float* /*outMaxAverageLuminance*/, float* /*outMinLuminance*/) {
+    // This isn't supported on HWC1, so per the HWC2 header, return numTypes = 0
+    *outNumTypes = 0;
+    return Error::None;
+}
+
+Error HWC2On1Adapter::Display::getName(uint32_t* outSize, char* outName) {
+    std::unique_lock<std::recursive_mutex> lock(mStateMutex);
+
+    if (!outName) {
+        *outSize = mName.size();
+        return Error::None;
+    }
+    auto numCopied = mName.copy(outName, *outSize);
+    *outSize = numCopied;
+    return Error::None;
+}
+
+Error HWC2On1Adapter::Display::getReleaseFences(uint32_t* outNumElements,
+        hwc2_layer_t* outLayers, int32_t* outFences) {
+    std::unique_lock<std::recursive_mutex> lock(mStateMutex);
+
+    uint32_t numWritten = 0;
+    bool outputsNonNull = (outLayers != nullptr) && (outFences != nullptr);
+    for (const auto& layer : mLayers) {
+        if (outputsNonNull && (numWritten == *outNumElements)) {
+            break;
+        }
+
+        auto releaseFence = layer->getReleaseFence();
+        if (releaseFence != MiniFence::NO_FENCE) {
+            if (outputsNonNull) {
+                outLayers[numWritten] = layer->getId();
+                outFences[numWritten] = releaseFence->dup();
+            }
+            ++numWritten;
+        }
+    }
+    *outNumElements = numWritten;
+
+    return Error::None;
+}
+
+Error HWC2On1Adapter::Display::getRequests(int32_t* outDisplayRequests,
+        uint32_t* outNumElements, hwc2_layer_t* outLayers,
+        int32_t* outLayerRequests) {
+    std::unique_lock<std::recursive_mutex> lock(mStateMutex);
+
+    if (!mChanges) {
+        return Error::NotValidated;
+    }
+
+    if (outLayers == nullptr || outLayerRequests == nullptr) {
+        *outNumElements = mChanges->getNumLayerRequests();
+        return Error::None;
+    }
+
+    // Display requests (HWC2::DisplayRequest) are not supported by hwc1:
+    // A hwc1 has always zero requests for the client.
+    *outDisplayRequests = 0;
+
+    uint32_t numWritten = 0;
+    for (const auto& request : mChanges->getLayerRequests()) {
+        if (numWritten == *outNumElements) {
+            break;
+        }
+        outLayers[numWritten] = request.first;
+        outLayerRequests[numWritten] = static_cast<int32_t>(request.second);
+        ++numWritten;
+    }
+
+    return Error::None;
+}
+
+Error HWC2On1Adapter::Display::getType(int32_t* outType) {
+    std::unique_lock<std::recursive_mutex> lock(mStateMutex);
+
+    *outType = static_cast<int32_t>(mType);
+    return Error::None;
+}
+
+Error HWC2On1Adapter::Display::present(int32_t* outRetireFence) {
+    std::unique_lock<std::recursive_mutex> lock(mStateMutex);
+
+    if (mChanges) {
+        Error error = mDevice.setAllDisplays();
+        if (error != Error::None) {
+            ALOGE("[%" PRIu64 "] present: setAllDisplaysFailed (%s)", mId,
+                    to_string(error).c_str());
+            return error;
+        }
+    }
+
+    *outRetireFence = mRetireFence.get()->dup();
+    ALOGV("[%" PRIu64 "] present returning retire fence %d", mId,
+            *outRetireFence);
+
+    return Error::None;
+}
+
+Error HWC2On1Adapter::Display::setActiveConfig(hwc2_config_t configId) {
+    std::unique_lock<std::recursive_mutex> lock(mStateMutex);
+
+    auto config = getConfig(configId);
+    if (!config) {
+        return Error::BadConfig;
+    }
+    if (config == mActiveConfig) {
+        return Error::None;
+    }
+
+    if (mDevice.mHwc1MinorVersion >= 4) {
+        uint32_t hwc1Id = 0;
+        auto error = config->getHwc1IdForColorMode(mActiveColorMode, &hwc1Id);
+        if (error != Error::None) {
+            return error;
+        }
+
+        int intError = mDevice.mHwc1Device->setActiveConfig(mDevice.mHwc1Device,
+                mHwc1Id, static_cast<int>(hwc1Id));
+        if (intError != 0) {
+            ALOGE("setActiveConfig: Failed to set active config on HWC1 (%d)",
+                intError);
+            return Error::BadConfig;
+        }
+        mActiveConfig = config;
+    }
+
+    return Error::None;
+}
+
+Error HWC2On1Adapter::Display::setClientTarget(buffer_handle_t target,
+        int32_t acquireFence, int32_t /*dataspace*/, hwc_region_t /*damage*/) {
+    std::unique_lock<std::recursive_mutex> lock(mStateMutex);
+
+    ALOGV("[%" PRIu64 "] setClientTarget(%p, %d)", mId, target, acquireFence);
+    mClientTarget.setBuffer(target);
+    mClientTarget.setFence(acquireFence);
+    // dataspace and damage can't be used by HWC1, so ignore them
+    return Error::None;
+}
+
+Error HWC2On1Adapter::Display::setColorMode(android_color_mode_t mode) {
+    std::unique_lock<std::recursive_mutex> lock (mStateMutex);
+
+    ALOGV("[%" PRIu64 "] setColorMode(%d)", mId, mode);
+
+    if (mode == mActiveColorMode) {
+        return Error::None;
+    }
+    if (mColorModes.count(mode) == 0) {
+        ALOGE("[%" PRIu64 "] Mode %d not found in mColorModes", mId, mode);
+        return Error::Unsupported;
+    }
+
+    uint32_t hwc1Config = 0;
+    auto error = mActiveConfig->getHwc1IdForColorMode(mode, &hwc1Config);
+    if (error != Error::None) {
+        return error;
+    }
+
+    ALOGV("[%" PRIu64 "] Setting HWC1 config %u", mId, hwc1Config);
+    int intError = mDevice.mHwc1Device->setActiveConfig(mDevice.mHwc1Device,
+            mHwc1Id, hwc1Config);
+    if (intError != 0) {
+        ALOGE("[%" PRIu64 "] Failed to set HWC1 config (%d)", mId, intError);
+        return Error::Unsupported;
+    }
+
+    mActiveColorMode = mode;
+    return Error::None;
+}
+
+Error HWC2On1Adapter::Display::setColorTransform(android_color_transform_t hint) {
+    std::unique_lock<std::recursive_mutex> lock(mStateMutex);
+
+    ALOGV("%" PRIu64 "] setColorTransform(%d)", mId,
+            static_cast<int32_t>(hint));
+    mHasColorTransform = (hint != HAL_COLOR_TRANSFORM_IDENTITY);
+    return Error::None;
+}
+
+Error HWC2On1Adapter::Display::setOutputBuffer(buffer_handle_t buffer,
+        int32_t releaseFence) {
+    std::unique_lock<std::recursive_mutex> lock(mStateMutex);
+
+    ALOGV("[%" PRIu64 "] setOutputBuffer(%p, %d)", mId, buffer, releaseFence);
+    mOutputBuffer.setBuffer(buffer);
+    mOutputBuffer.setFence(releaseFence);
+    return Error::None;
+}
+
+static bool isValid(PowerMode mode) {
+    switch (mode) {
+        case PowerMode::Off: // Fall-through
+        case PowerMode::DozeSuspend: // Fall-through
+        case PowerMode::Doze: // Fall-through
+        case PowerMode::On: return true;
+    }
+}
+
+static int getHwc1PowerMode(PowerMode mode) {
+    switch (mode) {
+        case PowerMode::Off: return HWC_POWER_MODE_OFF;
+        case PowerMode::DozeSuspend: return HWC_POWER_MODE_DOZE_SUSPEND;
+        case PowerMode::Doze: return HWC_POWER_MODE_DOZE;
+        case PowerMode::On: return HWC_POWER_MODE_NORMAL;
+    }
+}
+
+Error HWC2On1Adapter::Display::setPowerMode(PowerMode mode) {
+    if (!isValid(mode)) {
+        return Error::BadParameter;
+    }
+    if (mode == mPowerMode) {
+        return Error::None;
+    }
+
+    std::unique_lock<std::recursive_mutex> lock(mStateMutex);
+
+    int error = 0;
+    if (mDevice.mHwc1MinorVersion < 4) {
+        error = mDevice.mHwc1Device->blank(mDevice.mHwc1Device, mHwc1Id,
+                mode == PowerMode::Off);
+    } else {
+        error = mDevice.mHwc1Device->setPowerMode(mDevice.mHwc1Device,
+                mHwc1Id, getHwc1PowerMode(mode));
+    }
+    ALOGE_IF(error != 0, "setPowerMode: Failed to set power mode on HWC1 (%d)",
+            error);
+
+    ALOGV("[%" PRIu64 "] setPowerMode(%s)", mId, to_string(mode).c_str());
+    mPowerMode = mode;
+    return Error::None;
+}
+
+static bool isValid(Vsync enable) {
+    switch (enable) {
+        case Vsync::Enable: // Fall-through
+        case Vsync::Disable: return true;
+        case Vsync::Invalid: return false;
+    }
+}
+
+Error HWC2On1Adapter::Display::setVsyncEnabled(Vsync enable) {
+    if (!isValid(enable)) {
+        return Error::BadParameter;
+    }
+    if (enable == mVsyncEnabled) {
+        return Error::None;
+    }
+
+    std::unique_lock<std::recursive_mutex> lock(mStateMutex);
+
+    int error = mDevice.mHwc1Device->eventControl(mDevice.mHwc1Device,
+            mHwc1Id, HWC_EVENT_VSYNC, enable == Vsync::Enable);
+    ALOGE_IF(error != 0, "setVsyncEnabled: Failed to set vsync on HWC1 (%d)",
+            error);
+
+    mVsyncEnabled = enable;
+    return Error::None;
+}
+
+Error HWC2On1Adapter::Display::validate(uint32_t* outNumTypes,
+        uint32_t* outNumRequests) {
+    std::unique_lock<std::recursive_mutex> lock(mStateMutex);
+
+    if (!mChanges) {
+        if (!mDevice.prepareAllDisplays()) {
+            return Error::BadDisplay;
+        }
+    } else {
+        ALOGE("Validate was called more than once!");
+    }
+
+    *outNumTypes = mChanges->getNumTypes();
+    *outNumRequests = mChanges->getNumLayerRequests();
+    ALOGV("[%" PRIu64 "] validate --> %u types, %u requests", mId, *outNumTypes,
+            *outNumRequests);
+    for (auto request : mChanges->getTypeChanges()) {
+        ALOGV("Layer %" PRIu64 " --> %s", request.first,
+                to_string(request.second).c_str());
+    }
+    return *outNumTypes > 0 ? Error::HasChanges : Error::None;
+}
+
+Error HWC2On1Adapter::Display::updateLayerZ(hwc2_layer_t layerId, uint32_t z) {
+    std::unique_lock<std::recursive_mutex> lock(mStateMutex);
+
+    const auto mapLayer = mDevice.mLayers.find(layerId);
+    if (mapLayer == mDevice.mLayers.end()) {
+        ALOGE("[%" PRIu64 "] updateLayerZ failed to find layer", mId);
+        return Error::BadLayer;
+    }
+
+    const auto layer = mapLayer->second;
+    const auto zRange = mLayers.equal_range(layer);
+    bool layerOnDisplay = false;
+    for (auto current = zRange.first; current != zRange.second; ++current) {
+        if (**current == *layer) {
+            if ((*current)->getZ() == z) {
+                // Don't change anything if the Z hasn't changed
+                return Error::None;
+            }
+            current = mLayers.erase(current);
+            layerOnDisplay = true;
+            break;
+        }
+    }
+
+    if (!layerOnDisplay) {
+        ALOGE("[%" PRIu64 "] updateLayerZ failed to find layer on display",
+                mId);
+        return Error::BadLayer;
+    }
+
+    layer->setZ(z);
+    mLayers.emplace(std::move(layer));
+    markGeometryChanged();
+
+    return Error::None;
+}
+
+Error HWC2On1Adapter::Display::getClientTargetSupport(uint32_t width, uint32_t height,
+                                      int32_t format, int32_t dataspace){
+    if (mActiveConfig == nullptr) {
+        return Error::Unsupported;
+    }
+
+    if (width == mActiveConfig->getAttribute(Attribute::Width) &&
+            height == mActiveConfig->getAttribute(Attribute::Height) &&
+            format == HAL_PIXEL_FORMAT_RGBA_8888 &&
+            dataspace == HAL_DATASPACE_UNKNOWN) {
+        return Error::None;
+    }
+
+    return Error::Unsupported;
+}
+
+static constexpr uint32_t ATTRIBUTES_WITH_COLOR[] = {
+    HWC_DISPLAY_VSYNC_PERIOD,
+    HWC_DISPLAY_WIDTH,
+    HWC_DISPLAY_HEIGHT,
+    HWC_DISPLAY_DPI_X,
+    HWC_DISPLAY_DPI_Y,
+    HWC_DISPLAY_COLOR_TRANSFORM,
+    HWC_DISPLAY_NO_ATTRIBUTE,
+};
+
+static constexpr uint32_t ATTRIBUTES_WITHOUT_COLOR[] = {
+    HWC_DISPLAY_VSYNC_PERIOD,
+    HWC_DISPLAY_WIDTH,
+    HWC_DISPLAY_HEIGHT,
+    HWC_DISPLAY_DPI_X,
+    HWC_DISPLAY_DPI_Y,
+    HWC_DISPLAY_NO_ATTRIBUTE,
+};
+
+static constexpr size_t NUM_ATTRIBUTES_WITH_COLOR =
+        sizeof(ATTRIBUTES_WITH_COLOR) / sizeof(uint32_t);
+static_assert(sizeof(ATTRIBUTES_WITH_COLOR) > sizeof(ATTRIBUTES_WITHOUT_COLOR),
+        "Attribute tables have unexpected sizes");
+
+static constexpr uint32_t ATTRIBUTE_MAP_WITH_COLOR[] = {
+    6, // HWC_DISPLAY_NO_ATTRIBUTE = 0
+    0, // HWC_DISPLAY_VSYNC_PERIOD = 1,
+    1, // HWC_DISPLAY_WIDTH = 2,
+    2, // HWC_DISPLAY_HEIGHT = 3,
+    3, // HWC_DISPLAY_DPI_X = 4,
+    4, // HWC_DISPLAY_DPI_Y = 5,
+    5, // HWC_DISPLAY_COLOR_TRANSFORM = 6,
+};
+
+static constexpr uint32_t ATTRIBUTE_MAP_WITHOUT_COLOR[] = {
+    5, // HWC_DISPLAY_NO_ATTRIBUTE = 0
+    0, // HWC_DISPLAY_VSYNC_PERIOD = 1,
+    1, // HWC_DISPLAY_WIDTH = 2,
+    2, // HWC_DISPLAY_HEIGHT = 3,
+    3, // HWC_DISPLAY_DPI_X = 4,
+    4, // HWC_DISPLAY_DPI_Y = 5,
+};
+
+template <uint32_t attribute>
+static constexpr bool attributesMatch()
+{
+    bool match = (attribute ==
+            ATTRIBUTES_WITH_COLOR[ATTRIBUTE_MAP_WITH_COLOR[attribute]]);
+    if (attribute == HWC_DISPLAY_COLOR_TRANSFORM) {
+        return match;
+    }
+
+    return match && (attribute ==
+            ATTRIBUTES_WITHOUT_COLOR[ATTRIBUTE_MAP_WITHOUT_COLOR[attribute]]);
+}
+static_assert(attributesMatch<HWC_DISPLAY_VSYNC_PERIOD>(),
+        "Tables out of sync");
+static_assert(attributesMatch<HWC_DISPLAY_WIDTH>(), "Tables out of sync");
+static_assert(attributesMatch<HWC_DISPLAY_HEIGHT>(), "Tables out of sync");
+static_assert(attributesMatch<HWC_DISPLAY_DPI_X>(), "Tables out of sync");
+static_assert(attributesMatch<HWC_DISPLAY_DPI_Y>(), "Tables out of sync");
+static_assert(attributesMatch<HWC_DISPLAY_COLOR_TRANSFORM>(),
+        "Tables out of sync");
+
+void HWC2On1Adapter::Display::populateConfigs() {
+    std::unique_lock<std::recursive_mutex> lock(mStateMutex);
+
+    ALOGV("[%" PRIu64 "] populateConfigs", mId);
+
+    if (mHwc1Id == -1) {
+        ALOGE("populateConfigs: HWC1 ID not set");
+        return;
+    }
+
+    const size_t MAX_NUM_CONFIGS = 128;
+    uint32_t configs[MAX_NUM_CONFIGS] = {};
+    size_t numConfigs = MAX_NUM_CONFIGS;
+    mDevice.mHwc1Device->getDisplayConfigs(mDevice.mHwc1Device, mHwc1Id,
+            configs, &numConfigs);
+
+    for (size_t c = 0; c < numConfigs; ++c) {
+        uint32_t hwc1ConfigId = configs[c];
+        auto newConfig = std::make_shared<Config>(*this);
+
+        int32_t values[NUM_ATTRIBUTES_WITH_COLOR] = {};
+        bool hasColor = true;
+        auto result = mDevice.mHwc1Device->getDisplayAttributes(
+                mDevice.mHwc1Device, mHwc1Id, hwc1ConfigId,
+                ATTRIBUTES_WITH_COLOR, values);
+        if (result != 0) {
+            mDevice.mHwc1Device->getDisplayAttributes(mDevice.mHwc1Device,
+                    mHwc1Id, hwc1ConfigId, ATTRIBUTES_WITHOUT_COLOR, values);
+            hasColor = false;
+        }
+
+        auto attributeMap = hasColor ?
+                ATTRIBUTE_MAP_WITH_COLOR : ATTRIBUTE_MAP_WITHOUT_COLOR;
+
+        newConfig->setAttribute(Attribute::VsyncPeriod,
+                values[attributeMap[HWC_DISPLAY_VSYNC_PERIOD]]);
+        newConfig->setAttribute(Attribute::Width,
+                values[attributeMap[HWC_DISPLAY_WIDTH]]);
+        newConfig->setAttribute(Attribute::Height,
+                values[attributeMap[HWC_DISPLAY_HEIGHT]]);
+        newConfig->setAttribute(Attribute::DpiX,
+                values[attributeMap[HWC_DISPLAY_DPI_X]]);
+        newConfig->setAttribute(Attribute::DpiY,
+                values[attributeMap[HWC_DISPLAY_DPI_Y]]);
+        if (hasColor) {
+            // In HWC1, color modes are referred to as color transforms. To avoid confusion with
+            // the HWC2 concept of color transforms, we internally refer to them as color modes for
+            // both HWC1 and 2.
+            newConfig->setAttribute(ColorMode,
+                    values[attributeMap[HWC_DISPLAY_COLOR_TRANSFORM]]);
+        }
+
+        // We can only do this after attempting to read the color mode
+        newConfig->setHwc1Id(hwc1ConfigId);
+
+        for (auto& existingConfig : mConfigs) {
+            if (existingConfig->merge(*newConfig)) {
+                ALOGV("Merged config %d with existing config %u: %s",
+                        hwc1ConfigId, existingConfig->getId(),
+                        existingConfig->toString().c_str());
+                newConfig.reset();
+                break;
+            }
+        }
+
+        // If it wasn't merged with any existing config, add it to the end
+        if (newConfig) {
+            newConfig->setId(static_cast<hwc2_config_t>(mConfigs.size()));
+            ALOGV("Found new config %u: %s", newConfig->getId(),
+                    newConfig->toString().c_str());
+            mConfigs.emplace_back(std::move(newConfig));
+        }
+    }
+
+    initializeActiveConfig();
+    populateColorModes();
+}
+
+void HWC2On1Adapter::Display::populateConfigs(uint32_t width, uint32_t height) {
+    std::unique_lock<std::recursive_mutex> lock(mStateMutex);
+
+    mConfigs.emplace_back(std::make_shared<Config>(*this));
+    auto& config = mConfigs[0];
+
+    config->setAttribute(Attribute::Width, static_cast<int32_t>(width));
+    config->setAttribute(Attribute::Height, static_cast<int32_t>(height));
+    config->setHwc1Id(0);
+    config->setId(0);
+    mActiveConfig = config;
+}
+
+bool HWC2On1Adapter::Display::prepare() {
+    std::unique_lock<std::recursive_mutex> lock(mStateMutex);
+
+    // Only prepare display contents for displays HWC1 knows about
+    if (mHwc1Id == -1) {
+        return true;
+    }
+
+    // It doesn't make sense to prepare a display for which there is no active
+    // config, so return early
+    if (!mActiveConfig) {
+        ALOGE("[%" PRIu64 "] Attempted to prepare, but no config active", mId);
+        return false;
+    }
+
+    allocateRequestedContents();
+    assignHwc1LayerIds();
+
+    mHwc1RequestedContents->retireFenceFd = -1;
+    mHwc1RequestedContents->flags = 0;
+    if (mGeometryChanged) {
+        mHwc1RequestedContents->flags |= HWC_GEOMETRY_CHANGED;
+    }
+    mHwc1RequestedContents->outbuf = mOutputBuffer.getBuffer();
+    mHwc1RequestedContents->outbufAcquireFenceFd = mOutputBuffer.getFence();
+
+    // +1 is for framebuffer target layer.
+    mHwc1RequestedContents->numHwLayers = mLayers.size() + 1;
+    for (auto& layer : mLayers) {
+        auto& hwc1Layer = mHwc1RequestedContents->hwLayers[layer->getHwc1Id()];
+        hwc1Layer.releaseFenceFd = -1;
+        hwc1Layer.acquireFenceFd = -1;
+        ALOGV("Applying states for layer %" PRIu64 " ", layer->getId());
+        layer->applyState(hwc1Layer);
+    }
+
+    prepareFramebufferTarget();
+
+    resetGeometryMarker();
+
+    return true;
+}
+
+void HWC2On1Adapter::Display::generateChanges() {
+    std::unique_lock<std::recursive_mutex> lock(mStateMutex);
+
+    mChanges.reset(new Changes);
+
+    size_t numLayers = mHwc1RequestedContents->numHwLayers;
+    for (size_t hwc1Id = 0; hwc1Id < numLayers; ++hwc1Id) {
+        const auto& receivedLayer = mHwc1RequestedContents->hwLayers[hwc1Id];
+        if (mHwc1LayerMap.count(hwc1Id) == 0) {
+            ALOGE_IF(receivedLayer.compositionType != HWC_FRAMEBUFFER_TARGET,
+                    "generateChanges: HWC1 layer %zd doesn't have a"
+                    " matching HWC2 layer, and isn't the framebuffer target",
+                    hwc1Id);
+            continue;
+        }
+
+        Layer& layer = *mHwc1LayerMap[hwc1Id];
+        updateTypeChanges(receivedLayer, layer);
+        updateLayerRequests(receivedLayer, layer);
+    }
+}
+
+bool HWC2On1Adapter::Display::hasChanges() const {
+    std::unique_lock<std::recursive_mutex> lock(mStateMutex);
+    return mChanges != nullptr;
+}
+
+Error HWC2On1Adapter::Display::set(hwc_display_contents_1& hwcContents) {
+    std::unique_lock<std::recursive_mutex> lock(mStateMutex);
+
+    if (!mChanges || (mChanges->getNumTypes() > 0)) {
+        ALOGE("[%" PRIu64 "] set failed: not validated", mId);
+        return Error::NotValidated;
+    }
+
+    // Set up the client/framebuffer target
+    auto numLayers = hwcContents.numHwLayers;
+
+    // Close acquire fences on FRAMEBUFFER layers, since they will not be used
+    // by HWC
+    for (size_t l = 0; l < numLayers - 1; ++l) {
+        auto& layer = hwcContents.hwLayers[l];
+        if (layer.compositionType == HWC_FRAMEBUFFER) {
+            ALOGV("Closing fence %d for layer %zd", layer.acquireFenceFd, l);
+            close(layer.acquireFenceFd);
+            layer.acquireFenceFd = -1;
+        }
+    }
+
+    auto& clientTargetLayer = hwcContents.hwLayers[numLayers - 1];
+    if (clientTargetLayer.compositionType == HWC_FRAMEBUFFER_TARGET) {
+        clientTargetLayer.handle = mClientTarget.getBuffer();
+        clientTargetLayer.acquireFenceFd = mClientTarget.getFence();
+    } else {
+        ALOGE("[%" PRIu64 "] set: last HWC layer wasn't FRAMEBUFFER_TARGET",
+                mId);
+    }
+
+    mChanges.reset();
+
+    return Error::None;
+}
+
+void HWC2On1Adapter::Display::addRetireFence(int fenceFd) {
+    std::unique_lock<std::recursive_mutex> lock(mStateMutex);
+    mRetireFence.add(fenceFd);
+}
+
+void HWC2On1Adapter::Display::addReleaseFences(
+        const hwc_display_contents_1_t& hwcContents) {
+    std::unique_lock<std::recursive_mutex> lock(mStateMutex);
+
+    size_t numLayers = hwcContents.numHwLayers;
+    for (size_t hwc1Id = 0; hwc1Id < numLayers; ++hwc1Id) {
+        const auto& receivedLayer = hwcContents.hwLayers[hwc1Id];
+        if (mHwc1LayerMap.count(hwc1Id) == 0) {
+            if (receivedLayer.compositionType != HWC_FRAMEBUFFER_TARGET) {
+                ALOGE("addReleaseFences: HWC1 layer %zd doesn't have a"
+                        " matching HWC2 layer, and isn't the framebuffer"
+                        " target", hwc1Id);
+            }
+            // Close the framebuffer target release fence since we will use the
+            // display retire fence instead
+            if (receivedLayer.releaseFenceFd != -1) {
+                close(receivedLayer.releaseFenceFd);
+            }
+            continue;
+        }
+
+        Layer& layer = *mHwc1LayerMap[hwc1Id];
+        ALOGV("Adding release fence %d to layer %" PRIu64,
+                receivedLayer.releaseFenceFd, layer.getId());
+        layer.addReleaseFence(receivedLayer.releaseFenceFd);
+    }
+}
+
+bool HWC2On1Adapter::Display::hasColorTransform() const {
+    std::unique_lock<std::recursive_mutex> lock(mStateMutex);
+    return mHasColorTransform;
+}
+
+static std::string hwc1CompositionString(int32_t type) {
+    switch (type) {
+        case HWC_FRAMEBUFFER: return "Framebuffer";
+        case HWC_OVERLAY: return "Overlay";
+        case HWC_BACKGROUND: return "Background";
+        case HWC_FRAMEBUFFER_TARGET: return "FramebufferTarget";
+        case HWC_SIDEBAND: return "Sideband";
+        case HWC_CURSOR_OVERLAY: return "CursorOverlay";
+        default:
+            return std::string("Unknown (") + std::to_string(type) + ")";
+    }
+}
+
+static std::string hwc1TransformString(int32_t transform) {
+    switch (transform) {
+        case 0: return "None";
+        case HWC_TRANSFORM_FLIP_H: return "FlipH";
+        case HWC_TRANSFORM_FLIP_V: return "FlipV";
+        case HWC_TRANSFORM_ROT_90: return "Rotate90";
+        case HWC_TRANSFORM_ROT_180: return "Rotate180";
+        case HWC_TRANSFORM_ROT_270: return "Rotate270";
+        case HWC_TRANSFORM_FLIP_H_ROT_90: return "FlipHRotate90";
+        case HWC_TRANSFORM_FLIP_V_ROT_90: return "FlipVRotate90";
+        default:
+            return std::string("Unknown (") + std::to_string(transform) + ")";
+    }
+}
+
+static std::string hwc1BlendModeString(int32_t mode) {
+    switch (mode) {
+        case HWC_BLENDING_NONE: return "None";
+        case HWC_BLENDING_PREMULT: return "Premultiplied";
+        case HWC_BLENDING_COVERAGE: return "Coverage";
+        default:
+            return std::string("Unknown (") + std::to_string(mode) + ")";
+    }
+}
+
+static std::string rectString(hwc_rect_t rect) {
+    std::stringstream output;
+    output << "[" << rect.left << ", " << rect.top << ", ";
+    output << rect.right << ", " << rect.bottom << "]";
+    return output.str();
+}
+
+static std::string approximateFloatString(float f) {
+    if (static_cast<int32_t>(f) == f) {
+        return std::to_string(static_cast<int32_t>(f));
+    }
+    int32_t truncated = static_cast<int32_t>(f * 10);
+    bool approximate = (static_cast<float>(truncated) != f * 10);
+    const size_t BUFFER_SIZE = 32;
+    char buffer[BUFFER_SIZE] = {};
+    auto bytesWritten = snprintf(buffer, BUFFER_SIZE,
+            "%s%.1f", approximate ? "~" : "", f);
+    return std::string(buffer, bytesWritten);
+}
+
+static std::string frectString(hwc_frect_t frect) {
+    std::stringstream output;
+    output << "[" << approximateFloatString(frect.left) << ", ";
+    output << approximateFloatString(frect.top) << ", ";
+    output << approximateFloatString(frect.right) << ", ";
+    output << approximateFloatString(frect.bottom) << "]";
+    return output.str();
+}
+
+static std::string colorString(hwc_color_t color) {
+    std::stringstream output;
+    output << "RGBA [";
+    output << static_cast<int32_t>(color.r) << ", ";
+    output << static_cast<int32_t>(color.g) << ", ";
+    output << static_cast<int32_t>(color.b) << ", ";
+    output << static_cast<int32_t>(color.a) << "]";
+    return output.str();
+}
+
+static std::string alphaString(float f) {
+    const size_t BUFFER_SIZE = 8;
+    char buffer[BUFFER_SIZE] = {};
+    auto bytesWritten = snprintf(buffer, BUFFER_SIZE, "%.3f", f);
+    return std::string(buffer, bytesWritten);
+}
+
+static std::string to_string(const hwc_layer_1_t& hwcLayer,
+        int32_t hwc1MinorVersion) {
+    const char* fill = "          ";
+
+    std::stringstream output;
+
+    output << "  Composition: " <<
+            hwc1CompositionString(hwcLayer.compositionType);
+
+    if (hwcLayer.compositionType == HWC_BACKGROUND) {
+        output << "  Color: " << colorString(hwcLayer.backgroundColor) << '\n';
+    } else if (hwcLayer.compositionType == HWC_SIDEBAND) {
+        output << "  Stream: " << hwcLayer.sidebandStream << '\n';
+    } else {
+        output << "  Buffer: " << hwcLayer.handle << "/" <<
+                hwcLayer.acquireFenceFd << '\n';
+    }
+
+    output << fill << "Display frame: " << rectString(hwcLayer.displayFrame) <<
+            '\n';
+
+    output << fill << "Source crop: ";
+    if (hwc1MinorVersion >= 3) {
+        output << frectString(hwcLayer.sourceCropf) << '\n';
+    } else {
+        output << rectString(hwcLayer.sourceCropi) << '\n';
+    }
+
+    output << fill << "Transform: " << hwc1TransformString(hwcLayer.transform);
+    output << "  Blend mode: " << hwc1BlendModeString(hwcLayer.blending);
+    if (hwcLayer.planeAlpha != 0xFF) {
+        output << "  Alpha: " << alphaString(hwcLayer.planeAlpha / 255.0f);
+    }
+    output << '\n';
+
+    if (hwcLayer.hints != 0) {
+        output << fill << "Hints:";
+        if ((hwcLayer.hints & HWC_HINT_TRIPLE_BUFFER) != 0) {
+            output << " TripleBuffer";
+        }
+        if ((hwcLayer.hints & HWC_HINT_CLEAR_FB) != 0) {
+            output << " ClearFB";
+        }
+        output << '\n';
+    }
+
+    if (hwcLayer.flags != 0) {
+        output << fill << "Flags:";
+        if ((hwcLayer.flags & HWC_SKIP_LAYER) != 0) {
+            output << " SkipLayer";
+        }
+        if ((hwcLayer.flags & HWC_IS_CURSOR_LAYER) != 0) {
+            output << " IsCursorLayer";
+        }
+        output << '\n';
+    }
+
+    return output.str();
+}
+
+static std::string to_string(const hwc_display_contents_1_t& hwcContents,
+        int32_t hwc1MinorVersion) {
+    const char* fill = "      ";
+
+    std::stringstream output;
+    output << fill << "Geometry changed: " <<
+            ((hwcContents.flags & HWC_GEOMETRY_CHANGED) != 0 ? "Y\n" : "N\n");
+
+    output << fill << hwcContents.numHwLayers << " Layer" <<
+            ((hwcContents.numHwLayers == 1) ? "\n" : "s\n");
+    for (size_t layer = 0; layer < hwcContents.numHwLayers; ++layer) {
+        output << fill << "  Layer " << layer;
+        output << to_string(hwcContents.hwLayers[layer], hwc1MinorVersion);
+    }
+
+    if (hwcContents.outbuf != nullptr) {
+        output << fill << "Output buffer: " << hwcContents.outbuf << "/" <<
+                hwcContents.outbufAcquireFenceFd << '\n';
+    }
+
+    return output.str();
+}
+
+std::string HWC2On1Adapter::Display::dump() const {
+    std::unique_lock<std::recursive_mutex> lock(mStateMutex);
+
+    std::stringstream output;
+
+    output << "  Display " << mId << ": ";
+    output << to_string(mType) << "  ";
+    output << "HWC1 ID: " << mHwc1Id << "  ";
+    output << "Power mode: " << to_string(mPowerMode) << "  ";
+    output << "Vsync: " << to_string(mVsyncEnabled) << '\n';
+
+    output << "    Color modes [active]:";
+    for (const auto& mode : mColorModes) {
+        if (mode == mActiveColorMode) {
+            output << " [" << mode << ']';
+        } else {
+            output << " " << mode;
+        }
+    }
+    output << '\n';
+
+    output << "    " << mConfigs.size() << " Config" <<
+            (mConfigs.size() == 1 ? "" : "s") << " (* active)\n";
+    for (const auto& config : mConfigs) {
+        output << (config == mActiveConfig ? "    * " : "      ");
+        output << config->toString(true) << '\n';
+    }
+
+    output << "    " << mLayers.size() << " Layer" <<
+            (mLayers.size() == 1 ? "" : "s") << '\n';
+    for (const auto& layer : mLayers) {
+        output << layer->dump();
+    }
+
+    output << "    Client target: " << mClientTarget.getBuffer() << '\n';
+
+    if (mOutputBuffer.getBuffer() != nullptr) {
+        output << "    Output buffer: " << mOutputBuffer.getBuffer() << '\n';
+    }
+
+    if (mHwc1RequestedContents) {
+        output << "    Last requested HWC1 state\n";
+        output << to_string(*mHwc1RequestedContents, mDevice.mHwc1MinorVersion);
+    }
+
+    return output.str();
+}
+
+hwc_rect_t* HWC2On1Adapter::Display::GetRects(size_t numRects) {
+    if (numRects == 0) {
+        return nullptr;
+    }
+
+    if (numRects > mNumAvailableRects) {
+        // This should NEVER happen since we calculated how many rects the
+        // display would need.
+        ALOGE("Rect allocation failure! SF is likely to crash soon!");
+        return nullptr;
+
+    }
+    hwc_rect_t* rects = mNextAvailableRect;
+    mNextAvailableRect += numRects;
+    mNumAvailableRects -= numRects;
+    return rects;
+}
+
+hwc_display_contents_1* HWC2On1Adapter::Display::getDisplayContents() {
+    return mHwc1RequestedContents.get();
+}
+
+void HWC2On1Adapter::Display::Config::setAttribute(HWC2::Attribute attribute,
+        int32_t value) {
+    mAttributes[attribute] = value;
+}
+
+int32_t HWC2On1Adapter::Display::Config::getAttribute(Attribute attribute) const {
+    if (mAttributes.count(attribute) == 0) {
+        return -1;
+    }
+    return mAttributes.at(attribute);
+}
+
+void HWC2On1Adapter::Display::Config::setHwc1Id(uint32_t id) {
+    android_color_mode_t colorMode = static_cast<android_color_mode_t>(getAttribute(ColorMode));
+    mHwc1Ids.emplace(colorMode, id);
+}
+
+bool HWC2On1Adapter::Display::Config::hasHwc1Id(uint32_t id) const {
+    for (const auto& idPair : mHwc1Ids) {
+        if (id == idPair.second) {
+            return true;
+        }
+    }
+    return false;
+}
+
+Error HWC2On1Adapter::Display::Config::getColorModeForHwc1Id(
+        uint32_t id, android_color_mode_t* outMode) const {
+    for (const auto& idPair : mHwc1Ids) {
+        if (id == idPair.second) {
+            *outMode = idPair.first;
+            return Error::None;
+        }
+    }
+    ALOGE("Unable to find color mode for HWC ID %" PRIu32 " on config %u", id, mId);
+    return Error::BadParameter;
+}
+
+Error HWC2On1Adapter::Display::Config::getHwc1IdForColorMode(android_color_mode_t mode,
+        uint32_t* outId) const {
+    for (const auto& idPair : mHwc1Ids) {
+        if (mode == idPair.first) {
+            *outId = idPair.second;
+            return Error::None;
+        }
+    }
+    ALOGE("Unable to find HWC1 ID for color mode %d on config %u", mode, mId);
+    return Error::BadParameter;
+}
+
+bool HWC2On1Adapter::Display::Config::merge(const Config& other) {
+    auto attributes = {HWC2::Attribute::Width, HWC2::Attribute::Height,
+            HWC2::Attribute::VsyncPeriod, HWC2::Attribute::DpiX,
+            HWC2::Attribute::DpiY};
+    for (auto attribute : attributes) {
+        if (getAttribute(attribute) != other.getAttribute(attribute)) {
+            return false;
+        }
+    }
+    android_color_mode_t otherColorMode =
+            static_cast<android_color_mode_t>(other.getAttribute(ColorMode));
+    if (mHwc1Ids.count(otherColorMode) != 0) {
+        ALOGE("Attempted to merge two configs (%u and %u) which appear to be "
+                "identical", mHwc1Ids.at(otherColorMode),
+                other.mHwc1Ids.at(otherColorMode));
+        return false;
+    }
+    mHwc1Ids.emplace(otherColorMode,
+            other.mHwc1Ids.at(otherColorMode));
+    return true;
+}
+
+std::set<android_color_mode_t> HWC2On1Adapter::Display::Config::getColorModes() const {
+    std::set<android_color_mode_t> colorModes;
+    for (const auto& idPair : mHwc1Ids) {
+        colorModes.emplace(idPair.first);
+    }
+    return colorModes;
+}
+
+std::string HWC2On1Adapter::Display::Config::toString(bool splitLine) const {
+    std::string output;
+
+    const size_t BUFFER_SIZE = 100;
+    char buffer[BUFFER_SIZE] = {};
+    auto writtenBytes = snprintf(buffer, BUFFER_SIZE,
+            "%u x %u", mAttributes.at(HWC2::Attribute::Width),
+            mAttributes.at(HWC2::Attribute::Height));
+    output.append(buffer, writtenBytes);
+
+    if (mAttributes.count(HWC2::Attribute::VsyncPeriod) != 0) {
+        std::memset(buffer, 0, BUFFER_SIZE);
+        writtenBytes = snprintf(buffer, BUFFER_SIZE, " @ %.1f Hz",
+                1e9 / mAttributes.at(HWC2::Attribute::VsyncPeriod));
+        output.append(buffer, writtenBytes);
+    }
+
+    if (mAttributes.count(HWC2::Attribute::DpiX) != 0 &&
+            mAttributes.at(HWC2::Attribute::DpiX) != -1) {
+        std::memset(buffer, 0, BUFFER_SIZE);
+        writtenBytes = snprintf(buffer, BUFFER_SIZE,
+                ", DPI: %.1f x %.1f",
+                mAttributes.at(HWC2::Attribute::DpiX) / 1000.0f,
+                mAttributes.at(HWC2::Attribute::DpiY) / 1000.0f);
+        output.append(buffer, writtenBytes);
+    }
+
+    std::memset(buffer, 0, BUFFER_SIZE);
+    if (splitLine) {
+        writtenBytes = snprintf(buffer, BUFFER_SIZE,
+                "\n        HWC1 ID/Color transform:");
+    } else {
+        writtenBytes = snprintf(buffer, BUFFER_SIZE,
+                ", HWC1 ID/Color transform:");
+    }
+    output.append(buffer, writtenBytes);
+
+
+    for (const auto& id : mHwc1Ids) {
+        android_color_mode_t colorMode = id.first;
+        uint32_t hwc1Id = id.second;
+        std::memset(buffer, 0, BUFFER_SIZE);
+        if (colorMode == mDisplay.mActiveColorMode) {
+            writtenBytes = snprintf(buffer, BUFFER_SIZE, " [%u/%d]", hwc1Id,
+                    colorMode);
+        } else {
+            writtenBytes = snprintf(buffer, BUFFER_SIZE, " %u/%d", hwc1Id,
+                    colorMode);
+        }
+        output.append(buffer, writtenBytes);
+    }
+
+    return output;
+}
+
+std::shared_ptr<const HWC2On1Adapter::Display::Config>
+        HWC2On1Adapter::Display::getConfig(hwc2_config_t configId) const {
+    if (configId > mConfigs.size() || !mConfigs[configId]->isOnDisplay(*this)) {
+        return nullptr;
+    }
+    return mConfigs[configId];
+}
+
+void HWC2On1Adapter::Display::populateColorModes() {
+    mColorModes = mConfigs[0]->getColorModes();
+    for (const auto& config : mConfigs) {
+        std::set<android_color_mode_t> intersection;
+        auto configModes = config->getColorModes();
+        std::set_intersection(mColorModes.cbegin(), mColorModes.cend(),
+                configModes.cbegin(), configModes.cend(),
+                std::inserter(intersection, intersection.begin()));
+        std::swap(intersection, mColorModes);
+    }
+}
+
+void HWC2On1Adapter::Display::initializeActiveConfig() {
+    if (mDevice.mHwc1Device->getActiveConfig == nullptr) {
+        ALOGV("getActiveConfig is null, choosing config 0");
+        mActiveConfig = mConfigs[0];
+        mActiveColorMode = HAL_COLOR_MODE_NATIVE;
+        return;
+    }
+
+    auto activeConfig = mDevice.mHwc1Device->getActiveConfig(
+            mDevice.mHwc1Device, mHwc1Id);
+
+    // Some devices startup without an activeConfig:
+    // We need to set one ourselves.
+    if (activeConfig == HWC_ERROR) {
+        ALOGV("There is no active configuration: Picking the first one: 0.");
+        const int defaultIndex = 0;
+        mDevice.mHwc1Device->setActiveConfig(mDevice.mHwc1Device, mHwc1Id, defaultIndex);
+        activeConfig = defaultIndex;
+    }
+
+    for (const auto& config : mConfigs) {
+        if (config->hasHwc1Id(activeConfig)) {
+            ALOGE("Setting active config to %d for HWC1 config %u", config->getId(), activeConfig);
+            mActiveConfig = config;
+            if (config->getColorModeForHwc1Id(activeConfig, &mActiveColorMode) != Error::None) {
+                // This should never happen since we checked for the config's presence before
+                // setting it as active.
+                ALOGE("Unable to find color mode for active HWC1 config %d", config->getId());
+                mActiveColorMode = HAL_COLOR_MODE_NATIVE;
+            }
+            break;
+        }
+    }
+    if (!mActiveConfig) {
+        ALOGV("Unable to find active HWC1 config %u, defaulting to "
+                "config 0", activeConfig);
+        mActiveConfig = mConfigs[0];
+        mActiveColorMode = HAL_COLOR_MODE_NATIVE;
+    }
+
+
+
+
+}
+
+void HWC2On1Adapter::Display::allocateRequestedContents() {
+    // What needs to be allocated:
+    // 1 hwc_display_contents_1_t
+    // 1 hwc_layer_1_t for each layer
+    // 1 hwc_rect_t for each layer's surfaceDamage
+    // 1 hwc_rect_t for each layer's visibleRegion
+    // 1 hwc_layer_1_t for the framebuffer
+    // 1 hwc_rect_t for the framebuffer's visibleRegion
+
+    // Count # of surfaceDamage
+    size_t numSurfaceDamages = 0;
+    for (const auto& layer : mLayers) {
+        numSurfaceDamages += layer->getNumSurfaceDamages();
+    }
+
+    // Count # of visibleRegions (start at 1 for mandatory framebuffer target
+    // region)
+    size_t numVisibleRegion = 1;
+    for (const auto& layer : mLayers) {
+        numVisibleRegion += layer->getNumVisibleRegions();
+    }
+
+    size_t numRects = numVisibleRegion + numSurfaceDamages;
+    auto numLayers = mLayers.size() + 1;
+    size_t size = sizeof(hwc_display_contents_1_t) +
+            sizeof(hwc_layer_1_t) * numLayers +
+            sizeof(hwc_rect_t) * numRects;
+    auto contents = static_cast<hwc_display_contents_1_t*>(std::calloc(size, 1));
+    mHwc1RequestedContents.reset(contents);
+    mNextAvailableRect = reinterpret_cast<hwc_rect_t*>(&contents->hwLayers[numLayers]);
+    mNumAvailableRects = numRects;
+}
+
+void HWC2On1Adapter::Display::assignHwc1LayerIds() {
+    mHwc1LayerMap.clear();
+    size_t nextHwc1Id = 0;
+    for (auto& layer : mLayers) {
+        mHwc1LayerMap[nextHwc1Id] = layer;
+        layer->setHwc1Id(nextHwc1Id++);
+    }
+}
+
+void HWC2On1Adapter::Display::updateTypeChanges(const hwc_layer_1_t& hwc1Layer,
+        const Layer& layer) {
+    auto layerId = layer.getId();
+    switch (hwc1Layer.compositionType) {
+        case HWC_FRAMEBUFFER:
+            if (layer.getCompositionType() != Composition::Client) {
+                mChanges->addTypeChange(layerId, Composition::Client);
+            }
+            break;
+        case HWC_OVERLAY:
+            if (layer.getCompositionType() != Composition::Device) {
+                mChanges->addTypeChange(layerId, Composition::Device);
+            }
+            break;
+        case HWC_BACKGROUND:
+            ALOGE_IF(layer.getCompositionType() != Composition::SolidColor,
+                    "updateTypeChanges: HWC1 requested BACKGROUND, but HWC2"
+                    " wasn't expecting SolidColor");
+            break;
+        case HWC_FRAMEBUFFER_TARGET:
+            // Do nothing, since it shouldn't be modified by HWC1
+            break;
+        case HWC_SIDEBAND:
+            ALOGE_IF(layer.getCompositionType() != Composition::Sideband,
+                    "updateTypeChanges: HWC1 requested SIDEBAND, but HWC2"
+                    " wasn't expecting Sideband");
+            break;
+        case HWC_CURSOR_OVERLAY:
+            ALOGE_IF(layer.getCompositionType() != Composition::Cursor,
+                    "updateTypeChanges: HWC1 requested CURSOR_OVERLAY, but"
+                    " HWC2 wasn't expecting Cursor");
+            break;
+    }
+}
+
+void HWC2On1Adapter::Display::updateLayerRequests(
+        const hwc_layer_1_t& hwc1Layer, const Layer& layer) {
+    if ((hwc1Layer.hints & HWC_HINT_CLEAR_FB) != 0) {
+        mChanges->addLayerRequest(layer.getId(),
+                LayerRequest::ClearClientTarget);
+    }
+}
+
+void HWC2On1Adapter::Display::prepareFramebufferTarget() {
+    // We check that mActiveConfig is valid in Display::prepare
+    int32_t width = mActiveConfig->getAttribute(Attribute::Width);
+    int32_t height = mActiveConfig->getAttribute(Attribute::Height);
+
+    auto& hwc1Target = mHwc1RequestedContents->hwLayers[mLayers.size()];
+    hwc1Target.compositionType = HWC_FRAMEBUFFER_TARGET;
+    hwc1Target.releaseFenceFd = -1;
+    hwc1Target.hints = 0;
+    hwc1Target.flags = 0;
+    hwc1Target.transform = 0;
+    hwc1Target.blending = HWC_BLENDING_PREMULT;
+    if (mDevice.getHwc1MinorVersion() < 3) {
+        hwc1Target.sourceCropi = {0, 0, width, height};
+    } else {
+        hwc1Target.sourceCropf = {0.0f, 0.0f, static_cast<float>(width),
+                static_cast<float>(height)};
+    }
+    hwc1Target.displayFrame = {0, 0, width, height};
+    hwc1Target.planeAlpha = 255;
+
+    hwc1Target.visibleRegionScreen.numRects = 1;
+    hwc_rect_t* rects = GetRects(1);
+    rects[0].left = 0;
+    rects[0].top = 0;
+    rects[0].right = width;
+    rects[0].bottom = height;
+    hwc1Target.visibleRegionScreen.rects = rects;
+
+    // We will set this to the correct value in set
+    hwc1Target.acquireFenceFd = -1;
+}
+
+// Layer functions
+
+std::atomic<hwc2_layer_t> HWC2On1Adapter::Layer::sNextId(1);
+
+HWC2On1Adapter::Layer::Layer(Display& display)
+  : mId(sNextId++),
+    mDisplay(display),
+    mBuffer(),
+    mSurfaceDamage(),
+    mBlendMode(BlendMode::None),
+    mColor({0, 0, 0, 0}),
+    mCompositionType(Composition::Invalid),
+    mDisplayFrame({0, 0, -1, -1}),
+    mPlaneAlpha(0.0f),
+    mSidebandStream(nullptr),
+    mSourceCrop({0.0f, 0.0f, -1.0f, -1.0f}),
+    mTransform(Transform::None),
+    mVisibleRegion(),
+    mZ(0),
+    mReleaseFence(),
+    mHwc1Id(0),
+    mHasUnsupportedPlaneAlpha(false) {}
+
+bool HWC2On1Adapter::SortLayersByZ::operator()(
+        const std::shared_ptr<Layer>& lhs, const std::shared_ptr<Layer>& rhs) {
+    return lhs->getZ() < rhs->getZ();
+}
+
+Error HWC2On1Adapter::Layer::setBuffer(buffer_handle_t buffer,
+        int32_t acquireFence) {
+    ALOGV("Setting acquireFence to %d for layer %" PRIu64, acquireFence, mId);
+    mBuffer.setBuffer(buffer);
+    mBuffer.setFence(acquireFence);
+    return Error::None;
+}
+
+Error HWC2On1Adapter::Layer::setCursorPosition(int32_t x, int32_t y) {
+    if (mCompositionType != Composition::Cursor) {
+        return Error::BadLayer;
+    }
+
+    if (mDisplay.hasChanges()) {
+        return Error::NotValidated;
+    }
+
+    auto displayId = mDisplay.getHwc1Id();
+    auto hwc1Device = mDisplay.getDevice().getHwc1Device();
+    hwc1Device->setCursorPositionAsync(hwc1Device, displayId, x, y);
+    return Error::None;
+}
+
+Error HWC2On1Adapter::Layer::setSurfaceDamage(hwc_region_t damage) {
+    // HWC1 supports surface damage starting only with version 1.5.
+    if (mDisplay.getDevice().mHwc1MinorVersion < 5) {
+        return Error::None;
+    }
+    mSurfaceDamage.resize(damage.numRects);
+    std::copy_n(damage.rects, damage.numRects, mSurfaceDamage.begin());
+    return Error::None;
+}
+
+// Layer state functions
+
+Error HWC2On1Adapter::Layer::setBlendMode(BlendMode mode) {
+    mBlendMode = mode;
+    mDisplay.markGeometryChanged();
+    return Error::None;
+}
+
+Error HWC2On1Adapter::Layer::setColor(hwc_color_t color) {
+    mColor = color;
+    mDisplay.markGeometryChanged();
+    return Error::None;
+}
+
+Error HWC2On1Adapter::Layer::setCompositionType(Composition type) {
+    mCompositionType = type;
+    mDisplay.markGeometryChanged();
+    return Error::None;
+}
+
+Error HWC2On1Adapter::Layer::setDataspace(android_dataspace_t) {
+    return Error::None;
+}
+
+Error HWC2On1Adapter::Layer::setDisplayFrame(hwc_rect_t frame) {
+    mDisplayFrame = frame;
+    mDisplay.markGeometryChanged();
+    return Error::None;
+}
+
+Error HWC2On1Adapter::Layer::setPlaneAlpha(float alpha) {
+    mPlaneAlpha = alpha;
+    mDisplay.markGeometryChanged();
+    return Error::None;
+}
+
+Error HWC2On1Adapter::Layer::setSidebandStream(const native_handle_t* stream) {
+    mSidebandStream = stream;
+    mDisplay.markGeometryChanged();
+    return Error::None;
+}
+
+Error HWC2On1Adapter::Layer::setSourceCrop(hwc_frect_t crop) {
+    mSourceCrop = crop;
+    mDisplay.markGeometryChanged();
+    return Error::None;
+}
+
+Error HWC2On1Adapter::Layer::setTransform(Transform transform) {
+    mTransform = transform;
+    mDisplay.markGeometryChanged();
+    return Error::None;
+}
+
+static bool compareRects(const hwc_rect_t& rect1, const hwc_rect_t& rect2) {
+    return rect1.left == rect2.left &&
+            rect1.right == rect2.right &&
+            rect1.top == rect2.top &&
+            rect1.bottom == rect2.bottom;
+}
+
+Error HWC2On1Adapter::Layer::setVisibleRegion(hwc_region_t visible) {
+    if ((getNumVisibleRegions() != visible.numRects) ||
+        !std::equal(mVisibleRegion.begin(), mVisibleRegion.end(), visible.rects,
+                    compareRects)) {
+        mVisibleRegion.resize(visible.numRects);
+        std::copy_n(visible.rects, visible.numRects, mVisibleRegion.begin());
+        mDisplay.markGeometryChanged();
+    }
+    return Error::None;
+}
+
+Error HWC2On1Adapter::Layer::setZ(uint32_t z) {
+    mZ = z;
+    return Error::None;
+}
+
+void HWC2On1Adapter::Layer::addReleaseFence(int fenceFd) {
+    ALOGV("addReleaseFence %d to layer %" PRIu64, fenceFd, mId);
+    mReleaseFence.add(fenceFd);
+}
+
+const sp<MiniFence>& HWC2On1Adapter::Layer::getReleaseFence() const {
+    return mReleaseFence.get();
+}
+
+void HWC2On1Adapter::Layer::applyState(hwc_layer_1_t& hwc1Layer) {
+    applyCommonState(hwc1Layer);
+    applyCompositionType(hwc1Layer);
+    switch (mCompositionType) {
+        case Composition::SolidColor : applySolidColorState(hwc1Layer); break;
+        case Composition::Sideband : applySidebandState(hwc1Layer); break;
+        default: applyBufferState(hwc1Layer); break;
+    }
+}
+
+static std::string regionStrings(const std::vector<hwc_rect_t>& visibleRegion,
+        const std::vector<hwc_rect_t>& surfaceDamage) {
+    std::string regions;
+    regions += "        Visible Region";
+    regions.resize(40, ' ');
+    regions += "Surface Damage\n";
+
+    size_t numPrinted = 0;
+    size_t maxSize = std::max(visibleRegion.size(), surfaceDamage.size());
+    while (numPrinted < maxSize) {
+        std::string line("        ");
+        if (visibleRegion.empty() && numPrinted == 0) {
+            line += "None";
+        } else if (numPrinted < visibleRegion.size()) {
+            line += rectString(visibleRegion[numPrinted]);
+        }
+        line.resize(40, ' ');
+        if (surfaceDamage.empty() && numPrinted == 0) {
+            line += "None";
+        } else if (numPrinted < surfaceDamage.size()) {
+            line += rectString(surfaceDamage[numPrinted]);
+        }
+        line += '\n';
+        regions += line;
+        ++numPrinted;
+    }
+    return regions;
+}
+
+std::string HWC2On1Adapter::Layer::dump() const {
+    std::stringstream output;
+    const char* fill = "      ";
+
+    output << fill << to_string(mCompositionType);
+    output << " Layer  HWC2/1: " << mId << "/" << mHwc1Id << "  ";
+    output << "Z: " << mZ;
+    if (mCompositionType == HWC2::Composition::SolidColor) {
+        output << "  " << colorString(mColor);
+    } else if (mCompositionType == HWC2::Composition::Sideband) {
+        output << "  Handle: " << mSidebandStream << '\n';
+    } else {
+        output << "  Buffer: " << mBuffer.getBuffer() << "/" <<
+                mBuffer.getFence() << '\n';
+        output << fill << "  Display frame [LTRB]: " <<
+                rectString(mDisplayFrame) << '\n';
+        output << fill << "  Source crop: " <<
+                frectString(mSourceCrop) << '\n';
+        output << fill << "  Transform: " << to_string(mTransform);
+        output << "  Blend mode: " << to_string(mBlendMode);
+        if (mPlaneAlpha != 1.0f) {
+            output << "  Alpha: " <<
+                alphaString(mPlaneAlpha) << '\n';
+        } else {
+            output << '\n';
+        }
+        output << regionStrings(mVisibleRegion, mSurfaceDamage);
+    }
+    return output.str();
+}
+
+static int getHwc1Blending(HWC2::BlendMode blendMode) {
+    switch (blendMode) {
+        case BlendMode::Coverage: return HWC_BLENDING_COVERAGE;
+        case BlendMode::Premultiplied: return HWC_BLENDING_PREMULT;
+        default: return HWC_BLENDING_NONE;
+    }
+}
+
+void HWC2On1Adapter::Layer::applyCommonState(hwc_layer_1_t& hwc1Layer) {
+    auto minorVersion = mDisplay.getDevice().getHwc1MinorVersion();
+    hwc1Layer.blending = getHwc1Blending(mBlendMode);
+    hwc1Layer.displayFrame = mDisplayFrame;
+
+    auto pendingAlpha = mPlaneAlpha;
+    if (minorVersion < 2) {
+        mHasUnsupportedPlaneAlpha = pendingAlpha < 1.0f;
+    } else {
+        hwc1Layer.planeAlpha =
+                static_cast<uint8_t>(255.0f * pendingAlpha + 0.5f);
+    }
+
+    if (minorVersion < 3) {
+        auto pending = mSourceCrop;
+        hwc1Layer.sourceCropi.left =
+                static_cast<int32_t>(std::ceil(pending.left));
+        hwc1Layer.sourceCropi.top =
+                static_cast<int32_t>(std::ceil(pending.top));
+        hwc1Layer.sourceCropi.right =
+                static_cast<int32_t>(std::floor(pending.right));
+        hwc1Layer.sourceCropi.bottom =
+                static_cast<int32_t>(std::floor(pending.bottom));
+    } else {
+        hwc1Layer.sourceCropf = mSourceCrop;
+    }
+
+    hwc1Layer.transform = static_cast<uint32_t>(mTransform);
+
+    auto& hwc1VisibleRegion = hwc1Layer.visibleRegionScreen;
+    hwc1VisibleRegion.numRects = mVisibleRegion.size();
+    hwc_rect_t* rects = mDisplay.GetRects(hwc1VisibleRegion.numRects);
+    hwc1VisibleRegion.rects = rects;
+    for (size_t i = 0; i < mVisibleRegion.size(); i++) {
+        rects[i] = mVisibleRegion[i];
+    }
+}
+
+void HWC2On1Adapter::Layer::applySolidColorState(hwc_layer_1_t& hwc1Layer) {
+    // If the device does not support background color it is likely to make
+    // assumption regarding backgroundColor and handle (both fields occupy
+    // the same location in hwc_layer_1_t union).
+    // To not confuse these devices we don't set background color and we
+    // make sure handle is a null pointer.
+    if (hasUnsupportedBackgroundColor()) {
+        hwc1Layer.handle = nullptr;
+    } else {
+        hwc1Layer.backgroundColor = mColor;
+    }
+}
+
+void HWC2On1Adapter::Layer::applySidebandState(hwc_layer_1_t& hwc1Layer) {
+    hwc1Layer.sidebandStream = mSidebandStream;
+}
+
+void HWC2On1Adapter::Layer::applyBufferState(hwc_layer_1_t& hwc1Layer) {
+    hwc1Layer.handle = mBuffer.getBuffer();
+    hwc1Layer.acquireFenceFd = mBuffer.getFence();
+}
+
+void HWC2On1Adapter::Layer::applyCompositionType(hwc_layer_1_t& hwc1Layer) {
+    // HWC1 never supports color transforms or dataspaces and only sometimes
+    // supports plane alpha (depending on the version). These require us to drop
+    // some or all layers to client composition.
+    if (mHasUnsupportedPlaneAlpha || mDisplay.hasColorTransform() ||
+            hasUnsupportedBackgroundColor()) {
+        hwc1Layer.compositionType = HWC_FRAMEBUFFER;
+        hwc1Layer.flags = HWC_SKIP_LAYER;
+        return;
+    }
+
+    hwc1Layer.flags = 0;
+    switch (mCompositionType) {
+        case Composition::Client:
+            hwc1Layer.compositionType = HWC_FRAMEBUFFER;
+            hwc1Layer.flags |= HWC_SKIP_LAYER;
+            break;
+        case Composition::Device:
+            hwc1Layer.compositionType = HWC_FRAMEBUFFER;
+            break;
+        case Composition::SolidColor:
+            // In theory the following line should work, but since the HWC1
+            // version of SurfaceFlinger never used HWC_BACKGROUND, HWC1
+            // devices may not work correctly. To be on the safe side, we
+            // fall back to client composition.
+            //
+            // hwc1Layer.compositionType = HWC_BACKGROUND;
+            hwc1Layer.compositionType = HWC_FRAMEBUFFER;
+            hwc1Layer.flags |= HWC_SKIP_LAYER;
+            break;
+        case Composition::Cursor:
+            hwc1Layer.compositionType = HWC_FRAMEBUFFER;
+            if (mDisplay.getDevice().getHwc1MinorVersion() >= 4) {
+                hwc1Layer.hints |= HWC_IS_CURSOR_LAYER;
+            }
+            break;
+        case Composition::Sideband:
+            if (mDisplay.getDevice().getHwc1MinorVersion() < 4) {
+                hwc1Layer.compositionType = HWC_SIDEBAND;
+            } else {
+                hwc1Layer.compositionType = HWC_FRAMEBUFFER;
+                hwc1Layer.flags |= HWC_SKIP_LAYER;
+            }
+            break;
+        default:
+            hwc1Layer.compositionType = HWC_FRAMEBUFFER;
+            hwc1Layer.flags |= HWC_SKIP_LAYER;
+            break;
+    }
+    ALOGV("Layer %" PRIu64 " %s set to %d", mId,
+            to_string(mCompositionType).c_str(),
+            hwc1Layer.compositionType);
+    ALOGV_IF(hwc1Layer.flags & HWC_SKIP_LAYER, "    and skipping");
+}
+
+// Adapter helpers
+
+void HWC2On1Adapter::populateCapabilities() {
+    if (mHwc1MinorVersion >= 3U) {
+        int supportedTypes = 0;
+        auto result = mHwc1Device->query(mHwc1Device,
+                HWC_DISPLAY_TYPES_SUPPORTED, &supportedTypes);
+        if ((result == 0) && ((supportedTypes & HWC_DISPLAY_VIRTUAL_BIT) != 0)) {
+            ALOGI("Found support for HWC virtual displays");
+            mHwc1SupportsVirtualDisplays = true;
+        }
+    }
+    if (mHwc1MinorVersion >= 4U) {
+        mCapabilities.insert(Capability::SidebandStream);
+    }
+
+    // Check for HWC background color layer support.
+    if (mHwc1MinorVersion >= 1U) {
+        int backgroundColorSupported = 0;
+        auto result = mHwc1Device->query(mHwc1Device,
+                                         HWC_BACKGROUND_LAYER_SUPPORTED,
+                                         &backgroundColorSupported);
+        if ((result == 0) && (backgroundColorSupported == 1)) {
+            ALOGV("Found support for HWC background color");
+            mHwc1SupportsBackgroundColor = true;
+        }
+    }
+
+    // Some devices might have HWC1 retire fences that accurately emulate
+    // HWC2 present fences when they are deferred, but it's not very reliable.
+    // To be safe, we indicate PresentFenceIsNotReliable for all HWC1 devices.
+    mCapabilities.insert(Capability::PresentFenceIsNotReliable);
+}
+
+HWC2On1Adapter::Display* HWC2On1Adapter::getDisplay(hwc2_display_t id) {
+    std::unique_lock<std::recursive_timed_mutex> lock(mStateMutex);
+
+    auto display = mDisplays.find(id);
+    if (display == mDisplays.end()) {
+        return nullptr;
+    }
+
+    return display->second.get();
+}
+
+std::tuple<HWC2On1Adapter::Layer*, Error> HWC2On1Adapter::getLayer(
+        hwc2_display_t displayId, hwc2_layer_t layerId) {
+    auto display = getDisplay(displayId);
+    if (!display) {
+        return std::make_tuple(static_cast<Layer*>(nullptr), Error::BadDisplay);
+    }
+
+    auto layerEntry = mLayers.find(layerId);
+    if (layerEntry == mLayers.end()) {
+        return std::make_tuple(static_cast<Layer*>(nullptr), Error::BadLayer);
+    }
+
+    auto layer = layerEntry->second;
+    if (layer->getDisplay().getId() != displayId) {
+        return std::make_tuple(static_cast<Layer*>(nullptr), Error::BadLayer);
+    }
+    return std::make_tuple(layer.get(), Error::None);
+}
+
+void HWC2On1Adapter::populatePrimary() {
+    std::unique_lock<std::recursive_timed_mutex> lock(mStateMutex);
+
+    auto display = std::make_shared<Display>(*this, HWC2::DisplayType::Physical);
+    mHwc1DisplayMap[HWC_DISPLAY_PRIMARY] = display->getId();
+    display->setHwc1Id(HWC_DISPLAY_PRIMARY);
+    display->populateConfigs();
+    mDisplays.emplace(display->getId(), std::move(display));
+}
+
+bool HWC2On1Adapter::prepareAllDisplays() {
+    ATRACE_CALL();
+
+    std::unique_lock<std::recursive_timed_mutex> lock(mStateMutex);
+
+    for (const auto& displayPair : mDisplays) {
+        auto& display = displayPair.second;
+        if (!display->prepare()) {
+            return false;
+        }
+    }
+
+    if (mHwc1DisplayMap.count(HWC_DISPLAY_PRIMARY) == 0) {
+        ALOGE("prepareAllDisplays: Unable to find primary HWC1 display");
+        return false;
+    }
+
+    // Build an array of hwc_display_contents_1 to call prepare() on HWC1.
+    mHwc1Contents.clear();
+
+    // Always push the primary display
+    auto primaryDisplayId = mHwc1DisplayMap[HWC_DISPLAY_PRIMARY];
+    auto& primaryDisplay = mDisplays[primaryDisplayId];
+    mHwc1Contents.push_back(primaryDisplay->getDisplayContents());
+
+    // Push the external display, if present
+    if (mHwc1DisplayMap.count(HWC_DISPLAY_EXTERNAL) != 0) {
+        auto externalDisplayId = mHwc1DisplayMap[HWC_DISPLAY_EXTERNAL];
+        auto& externalDisplay = mDisplays[externalDisplayId];
+        mHwc1Contents.push_back(externalDisplay->getDisplayContents());
+    } else {
+        // Even if an external display isn't present, we still need to send
+        // at least two displays down to HWC1
+        mHwc1Contents.push_back(nullptr);
+    }
+
+    // Push the hardware virtual display, if supported and present
+    if (mHwc1MinorVersion >= 3) {
+        if (mHwc1DisplayMap.count(HWC_DISPLAY_VIRTUAL) != 0) {
+            auto virtualDisplayId = mHwc1DisplayMap[HWC_DISPLAY_VIRTUAL];
+            auto& virtualDisplay = mDisplays[virtualDisplayId];
+            mHwc1Contents.push_back(virtualDisplay->getDisplayContents());
+        } else {
+            mHwc1Contents.push_back(nullptr);
+        }
+    }
+
+    for (auto& displayContents : mHwc1Contents) {
+        if (!displayContents) {
+            continue;
+        }
+
+        ALOGV("Display %zd layers:", mHwc1Contents.size() - 1);
+        for (size_t l = 0; l < displayContents->numHwLayers; ++l) {
+            auto& layer = displayContents->hwLayers[l];
+            ALOGV("  %zd: %d", l, layer.compositionType);
+        }
+    }
+
+    ALOGV("Calling HWC1 prepare");
+    {
+        ATRACE_NAME("HWC1 prepare");
+        mHwc1Device->prepare(mHwc1Device, mHwc1Contents.size(),
+                mHwc1Contents.data());
+    }
+
+    for (size_t c = 0; c < mHwc1Contents.size(); ++c) {
+        auto& contents = mHwc1Contents[c];
+        if (!contents) {
+            continue;
+        }
+        ALOGV("Display %zd layers:", c);
+        for (size_t l = 0; l < contents->numHwLayers; ++l) {
+            ALOGV("  %zd: %d", l, contents->hwLayers[l].compositionType);
+        }
+    }
+
+    // Return the received contents to their respective displays
+    for (size_t hwc1Id = 0; hwc1Id < mHwc1Contents.size(); ++hwc1Id) {
+        if (mHwc1Contents[hwc1Id] == nullptr) {
+            continue;
+        }
+
+        auto displayId = mHwc1DisplayMap[hwc1Id];
+        auto& display = mDisplays[displayId];
+        display->generateChanges();
+    }
+
+    return true;
+}
+
+void dumpHWC1Message(hwc_composer_device_1* device, size_t numDisplays,
+                     hwc_display_contents_1_t** displays) {
+    ALOGV("*****************************");
+    size_t displayId = 0;
+    while (displayId < numDisplays) {
+        hwc_display_contents_1_t* display = displays[displayId];
+
+        ALOGV("hwc_display_contents_1_t[%zu] @0x%p", displayId, display);
+        if (display == nullptr) {
+            displayId++;
+            continue;
+        }
+        ALOGV("  retirefd:0x%08x", display->retireFenceFd);
+        ALOGV("  outbuf  :0x%p", display->outbuf);
+        ALOGV("  outbuffd:0x%08x", display->outbufAcquireFenceFd);
+        ALOGV("  flags   :0x%08x", display->flags);
+        for(size_t layerId=0 ; layerId < display->numHwLayers ; layerId++) {
+            hwc_layer_1_t& layer = display->hwLayers[layerId];
+            ALOGV("    Layer[%zu]:", layerId);
+            ALOGV("      composition        : 0x%08x", layer.compositionType);
+            ALOGV("      hints              : 0x%08x", layer.hints);
+            ALOGV("      flags              : 0x%08x", layer.flags);
+            ALOGV("      handle             : 0x%p", layer.handle);
+            ALOGV("      transform          : 0x%08x", layer.transform);
+            ALOGV("      blending           : 0x%08x", layer.blending);
+            ALOGV("      sourceCropf        : %f, %f, %f, %f",
+                  layer.sourceCropf.left,
+                  layer.sourceCropf.top,
+                  layer.sourceCropf.right,
+                  layer.sourceCropf.bottom);
+            ALOGV("      displayFrame       : %d, %d, %d, %d",
+                  layer.displayFrame.left,
+                  layer.displayFrame.left,
+                  layer.displayFrame.left,
+                  layer.displayFrame.left);
+            hwc_region_t& visReg = layer.visibleRegionScreen;
+            ALOGV("      visibleRegionScreen: #0x%08zx[@0x%p]",
+                  visReg.numRects,
+                  visReg.rects);
+            for (size_t visRegId=0; visRegId < visReg.numRects ; visRegId++) {
+                if (layer.visibleRegionScreen.rects == nullptr) {
+                    ALOGV("        null");
+                } else {
+                    ALOGV("        visibleRegionScreen[%zu] %d, %d, %d, %d",
+                          visRegId,
+                          visReg.rects[visRegId].left,
+                          visReg.rects[visRegId].top,
+                          visReg.rects[visRegId].right,
+                          visReg.rects[visRegId].bottom);
+                }
+            }
+            ALOGV("      acquireFenceFd     : 0x%08x", layer.acquireFenceFd);
+            ALOGV("      releaseFenceFd     : 0x%08x", layer.releaseFenceFd);
+            ALOGV("      planeAlpha         : 0x%08x", layer.planeAlpha);
+            if (getMinorVersion(device) < 5)
+               continue;
+            ALOGV("      surfaceDamage      : #0x%08zx[@0x%p]",
+                  layer.surfaceDamage.numRects,
+                  layer.surfaceDamage.rects);
+            for (size_t sdId=0; sdId < layer.surfaceDamage.numRects ; sdId++) {
+                if (layer.surfaceDamage.rects == nullptr) {
+                    ALOGV("      null");
+                } else {
+                    ALOGV("      surfaceDamage[%zu] %d, %d, %d, %d",
+                          sdId,
+                          layer.surfaceDamage.rects[sdId].left,
+                          layer.surfaceDamage.rects[sdId].top,
+                          layer.surfaceDamage.rects[sdId].right,
+                          layer.surfaceDamage.rects[sdId].bottom);
+                }
+            }
+        }
+        displayId++;
+    }
+    ALOGV("-----------------------------");
+}
+
+Error HWC2On1Adapter::setAllDisplays() {
+    ATRACE_CALL();
+
+    std::unique_lock<std::recursive_timed_mutex> lock(mStateMutex);
+
+    // Make sure we're ready to validate
+    for (size_t hwc1Id = 0; hwc1Id < mHwc1Contents.size(); ++hwc1Id) {
+        if (mHwc1Contents[hwc1Id] == nullptr) {
+            continue;
+        }
+
+        auto displayId = mHwc1DisplayMap[hwc1Id];
+        auto& display = mDisplays[displayId];
+        Error error = display->set(*mHwc1Contents[hwc1Id]);
+        if (error != Error::None) {
+            ALOGE("setAllDisplays: Failed to set display %zd: %s", hwc1Id,
+                    to_string(error).c_str());
+            return error;
+        }
+    }
+
+    ALOGV("Calling HWC1 set");
+    {
+        ATRACE_NAME("HWC1 set");
+        //dumpHWC1Message(mHwc1Device, mHwc1Contents.size(), mHwc1Contents.data());
+        mHwc1Device->set(mHwc1Device, mHwc1Contents.size(),
+                mHwc1Contents.data());
+    }
+
+    // Add retire and release fences
+    for (size_t hwc1Id = 0; hwc1Id < mHwc1Contents.size(); ++hwc1Id) {
+        if (mHwc1Contents[hwc1Id] == nullptr) {
+            continue;
+        }
+
+        auto displayId = mHwc1DisplayMap[hwc1Id];
+        auto& display = mDisplays[displayId];
+        auto retireFenceFd = mHwc1Contents[hwc1Id]->retireFenceFd;
+        ALOGV("setAllDisplays: Adding retire fence %d to display %zd",
+                retireFenceFd, hwc1Id);
+        display->addRetireFence(mHwc1Contents[hwc1Id]->retireFenceFd);
+        display->addReleaseFences(*mHwc1Contents[hwc1Id]);
+    }
+
+    return Error::None;
+}
+
+void HWC2On1Adapter::hwc1Invalidate() {
+    ALOGV("Received hwc1Invalidate");
+
+    std::unique_lock<std::recursive_timed_mutex> lock(mStateMutex);
+
+    // If the HWC2-side callback hasn't been registered yet, buffer this until
+    // it is registered.
+    if (mCallbacks.count(Callback::Refresh) == 0) {
+        mHasPendingInvalidate = true;
+        return;
+    }
+
+    const auto& callbackInfo = mCallbacks[Callback::Refresh];
+    std::vector<hwc2_display_t> displays;
+    for (const auto& displayPair : mDisplays) {
+        displays.emplace_back(displayPair.first);
+    }
+
+    // Call back without the state lock held.
+    lock.unlock();
+
+    auto refresh = reinterpret_cast<HWC2_PFN_REFRESH>(callbackInfo.pointer);
+    for (auto display : displays) {
+        refresh(callbackInfo.data, display);
+    }
+}
+
+void HWC2On1Adapter::hwc1Vsync(int hwc1DisplayId, int64_t timestamp) {
+    ALOGV("Received hwc1Vsync(%d, %" PRId64 ")", hwc1DisplayId, timestamp);
+
+    std::unique_lock<std::recursive_timed_mutex> lock(mStateMutex);
+
+    // If the HWC2-side callback hasn't been registered yet, buffer this until
+    // it is registered.
+    if (mCallbacks.count(Callback::Vsync) == 0) {
+        mPendingVsyncs.emplace_back(hwc1DisplayId, timestamp);
+        return;
+    }
+
+    if (mHwc1DisplayMap.count(hwc1DisplayId) == 0) {
+        ALOGE("hwc1Vsync: Couldn't find display for HWC1 id %d", hwc1DisplayId);
+        return;
+    }
+
+    const auto& callbackInfo = mCallbacks[Callback::Vsync];
+    auto displayId = mHwc1DisplayMap[hwc1DisplayId];
+
+    // Call back without the state lock held.
+    lock.unlock();
+
+    auto vsync = reinterpret_cast<HWC2_PFN_VSYNC>(callbackInfo.pointer);
+    vsync(callbackInfo.data, displayId, timestamp);
+}
+
+void HWC2On1Adapter::hwc1Hotplug(int hwc1DisplayId, int connected) {
+    ALOGV("Received hwc1Hotplug(%d, %d)", hwc1DisplayId, connected);
+
+    if (hwc1DisplayId != HWC_DISPLAY_EXTERNAL) {
+        ALOGE("hwc1Hotplug: Received hotplug for non-external display");
+        return;
+    }
+
+    std::unique_lock<std::recursive_timed_mutex> lock(mStateMutex);
+
+    // If the HWC2-side callback hasn't been registered yet, buffer this until
+    // it is registered
+    if (mCallbacks.count(Callback::Hotplug) == 0) {
+        mPendingHotplugs.emplace_back(hwc1DisplayId, connected);
+        return;
+    }
+
+    hwc2_display_t displayId = UINT64_MAX;
+    if (mHwc1DisplayMap.count(hwc1DisplayId) == 0) {
+        if (connected == 0) {
+            ALOGW("hwc1Hotplug: Received disconnect for unconnected display");
+            return;
+        }
+
+        // Create a new display on connect
+        auto display = std::make_shared<HWC2On1Adapter::Display>(*this,
+                HWC2::DisplayType::Physical);
+        display->setHwc1Id(HWC_DISPLAY_EXTERNAL);
+        display->populateConfigs();
+        displayId = display->getId();
+        mHwc1DisplayMap[HWC_DISPLAY_EXTERNAL] = displayId;
+        mDisplays.emplace(displayId, std::move(display));
+    } else {
+        if (connected != 0) {
+            ALOGW("hwc1Hotplug: Received connect for previously connected "
+                    "display");
+            return;
+        }
+
+        // Disconnect an existing display
+        displayId = mHwc1DisplayMap[hwc1DisplayId];
+        mHwc1DisplayMap.erase(HWC_DISPLAY_EXTERNAL);
+        mDisplays.erase(displayId);
+    }
+
+    const auto& callbackInfo = mCallbacks[Callback::Hotplug];
+
+    // Call back without the state lock held
+    lock.unlock();
+
+    auto hotplug = reinterpret_cast<HWC2_PFN_HOTPLUG>(callbackInfo.pointer);
+    auto hwc2Connected = (connected == 0) ?
+            HWC2::Connection::Disconnected : HWC2::Connection::Connected;
+    hotplug(callbackInfo.data, displayId, static_cast<int32_t>(hwc2Connected));
+}
+} // namespace android
diff --git a/graphics/composer/2.1/utils/hwc2on1adapter/MiniFence.cpp b/graphics/composer/2.1/utils/hwc2on1adapter/MiniFence.cpp
new file mode 100644
index 0000000..dfbe4d6
--- /dev/null
+++ b/graphics/composer/2.1/utils/hwc2on1adapter/MiniFence.cpp
@@ -0,0 +1,42 @@
+/*
+ * Copyright (C) 2017 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 "hwc2on1adapter/MiniFence.h"
+
+#include <unistd.h>
+
+namespace android {
+
+const sp<MiniFence> MiniFence::NO_FENCE = sp<MiniFence>(new MiniFence);
+
+MiniFence::MiniFence() :
+    mFenceFd(-1) {
+}
+
+MiniFence::MiniFence(int fenceFd) :
+    mFenceFd(fenceFd) {
+}
+
+MiniFence::~MiniFence() {
+    if (mFenceFd != -1) {
+        close(mFenceFd);
+    }
+}
+
+int MiniFence::dup() const {
+    return ::dup(mFenceFd);
+}
+}
diff --git a/graphics/composer/2.1/utils/hwc2on1adapter/include/hwc2on1adapter/HWC2On1Adapter.h b/graphics/composer/2.1/utils/hwc2on1adapter/include/hwc2on1adapter/HWC2On1Adapter.h
new file mode 100644
index 0000000..3badfce
--- /dev/null
+++ b/graphics/composer/2.1/utils/hwc2on1adapter/include/hwc2on1adapter/HWC2On1Adapter.h
@@ -0,0 +1,738 @@
+/*
+ * Copyright 2015 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.
+ */
+
+#ifndef ANDROID_SF_HWC2_ON_1_ADAPTER_H
+#define ANDROID_SF_HWC2_ON_1_ADAPTER_H
+
+#define HWC2_INCLUDE_STRINGIFICATION
+#define HWC2_USE_CPP11
+#include <hardware/hwcomposer2.h>
+#undef HWC2_INCLUDE_STRINGIFICATION
+#undef HWC2_USE_CPP11
+
+#include "MiniFence.h"
+
+#include <atomic>
+#include <map>
+#include <mutex>
+#include <queue>
+#include <set>
+#include <unordered_map>
+#include <unordered_set>
+#include <vector>
+
+struct hwc_composer_device_1;
+struct hwc_display_contents_1;
+struct hwc_layer_1;
+
+namespace android {
+
+// For devices unable to provide an implementation of HWC2 (see hwcomposer2.h),
+// we provide an adapter able to talk to HWC1 (see hwcomposer.h). It translates
+// streamed function calls ala HWC2 model to batched array of structs calls ala
+// HWC1 model.
+class HWC2On1Adapter : public hwc2_device_t
+{
+public:
+    explicit HWC2On1Adapter(struct hwc_composer_device_1* hwc1Device);
+    ~HWC2On1Adapter();
+
+    struct hwc_composer_device_1* getHwc1Device() const { return mHwc1Device; }
+    uint8_t getHwc1MinorVersion() const { return mHwc1MinorVersion; }
+
+private:
+    static inline HWC2On1Adapter* getAdapter(hwc2_device_t* device) {
+        return static_cast<HWC2On1Adapter*>(device);
+    }
+
+    // getCapabilities
+
+    void doGetCapabilities(uint32_t* outCount,
+            int32_t* /*hwc2_capability_t*/ outCapabilities);
+    static void getCapabilitiesHook(hwc2_device_t* device, uint32_t* outCount,
+            int32_t* /*hwc2_capability_t*/ outCapabilities) {
+        getAdapter(device)->doGetCapabilities(outCount, outCapabilities);
+    }
+
+    bool supportsBackgroundColor() {
+        return mHwc1SupportsBackgroundColor;
+    }
+
+    // getFunction
+
+    hwc2_function_pointer_t doGetFunction(HWC2::FunctionDescriptor descriptor);
+    static hwc2_function_pointer_t getFunctionHook(hwc2_device_t* device,
+            int32_t intDesc) {
+        auto descriptor = static_cast<HWC2::FunctionDescriptor>(intDesc);
+        return getAdapter(device)->doGetFunction(descriptor);
+    }
+
+    // Device functions
+
+    HWC2::Error createVirtualDisplay(uint32_t width, uint32_t height,
+            hwc2_display_t* outDisplay);
+    static int32_t createVirtualDisplayHook(hwc2_device_t* device,
+            uint32_t width, uint32_t height, int32_t* /*format*/,
+            hwc2_display_t* outDisplay) {
+        // HWC1 implementations cannot override the buffer format requested by
+        // the consumer
+        auto error = getAdapter(device)->createVirtualDisplay(width, height,
+                outDisplay);
+        return static_cast<int32_t>(error);
+    }
+
+    HWC2::Error destroyVirtualDisplay(hwc2_display_t display);
+    static int32_t destroyVirtualDisplayHook(hwc2_device_t* device,
+            hwc2_display_t display) {
+        auto error = getAdapter(device)->destroyVirtualDisplay(display);
+        return static_cast<int32_t>(error);
+    }
+
+    std::string mDumpString;
+    void dump(uint32_t* outSize, char* outBuffer);
+    static void dumpHook(hwc2_device_t* device, uint32_t* outSize,
+            char* outBuffer) {
+        getAdapter(device)->dump(outSize, outBuffer);
+    }
+
+    uint32_t getMaxVirtualDisplayCount();
+    static uint32_t getMaxVirtualDisplayCountHook(hwc2_device_t* device) {
+        return getAdapter(device)->getMaxVirtualDisplayCount();
+    }
+
+    HWC2::Error registerCallback(HWC2::Callback descriptor,
+            hwc2_callback_data_t callbackData, hwc2_function_pointer_t pointer);
+    static int32_t registerCallbackHook(hwc2_device_t* device,
+            int32_t intDesc, hwc2_callback_data_t callbackData,
+            hwc2_function_pointer_t pointer) {
+        auto descriptor = static_cast<HWC2::Callback>(intDesc);
+        auto error = getAdapter(device)->registerCallback(descriptor,
+                callbackData, pointer);
+        return static_cast<int32_t>(error);
+    }
+
+    // Display functions
+
+    class Layer;
+
+    class SortLayersByZ {
+        public:
+            bool operator()(const std::shared_ptr<Layer>& lhs,
+                    const std::shared_ptr<Layer>& rhs);
+    };
+
+    // The semantics of the fences returned by the device differ between
+    // hwc1.set() and hwc2.present(). Read hwcomposer.h and hwcomposer2.h
+    // for more information.
+    //
+    // Release fences in hwc1 are obtained on set() for a frame n and signaled
+    // when the layer buffer is not needed for read operations anymore
+    // (typically on frame n+1). In HWC2, release fences are obtained with a
+    // special call after present() for frame n. These fences signal
+    // on frame n: More specifically, the fence for a given buffer provided in
+    // frame n will signal when the prior buffer is no longer required.
+    //
+    // A retire fence (HWC1) is signaled when a composition is replaced
+    // on the panel whereas a present fence (HWC2) is signaled when a
+    // composition starts to be displayed on a panel.
+    //
+    // The HWC2to1Adapter emulates the new fence semantics for a frame
+    // n by returning the fence from frame n-1. For frame 0, the adapter
+    // returns NO_FENCE.
+    class DeferredFence {
+        public:
+            DeferredFence()
+              : mFences({MiniFence::NO_FENCE, MiniFence::NO_FENCE}) {}
+
+            void add(int32_t fenceFd) {
+                mFences.emplace(new MiniFence(fenceFd));
+                mFences.pop();
+            }
+
+            const sp<MiniFence>& get() const {
+                return mFences.front();
+            }
+
+        private:
+            // There are always two fences in this queue.
+            std::queue<sp<MiniFence>> mFences;
+    };
+
+    class FencedBuffer {
+        public:
+            FencedBuffer() : mBuffer(nullptr), mFence(MiniFence::NO_FENCE) {}
+
+            void setBuffer(buffer_handle_t buffer) { mBuffer = buffer; }
+            void setFence(int fenceFd) { mFence = new MiniFence(fenceFd); }
+
+            buffer_handle_t getBuffer() const { return mBuffer; }
+            int getFence() const { return mFence->dup(); }
+
+        private:
+            buffer_handle_t mBuffer;
+            sp<MiniFence> mFence;
+    };
+
+    class Display {
+        public:
+            Display(HWC2On1Adapter& device, HWC2::DisplayType type);
+
+            hwc2_display_t getId() const { return mId; }
+            HWC2On1Adapter& getDevice() const { return mDevice; }
+
+            // Does not require locking because it is set before adding the
+            // Displays to the Adapter's list of displays
+            void setHwc1Id(int32_t id) { mHwc1Id = id; }
+            int32_t getHwc1Id() const { return mHwc1Id; }
+
+            // HWC2 Display functions
+            HWC2::Error acceptChanges();
+            HWC2::Error createLayer(hwc2_layer_t* outLayerId);
+            HWC2::Error destroyLayer(hwc2_layer_t layerId);
+            HWC2::Error getActiveConfig(hwc2_config_t* outConfigId);
+            HWC2::Error getAttribute(hwc2_config_t configId,
+                    HWC2::Attribute attribute, int32_t* outValue);
+            HWC2::Error getChangedCompositionTypes(uint32_t* outNumElements,
+                    hwc2_layer_t* outLayers, int32_t* outTypes);
+            HWC2::Error getColorModes(uint32_t* outNumModes, int32_t* outModes);
+            HWC2::Error getConfigs(uint32_t* outNumConfigs,
+                    hwc2_config_t* outConfigIds);
+            HWC2::Error getDozeSupport(int32_t* outSupport);
+            HWC2::Error getHdrCapabilities(uint32_t* outNumTypes,
+                    int32_t* outTypes, float* outMaxLuminance,
+                    float* outMaxAverageLuminance, float* outMinLuminance);
+            HWC2::Error getName(uint32_t* outSize, char* outName);
+            HWC2::Error getReleaseFences(uint32_t* outNumElements,
+                    hwc2_layer_t* outLayers, int32_t* outFences);
+            HWC2::Error getRequests(int32_t* outDisplayRequests,
+                    uint32_t* outNumElements, hwc2_layer_t* outLayers,
+                    int32_t* outLayerRequests);
+            HWC2::Error getType(int32_t* outType);
+
+            // Since HWC1 "presents" (called "set" in HWC1) all Displays
+            // at once, the first call to any Display::present will trigger
+            // present() on all Displays in the Device. Subsequent calls without
+            // first calling validate() are noop (except for duping/returning
+            // the retire fence).
+            HWC2::Error present(int32_t* outRetireFence);
+
+            HWC2::Error setActiveConfig(hwc2_config_t configId);
+            HWC2::Error setClientTarget(buffer_handle_t target,
+                    int32_t acquireFence, int32_t dataspace,
+                    hwc_region_t damage);
+            HWC2::Error setColorMode(android_color_mode_t mode);
+            HWC2::Error setColorTransform(android_color_transform_t hint);
+            HWC2::Error setOutputBuffer(buffer_handle_t buffer,
+                    int32_t releaseFence);
+            HWC2::Error setPowerMode(HWC2::PowerMode mode);
+            HWC2::Error setVsyncEnabled(HWC2::Vsync enabled);
+
+            // Since HWC1 "validates" (called "prepare" in HWC1) all Displays
+            // at once, the first call to any Display::validate() will trigger
+            // validate() on all other Displays in the Device.
+            HWC2::Error validate(uint32_t* outNumTypes,
+                    uint32_t* outNumRequests);
+
+            HWC2::Error updateLayerZ(hwc2_layer_t layerId, uint32_t z);
+
+            HWC2::Error getClientTargetSupport(uint32_t width, uint32_t height,
+                     int32_t format, int32_t dataspace);
+
+            // Read configs from HWC1 device
+            void populateConfigs();
+
+            // Set configs for a virtual display
+            void populateConfigs(uint32_t width, uint32_t height);
+
+            bool prepare();
+
+            // Called after hwc.prepare() with responses from the device.
+            void generateChanges();
+
+            bool hasChanges() const;
+            HWC2::Error set(hwc_display_contents_1& hwcContents);
+            void addRetireFence(int fenceFd);
+            void addReleaseFences(const hwc_display_contents_1& hwcContents);
+
+            bool hasColorTransform() const;
+
+            std::string dump() const;
+
+            // Return a rect from the pool allocated during validate()
+            hwc_rect_t* GetRects(size_t numRects);
+
+            hwc_display_contents_1* getDisplayContents();
+
+            void markGeometryChanged() { mGeometryChanged = true; }
+            void resetGeometryMarker() { mGeometryChanged = false;}
+        private:
+            class Config {
+                public:
+                    Config(Display& display)
+                      : mDisplay(display),
+                        mId(0),
+                        mAttributes() {}
+
+                    bool isOnDisplay(const Display& display) const {
+                        return display.getId() == mDisplay.getId();
+                    }
+
+                    void setAttribute(HWC2::Attribute attribute, int32_t value);
+                    int32_t getAttribute(HWC2::Attribute attribute) const;
+
+                    void setHwc1Id(uint32_t id);
+                    bool hasHwc1Id(uint32_t id) const;
+                    HWC2::Error getColorModeForHwc1Id(uint32_t id,
+                            android_color_mode_t *outMode) const;
+                    HWC2::Error getHwc1IdForColorMode(android_color_mode_t mode,
+                            uint32_t* outId) const;
+
+                    void setId(hwc2_config_t id) { mId = id; }
+                    hwc2_config_t getId() const { return mId; }
+
+                    // Attempts to merge two configs that differ only in color
+                    // mode. Returns whether the merge was successful
+                    bool merge(const Config& other);
+
+                    std::set<android_color_mode_t> getColorModes() const;
+
+                    // splitLine divides the output into two lines suitable for
+                    // dumpsys SurfaceFlinger
+                    std::string toString(bool splitLine = false) const;
+
+                private:
+                    Display& mDisplay;
+                    hwc2_config_t mId;
+                    std::unordered_map<HWC2::Attribute, int32_t> mAttributes;
+
+                    // Maps from color transform to HWC1 config ID
+                    std::unordered_map<android_color_mode_t, uint32_t> mHwc1Ids;
+            };
+
+            // Stores changes requested from the device upon calling prepare().
+            // Handles change request to:
+            //   - Layer composition type.
+            //   - Layer hints.
+            class Changes {
+                public:
+                    uint32_t getNumTypes() const {
+                        return static_cast<uint32_t>(mTypeChanges.size());
+                    }
+
+                    uint32_t getNumLayerRequests() const {
+                        return static_cast<uint32_t>(mLayerRequests.size());
+                    }
+
+                    const std::unordered_map<hwc2_layer_t, HWC2::Composition>&
+                            getTypeChanges() const {
+                        return mTypeChanges;
+                    }
+
+                    const std::unordered_map<hwc2_layer_t, HWC2::LayerRequest>&
+                            getLayerRequests() const {
+                        return mLayerRequests;
+                    }
+
+                    void addTypeChange(hwc2_layer_t layerId,
+                            HWC2::Composition type) {
+                        mTypeChanges.insert({layerId, type});
+                    }
+
+                    void clearTypeChanges() { mTypeChanges.clear(); }
+
+                    void addLayerRequest(hwc2_layer_t layerId,
+                            HWC2::LayerRequest request) {
+                        mLayerRequests.insert({layerId, request});
+                    }
+
+                private:
+                    std::unordered_map<hwc2_layer_t, HWC2::Composition>
+                            mTypeChanges;
+                    std::unordered_map<hwc2_layer_t, HWC2::LayerRequest>
+                            mLayerRequests;
+            };
+
+            std::shared_ptr<const Config>
+                    getConfig(hwc2_config_t configId) const;
+
+            void populateColorModes();
+            void initializeActiveConfig();
+
+            // Creates a bi-directional mapping between index in HWC1
+            // prepare/set array and Layer object. Stores mapping in
+            // mHwc1LayerMap and also updates Layer's attribute mHwc1Id.
+            void assignHwc1LayerIds();
+
+            // Called after a response to prepare() has been received:
+            // Ingest composition type changes requested by the device.
+            void updateTypeChanges(const struct hwc_layer_1& hwc1Layer,
+                    const Layer& layer);
+
+            // Called after a response to prepare() has been received:
+            // Ingest layer hint changes requested by the device.
+            void updateLayerRequests(const struct hwc_layer_1& hwc1Layer,
+                    const Layer& layer);
+
+            // Set all fields in HWC1 comm array for layer containing the
+            // HWC_FRAMEBUFFER_TARGET (always the last layer).
+            void prepareFramebufferTarget();
+
+            // Display ID generator.
+            static std::atomic<hwc2_display_t> sNextId;
+            const hwc2_display_t mId;
+
+
+            HWC2On1Adapter& mDevice;
+
+            // The state of this display should only be modified from
+            // SurfaceFlinger's main loop, with the exception of when dump is
+            // called. To prevent a bad state from crashing us during a dump
+            // call, all public calls into Display must acquire this mutex.
+            //
+            // It is recursive because we don't want to deadlock in validate
+            // (or present) when we call HWC2On1Adapter::prepareAllDisplays
+            // (or setAllDisplays), which calls back into Display functions
+            // which require locking.
+            mutable std::recursive_mutex mStateMutex;
+
+            // Allocate RAM able to store all layers and rects used for
+            // communication with HWC1. Place allocated RAM in variable
+            // mHwc1RequestedContents.
+            void allocateRequestedContents();
+
+            // Array of structs exchanged between client and hwc1 device.
+            // Sent to device upon calling prepare().
+            std::unique_ptr<hwc_display_contents_1> mHwc1RequestedContents;
+    private:
+            DeferredFence mRetireFence;
+
+            // Will only be non-null after the Display has been validated and
+            // before it has been presented
+            std::unique_ptr<Changes> mChanges;
+
+            int32_t mHwc1Id;
+
+            std::vector<std::shared_ptr<Config>> mConfigs;
+            std::shared_ptr<const Config> mActiveConfig;
+            std::set<android_color_mode_t> mColorModes;
+            android_color_mode_t mActiveColorMode;
+            std::string mName;
+            HWC2::DisplayType mType;
+            HWC2::PowerMode mPowerMode;
+            HWC2::Vsync mVsyncEnabled;
+
+            // Used to populate HWC1 HWC_FRAMEBUFFER_TARGET layer
+            FencedBuffer mClientTarget;
+
+
+            FencedBuffer mOutputBuffer;
+
+            bool mHasColorTransform;
+
+            // All layers this Display is aware of.
+            std::multiset<std::shared_ptr<Layer>, SortLayersByZ> mLayers;
+
+            // Mapping between layer index in array of hwc_display_contents_1*
+            // passed to HWC1 during validate/set and Layer object.
+            std::unordered_map<size_t, std::shared_ptr<Layer>> mHwc1LayerMap;
+
+            // All communication with HWC1 via prepare/set is done with one
+            // alloc. This pointer is pointing to a pool of hwc_rect_t.
+            size_t mNumAvailableRects;
+            hwc_rect_t* mNextAvailableRect;
+
+            // True if any of the Layers contained in this Display have been
+            // updated with anything other than a buffer since last call to
+            // Display::set()
+            bool mGeometryChanged;
+    };
+
+    // Utility template calling a Display object method directly based on the
+    // hwc2_display_t displayId parameter.
+    template <typename ...Args>
+    static int32_t callDisplayFunction(hwc2_device_t* device,
+            hwc2_display_t displayId, HWC2::Error (Display::*member)(Args...),
+            Args... args) {
+        auto display = getAdapter(device)->getDisplay(displayId);
+        if (!display) {
+            return static_cast<int32_t>(HWC2::Error::BadDisplay);
+        }
+        auto error = ((*display).*member)(std::forward<Args>(args)...);
+        return static_cast<int32_t>(error);
+    }
+
+    template <typename MF, MF memFunc, typename ...Args>
+    static int32_t displayHook(hwc2_device_t* device, hwc2_display_t displayId,
+            Args... args) {
+        return HWC2On1Adapter::callDisplayFunction(device, displayId, memFunc,
+                std::forward<Args>(args)...);
+    }
+
+    static int32_t getDisplayAttributeHook(hwc2_device_t* device,
+            hwc2_display_t display, hwc2_config_t config,
+            int32_t intAttribute, int32_t* outValue) {
+        auto attribute = static_cast<HWC2::Attribute>(intAttribute);
+        return callDisplayFunction(device, display, &Display::getAttribute,
+                config, attribute, outValue);
+    }
+
+    static int32_t setColorTransformHook(hwc2_device_t* device,
+            hwc2_display_t display, const float* /*matrix*/,
+            int32_t /*android_color_transform_t*/ intHint) {
+        // We intentionally throw away the matrix, because if the hint is
+        // anything other than IDENTITY, we have to fall back to client
+        // composition anyway
+        auto hint = static_cast<android_color_transform_t>(intHint);
+        return callDisplayFunction(device, display, &Display::setColorTransform,
+                hint);
+    }
+
+    static int32_t setColorModeHook(hwc2_device_t* device,
+            hwc2_display_t display, int32_t /*android_color_mode_t*/ intMode) {
+        auto mode = static_cast<android_color_mode_t>(intMode);
+        return callDisplayFunction(device, display, &Display::setColorMode,
+                mode);
+    }
+
+    static int32_t setPowerModeHook(hwc2_device_t* device,
+            hwc2_display_t display, int32_t intMode) {
+        auto mode = static_cast<HWC2::PowerMode>(intMode);
+        return callDisplayFunction(device, display, &Display::setPowerMode,
+                mode);
+    }
+
+    static int32_t setVsyncEnabledHook(hwc2_device_t* device,
+            hwc2_display_t display, int32_t intEnabled) {
+        auto enabled = static_cast<HWC2::Vsync>(intEnabled);
+        return callDisplayFunction(device, display, &Display::setVsyncEnabled,
+                enabled);
+    }
+
+    class Layer {
+        public:
+            explicit Layer(Display& display);
+
+            bool operator==(const Layer& other) { return mId == other.mId; }
+            bool operator!=(const Layer& other) { return !(*this == other); }
+
+            hwc2_layer_t getId() const { return mId; }
+            Display& getDisplay() const { return mDisplay; }
+
+            // HWC2 Layer functions
+            HWC2::Error setBuffer(buffer_handle_t buffer, int32_t acquireFence);
+            HWC2::Error setCursorPosition(int32_t x, int32_t y);
+            HWC2::Error setSurfaceDamage(hwc_region_t damage);
+
+            // HWC2 Layer state functions
+            HWC2::Error setBlendMode(HWC2::BlendMode mode);
+            HWC2::Error setColor(hwc_color_t color);
+            HWC2::Error setCompositionType(HWC2::Composition type);
+            HWC2::Error setDataspace(android_dataspace_t dataspace);
+            HWC2::Error setDisplayFrame(hwc_rect_t frame);
+            HWC2::Error setPlaneAlpha(float alpha);
+            HWC2::Error setSidebandStream(const native_handle_t* stream);
+            HWC2::Error setSourceCrop(hwc_frect_t crop);
+            HWC2::Error setTransform(HWC2::Transform transform);
+            HWC2::Error setVisibleRegion(hwc_region_t visible);
+            HWC2::Error setZ(uint32_t z);
+
+            HWC2::Composition getCompositionType() const {
+                return mCompositionType;
+            }
+            uint32_t getZ() const { return mZ; }
+
+            void addReleaseFence(int fenceFd);
+            const sp<MiniFence>& getReleaseFence() const;
+
+            void setHwc1Id(size_t id) { mHwc1Id = id; }
+            size_t getHwc1Id() const { return mHwc1Id; }
+
+            // Write state to HWC1 communication struct.
+            void applyState(struct hwc_layer_1& hwc1Layer);
+
+            std::string dump() const;
+
+            std::size_t getNumVisibleRegions() { return mVisibleRegion.size(); }
+
+            std::size_t getNumSurfaceDamages() { return mSurfaceDamage.size(); }
+
+            // True if a layer cannot be properly rendered by the device due
+            // to usage of SolidColor (a.k.a BackgroundColor in HWC1).
+            bool hasUnsupportedBackgroundColor() {
+                return (mCompositionType == HWC2::Composition::SolidColor &&
+                        !mDisplay.getDevice().supportsBackgroundColor());
+            }
+        private:
+            void applyCommonState(struct hwc_layer_1& hwc1Layer);
+            void applySolidColorState(struct hwc_layer_1& hwc1Layer);
+            void applySidebandState(struct hwc_layer_1& hwc1Layer);
+            void applyBufferState(struct hwc_layer_1& hwc1Layer);
+            void applyCompositionType(struct hwc_layer_1& hwc1Layer);
+
+            static std::atomic<hwc2_layer_t> sNextId;
+            const hwc2_layer_t mId;
+            Display& mDisplay;
+
+            FencedBuffer mBuffer;
+            std::vector<hwc_rect_t> mSurfaceDamage;
+
+            HWC2::BlendMode mBlendMode;
+            hwc_color_t mColor;
+            HWC2::Composition mCompositionType;
+            hwc_rect_t mDisplayFrame;
+            float mPlaneAlpha;
+            const native_handle_t* mSidebandStream;
+            hwc_frect_t mSourceCrop;
+            HWC2::Transform mTransform;
+            std::vector<hwc_rect_t> mVisibleRegion;
+
+            uint32_t mZ;
+
+            DeferredFence mReleaseFence;
+
+            size_t mHwc1Id;
+            bool mHasUnsupportedPlaneAlpha;
+    };
+
+    // Utility tempate calling a Layer object method based on ID parameters:
+    // hwc2_display_t displayId
+    // and
+    // hwc2_layer_t layerId
+    template <typename ...Args>
+    static int32_t callLayerFunction(hwc2_device_t* device,
+            hwc2_display_t displayId, hwc2_layer_t layerId,
+            HWC2::Error (Layer::*member)(Args...), Args... args) {
+        auto result = getAdapter(device)->getLayer(displayId, layerId);
+        auto error = std::get<HWC2::Error>(result);
+        if (error == HWC2::Error::None) {
+            auto layer = std::get<Layer*>(result);
+            error = ((*layer).*member)(std::forward<Args>(args)...);
+        }
+        return static_cast<int32_t>(error);
+    }
+
+    template <typename MF, MF memFunc, typename ...Args>
+    static int32_t layerHook(hwc2_device_t* device, hwc2_display_t displayId,
+            hwc2_layer_t layerId, Args... args) {
+        return HWC2On1Adapter::callLayerFunction(device, displayId, layerId,
+                memFunc, std::forward<Args>(args)...);
+    }
+
+    // Layer state functions
+
+    static int32_t setLayerBlendModeHook(hwc2_device_t* device,
+            hwc2_display_t display, hwc2_layer_t layer, int32_t intMode) {
+        auto mode = static_cast<HWC2::BlendMode>(intMode);
+        return callLayerFunction(device, display, layer,
+                &Layer::setBlendMode, mode);
+    }
+
+    static int32_t setLayerCompositionTypeHook(hwc2_device_t* device,
+            hwc2_display_t display, hwc2_layer_t layer, int32_t intType) {
+        auto type = static_cast<HWC2::Composition>(intType);
+        return callLayerFunction(device, display, layer,
+                &Layer::setCompositionType, type);
+    }
+
+    static int32_t setLayerDataspaceHook(hwc2_device_t* device,
+            hwc2_display_t display, hwc2_layer_t layer, int32_t intDataspace) {
+        auto dataspace = static_cast<android_dataspace_t>(intDataspace);
+        return callLayerFunction(device, display, layer, &Layer::setDataspace,
+                dataspace);
+    }
+
+    static int32_t setLayerTransformHook(hwc2_device_t* device,
+            hwc2_display_t display, hwc2_layer_t layer, int32_t intTransform) {
+        auto transform = static_cast<HWC2::Transform>(intTransform);
+        return callLayerFunction(device, display, layer, &Layer::setTransform,
+                transform);
+    }
+
+    static int32_t setLayerZOrderHook(hwc2_device_t* device,
+            hwc2_display_t display, hwc2_layer_t layer, uint32_t z) {
+        return callDisplayFunction(device, display, &Display::updateLayerZ,
+                layer, z);
+    }
+
+    // Adapter internals
+
+    void populateCapabilities();
+    Display* getDisplay(hwc2_display_t id);
+    std::tuple<Layer*, HWC2::Error> getLayer(hwc2_display_t displayId,
+            hwc2_layer_t layerId);
+    void populatePrimary();
+
+    bool prepareAllDisplays();
+    std::vector<struct hwc_display_contents_1*> mHwc1Contents;
+    HWC2::Error setAllDisplays();
+
+    // Callbacks
+    void hwc1Invalidate();
+    void hwc1Vsync(int hwc1DisplayId, int64_t timestamp);
+    void hwc1Hotplug(int hwc1DisplayId, int connected);
+
+    // These are set in the constructor and before any asynchronous events are
+    // possible
+
+    struct hwc_composer_device_1* const mHwc1Device;
+    const uint8_t mHwc1MinorVersion;
+    bool mHwc1SupportsVirtualDisplays;
+    bool mHwc1SupportsBackgroundColor;
+
+    class Callbacks;
+    const std::unique_ptr<Callbacks> mHwc1Callbacks;
+
+    std::unordered_set<HWC2::Capability> mCapabilities;
+
+    // These are only accessed from the main SurfaceFlinger thread (not from
+    // callbacks or dump
+
+    std::map<hwc2_layer_t, std::shared_ptr<Layer>> mLayers;
+
+    // A HWC1 supports only one virtual display.
+    std::shared_ptr<Display> mHwc1VirtualDisplay;
+
+    // These are potentially accessed from multiple threads, and are protected
+    // by this mutex. This needs to be recursive, since the HWC1 implementation
+    // can call back into the invalidate callback on the same thread that is
+    // calling prepare.
+    std::recursive_timed_mutex mStateMutex;
+
+    struct CallbackInfo {
+        hwc2_callback_data_t data;
+        hwc2_function_pointer_t pointer;
+    };
+    std::unordered_map<HWC2::Callback, CallbackInfo> mCallbacks;
+    bool mHasPendingInvalidate;
+
+    // There is a small gap between the time the HWC1 module is started and
+    // when the callbacks for vsync and hotplugs are registered by the
+    // HWC2on1Adapter. To prevent losing events they are stored in these arrays
+    // and fed to the callback as soon as possible.
+    std::vector<std::pair<int, int64_t>> mPendingVsyncs;
+    std::vector<std::pair<int, int>> mPendingHotplugs;
+
+    // Mapping between HWC1 display id and Display objects.
+    std::map<hwc2_display_t, std::shared_ptr<Display>> mDisplays;
+
+    // Map HWC1 display type (HWC_DISPLAY_PRIMARY, HWC_DISPLAY_EXTERNAL,
+    // HWC_DISPLAY_VIRTUAL) to Display IDs generated by HWC2on1Adapter objects.
+    std::unordered_map<int, hwc2_display_t> mHwc1DisplayMap;
+};
+
+} // namespace android
+
+#endif
diff --git a/graphics/composer/2.1/utils/hwc2on1adapter/include/hwc2on1adapter/MiniFence.h b/graphics/composer/2.1/utils/hwc2on1adapter/include/hwc2on1adapter/MiniFence.h
new file mode 100644
index 0000000..75de764
--- /dev/null
+++ b/graphics/composer/2.1/utils/hwc2on1adapter/include/hwc2on1adapter/MiniFence.h
@@ -0,0 +1,59 @@
+/*
+ * Copyright (C) 2017 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.
+ */
+
+#ifndef MINIFENCE_H
+#define MINIFENCE_H
+
+#include <utils/RefBase.h>
+
+namespace android {
+
+/* MiniFence is a minimal re-implementation of Fence from libui. It exists to
+ * avoid linking the HWC2on1Adapter to libui and satisfy Treble requirements.
+ */
+class MiniFence : public LightRefBase<MiniFence> {
+public:
+    static const sp<MiniFence> NO_FENCE;
+
+    // Construct a new MiniFence object with an invalid file descriptor.
+    MiniFence();
+
+    // Construct a new MiniFence object to manage a given fence file descriptor.
+    // When the new MiniFence object is destructed the file descriptor will be
+    // closed.
+    explicit MiniFence(int fenceFd);
+
+    // Not copyable or movable.
+    MiniFence(const MiniFence& rhs) = delete;
+    MiniFence& operator=(const MiniFence& rhs) = delete;
+    MiniFence(MiniFence&& rhs) = delete;
+    MiniFence& operator=(MiniFence&& rhs) = delete;
+
+    // Return a duplicate of the fence file descriptor. The caller is
+    // responsible for closing the returned file descriptor. On error, -1 will
+    // be returned and errno will indicate the problem.
+    int dup() const;
+
+private:
+    // Only allow instantiation using ref counting.
+    friend class LightRefBase<MiniFence>;
+    ~MiniFence();
+
+    int mFenceFd;
+
+};
+}
+#endif //MINIFENCE_H
diff --git a/graphics/composer/2.1/utils/hwc2onfbadapter/Android.bp b/graphics/composer/2.1/utils/hwc2onfbadapter/Android.bp
new file mode 100644
index 0000000..73a41f7
--- /dev/null
+++ b/graphics/composer/2.1/utils/hwc2onfbadapter/Android.bp
@@ -0,0 +1,33 @@
+// Copyright 2010 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.
+
+cc_library_shared {
+    name: "libhwc2onfbadapter",
+    vendor: true,
+
+    clang: true,
+    cflags: [
+        "-Wall",
+        "-Wextra",
+        "-Werror",
+    ],
+
+    srcs: [
+        "HWC2OnFbAdapter.cpp",
+    ],
+
+    header_libs: ["libhardware_headers"],
+    shared_libs: ["liblog", "libsync"],
+    export_include_dirs: ["include"],
+}
diff --git a/graphics/composer/2.1/utils/hwc2onfbadapter/HWC2OnFbAdapter.cpp b/graphics/composer/2.1/utils/hwc2onfbadapter/HWC2OnFbAdapter.cpp
new file mode 100644
index 0000000..7c9e651
--- /dev/null
+++ b/graphics/composer/2.1/utils/hwc2onfbadapter/HWC2OnFbAdapter.cpp
@@ -0,0 +1,887 @@
+/*
+ * Copyright 2017 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 LOG_TAG "HWC2OnFbAdapter"
+
+//#define LOG_NDEBUG 0
+
+#include "hwc2onfbadapter/HWC2OnFbAdapter.h"
+
+#include <algorithm>
+#include <type_traits>
+
+#include <inttypes.h>
+#include <time.h>
+#include <sys/prctl.h>
+#include <unistd.h> // for close
+
+#include <hardware/fb.h>
+#include <log/log.h>
+#include <sync/sync.h>
+
+namespace android {
+
+namespace {
+
+void dumpHook(hwc2_device_t* device, uint32_t* outSize, char* outBuffer) {
+    auto& adapter = HWC2OnFbAdapter::cast(device);
+    if (outBuffer) {
+        *outSize = adapter.getDebugString().copy(outBuffer, *outSize);
+    } else {
+        adapter.updateDebugString();
+        *outSize = adapter.getDebugString().size();
+    }
+}
+
+int32_t registerCallbackHook(hwc2_device_t* device, int32_t descriptor,
+                             hwc2_callback_data_t callbackData, hwc2_function_pointer_t pointer) {
+    auto& adapter = HWC2OnFbAdapter::cast(device);
+    switch (descriptor) {
+        case HWC2_CALLBACK_HOTPLUG:
+            if (pointer) {
+                reinterpret_cast<HWC2_PFN_HOTPLUG>(pointer)(callbackData, adapter.getDisplayId(),
+                                                            HWC2_CONNECTION_CONNECTED);
+            }
+            break;
+        case HWC2_CALLBACK_REFRESH:
+            break;
+        case HWC2_CALLBACK_VSYNC:
+            adapter.setVsyncCallback(reinterpret_cast<HWC2_PFN_VSYNC>(pointer), callbackData);
+            break;
+        default:
+            return HWC2_ERROR_BAD_PARAMETER;
+    }
+
+    return HWC2_ERROR_NONE;
+}
+
+uint32_t getMaxVirtualDisplayCountHook(hwc2_device_t* /*device*/) {
+    return 0;
+}
+
+int32_t createVirtualDisplayHook(hwc2_device_t* /*device*/, uint32_t /*width*/, uint32_t /*height*/,
+                                 int32_t* /*format*/, hwc2_display_t* /*outDisplay*/) {
+    return HWC2_ERROR_NO_RESOURCES;
+}
+
+int32_t destroyVirtualDisplayHook(hwc2_device_t* /*device*/, hwc2_display_t /*display*/) {
+    return HWC2_ERROR_BAD_DISPLAY;
+}
+
+int32_t setOutputBufferHook(hwc2_device_t* /*device*/, hwc2_display_t /*display*/,
+                            buffer_handle_t /*buffer*/, int32_t /*releaseFence*/) {
+    return HWC2_ERROR_BAD_DISPLAY;
+}
+
+int32_t getDisplayNameHook(hwc2_device_t* device, hwc2_display_t display, uint32_t* outSize,
+                           char* outName) {
+    auto& adapter = HWC2OnFbAdapter::cast(device);
+    if (adapter.getDisplayId() != display) {
+        return HWC2_ERROR_BAD_DISPLAY;
+    }
+
+    const auto& info = adapter.getInfo();
+    if (outName) {
+        *outSize = info.name.copy(outName, *outSize);
+    } else {
+        *outSize = info.name.size();
+    }
+
+    return HWC2_ERROR_NONE;
+}
+
+int32_t getDisplayTypeHook(hwc2_device_t* device, hwc2_display_t display, int32_t* outType) {
+    auto& adapter = HWC2OnFbAdapter::cast(device);
+    if (adapter.getDisplayId() != display) {
+        return HWC2_ERROR_BAD_DISPLAY;
+    }
+
+    *outType = HWC2_DISPLAY_TYPE_PHYSICAL;
+    return HWC2_ERROR_NONE;
+}
+
+int32_t getDozeSupportHook(hwc2_device_t* device, hwc2_display_t display, int32_t* outSupport) {
+    auto& adapter = HWC2OnFbAdapter::cast(device);
+    if (adapter.getDisplayId() != display) {
+        return HWC2_ERROR_BAD_DISPLAY;
+    }
+
+    *outSupport = 0;
+    return HWC2_ERROR_NONE;
+}
+
+int32_t getHdrCapabilitiesHook(hwc2_device_t* device, hwc2_display_t display, uint32_t* outNumTypes,
+                               int32_t* /*outTypes*/, float* /*outMaxLuminance*/,
+                               float* /*outMaxAverageLuminance*/, float* /*outMinLuminance*/) {
+    auto& adapter = HWC2OnFbAdapter::cast(device);
+    if (adapter.getDisplayId() != display) {
+        return HWC2_ERROR_BAD_DISPLAY;
+    }
+
+    *outNumTypes = 0;
+    return HWC2_ERROR_NONE;
+}
+
+int32_t setPowerModeHook(hwc2_device_t* device, hwc2_display_t display, int32_t /*mode*/) {
+    auto& adapter = HWC2OnFbAdapter::cast(device);
+    if (adapter.getDisplayId() != display) {
+        return HWC2_ERROR_BAD_DISPLAY;
+    }
+
+    // pretend that it works
+    return HWC2_ERROR_NONE;
+}
+
+int32_t setVsyncEnabledHook(hwc2_device_t* device, hwc2_display_t display, int32_t enabled) {
+    auto& adapter = HWC2OnFbAdapter::cast(device);
+    if (adapter.getDisplayId() != display) {
+        return HWC2_ERROR_BAD_DISPLAY;
+    }
+
+    adapter.enableVsync(enabled == HWC2_VSYNC_ENABLE);
+    return HWC2_ERROR_NONE;
+}
+
+int32_t getColorModesHook(hwc2_device_t* device, hwc2_display_t display, uint32_t* outNumModes,
+                          int32_t* outModes) {
+    auto& adapter = HWC2OnFbAdapter::cast(device);
+    if (adapter.getDisplayId() != display) {
+        return HWC2_ERROR_BAD_DISPLAY;
+    }
+
+    if (outModes) {
+        if (*outNumModes > 0) {
+            outModes[0] = HAL_COLOR_MODE_NATIVE;
+            *outNumModes = 1;
+        }
+    } else {
+        *outNumModes = 1;
+    }
+
+    return HWC2_ERROR_NONE;
+}
+
+int32_t setColorModeHook(hwc2_device_t* device, hwc2_display_t display, int32_t mode) {
+    auto& adapter = HWC2OnFbAdapter::cast(device);
+    if (adapter.getDisplayId() != display) {
+        return HWC2_ERROR_BAD_DISPLAY;
+    }
+    if (mode != HAL_COLOR_MODE_NATIVE) {
+        return HWC2_ERROR_BAD_PARAMETER;
+    }
+
+    return HWC2_ERROR_NONE;
+}
+
+int32_t setColorTransformHook(hwc2_device_t* device, hwc2_display_t display,
+                              const float* /*matrix*/, int32_t /*hint*/) {
+    auto& adapter = HWC2OnFbAdapter::cast(device);
+    if (adapter.getDisplayId() != display) {
+        return HWC2_ERROR_BAD_DISPLAY;
+    }
+
+    // we always force client composition
+    adapter.setState(HWC2OnFbAdapter::State::MODIFIED);
+    return HWC2_ERROR_NONE;
+}
+
+int32_t getClientTargetSupportHook(hwc2_device_t* device, hwc2_display_t display, uint32_t width,
+                                   uint32_t height, int32_t format, int32_t dataspace) {
+    auto& adapter = HWC2OnFbAdapter::cast(device);
+    if (adapter.getDisplayId() != display) {
+        return HWC2_ERROR_BAD_DISPLAY;
+    }
+    if (dataspace != HAL_DATASPACE_UNKNOWN) {
+        return HWC2_ERROR_UNSUPPORTED;
+    }
+
+    const auto& info = adapter.getInfo();
+    return (info.width == width && info.height == height && info.format == format)
+            ? HWC2_ERROR_NONE
+            : HWC2_ERROR_UNSUPPORTED;
+}
+
+int32_t setClientTargetHook(hwc2_device_t* device, hwc2_display_t display, buffer_handle_t target,
+                            int32_t acquireFence, int32_t dataspace, hwc_region_t /*damage*/) {
+    if (acquireFence >= 0) {
+        sync_wait(acquireFence, -1);
+        close(acquireFence);
+    }
+
+    auto& adapter = HWC2OnFbAdapter::cast(device);
+    if (adapter.getDisplayId() != display) {
+        return HWC2_ERROR_BAD_DISPLAY;
+    }
+    if (dataspace != HAL_DATASPACE_UNKNOWN) {
+        return HWC2_ERROR_BAD_PARAMETER;
+    }
+
+    // no state change
+    adapter.setBuffer(target);
+    return HWC2_ERROR_NONE;
+}
+
+int32_t getDisplayConfigsHook(hwc2_device_t* device, hwc2_display_t display,
+                              uint32_t* outNumConfigs, hwc2_config_t* outConfigs) {
+    auto& adapter = HWC2OnFbAdapter::cast(device);
+    if (adapter.getDisplayId() != display) {
+        return HWC2_ERROR_BAD_DISPLAY;
+    }
+
+    if (outConfigs) {
+        if (*outNumConfigs > 0) {
+            outConfigs[0] = adapter.getConfigId();
+            *outNumConfigs = 1;
+        }
+    } else {
+        *outNumConfigs = 1;
+    }
+
+    return HWC2_ERROR_NONE;
+}
+
+int32_t getDisplayAttributeHook(hwc2_device_t* device, hwc2_display_t display, hwc2_config_t config,
+                                int32_t attribute, int32_t* outValue) {
+    auto& adapter = HWC2OnFbAdapter::cast(device);
+    if (adapter.getDisplayId() != display) {
+        return HWC2_ERROR_BAD_DISPLAY;
+    }
+    if (adapter.getConfigId() != config) {
+        return HWC2_ERROR_BAD_CONFIG;
+    }
+
+    const auto& info = adapter.getInfo();
+    switch (attribute) {
+        case HWC2_ATTRIBUTE_WIDTH:
+            *outValue = int32_t(info.width);
+            break;
+        case HWC2_ATTRIBUTE_HEIGHT:
+            *outValue = int32_t(info.height);
+            break;
+        case HWC2_ATTRIBUTE_VSYNC_PERIOD:
+            *outValue = int32_t(info.vsync_period_ns);
+            break;
+        case HWC2_ATTRIBUTE_DPI_X:
+            *outValue = int32_t(info.xdpi_scaled);
+            break;
+        case HWC2_ATTRIBUTE_DPI_Y:
+            *outValue = int32_t(info.ydpi_scaled);
+            break;
+        default:
+            return HWC2_ERROR_BAD_PARAMETER;
+    }
+
+    return HWC2_ERROR_NONE;
+}
+
+int32_t getActiveConfigHook(hwc2_device_t* device, hwc2_display_t display,
+                            hwc2_config_t* outConfig) {
+    auto& adapter = HWC2OnFbAdapter::cast(device);
+    if (adapter.getDisplayId() != display) {
+        return HWC2_ERROR_BAD_DISPLAY;
+    }
+
+    *outConfig = adapter.getConfigId();
+    return HWC2_ERROR_NONE;
+}
+
+int32_t setActiveConfigHook(hwc2_device_t* device, hwc2_display_t display, hwc2_config_t config) {
+    auto& adapter = HWC2OnFbAdapter::cast(device);
+    if (adapter.getDisplayId() != display) {
+        return HWC2_ERROR_BAD_DISPLAY;
+    }
+    if (adapter.getConfigId() != config) {
+        return HWC2_ERROR_BAD_CONFIG;
+    }
+
+    return HWC2_ERROR_NONE;
+}
+
+int32_t validateDisplayHook(hwc2_device_t* device, hwc2_display_t display, uint32_t* outNumTypes,
+                            uint32_t* outNumRequests) {
+    auto& adapter = HWC2OnFbAdapter::cast(device);
+    if (adapter.getDisplayId() != display) {
+        return HWC2_ERROR_BAD_DISPLAY;
+    }
+
+    const auto& dirtyLayers = adapter.getDirtyLayers();
+    *outNumTypes = dirtyLayers.size();
+    *outNumRequests = 0;
+
+    if (*outNumTypes > 0) {
+        adapter.setState(HWC2OnFbAdapter::State::VALIDATED_WITH_CHANGES);
+        return HWC2_ERROR_HAS_CHANGES;
+    } else {
+        adapter.setState(HWC2OnFbAdapter::State::VALIDATED);
+        return HWC2_ERROR_NONE;
+    }
+}
+
+int32_t getChangedCompositionTypesHook(hwc2_device_t* device, hwc2_display_t display,
+                                       uint32_t* outNumElements, hwc2_layer_t* outLayers,
+                                       int32_t* outTypes) {
+    auto& adapter = HWC2OnFbAdapter::cast(device);
+    if (adapter.getDisplayId() != display) {
+        return HWC2_ERROR_BAD_DISPLAY;
+    }
+    if (adapter.getState() == HWC2OnFbAdapter::State::MODIFIED) {
+        return HWC2_ERROR_NOT_VALIDATED;
+    }
+
+    // request client composition for all layers
+    const auto& dirtyLayers = adapter.getDirtyLayers();
+    if (outLayers && outTypes) {
+        *outNumElements = std::min(*outNumElements, uint32_t(dirtyLayers.size()));
+        auto iter = dirtyLayers.cbegin();
+        for (uint32_t i = 0; i < *outNumElements; i++) {
+            outLayers[i] = *iter++;
+            outTypes[i] = HWC2_COMPOSITION_CLIENT;
+        }
+    } else {
+        *outNumElements = dirtyLayers.size();
+    }
+
+    return HWC2_ERROR_NONE;
+}
+
+int32_t getDisplayRequestsHook(hwc2_device_t* device, hwc2_display_t display,
+                               int32_t* outDisplayRequests, uint32_t* outNumElements,
+                               hwc2_layer_t* /*outLayers*/, int32_t* /*outLayerRequests*/) {
+    auto& adapter = HWC2OnFbAdapter::cast(device);
+    if (adapter.getDisplayId() != display) {
+        return HWC2_ERROR_BAD_DISPLAY;
+    }
+    if (adapter.getState() == HWC2OnFbAdapter::State::MODIFIED) {
+        return HWC2_ERROR_NOT_VALIDATED;
+    }
+
+    *outDisplayRequests = 0;
+    *outNumElements = 0;
+    return HWC2_ERROR_NONE;
+}
+
+int32_t acceptDisplayChangesHook(hwc2_device_t* device, hwc2_display_t display) {
+    auto& adapter = HWC2OnFbAdapter::cast(device);
+    if (adapter.getDisplayId() != display) {
+        return HWC2_ERROR_BAD_DISPLAY;
+    }
+    if (adapter.getState() == HWC2OnFbAdapter::State::MODIFIED) {
+        return HWC2_ERROR_NOT_VALIDATED;
+    }
+
+    adapter.clearDirtyLayers();
+    adapter.setState(HWC2OnFbAdapter::State::VALIDATED);
+    return HWC2_ERROR_NONE;
+}
+
+int32_t presentDisplayHook(hwc2_device_t* device, hwc2_display_t display,
+                           int32_t* outPresentFence) {
+    auto& adapter = HWC2OnFbAdapter::cast(device);
+    if (adapter.getDisplayId() != display) {
+        return HWC2_ERROR_BAD_DISPLAY;
+    }
+    if (adapter.getState() != HWC2OnFbAdapter::State::VALIDATED) {
+        return HWC2_ERROR_NOT_VALIDATED;
+    }
+
+    adapter.postBuffer();
+    *outPresentFence = -1;
+
+    return HWC2_ERROR_NONE;
+}
+
+int32_t getReleaseFencesHook(hwc2_device_t* device, hwc2_display_t display,
+                             uint32_t* outNumElements, hwc2_layer_t* /*outLayers*/,
+                             int32_t* /*outFences*/) {
+    auto& adapter = HWC2OnFbAdapter::cast(device);
+    if (adapter.getDisplayId() != display) {
+        return HWC2_ERROR_BAD_DISPLAY;
+    }
+
+    *outNumElements = 0;
+    return HWC2_ERROR_NONE;
+}
+
+int32_t createLayerHook(hwc2_device_t* device, hwc2_display_t display, hwc2_layer_t* outLayer) {
+    auto& adapter = HWC2OnFbAdapter::cast(device);
+    if (adapter.getDisplayId() != display) {
+        return HWC2_ERROR_BAD_DISPLAY;
+    }
+
+    *outLayer = adapter.addLayer();
+    adapter.setState(HWC2OnFbAdapter::State::MODIFIED);
+    return HWC2_ERROR_NONE;
+}
+
+int32_t destroyLayerHook(hwc2_device_t* device, hwc2_display_t display, hwc2_layer_t layer) {
+    auto& adapter = HWC2OnFbAdapter::cast(device);
+    if (adapter.getDisplayId() != display) {
+        return HWC2_ERROR_BAD_DISPLAY;
+    }
+
+    if (adapter.removeLayer(layer)) {
+        adapter.setState(HWC2OnFbAdapter::State::MODIFIED);
+        return HWC2_ERROR_NONE;
+    } else {
+        return HWC2_ERROR_BAD_LAYER;
+    }
+}
+
+int32_t setCursorPositionHook(hwc2_device_t* device, hwc2_display_t display, hwc2_layer_t /*layer*/,
+                              int32_t /*x*/, int32_t /*y*/) {
+    auto& adapter = HWC2OnFbAdapter::cast(device);
+    if (adapter.getDisplayId() != display) {
+        return HWC2_ERROR_BAD_DISPLAY;
+    }
+
+    // always an error
+    return HWC2_ERROR_BAD_LAYER;
+}
+
+int32_t setLayerBufferHook(hwc2_device_t* device, hwc2_display_t display, hwc2_layer_t layer,
+                           buffer_handle_t /*buffer*/, int32_t acquireFence) {
+    if (acquireFence >= 0) {
+        sync_wait(acquireFence, -1);
+        close(acquireFence);
+    }
+
+    auto& adapter = HWC2OnFbAdapter::cast(device);
+    if (adapter.getDisplayId() != display) {
+        return HWC2_ERROR_BAD_DISPLAY;
+    }
+    if (!adapter.hasLayer(layer)) {
+        return HWC2_ERROR_BAD_LAYER;
+    }
+
+    // no state change
+    return HWC2_ERROR_NONE;
+}
+
+int32_t setLayerSurfaceDamageHook(hwc2_device_t* device, hwc2_display_t display, hwc2_layer_t layer,
+                                  hwc_region_t /*damage*/) {
+    auto& adapter = HWC2OnFbAdapter::cast(device);
+    if (adapter.getDisplayId() != display) {
+        return HWC2_ERROR_BAD_DISPLAY;
+    }
+    if (!adapter.hasLayer(layer)) {
+        return HWC2_ERROR_BAD_LAYER;
+    }
+
+    // no state change
+    return HWC2_ERROR_NONE;
+}
+
+int32_t setLayerCompositionTypeHook(hwc2_device_t* device, hwc2_display_t display,
+                                    hwc2_layer_t layer, int32_t type) {
+    auto& adapter = HWC2OnFbAdapter::cast(device);
+    if (adapter.getDisplayId() != display) {
+        return HWC2_ERROR_BAD_DISPLAY;
+    }
+    if (!adapter.markLayerDirty(layer, type != HWC2_COMPOSITION_CLIENT)) {
+        return HWC2_ERROR_BAD_LAYER;
+    }
+
+    adapter.setState(HWC2OnFbAdapter::State::MODIFIED);
+    return HWC2_ERROR_NONE;
+}
+
+template <typename... Args>
+int32_t setLayerStateHook(hwc2_device_t* device, hwc2_display_t display, hwc2_layer_t layer,
+                          Args... /*args*/) {
+    auto& adapter = HWC2OnFbAdapter::cast(device);
+    if (adapter.getDisplayId() != display) {
+        return HWC2_ERROR_BAD_DISPLAY;
+    }
+    if (!adapter.hasLayer(layer)) {
+        return HWC2_ERROR_BAD_LAYER;
+    }
+
+    adapter.setState(HWC2OnFbAdapter::State::MODIFIED);
+    return HWC2_ERROR_NONE;
+}
+
+template <typename PFN, typename T>
+static hwc2_function_pointer_t asFP(T function) {
+    static_assert(std::is_same<PFN, T>::value, "Incompatible function pointer");
+    return reinterpret_cast<hwc2_function_pointer_t>(function);
+}
+
+hwc2_function_pointer_t getFunctionHook(hwc2_device_t* /*device*/, int32_t descriptor) {
+    switch (descriptor) {
+        // global functions
+        case HWC2_FUNCTION_DUMP:
+            return asFP<HWC2_PFN_DUMP>(dumpHook);
+        case HWC2_FUNCTION_REGISTER_CALLBACK:
+            return asFP<HWC2_PFN_REGISTER_CALLBACK>(registerCallbackHook);
+
+        // virtual display functions
+        case HWC2_FUNCTION_GET_MAX_VIRTUAL_DISPLAY_COUNT:
+            return asFP<HWC2_PFN_GET_MAX_VIRTUAL_DISPLAY_COUNT>(getMaxVirtualDisplayCountHook);
+        case HWC2_FUNCTION_CREATE_VIRTUAL_DISPLAY:
+            return asFP<HWC2_PFN_CREATE_VIRTUAL_DISPLAY>(createVirtualDisplayHook);
+        case HWC2_FUNCTION_DESTROY_VIRTUAL_DISPLAY:
+            return asFP<HWC2_PFN_DESTROY_VIRTUAL_DISPLAY>(destroyVirtualDisplayHook);
+        case HWC2_FUNCTION_SET_OUTPUT_BUFFER:
+            return asFP<HWC2_PFN_SET_OUTPUT_BUFFER>(setOutputBufferHook);
+
+        // display functions
+        case HWC2_FUNCTION_GET_DISPLAY_NAME:
+            return asFP<HWC2_PFN_GET_DISPLAY_NAME>(getDisplayNameHook);
+        case HWC2_FUNCTION_GET_DISPLAY_TYPE:
+            return asFP<HWC2_PFN_GET_DISPLAY_TYPE>(getDisplayTypeHook);
+        case HWC2_FUNCTION_GET_DOZE_SUPPORT:
+            return asFP<HWC2_PFN_GET_DOZE_SUPPORT>(getDozeSupportHook);
+        case HWC2_FUNCTION_GET_HDR_CAPABILITIES:
+            return asFP<HWC2_PFN_GET_HDR_CAPABILITIES>(getHdrCapabilitiesHook);
+        case HWC2_FUNCTION_SET_POWER_MODE:
+            return asFP<HWC2_PFN_SET_POWER_MODE>(setPowerModeHook);
+        case HWC2_FUNCTION_SET_VSYNC_ENABLED:
+            return asFP<HWC2_PFN_SET_VSYNC_ENABLED>(setVsyncEnabledHook);
+        case HWC2_FUNCTION_GET_COLOR_MODES:
+            return asFP<HWC2_PFN_GET_COLOR_MODES>(getColorModesHook);
+        case HWC2_FUNCTION_SET_COLOR_MODE:
+            return asFP<HWC2_PFN_SET_COLOR_MODE>(setColorModeHook);
+        case HWC2_FUNCTION_SET_COLOR_TRANSFORM:
+            return asFP<HWC2_PFN_SET_COLOR_TRANSFORM>(setColorTransformHook);
+        case HWC2_FUNCTION_GET_CLIENT_TARGET_SUPPORT:
+            return asFP<HWC2_PFN_GET_CLIENT_TARGET_SUPPORT>(getClientTargetSupportHook);
+        case HWC2_FUNCTION_SET_CLIENT_TARGET:
+            return asFP<HWC2_PFN_SET_CLIENT_TARGET>(setClientTargetHook);
+
+        // config functions
+        case HWC2_FUNCTION_GET_DISPLAY_CONFIGS:
+            return asFP<HWC2_PFN_GET_DISPLAY_CONFIGS>(getDisplayConfigsHook);
+        case HWC2_FUNCTION_GET_DISPLAY_ATTRIBUTE:
+            return asFP<HWC2_PFN_GET_DISPLAY_ATTRIBUTE>(getDisplayAttributeHook);
+        case HWC2_FUNCTION_GET_ACTIVE_CONFIG:
+            return asFP<HWC2_PFN_GET_ACTIVE_CONFIG>(getActiveConfigHook);
+        case HWC2_FUNCTION_SET_ACTIVE_CONFIG:
+            return asFP<HWC2_PFN_SET_ACTIVE_CONFIG>(setActiveConfigHook);
+
+        // validate/present functions
+        case HWC2_FUNCTION_VALIDATE_DISPLAY:
+            return asFP<HWC2_PFN_VALIDATE_DISPLAY>(validateDisplayHook);
+        case HWC2_FUNCTION_GET_CHANGED_COMPOSITION_TYPES:
+            return asFP<HWC2_PFN_GET_CHANGED_COMPOSITION_TYPES>(getChangedCompositionTypesHook);
+        case HWC2_FUNCTION_GET_DISPLAY_REQUESTS:
+            return asFP<HWC2_PFN_GET_DISPLAY_REQUESTS>(getDisplayRequestsHook);
+        case HWC2_FUNCTION_ACCEPT_DISPLAY_CHANGES:
+            return asFP<HWC2_PFN_ACCEPT_DISPLAY_CHANGES>(acceptDisplayChangesHook);
+        case HWC2_FUNCTION_PRESENT_DISPLAY:
+            return asFP<HWC2_PFN_PRESENT_DISPLAY>(presentDisplayHook);
+        case HWC2_FUNCTION_GET_RELEASE_FENCES:
+            return asFP<HWC2_PFN_GET_RELEASE_FENCES>(getReleaseFencesHook);
+
+        // layer create/destroy
+        case HWC2_FUNCTION_CREATE_LAYER:
+            return asFP<HWC2_PFN_CREATE_LAYER>(createLayerHook);
+        case HWC2_FUNCTION_DESTROY_LAYER:
+            return asFP<HWC2_PFN_DESTROY_LAYER>(destroyLayerHook);
+
+        // layer functions; validateDisplay not required
+        case HWC2_FUNCTION_SET_CURSOR_POSITION:
+            return asFP<HWC2_PFN_SET_CURSOR_POSITION>(setCursorPositionHook);
+        case HWC2_FUNCTION_SET_LAYER_BUFFER:
+            return asFP<HWC2_PFN_SET_LAYER_BUFFER>(setLayerBufferHook);
+        case HWC2_FUNCTION_SET_LAYER_SURFACE_DAMAGE:
+            return asFP<HWC2_PFN_SET_LAYER_SURFACE_DAMAGE>(setLayerSurfaceDamageHook);
+
+        // layer state functions; validateDisplay required
+        case HWC2_FUNCTION_SET_LAYER_COMPOSITION_TYPE:
+            return asFP<HWC2_PFN_SET_LAYER_COMPOSITION_TYPE>(setLayerCompositionTypeHook);
+        case HWC2_FUNCTION_SET_LAYER_BLEND_MODE:
+            return asFP<HWC2_PFN_SET_LAYER_BLEND_MODE>(setLayerStateHook<int32_t>);
+        case HWC2_FUNCTION_SET_LAYER_COLOR:
+            return asFP<HWC2_PFN_SET_LAYER_COLOR>(setLayerStateHook<hwc_color_t>);
+        case HWC2_FUNCTION_SET_LAYER_DATASPACE:
+            return asFP<HWC2_PFN_SET_LAYER_DATASPACE>(setLayerStateHook<int32_t>);
+        case HWC2_FUNCTION_SET_LAYER_DISPLAY_FRAME:
+            return asFP<HWC2_PFN_SET_LAYER_DISPLAY_FRAME>(setLayerStateHook<hwc_rect_t>);
+        case HWC2_FUNCTION_SET_LAYER_PLANE_ALPHA:
+            return asFP<HWC2_PFN_SET_LAYER_PLANE_ALPHA>(setLayerStateHook<float>);
+        case HWC2_FUNCTION_SET_LAYER_SIDEBAND_STREAM:
+            return asFP<HWC2_PFN_SET_LAYER_SIDEBAND_STREAM>(setLayerStateHook<buffer_handle_t>);
+        case HWC2_FUNCTION_SET_LAYER_SOURCE_CROP:
+            return asFP<HWC2_PFN_SET_LAYER_SOURCE_CROP>(setLayerStateHook<hwc_frect_t>);
+        case HWC2_FUNCTION_SET_LAYER_TRANSFORM:
+            return asFP<HWC2_PFN_SET_LAYER_TRANSFORM>(setLayerStateHook<int32_t>);
+        case HWC2_FUNCTION_SET_LAYER_VISIBLE_REGION:
+            return asFP<HWC2_PFN_SET_LAYER_VISIBLE_REGION>(setLayerStateHook<hwc_region_t>);
+        case HWC2_FUNCTION_SET_LAYER_Z_ORDER:
+            return asFP<HWC2_PFN_SET_LAYER_Z_ORDER>(setLayerStateHook<uint32_t>);
+
+        default:
+            ALOGE("unknown function descriptor %d", descriptor);
+            return nullptr;
+    }
+}
+
+void getCapabilitiesHook(hwc2_device_t* /*device*/, uint32_t* outCount,
+                         int32_t* /*outCapabilities*/) {
+    *outCount = 0;
+}
+
+int closeHook(hw_device_t* device) {
+    auto& adapter = HWC2OnFbAdapter::cast(device);
+    adapter.close();
+    return 0;
+}
+
+} // anonymous namespace
+
+HWC2OnFbAdapter::HWC2OnFbAdapter(framebuffer_device_t* fbDevice)
+      : hwc2_device_t(), mFbDevice(fbDevice) {
+    common.close = closeHook;
+    hwc2_device::getCapabilities = getCapabilitiesHook;
+    hwc2_device::getFunction = getFunctionHook;
+
+    mFbInfo.name = "fbdev";
+    mFbInfo.width = mFbDevice->width;
+    mFbInfo.height = mFbDevice->height;
+    mFbInfo.format = mFbDevice->format;
+    mFbInfo.vsync_period_ns = int(1e9 / mFbDevice->fps);
+    mFbInfo.xdpi_scaled = int(mFbDevice->xdpi * 1000.0f);
+    mFbInfo.ydpi_scaled = int(mFbDevice->ydpi * 1000.0f);
+
+    mVsyncThread.start(0, mFbInfo.vsync_period_ns);
+}
+
+HWC2OnFbAdapter& HWC2OnFbAdapter::cast(hw_device_t* device) {
+    return *reinterpret_cast<HWC2OnFbAdapter*>(device);
+}
+
+HWC2OnFbAdapter& HWC2OnFbAdapter::cast(hwc2_device_t* device) {
+    return *reinterpret_cast<HWC2OnFbAdapter*>(device);
+}
+
+hwc2_display_t HWC2OnFbAdapter::getDisplayId() {
+    return 0;
+}
+
+hwc2_config_t HWC2OnFbAdapter::getConfigId() {
+    return 0;
+}
+
+void HWC2OnFbAdapter::close() {
+    mVsyncThread.stop();
+    framebuffer_close(mFbDevice);
+}
+
+const HWC2OnFbAdapter::Info& HWC2OnFbAdapter::getInfo() const {
+    return mFbInfo;
+}
+
+void HWC2OnFbAdapter::updateDebugString() {
+    if (mFbDevice->common.version >= 1 && mFbDevice->dump) {
+        char buffer[4096];
+        mFbDevice->dump(mFbDevice, buffer, sizeof(buffer));
+        buffer[sizeof(buffer) - 1] = '\0';
+
+        mDebugString = buffer;
+    }
+}
+
+const std::string& HWC2OnFbAdapter::getDebugString() const {
+    return mDebugString;
+}
+
+void HWC2OnFbAdapter::setState(State state) {
+    mState = state;
+}
+
+HWC2OnFbAdapter::State HWC2OnFbAdapter::getState() const {
+    return mState;
+}
+
+hwc2_layer_t HWC2OnFbAdapter::addLayer() {
+    hwc2_layer_t id = ++mNextLayerId;
+
+    mLayers.insert(id);
+    mDirtyLayers.insert(id);
+
+    return id;
+}
+
+bool HWC2OnFbAdapter::removeLayer(hwc2_layer_t layer) {
+    mDirtyLayers.erase(layer);
+    return mLayers.erase(layer);
+}
+
+bool HWC2OnFbAdapter::hasLayer(hwc2_layer_t layer) const {
+    return mLayers.count(layer) > 0;
+}
+
+bool HWC2OnFbAdapter::markLayerDirty(hwc2_layer_t layer, bool dirty) {
+    if (mLayers.count(layer) == 0) {
+        return false;
+    }
+
+    if (dirty) {
+        mDirtyLayers.insert(layer);
+    } else {
+        mDirtyLayers.erase(layer);
+    }
+
+    return true;
+}
+
+const std::unordered_set<hwc2_layer_t>& HWC2OnFbAdapter::getDirtyLayers() const {
+    return mDirtyLayers;
+}
+
+void HWC2OnFbAdapter::clearDirtyLayers() {
+    mDirtyLayers.clear();
+}
+
+/*
+ * For each frame, SurfaceFlinger
+ *
+ *  - peforms GLES composition
+ *  - calls eglSwapBuffers
+ *  - calls setClientTarget, which maps to setBuffer below
+ *  - calls presentDisplay, which maps to postBuffer below
+ *
+ * setBuffer should be a good place to call compositionComplete.
+ *
+ * As for post, it
+ *
+ *  - schedules the buffer for presentation on the next vsync
+ *  - locks the buffer and blocks all other users trying to lock it
+ *
+ * It does not give us a way to return a present fence, and we need to live
+ * with that.  The implication is that, when we are double-buffered,
+ * SurfaceFlinger assumes the front buffer is available for rendering again
+ * immediately after the back buffer is posted.  The locking semantics
+ * hopefully are strong enough that the rendering will be blocked.
+ */
+void HWC2OnFbAdapter::setBuffer(buffer_handle_t buffer) {
+    if (mFbDevice->compositionComplete) {
+        mFbDevice->compositionComplete(mFbDevice);
+    }
+    mBuffer = buffer;
+}
+
+bool HWC2OnFbAdapter::postBuffer() {
+    int error = 0;
+    if (mBuffer) {
+        error = mFbDevice->post(mFbDevice, mBuffer);
+    }
+
+    return error == 0;
+}
+
+void HWC2OnFbAdapter::setVsyncCallback(HWC2_PFN_VSYNC callback, hwc2_callback_data_t data) {
+    mVsyncThread.setCallback(callback, data);
+}
+
+void HWC2OnFbAdapter::enableVsync(bool enable) {
+    mVsyncThread.enableCallback(enable);
+}
+
+int64_t HWC2OnFbAdapter::VsyncThread::now() {
+    struct timespec ts;
+    clock_gettime(CLOCK_MONOTONIC, &ts);
+
+    return int64_t(ts.tv_sec) * 1'000'000'000 + ts.tv_nsec;
+}
+
+bool HWC2OnFbAdapter::VsyncThread::sleepUntil(int64_t t) {
+    struct timespec ts;
+    ts.tv_sec = t / 1'000'000'000;
+    ts.tv_nsec = t % 1'000'000'000;
+
+    while (true) {
+        int error = clock_nanosleep(CLOCK_MONOTONIC, TIMER_ABSTIME, &ts, nullptr);
+        if (error) {
+            if (error == EINTR) {
+                continue;
+            }
+            return false;
+        } else {
+            return true;
+        }
+    }
+}
+
+void HWC2OnFbAdapter::VsyncThread::start(int64_t firstVsync, int64_t period) {
+    mNextVsync = firstVsync;
+    mPeriod = period;
+    mStarted = true;
+    mThread = std::thread(&VsyncThread::vsyncLoop, this);
+}
+
+void HWC2OnFbAdapter::VsyncThread::stop() {
+    {
+        std::lock_guard<std::mutex> lock(mMutex);
+        mStarted = false;
+    }
+    mCondition.notify_all();
+    mThread.join();
+}
+
+void HWC2OnFbAdapter::VsyncThread::setCallback(HWC2_PFN_VSYNC callback, hwc2_callback_data_t data) {
+    std::lock_guard<std::mutex> lock(mMutex);
+    mCallback = callback;
+    mCallbackData = data;
+}
+
+void HWC2OnFbAdapter::VsyncThread::enableCallback(bool enable) {
+    {
+        std::lock_guard<std::mutex> lock(mMutex);
+        mCallbackEnabled = enable;
+    }
+    mCondition.notify_all();
+}
+
+void HWC2OnFbAdapter::VsyncThread::vsyncLoop() {
+    prctl(PR_SET_NAME, "VsyncThread", 0, 0, 0);
+
+    std::unique_lock<std::mutex> lock(mMutex);
+    if (!mStarted) {
+        return;
+    }
+
+    while (true) {
+        if (!mCallbackEnabled) {
+            mCondition.wait(lock, [this] { return mCallbackEnabled || !mStarted; });
+            if (!mStarted) {
+                break;
+            }
+        }
+
+        lock.unlock();
+
+        // adjust mNextVsync if necessary
+        int64_t t = now();
+        if (mNextVsync < t) {
+            int64_t n = (t - mNextVsync + mPeriod - 1) / mPeriod;
+            mNextVsync += mPeriod * n;
+        }
+        bool fire = sleepUntil(mNextVsync);
+
+        lock.lock();
+
+        if (fire) {
+            ALOGV("VsyncThread(%" PRId64 ")", mNextVsync);
+            if (mCallback) {
+                mCallback(mCallbackData, getDisplayId(), mNextVsync);
+            }
+            mNextVsync += mPeriod;
+        }
+    }
+}
+
+} // namespace android
diff --git a/graphics/composer/2.1/utils/hwc2onfbadapter/include/hwc2onfbadapter/HWC2OnFbAdapter.h b/graphics/composer/2.1/utils/hwc2onfbadapter/include/hwc2onfbadapter/HWC2OnFbAdapter.h
new file mode 100644
index 0000000..d6272fd
--- /dev/null
+++ b/graphics/composer/2.1/utils/hwc2onfbadapter/include/hwc2onfbadapter/HWC2OnFbAdapter.h
@@ -0,0 +1,123 @@
+/*
+ * Copyright 2017 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.
+ */
+
+#ifndef ANDROID_SF_HWC2_ON_FB_ADAPTER_H
+#define ANDROID_SF_HWC2_ON_FB_ADAPTER_H
+
+#include <condition_variable>
+#include <mutex>
+#include <string>
+#include <thread>
+#include <unordered_set>
+
+#include <hardware/hwcomposer2.h>
+
+struct framebuffer_device_t;
+
+namespace android {
+
+class HWC2OnFbAdapter : public hwc2_device_t {
+public:
+    HWC2OnFbAdapter(framebuffer_device_t* fbDevice);
+
+    static HWC2OnFbAdapter& cast(hw_device_t* device);
+    static HWC2OnFbAdapter& cast(hwc2_device_t* device);
+
+    static hwc2_display_t getDisplayId();
+    static hwc2_config_t getConfigId();
+
+    void close();
+
+    struct Info {
+        std::string name;
+        uint32_t width;
+        uint32_t height;
+        int format;
+        int vsync_period_ns;
+        int xdpi_scaled;
+        int ydpi_scaled;
+    };
+    const Info& getInfo() const;
+
+    void updateDebugString();
+    const std::string& getDebugString() const;
+
+    enum class State {
+        MODIFIED,
+        VALIDATED_WITH_CHANGES,
+        VALIDATED,
+    };
+    void setState(State state);
+    State getState() const;
+
+    hwc2_layer_t addLayer();
+    bool removeLayer(hwc2_layer_t layer);
+    bool hasLayer(hwc2_layer_t layer) const;
+    bool markLayerDirty(hwc2_layer_t layer, bool dirty);
+    const std::unordered_set<hwc2_layer_t>& getDirtyLayers() const;
+    void clearDirtyLayers();
+
+    void setBuffer(buffer_handle_t buffer);
+    bool postBuffer();
+
+    void setVsyncCallback(HWC2_PFN_VSYNC callback, hwc2_callback_data_t data);
+    void enableVsync(bool enable);
+
+private:
+    framebuffer_device_t* mFbDevice{nullptr};
+    Info mFbInfo{};
+
+    std::string mDebugString;
+
+    State mState{State::MODIFIED};
+
+    uint64_t mNextLayerId{0};
+    std::unordered_set<hwc2_layer_t> mLayers;
+    std::unordered_set<hwc2_layer_t> mDirtyLayers;
+
+    buffer_handle_t mBuffer{nullptr};
+
+    class VsyncThread {
+    public:
+        static int64_t now();
+        static bool sleepUntil(int64_t t);
+
+        void start(int64_t first, int64_t period);
+        void stop();
+        void setCallback(HWC2_PFN_VSYNC callback, hwc2_callback_data_t data);
+        void enableCallback(bool enable);
+
+    private:
+        void vsyncLoop();
+        bool waitUntilNextVsync();
+
+        std::thread mThread;
+        int64_t mNextVsync{0};
+        int64_t mPeriod{0};
+
+        std::mutex mMutex;
+        std::condition_variable mCondition;
+        bool mStarted{false};
+        HWC2_PFN_VSYNC mCallback{nullptr};
+        hwc2_callback_data_t mCallbackData{nullptr};
+        bool mCallbackEnabled{false};
+    };
+    VsyncThread mVsyncThread;
+};
+
+} // namespace android
+
+#endif // ANDROID_SF_HWC2_ON_FB_ADAPTER_H
diff --git a/graphics/composer/2.1/utils/passthrough/Android.bp b/graphics/composer/2.1/utils/passthrough/Android.bp
new file mode 100644
index 0000000..4d3c976
--- /dev/null
+++ b/graphics/composer/2.1/utils/passthrough/Android.bp
@@ -0,0 +1,22 @@
+cc_library_headers {
+    name: "android.hardware.graphics.composer@2.1-passthrough",
+    defaults: ["hidl_defaults"],
+    vendor: true,
+    shared_libs: [
+        "libhardware",
+        "libhwc2on1adapter",
+        "libhwc2onfbadapter",
+    ],
+    export_shared_lib_headers: [
+        "libhardware",
+        "libhwc2on1adapter",
+        "libhwc2onfbadapter",
+    ],
+    header_libs: [
+        "android.hardware.graphics.composer@2.1-hal",
+    ],
+    export_header_lib_headers: [
+        "android.hardware.graphics.composer@2.1-hal",
+    ],
+    export_include_dirs: ["include"],
+}
diff --git a/graphics/composer/2.1/utils/passthrough/include/composer-passthrough/2.1/HwcHal.h b/graphics/composer/2.1/utils/passthrough/include/composer-passthrough/2.1/HwcHal.h
new file mode 100644
index 0000000..964e75b
--- /dev/null
+++ b/graphics/composer/2.1/utils/passthrough/include/composer-passthrough/2.1/HwcHal.h
@@ -0,0 +1,670 @@
+/*
+ * Copyright 2016 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
+
+#ifndef LOG_TAG
+#warning "HwcHal.h included without LOG_TAG"
+#endif
+
+#include <atomic>
+#include <cstring>  // for strerror
+#include <type_traits>
+#include <unordered_set>
+#include <vector>
+
+#include <android/hardware/graphics/composer/2.1/IComposer.h>
+#include <composer-hal/2.1/ComposerHal.h>
+#define HWC2_INCLUDE_STRINGIFICATION
+#define HWC2_USE_CPP11
+#include <hardware/hwcomposer2.h>
+#undef HWC2_INCLUDE_STRINGIFICATION
+#undef HWC2_USE_CPP11
+#include <log/log.h>
+
+namespace android {
+namespace hardware {
+namespace graphics {
+namespace composer {
+namespace V2_1 {
+namespace passthrough {
+
+namespace detail {
+
+using android::hardware::graphics::common::V1_0::ColorMode;
+using android::hardware::graphics::common::V1_0::ColorTransform;
+using android::hardware::graphics::common::V1_0::Dataspace;
+using android::hardware::graphics::common::V1_0::Hdr;
+using android::hardware::graphics::common::V1_0::PixelFormat;
+using android::hardware::graphics::common::V1_0::Transform;
+
+// HwcHalImpl implements V2_*::hal::ComposerHal on top of hwcomposer2
+template <typename Hal>
+class HwcHalImpl : public Hal {
+   public:
+    virtual ~HwcHalImpl() {
+        if (mDevice) {
+            hwc2_close(mDevice);
+        }
+    }
+
+    bool initWithModule(const hw_module_t* module) {
+        hwc2_device_t* device;
+        int result = hwc2_open(module, &device);
+        if (result) {
+            ALOGE("failed to open hwcomposer2 device: %s", strerror(-result));
+            return false;
+        }
+
+        return initWithDevice(std::move(device), true);
+    }
+
+    bool initWithDevice(hwc2_device_t* device, bool requireReliablePresentFence) {
+        // we own the device from this point on
+        mDevice = device;
+
+        initCapabilities();
+        if (requireReliablePresentFence &&
+            hasCapability(HWC2_CAPABILITY_PRESENT_FENCE_IS_NOT_RELIABLE)) {
+            ALOGE("present fence must be reliable");
+            mDevice->common.close(&mDevice->common);
+            mDevice = nullptr;
+            return false;
+        }
+
+        if (!initDispatch()) {
+            mDevice->common.close(&mDevice->common);
+            mDevice = nullptr;
+            return false;
+        }
+
+        return true;
+    }
+
+    bool hasCapability(hwc2_capability_t capability) override {
+        return (mCapabilities.count(capability) > 0);
+    }
+
+    std::string dumpDebugInfo() override {
+        uint32_t len = 0;
+        mDispatch.dump(mDevice, &len, nullptr);
+
+        std::vector<char> buf(len + 1);
+        mDispatch.dump(mDevice, &len, buf.data());
+        buf.resize(len + 1);
+        buf[len] = '\0';
+
+        return buf.data();
+    }
+
+    void registerEventCallback(hal::ComposerHal::EventCallback* callback) override {
+        mMustValidateDisplay = true;
+        mEventCallback = callback;
+
+        mDispatch.registerCallback(mDevice, HWC2_CALLBACK_HOTPLUG, this,
+                                   reinterpret_cast<hwc2_function_pointer_t>(hotplugHook));
+        mDispatch.registerCallback(mDevice, HWC2_CALLBACK_REFRESH, this,
+                                   reinterpret_cast<hwc2_function_pointer_t>(refreshHook));
+        mDispatch.registerCallback(mDevice, HWC2_CALLBACK_VSYNC, this,
+                                   reinterpret_cast<hwc2_function_pointer_t>(vsyncHook));
+    }
+
+    void unregisterEventCallback() override {
+        // we assume the callback functions
+        //
+        //  - can be unregistered
+        //  - can be in-flight
+        //  - will never be called afterward
+        //
+        // which is likely incorrect
+        mDispatch.registerCallback(mDevice, HWC2_CALLBACK_HOTPLUG, this, nullptr);
+        mDispatch.registerCallback(mDevice, HWC2_CALLBACK_REFRESH, this, nullptr);
+        mDispatch.registerCallback(mDevice, HWC2_CALLBACK_VSYNC, this, nullptr);
+
+        mEventCallback = nullptr;
+    }
+
+    uint32_t getMaxVirtualDisplayCount() override {
+        return mDispatch.getMaxVirtualDisplayCount(mDevice);
+    }
+
+    Error createVirtualDisplay(uint32_t width, uint32_t height, PixelFormat* format,
+                               Display* outDisplay) override {
+        int32_t hwc_format = static_cast<int32_t>(*format);
+        int32_t err =
+            mDispatch.createVirtualDisplay(mDevice, width, height, &hwc_format, outDisplay);
+        *format = static_cast<PixelFormat>(hwc_format);
+
+        return static_cast<Error>(err);
+    }
+
+    Error destroyVirtualDisplay(Display display) override {
+        int32_t err = mDispatch.destroyVirtualDisplay(mDevice, display);
+        return static_cast<Error>(err);
+    }
+
+    Error createLayer(Display display, Layer* outLayer) override {
+        int32_t err = mDispatch.createLayer(mDevice, display, outLayer);
+        return static_cast<Error>(err);
+    }
+
+    Error destroyLayer(Display display, Layer layer) override {
+        int32_t err = mDispatch.destroyLayer(mDevice, display, layer);
+        return static_cast<Error>(err);
+    }
+
+    Error getActiveConfig(Display display, Config* outConfig) override {
+        int32_t err = mDispatch.getActiveConfig(mDevice, display, outConfig);
+        return static_cast<Error>(err);
+    }
+
+    Error getClientTargetSupport(Display display, uint32_t width, uint32_t height,
+                                 PixelFormat format, Dataspace dataspace) override {
+        int32_t err = mDispatch.getClientTargetSupport(mDevice, display, width, height,
+                                                       static_cast<int32_t>(format),
+                                                       static_cast<int32_t>(dataspace));
+        return static_cast<Error>(err);
+    }
+
+    Error getColorModes(Display display, hidl_vec<ColorMode>* outModes) override {
+        uint32_t count = 0;
+        int32_t err = mDispatch.getColorModes(mDevice, display, &count, nullptr);
+        if (err != HWC2_ERROR_NONE) {
+            return static_cast<Error>(err);
+        }
+
+        outModes->resize(count);
+        err = mDispatch.getColorModes(
+            mDevice, display, &count,
+            reinterpret_cast<std::underlying_type<ColorMode>::type*>(outModes->data()));
+        if (err != HWC2_ERROR_NONE) {
+            *outModes = hidl_vec<ColorMode>();
+            return static_cast<Error>(err);
+        }
+
+        return Error::NONE;
+    }
+
+    Error getDisplayAttribute(Display display, Config config, IComposerClient::Attribute attribute,
+                              int32_t* outValue) override {
+        int32_t err = mDispatch.getDisplayAttribute(mDevice, display, config,
+                                                    static_cast<int32_t>(attribute), outValue);
+        return static_cast<Error>(err);
+    }
+
+    Error getDisplayConfigs(Display display, hidl_vec<Config>* outConfigs) override {
+        uint32_t count = 0;
+        int32_t err = mDispatch.getDisplayConfigs(mDevice, display, &count, nullptr);
+        if (err != HWC2_ERROR_NONE) {
+            return static_cast<Error>(err);
+        }
+
+        outConfigs->resize(count);
+        err = mDispatch.getDisplayConfigs(mDevice, display, &count, outConfigs->data());
+        if (err != HWC2_ERROR_NONE) {
+            *outConfigs = hidl_vec<Config>();
+            return static_cast<Error>(err);
+        }
+
+        return Error::NONE;
+    }
+
+    Error getDisplayName(Display display, hidl_string* outName) override {
+        uint32_t count = 0;
+        int32_t err = mDispatch.getDisplayName(mDevice, display, &count, nullptr);
+        if (err != HWC2_ERROR_NONE) {
+            return static_cast<Error>(err);
+        }
+
+        std::vector<char> buf(count + 1);
+        err = mDispatch.getDisplayName(mDevice, display, &count, buf.data());
+        if (err != HWC2_ERROR_NONE) {
+            return static_cast<Error>(err);
+        }
+        buf.resize(count + 1);
+        buf[count] = '\0';
+
+        *outName = buf.data();
+
+        return Error::NONE;
+    }
+
+    Error getDisplayType(Display display, IComposerClient::DisplayType* outType) override {
+        int32_t hwc_type = HWC2_DISPLAY_TYPE_INVALID;
+        int32_t err = mDispatch.getDisplayType(mDevice, display, &hwc_type);
+        *outType = static_cast<IComposerClient::DisplayType>(hwc_type);
+
+        return static_cast<Error>(err);
+    }
+
+    Error getDozeSupport(Display display, bool* outSupport) override {
+        int32_t hwc_support = 0;
+        int32_t err = mDispatch.getDozeSupport(mDevice, display, &hwc_support);
+        *outSupport = hwc_support;
+
+        return static_cast<Error>(err);
+    }
+
+    Error getHdrCapabilities(Display display, hidl_vec<Hdr>* outTypes, float* outMaxLuminance,
+                             float* outMaxAverageLuminance, float* outMinLuminance) override {
+        uint32_t count = 0;
+        int32_t err =
+            mDispatch.getHdrCapabilities(mDevice, display, &count, nullptr, outMaxLuminance,
+                                         outMaxAverageLuminance, outMinLuminance);
+        if (err != HWC2_ERROR_NONE) {
+            return static_cast<Error>(err);
+        }
+
+        outTypes->resize(count);
+        err = mDispatch.getHdrCapabilities(
+            mDevice, display, &count,
+            reinterpret_cast<std::underlying_type<Hdr>::type*>(outTypes->data()), outMaxLuminance,
+            outMaxAverageLuminance, outMinLuminance);
+        if (err != HWC2_ERROR_NONE) {
+            *outTypes = hidl_vec<Hdr>();
+            return static_cast<Error>(err);
+        }
+
+        return Error::NONE;
+    }
+
+    Error setActiveConfig(Display display, Config config) override {
+        int32_t err = mDispatch.setActiveConfig(mDevice, display, config);
+        return static_cast<Error>(err);
+    }
+
+    Error setColorMode(Display display, ColorMode mode) override {
+        int32_t err = mDispatch.setColorMode(mDevice, display, static_cast<int32_t>(mode));
+        return static_cast<Error>(err);
+    }
+
+    Error setPowerMode(Display display, IComposerClient::PowerMode mode) override {
+        int32_t err = mDispatch.setPowerMode(mDevice, display, static_cast<int32_t>(mode));
+        return static_cast<Error>(err);
+    }
+
+    Error setVsyncEnabled(Display display, IComposerClient::Vsync enabled) override {
+        int32_t err = mDispatch.setVsyncEnabled(mDevice, display, static_cast<int32_t>(enabled));
+        return static_cast<Error>(err);
+    }
+
+    Error setColorTransform(Display display, const float* matrix, int32_t hint) override {
+        int32_t err = mDispatch.setColorTransform(mDevice, display, matrix, hint);
+        return static_cast<Error>(err);
+    }
+
+    Error setClientTarget(Display display, buffer_handle_t target, int32_t acquireFence,
+                          int32_t dataspace, const std::vector<hwc_rect_t>& damage) override {
+        hwc_region region = {damage.size(), damage.data()};
+        int32_t err =
+            mDispatch.setClientTarget(mDevice, display, target, acquireFence, dataspace, region);
+        return static_cast<Error>(err);
+    }
+
+    Error setOutputBuffer(Display display, buffer_handle_t buffer, int32_t releaseFence) override {
+        int32_t err = mDispatch.setOutputBuffer(mDevice, display, buffer, releaseFence);
+        // unlike in setClientTarget, releaseFence is owned by us
+        if (err == HWC2_ERROR_NONE && releaseFence >= 0) {
+            close(releaseFence);
+        }
+
+        return static_cast<Error>(err);
+    }
+
+    Error validateDisplay(Display display, std::vector<Layer>* outChangedLayers,
+                          std::vector<IComposerClient::Composition>* outCompositionTypes,
+                          uint32_t* outDisplayRequestMask, std::vector<Layer>* outRequestedLayers,
+                          std::vector<uint32_t>* outRequestMasks) override {
+        uint32_t typesCount = 0;
+        uint32_t reqsCount = 0;
+        int32_t err = mDispatch.validateDisplay(mDevice, display, &typesCount, &reqsCount);
+        mMustValidateDisplay = false;
+
+        if (err != HWC2_ERROR_NONE && err != HWC2_ERROR_HAS_CHANGES) {
+            return static_cast<Error>(err);
+        }
+
+        err = mDispatch.getChangedCompositionTypes(mDevice, display, &typesCount, nullptr, nullptr);
+        if (err != HWC2_ERROR_NONE) {
+            return static_cast<Error>(err);
+        }
+
+        std::vector<Layer> changedLayers(typesCount);
+        std::vector<IComposerClient::Composition> compositionTypes(typesCount);
+        err = mDispatch.getChangedCompositionTypes(
+            mDevice, display, &typesCount, changedLayers.data(),
+            reinterpret_cast<std::underlying_type<IComposerClient::Composition>::type*>(
+                compositionTypes.data()));
+        if (err != HWC2_ERROR_NONE) {
+            return static_cast<Error>(err);
+        }
+
+        int32_t displayReqs = 0;
+        err = mDispatch.getDisplayRequests(mDevice, display, &displayReqs, &reqsCount, nullptr,
+                                           nullptr);
+        if (err != HWC2_ERROR_NONE) {
+            return static_cast<Error>(err);
+        }
+
+        std::vector<Layer> requestedLayers(reqsCount);
+        std::vector<uint32_t> requestMasks(reqsCount);
+        err = mDispatch.getDisplayRequests(mDevice, display, &displayReqs, &reqsCount,
+                                           requestedLayers.data(),
+                                           reinterpret_cast<int32_t*>(requestMasks.data()));
+        if (err != HWC2_ERROR_NONE) {
+            return static_cast<Error>(err);
+        }
+
+        *outChangedLayers = std::move(changedLayers);
+        *outCompositionTypes = std::move(compositionTypes);
+        *outDisplayRequestMask = displayReqs;
+        *outRequestedLayers = std::move(requestedLayers);
+        *outRequestMasks = std::move(requestMasks);
+
+        return static_cast<Error>(err);
+    }
+
+    Error acceptDisplayChanges(Display display) override {
+        int32_t err = mDispatch.acceptDisplayChanges(mDevice, display);
+        return static_cast<Error>(err);
+    }
+
+    Error presentDisplay(Display display, int32_t* outPresentFence, std::vector<Layer>* outLayers,
+                         std::vector<int32_t>* outReleaseFences) override {
+        if (mMustValidateDisplay) {
+            return Error::NOT_VALIDATED;
+        }
+
+        *outPresentFence = -1;
+        int32_t err = mDispatch.presentDisplay(mDevice, display, outPresentFence);
+        if (err != HWC2_ERROR_NONE) {
+            return static_cast<Error>(err);
+        }
+
+        uint32_t count = 0;
+        err = mDispatch.getReleaseFences(mDevice, display, &count, nullptr, nullptr);
+        if (err != HWC2_ERROR_NONE) {
+            ALOGW("failed to get release fences");
+            return Error::NONE;
+        }
+
+        outLayers->resize(count);
+        outReleaseFences->resize(count);
+        err = mDispatch.getReleaseFences(mDevice, display, &count, outLayers->data(),
+                                         outReleaseFences->data());
+        if (err != HWC2_ERROR_NONE) {
+            ALOGW("failed to get release fences");
+            outLayers->clear();
+            outReleaseFences->clear();
+            return Error::NONE;
+        }
+
+        return static_cast<Error>(err);
+    }
+
+    Error setLayerCursorPosition(Display display, Layer layer, int32_t x, int32_t y) override {
+        int32_t err = mDispatch.setCursorPosition(mDevice, display, layer, x, y);
+        return static_cast<Error>(err);
+    }
+
+    Error setLayerBuffer(Display display, Layer layer, buffer_handle_t buffer,
+                         int32_t acquireFence) override {
+        int32_t err = mDispatch.setLayerBuffer(mDevice, display, layer, buffer, acquireFence);
+        return static_cast<Error>(err);
+    }
+
+    Error setLayerSurfaceDamage(Display display, Layer layer,
+                                const std::vector<hwc_rect_t>& damage) override {
+        hwc_region region = {damage.size(), damage.data()};
+        int32_t err = mDispatch.setLayerSurfaceDamage(mDevice, display, layer, region);
+        return static_cast<Error>(err);
+    }
+
+    Error setLayerBlendMode(Display display, Layer layer, int32_t mode) override {
+        int32_t err = mDispatch.setLayerBlendMode(mDevice, display, layer, mode);
+        return static_cast<Error>(err);
+    }
+
+    Error setLayerColor(Display display, Layer layer, IComposerClient::Color color) override {
+        hwc_color_t hwc_color{color.r, color.g, color.b, color.a};
+        int32_t err = mDispatch.setLayerColor(mDevice, display, layer, hwc_color);
+        return static_cast<Error>(err);
+    }
+
+    Error setLayerCompositionType(Display display, Layer layer, int32_t type) override {
+        int32_t err = mDispatch.setLayerCompositionType(mDevice, display, layer, type);
+        return static_cast<Error>(err);
+    }
+
+    Error setLayerDataspace(Display display, Layer layer, int32_t dataspace) override {
+        int32_t err = mDispatch.setLayerDataspace(mDevice, display, layer, dataspace);
+        return static_cast<Error>(err);
+    }
+
+    Error setLayerDisplayFrame(Display display, Layer layer, const hwc_rect_t& frame) override {
+        int32_t err = mDispatch.setLayerDisplayFrame(mDevice, display, layer, frame);
+        return static_cast<Error>(err);
+    }
+
+    Error setLayerPlaneAlpha(Display display, Layer layer, float alpha) override {
+        int32_t err = mDispatch.setLayerPlaneAlpha(mDevice, display, layer, alpha);
+        return static_cast<Error>(err);
+    }
+
+    Error setLayerSidebandStream(Display display, Layer layer, buffer_handle_t stream) override {
+        int32_t err = mDispatch.setLayerSidebandStream(mDevice, display, layer, stream);
+        return static_cast<Error>(err);
+    }
+
+    Error setLayerSourceCrop(Display display, Layer layer, const hwc_frect_t& crop) override {
+        int32_t err = mDispatch.setLayerSourceCrop(mDevice, display, layer, crop);
+        return static_cast<Error>(err);
+    }
+
+    Error setLayerTransform(Display display, Layer layer, int32_t transform) override {
+        int32_t err = mDispatch.setLayerTransform(mDevice, display, layer, transform);
+        return static_cast<Error>(err);
+    }
+
+    Error setLayerVisibleRegion(Display display, Layer layer,
+                                const std::vector<hwc_rect_t>& visible) override {
+        hwc_region_t region = {visible.size(), visible.data()};
+        int32_t err = mDispatch.setLayerVisibleRegion(mDevice, display, layer, region);
+        return static_cast<Error>(err);
+    }
+
+    Error setLayerZOrder(Display display, Layer layer, uint32_t z) override {
+        int32_t err = mDispatch.setLayerZOrder(mDevice, display, layer, z);
+        return static_cast<Error>(err);
+    }
+
+   protected:
+    virtual void initCapabilities() {
+        uint32_t count = 0;
+        mDevice->getCapabilities(mDevice, &count, nullptr);
+
+        std::vector<int32_t> caps(count);
+        mDevice->getCapabilities(mDevice, &count, caps.data());
+        caps.resize(count);
+
+        mCapabilities.reserve(count);
+        for (auto cap : caps) {
+            mCapabilities.insert(static_cast<hwc2_capability_t>(cap));
+        }
+    }
+
+    template <typename T>
+    bool initDispatch(hwc2_function_descriptor_t desc, T* outPfn) {
+        auto pfn = mDevice->getFunction(mDevice, desc);
+        if (pfn) {
+            *outPfn = reinterpret_cast<T>(pfn);
+            return true;
+        } else {
+            ALOGE("failed to get hwcomposer2 function %d", desc);
+            return false;
+        }
+    }
+
+    virtual bool initDispatch() {
+        if (!initDispatch(HWC2_FUNCTION_ACCEPT_DISPLAY_CHANGES, &mDispatch.acceptDisplayChanges) ||
+            !initDispatch(HWC2_FUNCTION_CREATE_LAYER, &mDispatch.createLayer) ||
+            !initDispatch(HWC2_FUNCTION_CREATE_VIRTUAL_DISPLAY, &mDispatch.createVirtualDisplay) ||
+            !initDispatch(HWC2_FUNCTION_DESTROY_LAYER, &mDispatch.destroyLayer) ||
+            !initDispatch(HWC2_FUNCTION_DESTROY_VIRTUAL_DISPLAY,
+                          &mDispatch.destroyVirtualDisplay) ||
+            !initDispatch(HWC2_FUNCTION_DUMP, &mDispatch.dump) ||
+            !initDispatch(HWC2_FUNCTION_GET_ACTIVE_CONFIG, &mDispatch.getActiveConfig) ||
+            !initDispatch(HWC2_FUNCTION_GET_CHANGED_COMPOSITION_TYPES,
+                          &mDispatch.getChangedCompositionTypes) ||
+            !initDispatch(HWC2_FUNCTION_GET_CLIENT_TARGET_SUPPORT,
+                          &mDispatch.getClientTargetSupport) ||
+            !initDispatch(HWC2_FUNCTION_GET_COLOR_MODES, &mDispatch.getColorModes) ||
+            !initDispatch(HWC2_FUNCTION_GET_DISPLAY_ATTRIBUTE, &mDispatch.getDisplayAttribute) ||
+            !initDispatch(HWC2_FUNCTION_GET_DISPLAY_CONFIGS, &mDispatch.getDisplayConfigs) ||
+            !initDispatch(HWC2_FUNCTION_GET_DISPLAY_NAME, &mDispatch.getDisplayName) ||
+            !initDispatch(HWC2_FUNCTION_GET_DISPLAY_REQUESTS, &mDispatch.getDisplayRequests) ||
+            !initDispatch(HWC2_FUNCTION_GET_DISPLAY_TYPE, &mDispatch.getDisplayType) ||
+            !initDispatch(HWC2_FUNCTION_GET_DOZE_SUPPORT, &mDispatch.getDozeSupport) ||
+            !initDispatch(HWC2_FUNCTION_GET_HDR_CAPABILITIES, &mDispatch.getHdrCapabilities) ||
+            !initDispatch(HWC2_FUNCTION_GET_MAX_VIRTUAL_DISPLAY_COUNT,
+                          &mDispatch.getMaxVirtualDisplayCount) ||
+            !initDispatch(HWC2_FUNCTION_GET_RELEASE_FENCES, &mDispatch.getReleaseFences) ||
+            !initDispatch(HWC2_FUNCTION_PRESENT_DISPLAY, &mDispatch.presentDisplay) ||
+            !initDispatch(HWC2_FUNCTION_REGISTER_CALLBACK, &mDispatch.registerCallback) ||
+            !initDispatch(HWC2_FUNCTION_SET_ACTIVE_CONFIG, &mDispatch.setActiveConfig) ||
+            !initDispatch(HWC2_FUNCTION_SET_CLIENT_TARGET, &mDispatch.setClientTarget) ||
+            !initDispatch(HWC2_FUNCTION_SET_COLOR_MODE, &mDispatch.setColorMode) ||
+            !initDispatch(HWC2_FUNCTION_SET_COLOR_TRANSFORM, &mDispatch.setColorTransform) ||
+            !initDispatch(HWC2_FUNCTION_SET_CURSOR_POSITION, &mDispatch.setCursorPosition) ||
+            !initDispatch(HWC2_FUNCTION_SET_LAYER_BLEND_MODE, &mDispatch.setLayerBlendMode) ||
+            !initDispatch(HWC2_FUNCTION_SET_LAYER_BUFFER, &mDispatch.setLayerBuffer) ||
+            !initDispatch(HWC2_FUNCTION_SET_LAYER_COLOR, &mDispatch.setLayerColor) ||
+            !initDispatch(HWC2_FUNCTION_SET_LAYER_COMPOSITION_TYPE,
+                          &mDispatch.setLayerCompositionType) ||
+            !initDispatch(HWC2_FUNCTION_SET_LAYER_DATASPACE, &mDispatch.setLayerDataspace) ||
+            !initDispatch(HWC2_FUNCTION_SET_LAYER_DISPLAY_FRAME, &mDispatch.setLayerDisplayFrame) ||
+            !initDispatch(HWC2_FUNCTION_SET_LAYER_PLANE_ALPHA, &mDispatch.setLayerPlaneAlpha)) {
+            return false;
+        }
+
+        if (hasCapability(HWC2_CAPABILITY_SIDEBAND_STREAM)) {
+            if (!initDispatch(HWC2_FUNCTION_SET_LAYER_SIDEBAND_STREAM,
+                              &mDispatch.setLayerSidebandStream)) {
+                return false;
+            }
+        }
+
+        if (!initDispatch(HWC2_FUNCTION_SET_LAYER_SOURCE_CROP, &mDispatch.setLayerSourceCrop) ||
+            !initDispatch(HWC2_FUNCTION_SET_LAYER_SURFACE_DAMAGE,
+                          &mDispatch.setLayerSurfaceDamage) ||
+            !initDispatch(HWC2_FUNCTION_SET_LAYER_TRANSFORM, &mDispatch.setLayerTransform) ||
+            !initDispatch(HWC2_FUNCTION_SET_LAYER_VISIBLE_REGION,
+                          &mDispatch.setLayerVisibleRegion) ||
+            !initDispatch(HWC2_FUNCTION_SET_LAYER_Z_ORDER, &mDispatch.setLayerZOrder) ||
+            !initDispatch(HWC2_FUNCTION_SET_OUTPUT_BUFFER, &mDispatch.setOutputBuffer) ||
+            !initDispatch(HWC2_FUNCTION_SET_POWER_MODE, &mDispatch.setPowerMode) ||
+            !initDispatch(HWC2_FUNCTION_SET_VSYNC_ENABLED, &mDispatch.setVsyncEnabled) ||
+            !initDispatch(HWC2_FUNCTION_VALIDATE_DISPLAY, &mDispatch.validateDisplay)) {
+            return false;
+        }
+
+        return true;
+    }
+
+    static void hotplugHook(hwc2_callback_data_t callbackData, hwc2_display_t display,
+                            int32_t connected) {
+        auto hal = static_cast<HwcHalImpl*>(callbackData);
+        hal->mEventCallback->onHotplug(display,
+                                       static_cast<IComposerCallback::Connection>(connected));
+    }
+
+    static void refreshHook(hwc2_callback_data_t callbackData, hwc2_display_t display) {
+        auto hal = static_cast<HwcHalImpl*>(callbackData);
+        hal->mMustValidateDisplay = true;
+        hal->mEventCallback->onRefresh(display);
+    }
+
+    static void vsyncHook(hwc2_callback_data_t callbackData, hwc2_display_t display,
+                          int64_t timestamp) {
+        auto hal = static_cast<HwcHalImpl*>(callbackData);
+        hal->mEventCallback->onVsync(display, timestamp);
+    }
+
+    hwc2_device_t* mDevice = nullptr;
+
+    std::unordered_set<hwc2_capability_t> mCapabilities;
+
+    struct {
+        HWC2_PFN_ACCEPT_DISPLAY_CHANGES acceptDisplayChanges;
+        HWC2_PFN_CREATE_LAYER createLayer;
+        HWC2_PFN_CREATE_VIRTUAL_DISPLAY createVirtualDisplay;
+        HWC2_PFN_DESTROY_LAYER destroyLayer;
+        HWC2_PFN_DESTROY_VIRTUAL_DISPLAY destroyVirtualDisplay;
+        HWC2_PFN_DUMP dump;
+        HWC2_PFN_GET_ACTIVE_CONFIG getActiveConfig;
+        HWC2_PFN_GET_CHANGED_COMPOSITION_TYPES getChangedCompositionTypes;
+        HWC2_PFN_GET_CLIENT_TARGET_SUPPORT getClientTargetSupport;
+        HWC2_PFN_GET_COLOR_MODES getColorModes;
+        HWC2_PFN_GET_DISPLAY_ATTRIBUTE getDisplayAttribute;
+        HWC2_PFN_GET_DISPLAY_CONFIGS getDisplayConfigs;
+        HWC2_PFN_GET_DISPLAY_NAME getDisplayName;
+        HWC2_PFN_GET_DISPLAY_REQUESTS getDisplayRequests;
+        HWC2_PFN_GET_DISPLAY_TYPE getDisplayType;
+        HWC2_PFN_GET_DOZE_SUPPORT getDozeSupport;
+        HWC2_PFN_GET_HDR_CAPABILITIES getHdrCapabilities;
+        HWC2_PFN_GET_MAX_VIRTUAL_DISPLAY_COUNT getMaxVirtualDisplayCount;
+        HWC2_PFN_GET_RELEASE_FENCES getReleaseFences;
+        HWC2_PFN_PRESENT_DISPLAY presentDisplay;
+        HWC2_PFN_REGISTER_CALLBACK registerCallback;
+        HWC2_PFN_SET_ACTIVE_CONFIG setActiveConfig;
+        HWC2_PFN_SET_CLIENT_TARGET setClientTarget;
+        HWC2_PFN_SET_COLOR_MODE setColorMode;
+        HWC2_PFN_SET_COLOR_TRANSFORM setColorTransform;
+        HWC2_PFN_SET_CURSOR_POSITION setCursorPosition;
+        HWC2_PFN_SET_LAYER_BLEND_MODE setLayerBlendMode;
+        HWC2_PFN_SET_LAYER_BUFFER setLayerBuffer;
+        HWC2_PFN_SET_LAYER_COLOR setLayerColor;
+        HWC2_PFN_SET_LAYER_COMPOSITION_TYPE setLayerCompositionType;
+        HWC2_PFN_SET_LAYER_DATASPACE setLayerDataspace;
+        HWC2_PFN_SET_LAYER_DISPLAY_FRAME setLayerDisplayFrame;
+        HWC2_PFN_SET_LAYER_PLANE_ALPHA setLayerPlaneAlpha;
+        HWC2_PFN_SET_LAYER_SIDEBAND_STREAM setLayerSidebandStream;
+        HWC2_PFN_SET_LAYER_SOURCE_CROP setLayerSourceCrop;
+        HWC2_PFN_SET_LAYER_SURFACE_DAMAGE setLayerSurfaceDamage;
+        HWC2_PFN_SET_LAYER_TRANSFORM setLayerTransform;
+        HWC2_PFN_SET_LAYER_VISIBLE_REGION setLayerVisibleRegion;
+        HWC2_PFN_SET_LAYER_Z_ORDER setLayerZOrder;
+        HWC2_PFN_SET_OUTPUT_BUFFER setOutputBuffer;
+        HWC2_PFN_SET_POWER_MODE setPowerMode;
+        HWC2_PFN_SET_VSYNC_ENABLED setVsyncEnabled;
+        HWC2_PFN_VALIDATE_DISPLAY validateDisplay;
+    } mDispatch = {};
+
+    hal::ComposerHal::EventCallback* mEventCallback = nullptr;
+
+    std::atomic<bool> mMustValidateDisplay{true};
+};
+
+}  // namespace detail
+
+using HwcHal = detail::HwcHalImpl<hal::ComposerHal>;
+
+}  // namespace passthrough
+}  // namespace V2_1
+}  // namespace composer
+}  // namespace graphics
+}  // namespace hardware
+}  // namespace android
diff --git a/graphics/composer/2.1/utils/passthrough/include/composer-passthrough/2.1/HwcLoader.h b/graphics/composer/2.1/utils/passthrough/include/composer-passthrough/2.1/HwcLoader.h
new file mode 100644
index 0000000..33c914d
--- /dev/null
+++ b/graphics/composer/2.1/utils/passthrough/include/composer-passthrough/2.1/HwcLoader.h
@@ -0,0 +1,152 @@
+/*
+ * Copyright 2016 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
+
+#ifndef LOG_TAG
+#warning "HwcLoader.h included without LOG_TAG"
+#endif
+
+#include <memory>
+
+#include <composer-hal/2.1/Composer.h>
+#include <composer-passthrough/2.1/HwcHal.h>
+#include <hardware/fb.h>
+#include <hardware/gralloc.h>
+#include <hardware/hardware.h>
+#include <hardware/hwcomposer.h>
+#include <hardware/hwcomposer2.h>
+#include <hwc2on1adapter/HWC2On1Adapter.h>
+#include <hwc2onfbadapter/HWC2OnFbAdapter.h>
+#include <log/log.h>
+
+namespace android {
+namespace hardware {
+namespace graphics {
+namespace composer {
+namespace V2_1 {
+namespace passthrough {
+
+class HwcLoader {
+   public:
+    static IComposer* load() {
+        const hw_module_t* module = loadModule();
+        if (!module) {
+            return nullptr;
+        }
+
+        auto hal = createHalWithAdapter(module);
+        if (!hal) {
+            return nullptr;
+        }
+
+        return createComposer(std::move(hal));
+    }
+
+    // load hwcomposer2 module
+    static const hw_module_t* loadModule() {
+        const hw_module_t* module;
+        int error = hw_get_module(HWC_HARDWARE_MODULE_ID, &module);
+        if (error) {
+            ALOGI("falling back to gralloc module");
+            error = hw_get_module(GRALLOC_HARDWARE_MODULE_ID, &module);
+        }
+
+        if (error) {
+            ALOGE("failed to get hwcomposer or gralloc module");
+            return nullptr;
+        }
+
+        return module;
+    }
+
+    // create a ComposerHal instance
+    static std::unique_ptr<hal::ComposerHal> createHal(const hw_module_t* module) {
+        auto hal = std::make_unique<HwcHal>();
+        return hal->initWithModule(module) ? std::move(hal) : nullptr;
+    }
+
+    // create a ComposerHal instance, insert an adapter if necessary
+    static std::unique_ptr<hal::ComposerHal> createHalWithAdapter(const hw_module_t* module) {
+        bool adapted;
+        hwc2_device_t* device = openDeviceWithAdapter(module, &adapted);
+        if (!device) {
+            return nullptr;
+        }
+        auto hal = std::make_unique<HwcHal>();
+        return hal->initWithDevice(std::move(device), !adapted) ? std::move(hal) : nullptr;
+    }
+
+    // create an IComposer instance
+    static IComposer* createComposer(std::unique_ptr<hal::ComposerHal> hal) {
+        return hal::Composer::create(std::move(hal)).release();
+    }
+
+   protected:
+    // open hwcomposer2 device, install an adapter if necessary
+    static hwc2_device_t* openDeviceWithAdapter(const hw_module_t* module, bool* outAdapted) {
+        if (module->id && std::string(module->id) == GRALLOC_HARDWARE_MODULE_ID) {
+            *outAdapted = true;
+            return adaptGrallocModule(module);
+        }
+
+        hw_device_t* device;
+        int error = module->methods->open(module, HWC_HARDWARE_COMPOSER, &device);
+        if (error) {
+            ALOGE("failed to open hwcomposer device: %s", strerror(-error));
+            return nullptr;
+        }
+
+        int major = (device->version >> 24) & 0xf;
+        if (major != 2) {
+            *outAdapted = true;
+            return adaptHwc1Device(std::move(reinterpret_cast<hwc_composer_device_1*>(device)));
+        }
+
+        *outAdapted = false;
+        return reinterpret_cast<hwc2_device_t*>(device);
+    }
+
+   private:
+    static hwc2_device_t* adaptGrallocModule(const hw_module_t* module) {
+        framebuffer_device_t* device;
+        int error = framebuffer_open(module, &device);
+        if (error) {
+            ALOGE("failed to open framebuffer device: %s", strerror(-error));
+            return nullptr;
+        }
+
+        return new HWC2OnFbAdapter(device);
+    }
+
+    static hwc2_device_t* adaptHwc1Device(hwc_composer_device_1* device) {
+        int minor = (device->common.version >> 16) & 0xf;
+        if (minor < 1) {
+            ALOGE("hwcomposer 1.0 is not supported");
+            device->common.close(&device->common);
+            return nullptr;
+        }
+
+        return new HWC2On1Adapter(device);
+    }
+};
+
+}  // namespace passthrough
+}  // namespace V2_1
+}  // namespace composer
+}  // namespace graphics
+}  // namespace hardware
+}  // namespace android
diff --git a/graphics/composer/2.1/utils/vts/Android.bp b/graphics/composer/2.1/utils/vts/Android.bp
new file mode 100644
index 0000000..846cfdf
--- /dev/null
+++ b/graphics/composer/2.1/utils/vts/Android.bp
@@ -0,0 +1,38 @@
+//
+// Copyright (C) 2016 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.
+//
+
+cc_library_static {
+    name: "android.hardware.graphics.composer@2.1-vts",
+    defaults: ["hidl_defaults"],
+    srcs: [
+        "ComposerVts.cpp",
+        "GraphicsComposerCallback.cpp",
+        "TestCommandReader.cpp",
+    ],
+    static_libs: [
+        "VtsHalHidlTargetTestBase",
+        "android.hardware.graphics.composer@2.1",
+    ],
+    header_libs: [
+        "android.hardware.graphics.composer@2.1-command-buffer",
+    ],
+    cflags: [
+        "-O0",
+        "-g",
+        "-DLOG_TAG=\"ComposerVts\"",
+    ],
+    export_include_dirs: ["include"],
+}
diff --git a/graphics/composer/2.1/utils/vts/ComposerVts.cpp b/graphics/composer/2.1/utils/vts/ComposerVts.cpp
new file mode 100644
index 0000000..2f531b4
--- /dev/null
+++ b/graphics/composer/2.1/utils/vts/ComposerVts.cpp
@@ -0,0 +1,324 @@
+/*
+ * Copyright (C) 2017 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 <composer-vts/2.1/ComposerVts.h>
+
+#include <VtsHalHidlTargetTestBase.h>
+
+namespace android {
+namespace hardware {
+namespace graphics {
+namespace composer {
+namespace V2_1 {
+namespace vts {
+
+Composer::Composer() {
+    mComposer = ::testing::VtsHalHidlTargetTestBase::getService<IComposer>();
+    init();
+}
+
+Composer::Composer(const std::string& name) {
+    mComposer = ::testing::VtsHalHidlTargetTestBase::getService<IComposer>(name);
+    init();
+}
+
+void Composer::init() {
+    ASSERT_NE(nullptr, mComposer.get()) << "failed to get composer service";
+
+    std::vector<IComposer::Capability> capabilities = getCapabilities();
+    mCapabilities.insert(capabilities.begin(), capabilities.end());
+}
+
+sp<IComposer> Composer::getRaw() const {
+    return mComposer;
+}
+
+bool Composer::hasCapability(IComposer::Capability capability) const {
+    return mCapabilities.count(capability) > 0;
+}
+
+std::vector<IComposer::Capability> Composer::getCapabilities() {
+    std::vector<IComposer::Capability> capabilities;
+    mComposer->getCapabilities(
+        [&](const auto& tmpCapabilities) { capabilities = tmpCapabilities; });
+
+    return capabilities;
+}
+
+std::string Composer::dumpDebugInfo() {
+    std::string debugInfo;
+    mComposer->dumpDebugInfo([&](const auto& tmpDebugInfo) { debugInfo = tmpDebugInfo.c_str(); });
+
+    return debugInfo;
+}
+
+std::unique_ptr<ComposerClient> Composer::createClient() {
+    std::unique_ptr<ComposerClient> client;
+    mComposer->createClient([&](const auto& tmpError, const auto& tmpClient) {
+        ASSERT_EQ(Error::NONE, tmpError) << "failed to create client";
+        client = std::make_unique<ComposerClient>(tmpClient);
+    });
+
+    return client;
+}
+
+ComposerClient::ComposerClient(const sp<IComposerClient>& client) : mClient(client) {}
+
+ComposerClient::~ComposerClient() {
+    for (auto it : mDisplayResources) {
+        Display display = it.first;
+        DisplayResource& resource = it.second;
+
+        for (auto layer : resource.layers) {
+            EXPECT_EQ(Error::NONE, mClient->destroyLayer(display, layer))
+                << "failed to destroy layer " << layer;
+        }
+
+        if (resource.isVirtual) {
+            EXPECT_EQ(Error::NONE, mClient->destroyVirtualDisplay(display))
+                << "failed to destroy virtual display " << display;
+        }
+    }
+    mDisplayResources.clear();
+}
+
+sp<IComposerClient> ComposerClient::getRaw() const {
+    return mClient;
+}
+
+void ComposerClient::registerCallback(const sp<IComposerCallback>& callback) {
+    mClient->registerCallback(callback);
+}
+
+uint32_t ComposerClient::getMaxVirtualDisplayCount() {
+    return mClient->getMaxVirtualDisplayCount();
+}
+
+Display ComposerClient::createVirtualDisplay(uint32_t width, uint32_t height,
+                                             PixelFormat formatHint, uint32_t outputBufferSlotCount,
+                                             PixelFormat* outFormat) {
+    Display display = 0;
+    mClient->createVirtualDisplay(
+        width, height, formatHint, outputBufferSlotCount,
+        [&](const auto& tmpError, const auto& tmpDisplay, const auto& tmpFormat) {
+            ASSERT_EQ(Error::NONE, tmpError) << "failed to create virtual display";
+            display = tmpDisplay;
+            *outFormat = tmpFormat;
+
+            ASSERT_TRUE(mDisplayResources.insert({display, DisplayResource(true)}).second)
+                << "duplicated virtual display id " << display;
+        });
+
+    return display;
+}
+
+void ComposerClient::destroyVirtualDisplay(Display display) {
+    Error error = mClient->destroyVirtualDisplay(display);
+    ASSERT_EQ(Error::NONE, error) << "failed to destroy virtual display " << display;
+
+    mDisplayResources.erase(display);
+}
+
+Layer ComposerClient::createLayer(Display display, uint32_t bufferSlotCount) {
+    Layer layer = 0;
+    mClient->createLayer(display, bufferSlotCount, [&](const auto& tmpError, const auto& tmpLayer) {
+        ASSERT_EQ(Error::NONE, tmpError) << "failed to create layer";
+        layer = tmpLayer;
+
+        auto resourceIt = mDisplayResources.find(display);
+        if (resourceIt == mDisplayResources.end()) {
+            resourceIt = mDisplayResources.insert({display, DisplayResource(false)}).first;
+        }
+
+        ASSERT_TRUE(resourceIt->second.layers.insert(layer).second)
+            << "duplicated layer id " << layer;
+    });
+
+    return layer;
+}
+
+void ComposerClient::destroyLayer(Display display, Layer layer) {
+    Error error = mClient->destroyLayer(display, layer);
+    ASSERT_EQ(Error::NONE, error) << "failed to destroy layer " << layer;
+
+    auto resourceIt = mDisplayResources.find(display);
+    ASSERT_NE(mDisplayResources.end(), resourceIt);
+    resourceIt->second.layers.erase(layer);
+}
+
+Config ComposerClient::getActiveConfig(Display display) {
+    Config config = 0;
+    mClient->getActiveConfig(display, [&](const auto& tmpError, const auto& tmpConfig) {
+        ASSERT_EQ(Error::NONE, tmpError) << "failed to get active config";
+        config = tmpConfig;
+    });
+
+    return config;
+}
+
+bool ComposerClient::getClientTargetSupport(Display display, uint32_t width, uint32_t height,
+                                            PixelFormat format, Dataspace dataspace) {
+    Error error = mClient->getClientTargetSupport(display, width, height, format, dataspace);
+    return error == Error::NONE;
+}
+
+std::vector<ColorMode> ComposerClient::getColorModes(Display display) {
+    std::vector<ColorMode> modes;
+    mClient->getColorModes(display, [&](const auto& tmpError, const auto& tmpMode) {
+        ASSERT_EQ(Error::NONE, tmpError) << "failed to get color mode";
+        modes = tmpMode;
+    });
+
+    return modes;
+}
+
+int32_t ComposerClient::getDisplayAttribute(Display display, Config config,
+                                            IComposerClient::Attribute attribute) {
+    int32_t value = 0;
+    mClient->getDisplayAttribute(
+        display, config, attribute, [&](const auto& tmpError, const auto& tmpValue) {
+            ASSERT_EQ(Error::NONE, tmpError) << "failed to get display attribute";
+            value = tmpValue;
+        });
+
+    return value;
+}
+
+std::vector<Config> ComposerClient::getDisplayConfigs(Display display) {
+    std::vector<Config> configs;
+    mClient->getDisplayConfigs(display, [&](const auto& tmpError, const auto& tmpConfigs) {
+        ASSERT_EQ(Error::NONE, tmpError) << "failed to get display configs";
+        configs = tmpConfigs;
+    });
+
+    return configs;
+}
+
+std::string ComposerClient::getDisplayName(Display display) {
+    std::string name;
+    mClient->getDisplayName(display, [&](const auto& tmpError, const auto& tmpName) {
+        ASSERT_EQ(Error::NONE, tmpError) << "failed to get display name";
+        name = tmpName.c_str();
+    });
+
+    return name;
+}
+
+IComposerClient::DisplayType ComposerClient::getDisplayType(Display display) {
+    IComposerClient::DisplayType type = IComposerClient::DisplayType::INVALID;
+    mClient->getDisplayType(display, [&](const auto& tmpError, const auto& tmpType) {
+        ASSERT_EQ(Error::NONE, tmpError) << "failed to get display type";
+        type = tmpType;
+    });
+
+    return type;
+}
+
+bool ComposerClient::getDozeSupport(Display display) {
+    bool support = false;
+    mClient->getDozeSupport(display, [&](const auto& tmpError, const auto& tmpSupport) {
+        ASSERT_EQ(Error::NONE, tmpError) << "failed to get doze support";
+        support = tmpSupport;
+    });
+
+    return support;
+}
+
+std::vector<Hdr> ComposerClient::getHdrCapabilities(Display display, float* outMaxLuminance,
+                                                    float* outMaxAverageLuminance,
+                                                    float* outMinLuminance) {
+    std::vector<Hdr> types;
+    mClient->getHdrCapabilities(
+        display, [&](const auto& tmpError, const auto& tmpTypes, const auto& tmpMaxLuminance,
+                     const auto& tmpMaxAverageLuminance, const auto& tmpMinLuminance) {
+            ASSERT_EQ(Error::NONE, tmpError) << "failed to get HDR capabilities";
+            types = tmpTypes;
+            *outMaxLuminance = tmpMaxLuminance;
+            *outMaxAverageLuminance = tmpMaxAverageLuminance;
+            *outMinLuminance = tmpMinLuminance;
+        });
+
+    return types;
+}
+
+void ComposerClient::setClientTargetSlotCount(Display display, uint32_t clientTargetSlotCount) {
+    Error error = mClient->setClientTargetSlotCount(display, clientTargetSlotCount);
+    ASSERT_EQ(Error::NONE, error) << "failed to set client target slot count";
+}
+
+void ComposerClient::setActiveConfig(Display display, Config config) {
+    Error error = mClient->setActiveConfig(display, config);
+    ASSERT_EQ(Error::NONE, error) << "failed to set active config";
+}
+
+void ComposerClient::setColorMode(Display display, ColorMode mode) {
+    Error error = mClient->setColorMode(display, mode);
+    ASSERT_EQ(Error::NONE, error) << "failed to set color mode";
+}
+
+void ComposerClient::setPowerMode(Display display, IComposerClient::PowerMode mode) {
+    Error error = mClient->setPowerMode(display, mode);
+    ASSERT_EQ(Error::NONE, error) << "failed to set power mode";
+}
+
+void ComposerClient::setVsyncEnabled(Display display, bool enabled) {
+    IComposerClient::Vsync vsync =
+        (enabled) ? IComposerClient::Vsync::ENABLE : IComposerClient::Vsync::DISABLE;
+    Error error = mClient->setVsyncEnabled(display, vsync);
+    ASSERT_EQ(Error::NONE, error) << "failed to set vsync mode";
+
+    // give the hwbinder thread some time to handle any pending vsync callback
+    if (!enabled) {
+        usleep(5 * 1000);
+    }
+}
+
+void ComposerClient::execute(TestCommandReader* reader, CommandWriterBase* writer) {
+    bool queueChanged = false;
+    uint32_t commandLength = 0;
+    hidl_vec<hidl_handle> commandHandles;
+    ASSERT_TRUE(writer->writeQueue(&queueChanged, &commandLength, &commandHandles));
+
+    if (queueChanged) {
+        auto ret = mClient->setInputCommandQueue(*writer->getMQDescriptor());
+        ASSERT_EQ(Error::NONE, static_cast<Error>(ret));
+        return;
+    }
+
+    mClient->executeCommands(commandLength, commandHandles,
+                             [&](const auto& tmpError, const auto& tmpOutQueueChanged,
+                                 const auto& tmpOutLength, const auto& tmpOutHandles) {
+                                 ASSERT_EQ(Error::NONE, tmpError);
+
+                                 if (tmpOutQueueChanged) {
+                                     mClient->getOutputCommandQueue(
+                                         [&](const auto& tmpError, const auto& tmpDescriptor) {
+                                             ASSERT_EQ(Error::NONE, tmpError);
+                                             reader->setMQDescriptor(tmpDescriptor);
+                                         });
+                                 }
+
+                                 ASSERT_TRUE(reader->readQueue(tmpOutLength, tmpOutHandles));
+                                 reader->parse();
+                             });
+}
+
+}  // namespace vts
+}  // namespace V2_1
+}  // namespace composer
+}  // namespace graphics
+}  // namespace hardware
+}  // namespace android
diff --git a/graphics/composer/2.1/utils/vts/GraphicsComposerCallback.cpp b/graphics/composer/2.1/utils/vts/GraphicsComposerCallback.cpp
new file mode 100644
index 0000000..1ead138
--- /dev/null
+++ b/graphics/composer/2.1/utils/vts/GraphicsComposerCallback.cpp
@@ -0,0 +1,92 @@
+/*
+ * Copyright (C) 2017 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 <composer-vts/2.1/GraphicsComposerCallback.h>
+
+namespace android {
+namespace hardware {
+namespace graphics {
+namespace composer {
+namespace V2_1 {
+namespace vts {
+
+void GraphicsComposerCallback::setVsyncAllowed(bool allowed) {
+    std::lock_guard<std::mutex> lock(mMutex);
+    mVsyncAllowed = allowed;
+}
+
+std::vector<Display> GraphicsComposerCallback::getDisplays() const {
+    std::lock_guard<std::mutex> lock(mMutex);
+    return std::vector<Display>(mDisplays.begin(), mDisplays.end());
+}
+
+int GraphicsComposerCallback::getInvalidHotplugCount() const {
+    std::lock_guard<std::mutex> lock(mMutex);
+    return mInvalidHotplugCount;
+}
+
+int GraphicsComposerCallback::getInvalidRefreshCount() const {
+    std::lock_guard<std::mutex> lock(mMutex);
+    return mInvalidRefreshCount;
+}
+
+int GraphicsComposerCallback::getInvalidVsyncCount() const {
+    std::lock_guard<std::mutex> lock(mMutex);
+    return mInvalidVsyncCount;
+}
+
+Return<void> GraphicsComposerCallback::onHotplug(Display display, Connection connection) {
+    std::lock_guard<std::mutex> lock(mMutex);
+
+    if (connection == Connection::CONNECTED) {
+        if (!mDisplays.insert(display).second) {
+            mInvalidHotplugCount++;
+        }
+    } else if (connection == Connection::DISCONNECTED) {
+        if (!mDisplays.erase(display)) {
+            mInvalidHotplugCount++;
+        }
+    }
+
+    return Void();
+}
+
+Return<void> GraphicsComposerCallback::onRefresh(Display display) {
+    std::lock_guard<std::mutex> lock(mMutex);
+
+    if (mDisplays.count(display) == 0) {
+        mInvalidRefreshCount++;
+    }
+
+    return Void();
+}
+
+Return<void> GraphicsComposerCallback::onVsync(Display display, int64_t) {
+    std::lock_guard<std::mutex> lock(mMutex);
+
+    if (!mVsyncAllowed || mDisplays.count(display) == 0) {
+        mInvalidVsyncCount++;
+    }
+
+    return Void();
+}
+
+}  // namespace vts
+}  // namespace V2_1
+}  // namespace composer
+}  // namespace graphics
+}  // namespace hardware
+}  // namespace android
diff --git a/graphics/composer/2.1/utils/vts/TestCommandReader.cpp b/graphics/composer/2.1/utils/vts/TestCommandReader.cpp
new file mode 100644
index 0000000..6f8f1ad
--- /dev/null
+++ b/graphics/composer/2.1/utils/vts/TestCommandReader.cpp
@@ -0,0 +1,62 @@
+/*
+ * Copyright (C) 2017 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 <composer-vts/2.1/TestCommandReader.h>
+
+#include <gtest/gtest.h>
+
+namespace android {
+namespace hardware {
+namespace graphics {
+namespace composer {
+namespace V2_1 {
+namespace vts {
+
+void TestCommandReader::parse() {
+    while (!isEmpty()) {
+        IComposerClient::Command command;
+        uint16_t length;
+        ASSERT_TRUE(beginCommand(&command, &length));
+
+        switch (command) {
+            case IComposerClient::Command::SET_ERROR: {
+                ASSERT_EQ(2, length);
+                auto loc = read();
+                auto err = readSigned();
+                GTEST_FAIL() << "unexpected error " << err << " at location " << loc;
+            } break;
+            case IComposerClient::Command::SELECT_DISPLAY:
+            case IComposerClient::Command::SET_CHANGED_COMPOSITION_TYPES:
+            case IComposerClient::Command::SET_DISPLAY_REQUESTS:
+            case IComposerClient::Command::SET_PRESENT_FENCE:
+            case IComposerClient::Command::SET_RELEASE_FENCES:
+                break;
+            default:
+                GTEST_FAIL() << "unexpected return command " << std::hex
+                             << static_cast<int>(command);
+                break;
+        }
+
+        endCommand();
+    }
+}
+
+}  // namespace vts
+}  // namespace V2_1
+}  // namespace composer
+}  // namespace graphics
+}  // namespace hardware
+}  // namespace android
diff --git a/graphics/composer/2.1/utils/vts/include/composer-vts/2.1/ComposerVts.h b/graphics/composer/2.1/utils/vts/include/composer-vts/2.1/ComposerVts.h
new file mode 100644
index 0000000..0d883e4
--- /dev/null
+++ b/graphics/composer/2.1/utils/vts/include/composer-vts/2.1/ComposerVts.h
@@ -0,0 +1,126 @@
+/*
+ * Copyright (C) 2017 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 <memory>
+#include <string>
+#include <unordered_map>
+#include <unordered_set>
+#include <vector>
+
+#include <android/hardware/graphics/composer/2.1/IComposer.h>
+#include <composer-command-buffer/2.1/ComposerCommandBuffer.h>
+#include <composer-vts/2.1/TestCommandReader.h>
+#include <utils/StrongPointer.h>
+
+namespace android {
+namespace hardware {
+namespace graphics {
+namespace composer {
+namespace V2_1 {
+namespace vts {
+
+using android::hardware::graphics::common::V1_0::ColorMode;
+using android::hardware::graphics::common::V1_0::Dataspace;
+using android::hardware::graphics::common::V1_0::Hdr;
+using android::hardware::graphics::common::V1_0::PixelFormat;
+
+class ComposerClient;
+
+// A wrapper to IComposer.
+class Composer {
+   public:
+    Composer();
+    explicit Composer(const std::string& name);
+
+    sp<IComposer> getRaw() const;
+
+    // Returns true when the composer supports the specified capability.
+    bool hasCapability(IComposer::Capability capability) const;
+
+    std::vector<IComposer::Capability> getCapabilities();
+    std::string dumpDebugInfo();
+    std::unique_ptr<ComposerClient> createClient();
+
+   protected:
+    sp<IComposer> mComposer;
+
+   private:
+    void init();
+
+    std::unordered_set<IComposer::Capability> mCapabilities;
+};
+
+// A wrapper to IComposerClient.
+class ComposerClient {
+   public:
+    ComposerClient(const sp<IComposerClient>& client);
+    ~ComposerClient();
+
+    sp<IComposerClient> getRaw() const;
+
+    void registerCallback(const sp<IComposerCallback>& callback);
+    uint32_t getMaxVirtualDisplayCount();
+
+    Display createVirtualDisplay(uint32_t width, uint32_t height, PixelFormat formatHint,
+                                 uint32_t outputBufferSlotCount, PixelFormat* outFormat);
+    void destroyVirtualDisplay(Display display);
+
+    Layer createLayer(Display display, uint32_t bufferSlotCount);
+    void destroyLayer(Display display, Layer layer);
+
+    Config getActiveConfig(Display display);
+    bool getClientTargetSupport(Display display, uint32_t width, uint32_t height,
+                                PixelFormat format, Dataspace dataspace);
+    std::vector<ColorMode> getColorModes(Display display);
+    int32_t getDisplayAttribute(Display display, Config config,
+                                IComposerClient::Attribute attribute);
+    std::vector<Config> getDisplayConfigs(Display display);
+    std::string getDisplayName(Display display);
+    IComposerClient::DisplayType getDisplayType(Display display);
+    bool getDozeSupport(Display display);
+    std::vector<Hdr> getHdrCapabilities(Display display, float* outMaxLuminance,
+                                        float* outMaxAverageLuminance, float* outMinLuminance);
+
+    void setClientTargetSlotCount(Display display, uint32_t clientTargetSlotCount);
+    void setActiveConfig(Display display, Config config);
+    void setColorMode(Display display, ColorMode mode);
+    void setPowerMode(Display display, IComposerClient::PowerMode mode);
+    void setVsyncEnabled(Display display, bool enabled);
+
+    void execute(TestCommandReader* reader, CommandWriterBase* writer);
+
+   private:
+    sp<IComposerClient> mClient;
+
+    // Keep track of all virtual displays and layers.  When a test fails with
+    // ASSERT_*, the destructor will clean up the resources for the test.
+    struct DisplayResource {
+        DisplayResource(bool isVirtual_) : isVirtual(isVirtual_) {}
+
+        bool isVirtual;
+        std::unordered_set<Layer> layers;
+    };
+    std::unordered_map<Display, DisplayResource> mDisplayResources;
+};
+
+}  // namespace vts
+}  // namespace V2_1
+}  // namespace composer
+}  // namespace graphics
+}  // namespace hardware
+}  // namespace android
diff --git a/graphics/composer/2.1/utils/vts/include/composer-vts/2.1/GraphicsComposerCallback.h b/graphics/composer/2.1/utils/vts/include/composer-vts/2.1/GraphicsComposerCallback.h
new file mode 100644
index 0000000..e3c348f
--- /dev/null
+++ b/graphics/composer/2.1/utils/vts/include/composer-vts/2.1/GraphicsComposerCallback.h
@@ -0,0 +1,66 @@
+/*
+ * Copyright (C) 2017 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/hardware/graphics/composer/2.1/IComposerCallback.h>
+
+#include <mutex>
+#include <unordered_set>
+
+namespace android {
+namespace hardware {
+namespace graphics {
+namespace composer {
+namespace V2_1 {
+namespace vts {
+
+// IComposerCallback to be installed with IComposerClient::registerCallback.
+class GraphicsComposerCallback : public IComposerCallback {
+   public:
+    void setVsyncAllowed(bool allowed);
+
+    std::vector<Display> getDisplays() const;
+
+    int getInvalidHotplugCount() const;
+
+    int getInvalidRefreshCount() const;
+
+    int getInvalidVsyncCount() const;
+
+   private:
+    Return<void> onHotplug(Display display, Connection connection) override;
+    Return<void> onRefresh(Display display) override;
+    Return<void> onVsync(Display display, int64_t) override;
+
+    mutable std::mutex mMutex;
+    // the set of all currently connected displays
+    std::unordered_set<Display> mDisplays;
+    // true only when vsync is enabled
+    bool mVsyncAllowed = true;
+
+    // track invalid callbacks
+    int mInvalidHotplugCount = 0;
+    int mInvalidRefreshCount = 0;
+    int mInvalidVsyncCount = 0;
+};
+
+}  // namespace vts
+}  // namespace V2_1
+}  // namespace composer
+}  // namespace graphics
+}  // namespace hardware
+}  // namespace android
diff --git a/graphics/composer/2.1/vts/functional/TestCommandReader.h b/graphics/composer/2.1/utils/vts/include/composer-vts/2.1/TestCommandReader.h
similarity index 79%
rename from graphics/composer/2.1/vts/functional/TestCommandReader.h
rename to graphics/composer/2.1/utils/vts/include/composer-vts/2.1/TestCommandReader.h
index ae25d2d..3888eeb 100644
--- a/graphics/composer/2.1/vts/functional/TestCommandReader.h
+++ b/graphics/composer/2.1/utils/vts/include/composer-vts/2.1/TestCommandReader.h
@@ -14,8 +14,7 @@
  * limitations under the License.
  */
 
-#ifndef TEST_COMMAND_READER_H
-#define TEST_COMMAND_READER_H
+#pragma once
 
 #include <composer-command-buffer/2.1/ComposerCommandBuffer.h>
 
@@ -24,22 +23,20 @@
 namespace graphics {
 namespace composer {
 namespace V2_1 {
-namespace tests {
+namespace vts {
 
 // A command parser that checks that no error nor unexpected commands are
 // returned.
 class TestCommandReader : public CommandReaderBase {
- public:
-  // Parse all commands in the return command queue.  Call GTEST_FAIL() for
-  // unexpected errors or commands.
-  void parse();
+   public:
+    // Parse all commands in the return command queue.  Call GTEST_FAIL() for
+    // unexpected errors or commands.
+    void parse();
 };
 
-}  // namespace tests
+}  // namespace vts
 }  // namespace V2_1
 }  // namespace composer
 }  // namespace graphics
 }  // namespace hardware
 }  // namespace android
-
-#endif  // TEST_COMMAND_READER_H
diff --git a/graphics/composer/2.1/vts/functional/Android.bp b/graphics/composer/2.1/vts/functional/Android.bp
index 92b65a3..8e346df 100644
--- a/graphics/composer/2.1/vts/functional/Android.bp
+++ b/graphics/composer/2.1/vts/functional/Android.bp
@@ -14,36 +14,6 @@
 // limitations under the License.
 //
 
-cc_library_static {
-    name: "libVtsHalGraphicsComposerTestUtils",
-    defaults: ["hidl_defaults"],
-    srcs: [
-        "GraphicsComposerCallback.cpp",
-        "TestCommandReader.cpp",
-        "VtsHalGraphicsComposerTestUtils.cpp",
-    ],
-    shared_libs: [
-        "android.hardware.graphics.composer@2.1",
-        "libfmq",
-        "libsync",
-    ],
-    static_libs: [
-        "VtsHalHidlTargetTestBase",
-    ],
-    header_libs: [
-        "android.hardware.graphics.composer@2.1-command-buffer",
-    ],
-    cflags: [
-        "-Wall",
-        "-Wextra",
-        "-Werror",
-        "-O0",
-        "-g",
-        "-DLOG_TAG=\"GraphicsComposerTestUtils\"",
-    ],
-    export_include_dirs: ["."],
-}
-
 cc_test {
     name: "VtsHalGraphicsComposerV2_1TargetTest",
     defaults: ["VtsHalTargetTestDefaults"],
@@ -57,10 +27,9 @@
     static_libs: [
         "android.hardware.graphics.allocator@2.0",
         "android.hardware.graphics.composer@2.1",
+        "android.hardware.graphics.composer@2.1-vts",
         "android.hardware.graphics.mapper@2.0",
         "android.hardware.graphics.mapper@2.0-vts",
-        "libVtsHalGraphicsComposerTestUtils",
-        "libnativehelper",
     ],
     header_libs: [
         "android.hardware.graphics.composer@2.1-command-buffer",
diff --git a/graphics/composer/2.1/vts/functional/GraphicsComposerCallback.cpp b/graphics/composer/2.1/vts/functional/GraphicsComposerCallback.cpp
deleted file mode 100644
index 0ad440c..0000000
--- a/graphics/composer/2.1/vts/functional/GraphicsComposerCallback.cpp
+++ /dev/null
@@ -1,93 +0,0 @@
-/*
- * Copyright (C) 2017 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 "GraphicsComposerCallback.h"
-
-namespace android {
-namespace hardware {
-namespace graphics {
-namespace composer {
-namespace V2_1 {
-namespace tests {
-
-void GraphicsComposerCallback::setVsyncAllowed(bool allowed) {
-  std::lock_guard<std::mutex> lock(mMutex);
-  mVsyncAllowed = allowed;
-}
-
-std::vector<Display> GraphicsComposerCallback::getDisplays() const {
-  std::lock_guard<std::mutex> lock(mMutex);
-  return std::vector<Display>(mDisplays.begin(), mDisplays.end());
-}
-
-int GraphicsComposerCallback::getInvalidHotplugCount() const {
-  std::lock_guard<std::mutex> lock(mMutex);
-  return mInvalidHotplugCount;
-}
-
-int GraphicsComposerCallback::getInvalidRefreshCount() const {
-  std::lock_guard<std::mutex> lock(mMutex);
-  return mInvalidRefreshCount;
-}
-
-int GraphicsComposerCallback::getInvalidVsyncCount() const {
-  std::lock_guard<std::mutex> lock(mMutex);
-  return mInvalidVsyncCount;
-}
-
-Return<void> GraphicsComposerCallback::onHotplug(Display display,
-                                                 Connection connection) {
-  std::lock_guard<std::mutex> lock(mMutex);
-
-  if (connection == Connection::CONNECTED) {
-    if (!mDisplays.insert(display).second) {
-      mInvalidHotplugCount++;
-    }
-  } else if (connection == Connection::DISCONNECTED) {
-    if (!mDisplays.erase(display)) {
-      mInvalidHotplugCount++;
-    }
-  }
-
-  return Void();
-}
-
-Return<void> GraphicsComposerCallback::onRefresh(Display display) {
-  std::lock_guard<std::mutex> lock(mMutex);
-
-  if (mDisplays.count(display) == 0) {
-    mInvalidRefreshCount++;
-  }
-
-  return Void();
-}
-
-Return<void> GraphicsComposerCallback::onVsync(Display display, int64_t) {
-  std::lock_guard<std::mutex> lock(mMutex);
-
-  if (!mVsyncAllowed || mDisplays.count(display) == 0) {
-    mInvalidVsyncCount++;
-  }
-
-  return Void();
-}
-
-}  // namespace tests
-}  // namespace V2_1
-}  // namespace composer
-}  // namespace graphics
-}  // namespace hardware
-}  // namespace android
diff --git a/graphics/composer/2.1/vts/functional/GraphicsComposerCallback.h b/graphics/composer/2.1/vts/functional/GraphicsComposerCallback.h
deleted file mode 100644
index e332086..0000000
--- a/graphics/composer/2.1/vts/functional/GraphicsComposerCallback.h
+++ /dev/null
@@ -1,69 +0,0 @@
-/*
- * Copyright (C) 2017 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.
- */
-
-#ifndef GRAPHICS_COMPOSER_CALLBACK_H
-#define GRAPHICS_COMPOSER_CALLBACK_H
-
-#include <android/hardware/graphics/composer/2.1/IComposerCallback.h>
-
-#include <mutex>
-#include <unordered_set>
-
-namespace android {
-namespace hardware {
-namespace graphics {
-namespace composer {
-namespace V2_1 {
-namespace tests {
-
-// IComposerCallback to be installed with IComposerClient::registerCallback.
-class GraphicsComposerCallback : public IComposerCallback {
- public:
-  void setVsyncAllowed(bool allowed);
-
-  std::vector<Display> getDisplays() const;
-
-  int getInvalidHotplugCount() const;
-
-  int getInvalidRefreshCount() const;
-
-  int getInvalidVsyncCount() const;
-
- private:
-  Return<void> onHotplug(Display display, Connection connection) override;
-  Return<void> onRefresh(Display display) override;
-  Return<void> onVsync(Display display, int64_t) override;
-
-  mutable std::mutex mMutex;
-  // the set of all currently connected displays
-  std::unordered_set<Display> mDisplays;
-  // true only when vsync is enabled
-  bool mVsyncAllowed = true;
-
-  // track invalid callbacks
-  int mInvalidHotplugCount = 0;
-  int mInvalidRefreshCount = 0;
-  int mInvalidVsyncCount = 0;
-};
-
-}  // namespace tests
-}  // namespace V2_1
-}  // namespace composer
-}  // namespace graphics
-}  // namespace hardware
-}  // namespace android
-
-#endif  // GRAPHICS_COMPOSER_CALLBACK_H
diff --git a/graphics/composer/2.1/vts/functional/TestCommandReader.cpp b/graphics/composer/2.1/vts/functional/TestCommandReader.cpp
deleted file mode 100644
index b1f9aca..0000000
--- a/graphics/composer/2.1/vts/functional/TestCommandReader.cpp
+++ /dev/null
@@ -1,62 +0,0 @@
-/*
- * Copyright (C) 2017 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 "TestCommandReader.h"
-
-#include <gtest/gtest.h>
-
-namespace android {
-namespace hardware {
-namespace graphics {
-namespace composer {
-namespace V2_1 {
-namespace tests {
-
-void TestCommandReader::parse() {
-  while (!isEmpty()) {
-    IComposerClient::Command command;
-    uint16_t length;
-    ASSERT_TRUE(beginCommand(&command, &length));
-
-    switch (command) {
-      case IComposerClient::Command::SET_ERROR: {
-        ASSERT_EQ(2, length);
-        auto loc = read();
-        auto err = readSigned();
-        GTEST_FAIL() << "unexpected error " << err << " at location " << loc;
-      } break;
-      case IComposerClient::Command::SELECT_DISPLAY:
-      case IComposerClient::Command::SET_CHANGED_COMPOSITION_TYPES:
-      case IComposerClient::Command::SET_DISPLAY_REQUESTS:
-      case IComposerClient::Command::SET_PRESENT_FENCE:
-      case IComposerClient::Command::SET_RELEASE_FENCES:
-        break;
-      default:
-        GTEST_FAIL() << "unexpected return command " << std::hex
-                     << static_cast<int>(command);
-        break;
-    }
-
-    endCommand();
-  }
-}
-
-}  // namespace tests
-}  // namespace V2_1
-}  // namespace composer
-}  // namespace graphics
-}  // namespace hardware
-}  // namespace android
diff --git a/graphics/composer/2.1/vts/functional/VtsHalGraphicsComposerTestUtils.cpp b/graphics/composer/2.1/vts/functional/VtsHalGraphicsComposerTestUtils.cpp
deleted file mode 100644
index c66cdd0..0000000
--- a/graphics/composer/2.1/vts/functional/VtsHalGraphicsComposerTestUtils.cpp
+++ /dev/null
@@ -1,345 +0,0 @@
-/*
- * Copyright (C) 2017 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 <VtsHalHidlTargetTestBase.h>
-
-#include "VtsHalGraphicsComposerTestUtils.h"
-
-namespace android {
-namespace hardware {
-namespace graphics {
-namespace composer {
-namespace V2_1 {
-namespace tests {
-
-Composer::Composer() {
-  mComposer = ::testing::VtsHalHidlTargetTestBase::getService<IComposer>();
-  init();
-}
-
-Composer::Composer(const std::string& name) {
-  mComposer = ::testing::VtsHalHidlTargetTestBase::getService<IComposer>(name);
-  init();
-}
-
-void Composer::init() {
-  ASSERT_NE(nullptr, mComposer.get()) << "failed to get composer service";
-
-  std::vector<IComposer::Capability> capabilities = getCapabilities();
-  mCapabilities.insert(capabilities.begin(), capabilities.end());
-}
-
-sp<IComposer> Composer::getRaw() const { return mComposer; }
-
-bool Composer::hasCapability(IComposer::Capability capability) const {
-  return mCapabilities.count(capability) > 0;
-}
-
-std::vector<IComposer::Capability> Composer::getCapabilities() {
-  std::vector<IComposer::Capability> capabilities;
-  mComposer->getCapabilities(
-      [&](const auto& tmpCapabilities) { capabilities = tmpCapabilities; });
-
-  return capabilities;
-}
-
-std::string Composer::dumpDebugInfo() {
-  std::string debugInfo;
-  mComposer->dumpDebugInfo(
-      [&](const auto& tmpDebugInfo) { debugInfo = tmpDebugInfo.c_str(); });
-
-  return debugInfo;
-}
-
-std::unique_ptr<ComposerClient> Composer::createClient() {
-  std::unique_ptr<ComposerClient> client;
-  mComposer->createClient([&](const auto& tmpError, const auto& tmpClient) {
-    ASSERT_EQ(Error::NONE, tmpError) << "failed to create client";
-    client = std::make_unique<ComposerClient>(tmpClient);
-  });
-
-  return client;
-}
-
-ComposerClient::ComposerClient(const sp<IComposerClient>& client)
-    : mClient(client) {}
-
-ComposerClient::~ComposerClient() {
-  for (auto it : mDisplayResources) {
-    Display display = it.first;
-    DisplayResource& resource = it.second;
-
-    for (auto layer : resource.layers) {
-      EXPECT_EQ(Error::NONE, mClient->destroyLayer(display, layer))
-          << "failed to destroy layer " << layer;
-    }
-
-    if (resource.isVirtual) {
-      EXPECT_EQ(Error::NONE, mClient->destroyVirtualDisplay(display))
-          << "failed to destroy virtual display " << display;
-    }
-  }
-  mDisplayResources.clear();
-}
-
-sp<IComposerClient> ComposerClient::getRaw() const { return mClient; }
-
-void ComposerClient::registerCallback(const sp<IComposerCallback>& callback) {
-  mClient->registerCallback(callback);
-}
-
-uint32_t ComposerClient::getMaxVirtualDisplayCount() {
-  return mClient->getMaxVirtualDisplayCount();
-}
-
-Display ComposerClient::createVirtualDisplay(uint32_t width, uint32_t height,
-                                             PixelFormat formatHint,
-                                             uint32_t outputBufferSlotCount,
-                                             PixelFormat* outFormat) {
-  Display display = 0;
-  mClient->createVirtualDisplay(
-      width, height, formatHint, outputBufferSlotCount,
-      [&](const auto& tmpError, const auto& tmpDisplay, const auto& tmpFormat) {
-        ASSERT_EQ(Error::NONE, tmpError) << "failed to create virtual display";
-        display = tmpDisplay;
-        *outFormat = tmpFormat;
-
-        ASSERT_TRUE(
-            mDisplayResources.insert({display, DisplayResource(true)}).second)
-            << "duplicated virtual display id " << display;
-      });
-
-  return display;
-}
-
-void ComposerClient::destroyVirtualDisplay(Display display) {
-  Error error = mClient->destroyVirtualDisplay(display);
-  ASSERT_EQ(Error::NONE, error)
-      << "failed to destroy virtual display " << display;
-
-  mDisplayResources.erase(display);
-}
-
-Layer ComposerClient::createLayer(Display display, uint32_t bufferSlotCount) {
-  Layer layer = 0;
-  mClient->createLayer(
-      display, bufferSlotCount,
-      [&](const auto& tmpError, const auto& tmpLayer) {
-        ASSERT_EQ(Error::NONE, tmpError) << "failed to create layer";
-        layer = tmpLayer;
-
-        auto resourceIt = mDisplayResources.find(display);
-        if (resourceIt == mDisplayResources.end()) {
-          resourceIt =
-              mDisplayResources.insert({display, DisplayResource(false)}).first;
-        }
-
-        ASSERT_TRUE(resourceIt->second.layers.insert(layer).second)
-            << "duplicated layer id " << layer;
-      });
-
-  return layer;
-}
-
-void ComposerClient::destroyLayer(Display display, Layer layer) {
-  Error error = mClient->destroyLayer(display, layer);
-  ASSERT_EQ(Error::NONE, error) << "failed to destroy layer " << layer;
-
-  auto resourceIt = mDisplayResources.find(display);
-  ASSERT_NE(mDisplayResources.end(), resourceIt);
-  resourceIt->second.layers.erase(layer);
-}
-
-Config ComposerClient::getActiveConfig(Display display) {
-  Config config = 0;
-  mClient->getActiveConfig(
-      display, [&](const auto& tmpError, const auto& tmpConfig) {
-        ASSERT_EQ(Error::NONE, tmpError) << "failed to get active config";
-        config = tmpConfig;
-      });
-
-  return config;
-}
-
-bool ComposerClient::getClientTargetSupport(Display display, uint32_t width,
-                                            uint32_t height, PixelFormat format,
-                                            Dataspace dataspace) {
-  Error error = mClient->getClientTargetSupport(display, width, height, format,
-                                                dataspace);
-  return error == Error::NONE;
-}
-
-std::vector<ColorMode> ComposerClient::getColorModes(Display display) {
-  std::vector<ColorMode> modes;
-  mClient->getColorModes(
-      display, [&](const auto& tmpError, const auto& tmpMode) {
-        ASSERT_EQ(Error::NONE, tmpError) << "failed to get color mode";
-        modes = tmpMode;
-      });
-
-  return modes;
-}
-
-int32_t ComposerClient::getDisplayAttribute(
-    Display display, Config config, IComposerClient::Attribute attribute) {
-  int32_t value = 0;
-  mClient->getDisplayAttribute(display, config, attribute,
-                               [&](const auto& tmpError, const auto& tmpValue) {
-                                 ASSERT_EQ(Error::NONE, tmpError)
-                                     << "failed to get display attribute";
-                                 value = tmpValue;
-                               });
-
-  return value;
-}
-
-std::vector<Config> ComposerClient::getDisplayConfigs(Display display) {
-  std::vector<Config> configs;
-  mClient->getDisplayConfigs(
-      display, [&](const auto& tmpError, const auto& tmpConfigs) {
-        ASSERT_EQ(Error::NONE, tmpError) << "failed to get display configs";
-        configs = tmpConfigs;
-      });
-
-  return configs;
-}
-
-std::string ComposerClient::getDisplayName(Display display) {
-  std::string name;
-  mClient->getDisplayName(
-      display, [&](const auto& tmpError, const auto& tmpName) {
-        ASSERT_EQ(Error::NONE, tmpError) << "failed to get display name";
-        name = tmpName.c_str();
-      });
-
-  return name;
-}
-
-IComposerClient::DisplayType ComposerClient::getDisplayType(Display display) {
-  IComposerClient::DisplayType type = IComposerClient::DisplayType::INVALID;
-  mClient->getDisplayType(
-      display, [&](const auto& tmpError, const auto& tmpType) {
-        ASSERT_EQ(Error::NONE, tmpError) << "failed to get display type";
-        type = tmpType;
-      });
-
-  return type;
-}
-
-bool ComposerClient::getDozeSupport(Display display) {
-  bool support = false;
-  mClient->getDozeSupport(
-      display, [&](const auto& tmpError, const auto& tmpSupport) {
-        ASSERT_EQ(Error::NONE, tmpError) << "failed to get doze support";
-        support = tmpSupport;
-      });
-
-  return support;
-}
-
-std::vector<Hdr> ComposerClient::getHdrCapabilities(
-    Display display, float* outMaxLuminance, float* outMaxAverageLuminance,
-    float* outMinLuminance) {
-  std::vector<Hdr> types;
-  mClient->getHdrCapabilities(
-      display,
-      [&](const auto& tmpError, const auto& tmpTypes,
-          const auto& tmpMaxLuminance, const auto& tmpMaxAverageLuminance,
-          const auto& tmpMinLuminance) {
-        ASSERT_EQ(Error::NONE, tmpError) << "failed to get HDR capabilities";
-        types = tmpTypes;
-        *outMaxLuminance = tmpMaxLuminance;
-        *outMaxAverageLuminance = tmpMaxAverageLuminance;
-        *outMinLuminance = tmpMinLuminance;
-      });
-
-  return types;
-}
-
-void ComposerClient::setClientTargetSlotCount(Display display,
-                                              uint32_t clientTargetSlotCount) {
-  Error error =
-      mClient->setClientTargetSlotCount(display, clientTargetSlotCount);
-  ASSERT_EQ(Error::NONE, error) << "failed to set client target slot count";
-}
-
-void ComposerClient::setActiveConfig(Display display, Config config) {
-  Error error = mClient->setActiveConfig(display, config);
-  ASSERT_EQ(Error::NONE, error) << "failed to set active config";
-}
-
-void ComposerClient::setColorMode(Display display, ColorMode mode) {
-  Error error = mClient->setColorMode(display, mode);
-  ASSERT_EQ(Error::NONE, error) << "failed to set color mode";
-}
-
-void ComposerClient::setPowerMode(Display display,
-                                  IComposerClient::PowerMode mode) {
-  Error error = mClient->setPowerMode(display, mode);
-  ASSERT_EQ(Error::NONE, error) << "failed to set power mode";
-}
-
-void ComposerClient::setVsyncEnabled(Display display, bool enabled) {
-  IComposerClient::Vsync vsync = (enabled) ? IComposerClient::Vsync::ENABLE
-                                           : IComposerClient::Vsync::DISABLE;
-  Error error = mClient->setVsyncEnabled(display, vsync);
-  ASSERT_EQ(Error::NONE, error) << "failed to set vsync mode";
-
-  // give the hwbinder thread some time to handle any pending vsync callback
-  if (!enabled) {
-      usleep(5 * 1000);
-  }
-}
-
-void ComposerClient::execute(TestCommandReader* reader,
-                             CommandWriterBase* writer) {
-  bool queueChanged = false;
-  uint32_t commandLength = 0;
-  hidl_vec<hidl_handle> commandHandles;
-  ASSERT_TRUE(
-      writer->writeQueue(&queueChanged, &commandLength, &commandHandles));
-
-  if (queueChanged) {
-    auto ret = mClient->setInputCommandQueue(*writer->getMQDescriptor());
-    ASSERT_EQ(Error::NONE, static_cast<Error>(ret));
-    return;
-  }
-
-  mClient->executeCommands(
-      commandLength, commandHandles,
-      [&](const auto& tmpError, const auto& tmpOutQueueChanged,
-          const auto& tmpOutLength, const auto& tmpOutHandles) {
-        ASSERT_EQ(Error::NONE, tmpError);
-
-        if (tmpOutQueueChanged) {
-          mClient->getOutputCommandQueue(
-              [&](const auto& tmpError, const auto& tmpDescriptor) {
-                ASSERT_EQ(Error::NONE, tmpError);
-                reader->setMQDescriptor(tmpDescriptor);
-              });
-        }
-
-        ASSERT_TRUE(reader->readQueue(tmpOutLength, tmpOutHandles));
-        reader->parse();
-      });
-}
-
-}  // namespace tests
-}  // namespace V2_1
-}  // namespace composer
-}  // namespace graphics
-}  // namespace hardware
-}  // namespace android
diff --git a/graphics/composer/2.1/vts/functional/VtsHalGraphicsComposerTestUtils.h b/graphics/composer/2.1/vts/functional/VtsHalGraphicsComposerTestUtils.h
deleted file mode 100644
index 00d9d8c..0000000
--- a/graphics/composer/2.1/vts/functional/VtsHalGraphicsComposerTestUtils.h
+++ /dev/null
@@ -1,134 +0,0 @@
-/*
- * Copyright (C) 2017 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.
- */
-
-#ifndef VTS_HAL_GRAPHICS_COMPOSER_UTILS
-#define VTS_HAL_GRAPHICS_COMPOSER_UTILS
-
-#include <memory>
-#include <string>
-#include <unordered_map>
-#include <unordered_set>
-#include <vector>
-
-#include <android/hardware/graphics/composer/2.1/IComposer.h>
-#include <composer-command-buffer/2.1/ComposerCommandBuffer.h>
-#include <utils/StrongPointer.h>
-
-#include "TestCommandReader.h"
-
-namespace android {
-namespace hardware {
-namespace graphics {
-namespace composer {
-namespace V2_1 {
-namespace tests {
-
-using android::hardware::graphics::common::V1_0::ColorMode;
-using android::hardware::graphics::common::V1_0::Dataspace;
-using android::hardware::graphics::common::V1_0::Hdr;
-using android::hardware::graphics::common::V1_0::PixelFormat;
-
-class ComposerClient;
-
-// A wrapper to IComposer.
-class Composer {
- public:
-  Composer();
-  explicit Composer(const std::string& name);
-
-  sp<IComposer> getRaw() const;
-
-  // Returns true when the composer supports the specified capability.
-  bool hasCapability(IComposer::Capability capability) const;
-
-  std::vector<IComposer::Capability> getCapabilities();
-  std::string dumpDebugInfo();
-  std::unique_ptr<ComposerClient> createClient();
-
- protected:
-  sp<IComposer> mComposer;
-
- private:
-  void init();
-
-  std::unordered_set<IComposer::Capability> mCapabilities;
-};
-
-// A wrapper to IComposerClient.
-class ComposerClient {
- public:
-  ComposerClient(const sp<IComposerClient>& client);
-  ~ComposerClient();
-
-  sp<IComposerClient> getRaw() const;
-
-  void registerCallback(const sp<IComposerCallback>& callback);
-  uint32_t getMaxVirtualDisplayCount();
-
-  Display createVirtualDisplay(uint32_t width, uint32_t height,
-                               PixelFormat formatHint,
-                               uint32_t outputBufferSlotCount,
-                               PixelFormat* outFormat);
-  void destroyVirtualDisplay(Display display);
-
-  Layer createLayer(Display display, uint32_t bufferSlotCount);
-  void destroyLayer(Display display, Layer layer);
-
-  Config getActiveConfig(Display display);
-  bool getClientTargetSupport(Display display, uint32_t width, uint32_t height,
-                              PixelFormat format, Dataspace dataspace);
-  std::vector<ColorMode> getColorModes(Display display);
-  int32_t getDisplayAttribute(Display display, Config config,
-                              IComposerClient::Attribute attribute);
-  std::vector<Config> getDisplayConfigs(Display display);
-  std::string getDisplayName(Display display);
-  IComposerClient::DisplayType getDisplayType(Display display);
-  bool getDozeSupport(Display display);
-  std::vector<Hdr> getHdrCapabilities(Display display, float* outMaxLuminance,
-                                      float* outMaxAverageLuminance,
-                                      float* outMinLuminance);
-
-  void setClientTargetSlotCount(Display display,
-                                uint32_t clientTargetSlotCount);
-  void setActiveConfig(Display display, Config config);
-  void setColorMode(Display display, ColorMode mode);
-  void setPowerMode(Display display, IComposerClient::PowerMode mode);
-  void setVsyncEnabled(Display display, bool enabled);
-
-  void execute(TestCommandReader* reader, CommandWriterBase* writer);
-
- private:
-  sp<IComposerClient> mClient;
-
-  // Keep track of all virtual displays and layers.  When a test fails with
-  // ASSERT_*, the destructor will clean up the resources for the test.
-  struct DisplayResource {
-    DisplayResource(bool isVirtual_) : isVirtual(isVirtual_) {}
-
-    bool isVirtual;
-    std::unordered_set<Layer> layers;
-  };
-  std::unordered_map<Display, DisplayResource> mDisplayResources;
-};
-
-}  // namespace tests
-}  // namespace V2_1
-}  // namespace composer
-}  // namespace graphics
-}  // namespace hardware
-}  // namespace android
-
-#endif  // VTS_HAL_GRAPHICS_COMPOSER_UTILS
diff --git a/graphics/composer/2.1/vts/functional/VtsHalGraphicsComposerV2_1TargetTest.cpp b/graphics/composer/2.1/vts/functional/VtsHalGraphicsComposerV2_1TargetTest.cpp
index 376ee37..8b8b530 100644
--- a/graphics/composer/2.1/vts/functional/VtsHalGraphicsComposerV2_1TargetTest.cpp
+++ b/graphics/composer/2.1/vts/functional/VtsHalGraphicsComposerV2_1TargetTest.cpp
@@ -17,10 +17,10 @@
 #define LOG_TAG "graphics_composer_hidl_hal_test"
 
 #include <android-base/logging.h>
+#include <composer-vts/2.1/ComposerVts.h>
+#include <composer-vts/2.1/GraphicsComposerCallback.h>
+#include <composer-vts/2.1/TestCommandReader.h>
 #include <mapper-vts/2.0/MapperVts.h>
-#include "GraphicsComposerCallback.h"
-#include "TestCommandReader.h"
-#include "VtsHalGraphicsComposerTestUtils.h"
 
 #include <VtsHalHidlTargetTestBase.h>
 #include <VtsHalHidlTargetTestEnvBase.h>
@@ -38,7 +38,7 @@
 namespace graphics {
 namespace composer {
 namespace V2_1 {
-namespace tests {
+namespace vts {
 namespace {
 
 using android::hardware::graphics::common::V1_0::BufferUsage;
@@ -69,53 +69,53 @@
 };
 
 class GraphicsComposerHidlTest : public ::testing::VtsHalHidlTargetTestBase {
- protected:
-  void SetUp() override {
-      ASSERT_NO_FATAL_FAILURE(
-          mComposer = std::make_unique<Composer>(
-              GraphicsComposerHidlEnvironment::Instance()->getServiceName<IComposer>()));
-      ASSERT_NO_FATAL_FAILURE(mComposerClient = mComposer->createClient());
+   protected:
+    void SetUp() override {
+        ASSERT_NO_FATAL_FAILURE(
+            mComposer = std::make_unique<Composer>(
+                GraphicsComposerHidlEnvironment::Instance()->getServiceName<IComposer>()));
+        ASSERT_NO_FATAL_FAILURE(mComposerClient = mComposer->createClient());
 
-      mComposerCallback = new GraphicsComposerCallback;
-      mComposerClient->registerCallback(mComposerCallback);
+        mComposerCallback = new GraphicsComposerCallback;
+        mComposerClient->registerCallback(mComposerCallback);
 
-      // assume the first display is primary and is never removed
-      mPrimaryDisplay = waitForFirstDisplay();
+        // assume the first display is primary and is never removed
+        mPrimaryDisplay = waitForFirstDisplay();
 
-      // explicitly disable vsync
-      mComposerClient->setVsyncEnabled(mPrimaryDisplay, false);
-      mComposerCallback->setVsyncAllowed(false);
-  }
-
-  void TearDown() override {
-    if (mComposerCallback != nullptr) {
-      EXPECT_EQ(0, mComposerCallback->getInvalidHotplugCount());
-      EXPECT_EQ(0, mComposerCallback->getInvalidRefreshCount());
-      EXPECT_EQ(0, mComposerCallback->getInvalidVsyncCount());
+        // explicitly disable vsync
+        mComposerClient->setVsyncEnabled(mPrimaryDisplay, false);
+        mComposerCallback->setVsyncAllowed(false);
     }
-  }
 
-  // use the slot count usually set by SF
-  static constexpr uint32_t kBufferSlotCount = 64;
-
-  std::unique_ptr<Composer> mComposer;
-  std::unique_ptr<ComposerClient> mComposerClient;
-  sp<GraphicsComposerCallback> mComposerCallback;
-  // the first display and is assumed never to be removed
-  Display mPrimaryDisplay;
-
- private:
-  Display waitForFirstDisplay() {
-    while (true) {
-      std::vector<Display> displays = mComposerCallback->getDisplays();
-      if (displays.empty()) {
-        usleep(5 * 1000);
-        continue;
-      }
-
-      return displays[0];
+    void TearDown() override {
+        if (mComposerCallback != nullptr) {
+            EXPECT_EQ(0, mComposerCallback->getInvalidHotplugCount());
+            EXPECT_EQ(0, mComposerCallback->getInvalidRefreshCount());
+            EXPECT_EQ(0, mComposerCallback->getInvalidVsyncCount());
+        }
     }
-  }
+
+    // use the slot count usually set by SF
+    static constexpr uint32_t kBufferSlotCount = 64;
+
+    std::unique_ptr<Composer> mComposer;
+    std::unique_ptr<ComposerClient> mComposerClient;
+    sp<GraphicsComposerCallback> mComposerCallback;
+    // the first display and is assumed never to be removed
+    Display mPrimaryDisplay;
+
+   private:
+    Display waitForFirstDisplay() {
+        while (true) {
+            std::vector<Display> displays = mComposerCallback->getDisplays();
+            if (displays.empty()) {
+                usleep(5 * 1000);
+                continue;
+            }
+
+            return displays[0];
+        }
+    }
 };
 
 /**
@@ -124,16 +124,17 @@
  * Test that IComposer::getCapabilities returns no invalid capabilities.
  */
 TEST_F(GraphicsComposerHidlTest, GetCapabilities) {
-  auto capabilities = mComposer->getCapabilities();
-  ASSERT_EQ(capabilities.end(),
-            std::find(capabilities.begin(), capabilities.end(),
-                      IComposer::Capability::INVALID));
+    auto capabilities = mComposer->getCapabilities();
+    ASSERT_EQ(capabilities.end(),
+              std::find(capabilities.begin(), capabilities.end(), IComposer::Capability::INVALID));
 }
 
 /**
  * Test IComposer::dumpDebugInfo.
  */
-TEST_F(GraphicsComposerHidlTest, DumpDebugInfo) { mComposer->dumpDebugInfo(); }
+TEST_F(GraphicsComposerHidlTest, DumpDebugInfo) {
+    mComposer->dumpDebugInfo();
+}
 
 /**
  * Test IComposer::createClient.
@@ -141,9 +142,8 @@
  * Test that IComposerClient is a singleton.
  */
 TEST_F(GraphicsComposerHidlTest, CreateClientSingleton) {
-  mComposer->getRaw()->createClient([&](const auto& tmpError, const auto&) {
-    EXPECT_EQ(Error::NO_RESOURCES, tmpError);
-  });
+    mComposer->getRaw()->createClient(
+        [&](const auto& tmpError, const auto&) { EXPECT_EQ(Error::NO_RESOURCES, tmpError); });
 }
 
 /**
@@ -153,22 +153,22 @@
  * Test that virtual displays can be created and has the correct display type.
  */
 TEST_F(GraphicsComposerHidlTest, CreateVirtualDisplay) {
-  if (mComposerClient->getMaxVirtualDisplayCount() == 0) {
-    GTEST_SUCCEED() << "no virtual display support";
-    return;
-  }
+    if (mComposerClient->getMaxVirtualDisplayCount() == 0) {
+        GTEST_SUCCEED() << "no virtual display support";
+        return;
+    }
 
-  Display display;
-  PixelFormat format;
-  ASSERT_NO_FATAL_FAILURE(display = mComposerClient->createVirtualDisplay(
-                              64, 64, PixelFormat::IMPLEMENTATION_DEFINED,
-                              kBufferSlotCount, &format));
+    Display display;
+    PixelFormat format;
+    ASSERT_NO_FATAL_FAILURE(
+        display = mComposerClient->createVirtualDisplay(64, 64, PixelFormat::IMPLEMENTATION_DEFINED,
+                                                        kBufferSlotCount, &format));
 
-  // test display type
-  IComposerClient::DisplayType type = mComposerClient->getDisplayType(display);
-  EXPECT_EQ(IComposerClient::DisplayType::VIRTUAL, type);
+    // test display type
+    IComposerClient::DisplayType type = mComposerClient->getDisplayType(display);
+    EXPECT_EQ(IComposerClient::DisplayType::VIRTUAL, type);
 
-  mComposerClient->destroyVirtualDisplay(display);
+    mComposerClient->destroyVirtualDisplay(display);
 }
 
 /**
@@ -177,18 +177,18 @@
  * Test that layers can be created and destroyed.
  */
 TEST_F(GraphicsComposerHidlTest, CreateLayer) {
-  Layer layer;
-  ASSERT_NO_FATAL_FAILURE(
-      layer = mComposerClient->createLayer(mPrimaryDisplay, kBufferSlotCount));
+    Layer layer;
+    ASSERT_NO_FATAL_FAILURE(layer =
+                                mComposerClient->createLayer(mPrimaryDisplay, kBufferSlotCount));
 
-  mComposerClient->destroyLayer(mPrimaryDisplay, layer);
+    mComposerClient->destroyLayer(mPrimaryDisplay, layer);
 }
 
 /**
  * Test IComposerClient::getDisplayName.
  */
 TEST_F(GraphicsComposerHidlTest, GetDisplayName) {
-  mComposerClient->getDisplayName(mPrimaryDisplay);
+    mComposerClient->getDisplayName(mPrimaryDisplay);
 }
 
 /**
@@ -198,8 +198,8 @@
  * for the primary display.
  */
 TEST_F(GraphicsComposerHidlTest, GetDisplayType) {
-  ASSERT_EQ(IComposerClient::DisplayType::PHYSICAL,
-            mComposerClient->getDisplayType(mPrimaryDisplay));
+    ASSERT_EQ(IComposerClient::DisplayType::PHYSICAL,
+              mComposerClient->getDisplayType(mPrimaryDisplay));
 }
 
 /**
@@ -209,22 +209,20 @@
  * required client targets.
  */
 TEST_F(GraphicsComposerHidlTest, GetClientTargetSupport) {
-  std::vector<Config> configs =
-      mComposerClient->getDisplayConfigs(mPrimaryDisplay);
-  for (auto config : configs) {
-    int32_t width = mComposerClient->getDisplayAttribute(
-        mPrimaryDisplay, config, IComposerClient::Attribute::WIDTH);
-    int32_t height = mComposerClient->getDisplayAttribute(
-        mPrimaryDisplay, config, IComposerClient::Attribute::HEIGHT);
-    ASSERT_LT(0, width);
-    ASSERT_LT(0, height);
+    std::vector<Config> configs = mComposerClient->getDisplayConfigs(mPrimaryDisplay);
+    for (auto config : configs) {
+        int32_t width = mComposerClient->getDisplayAttribute(mPrimaryDisplay, config,
+                                                             IComposerClient::Attribute::WIDTH);
+        int32_t height = mComposerClient->getDisplayAttribute(mPrimaryDisplay, config,
+                                                              IComposerClient::Attribute::HEIGHT);
+        ASSERT_LT(0, width);
+        ASSERT_LT(0, height);
 
-    mComposerClient->setActiveConfig(mPrimaryDisplay, config);
+        mComposerClient->setActiveConfig(mPrimaryDisplay, config);
 
-    ASSERT_TRUE(mComposerClient->getClientTargetSupport(
-        mPrimaryDisplay, width, height, PixelFormat::RGBA_8888,
-        Dataspace::UNKNOWN));
-  }
+        ASSERT_TRUE(mComposerClient->getClientTargetSupport(
+            mPrimaryDisplay, width, height, PixelFormat::RGBA_8888, Dataspace::UNKNOWN));
+    }
 }
 
 /**
@@ -234,47 +232,44 @@
  * formats, and succeeds or fails correctly for optional attributes.
  */
 TEST_F(GraphicsComposerHidlTest, GetDisplayAttribute) {
-  std::vector<Config> configs =
-      mComposerClient->getDisplayConfigs(mPrimaryDisplay);
-  for (auto config : configs) {
-    const std::array<IComposerClient::Attribute, 3> requiredAttributes = {{
-        IComposerClient::Attribute::WIDTH, IComposerClient::Attribute::HEIGHT,
-        IComposerClient::Attribute::VSYNC_PERIOD,
-    }};
-    for (auto attribute : requiredAttributes) {
-      mComposerClient->getDisplayAttribute(mPrimaryDisplay, config, attribute);
-    }
+    std::vector<Config> configs = mComposerClient->getDisplayConfigs(mPrimaryDisplay);
+    for (auto config : configs) {
+        const std::array<IComposerClient::Attribute, 3> requiredAttributes = {{
+            IComposerClient::Attribute::WIDTH, IComposerClient::Attribute::HEIGHT,
+            IComposerClient::Attribute::VSYNC_PERIOD,
+        }};
+        for (auto attribute : requiredAttributes) {
+            mComposerClient->getDisplayAttribute(mPrimaryDisplay, config, attribute);
+        }
 
-    const std::array<IComposerClient::Attribute, 2> optionalAttributes = {{
-        IComposerClient::Attribute::DPI_X, IComposerClient::Attribute::DPI_Y,
-    }};
-    for (auto attribute : optionalAttributes) {
-      mComposerClient->getRaw()->getDisplayAttribute(
-          mPrimaryDisplay, config, attribute,
-          [&](const auto& tmpError, const auto&) {
-            EXPECT_TRUE(tmpError == Error::NONE ||
-                        tmpError == Error::UNSUPPORTED);
-          });
+        const std::array<IComposerClient::Attribute, 2> optionalAttributes = {{
+            IComposerClient::Attribute::DPI_X, IComposerClient::Attribute::DPI_Y,
+        }};
+        for (auto attribute : optionalAttributes) {
+            mComposerClient->getRaw()->getDisplayAttribute(
+                mPrimaryDisplay, config, attribute, [&](const auto& tmpError, const auto&) {
+                    EXPECT_TRUE(tmpError == Error::NONE || tmpError == Error::UNSUPPORTED);
+                });
+        }
     }
-  }
 }
 
 /**
  * Test IComposerClient::getHdrCapabilities.
  */
 TEST_F(GraphicsComposerHidlTest, GetHdrCapabilities) {
-  float maxLuminance;
-  float maxAverageLuminance;
-  float minLuminance;
-  mComposerClient->getHdrCapabilities(mPrimaryDisplay, &maxLuminance,
-                                      &maxAverageLuminance, &minLuminance);
+    float maxLuminance;
+    float maxAverageLuminance;
+    float minLuminance;
+    mComposerClient->getHdrCapabilities(mPrimaryDisplay, &maxLuminance, &maxAverageLuminance,
+                                        &minLuminance);
 }
 
 /**
  * Test IComposerClient::setClientTargetSlotCount.
  */
 TEST_F(GraphicsComposerHidlTest, SetClientTargetSlotCount) {
-  mComposerClient->setClientTargetSlotCount(mPrimaryDisplay, kBufferSlotCount);
+    mComposerClient->setClientTargetSlotCount(mPrimaryDisplay, kBufferSlotCount);
 }
 
 /**
@@ -284,12 +279,11 @@
  * configs.
  */
 TEST_F(GraphicsComposerHidlTest, SetActiveConfig) {
-  std::vector<Config> configs =
-      mComposerClient->getDisplayConfigs(mPrimaryDisplay);
-  for (auto config : configs) {
-    mComposerClient->setActiveConfig(mPrimaryDisplay, config);
-    ASSERT_EQ(config, mComposerClient->getActiveConfig(mPrimaryDisplay));
-  }
+    std::vector<Config> configs = mComposerClient->getDisplayConfigs(mPrimaryDisplay);
+    for (auto config : configs) {
+        mComposerClient->setActiveConfig(mPrimaryDisplay, config);
+        ASSERT_EQ(config, mComposerClient->getActiveConfig(mPrimaryDisplay));
+    }
 }
 
 /**
@@ -298,11 +292,10 @@
  * Test that IComposerClient::setColorMode succeeds for all color modes.
  */
 TEST_F(GraphicsComposerHidlTest, SetColorMode) {
-  std::vector<ColorMode> modes =
-      mComposerClient->getColorModes(mPrimaryDisplay);
-  for (auto mode : modes) {
-    mComposerClient->setColorMode(mPrimaryDisplay, mode);
-  }
+    std::vector<ColorMode> modes = mComposerClient->getColorModes(mPrimaryDisplay);
+    for (auto mode : modes) {
+        mComposerClient->setColorMode(mPrimaryDisplay, mode);
+    }
 }
 
 /**
@@ -311,20 +304,20 @@
  * Test that IComposerClient::setPowerMode succeeds for all power modes.
  */
 TEST_F(GraphicsComposerHidlTest, SetPowerMode) {
-  std::vector<IComposerClient::PowerMode> modes;
-  modes.push_back(IComposerClient::PowerMode::OFF);
+    std::vector<IComposerClient::PowerMode> modes;
+    modes.push_back(IComposerClient::PowerMode::OFF);
 
-  if (mComposerClient->getDozeSupport(mPrimaryDisplay)) {
-    modes.push_back(IComposerClient::PowerMode::DOZE);
-    modes.push_back(IComposerClient::PowerMode::DOZE_SUSPEND);
-  }
+    if (mComposerClient->getDozeSupport(mPrimaryDisplay)) {
+        modes.push_back(IComposerClient::PowerMode::DOZE);
+        modes.push_back(IComposerClient::PowerMode::DOZE_SUSPEND);
+    }
 
-  // push ON last
-  modes.push_back(IComposerClient::PowerMode::ON);
+    // push ON last
+    modes.push_back(IComposerClient::PowerMode::ON);
 
-  for (auto mode : modes) {
-    mComposerClient->setPowerMode(mPrimaryDisplay, mode);
-  }
+    for (auto mode : modes) {
+        mComposerClient->setPowerMode(mPrimaryDisplay, mode);
+    }
 }
 
 /**
@@ -334,369 +327,365 @@
  * spurious vsync events.
  */
 TEST_F(GraphicsComposerHidlTest, SetVsyncEnabled) {
-  mComposerCallback->setVsyncAllowed(true);
+    mComposerCallback->setVsyncAllowed(true);
 
-  mComposerClient->setVsyncEnabled(mPrimaryDisplay, true);
-  usleep(60 * 1000);
-  mComposerClient->setVsyncEnabled(mPrimaryDisplay, false);
+    mComposerClient->setVsyncEnabled(mPrimaryDisplay, true);
+    usleep(60 * 1000);
+    mComposerClient->setVsyncEnabled(mPrimaryDisplay, false);
 
-  mComposerCallback->setVsyncAllowed(false);
+    mComposerCallback->setVsyncAllowed(false);
 }
 
 // Tests for IComposerClient::Command.
 class GraphicsComposerHidlCommandTest : public GraphicsComposerHidlTest {
- protected:
-  void SetUp() override {
-    ASSERT_NO_FATAL_FAILURE(GraphicsComposerHidlTest::SetUp());
+   protected:
+    void SetUp() override {
+        ASSERT_NO_FATAL_FAILURE(GraphicsComposerHidlTest::SetUp());
 
-    ASSERT_NO_FATAL_FAILURE(mGralloc = std::make_unique<Gralloc>());
+        ASSERT_NO_FATAL_FAILURE(mGralloc = std::make_unique<Gralloc>());
 
-    mWriter = std::make_unique<CommandWriterBase>(1024);
-    mReader = std::make_unique<TestCommandReader>();
-  }
+        mWriter = std::make_unique<CommandWriterBase>(1024);
+        mReader = std::make_unique<TestCommandReader>();
+    }
 
-  void TearDown() override {
-    ASSERT_NO_FATAL_FAILURE(GraphicsComposerHidlTest::TearDown());
-  }
+    void TearDown() override { ASSERT_NO_FATAL_FAILURE(GraphicsComposerHidlTest::TearDown()); }
 
-  const native_handle_t* allocate() {
-      IMapper::BufferDescriptorInfo info{};
-      info.width = 64;
-      info.height = 64;
-      info.layerCount = 1;
-      info.format = PixelFormat::RGBA_8888;
-      info.usage = static_cast<uint64_t>(BufferUsage::CPU_WRITE_OFTEN |
-                                         BufferUsage::CPU_READ_OFTEN);
+    const native_handle_t* allocate() {
+        IMapper::BufferDescriptorInfo info{};
+        info.width = 64;
+        info.height = 64;
+        info.layerCount = 1;
+        info.format = PixelFormat::RGBA_8888;
+        info.usage =
+            static_cast<uint64_t>(BufferUsage::CPU_WRITE_OFTEN | BufferUsage::CPU_READ_OFTEN);
 
-      return mGralloc->allocate(info);
-  }
+        return mGralloc->allocate(info);
+    }
 
-  void execute() { mComposerClient->execute(mReader.get(), mWriter.get()); }
+    void execute() { mComposerClient->execute(mReader.get(), mWriter.get()); }
 
-  std::unique_ptr<CommandWriterBase> mWriter;
-  std::unique_ptr<TestCommandReader> mReader;
+    std::unique_ptr<CommandWriterBase> mWriter;
+    std::unique_ptr<TestCommandReader> mReader;
 
- private:
-  std::unique_ptr<Gralloc> mGralloc;
+   private:
+    std::unique_ptr<Gralloc> mGralloc;
 };
 
 /**
  * Test IComposerClient::Command::SET_COLOR_TRANSFORM.
  */
 TEST_F(GraphicsComposerHidlCommandTest, SET_COLOR_TRANSFORM) {
-  const std::array<float, 16> identity = {{
-      1.0f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f, 0.0f,
-      0.0f, 0.0f, 0.0f, 1.0f,
-  }};
+    const std::array<float, 16> identity = {{
+        1.0f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f, 0.0f, 0.0f, 0.0f, 0.0f,
+        1.0f,
+    }};
 
-  mWriter->selectDisplay(mPrimaryDisplay);
-  mWriter->setColorTransform(identity.data(), ColorTransform::IDENTITY);
+    mWriter->selectDisplay(mPrimaryDisplay);
+    mWriter->setColorTransform(identity.data(), ColorTransform::IDENTITY);
 
-  execute();
+    execute();
 }
 
 /**
  * Test IComposerClient::Command::SET_CLIENT_TARGET.
  */
 TEST_F(GraphicsComposerHidlCommandTest, SET_CLIENT_TARGET) {
-  mComposerClient->setClientTargetSlotCount(mPrimaryDisplay, kBufferSlotCount);
+    mComposerClient->setClientTargetSlotCount(mPrimaryDisplay, kBufferSlotCount);
 
-  mWriter->selectDisplay(mPrimaryDisplay);
-  mWriter->setClientTarget(0, nullptr, -1, Dataspace::UNKNOWN,
-                           std::vector<IComposerClient::Rect>());
+    mWriter->selectDisplay(mPrimaryDisplay);
+    mWriter->setClientTarget(0, nullptr, -1, Dataspace::UNKNOWN,
+                             std::vector<IComposerClient::Rect>());
 
-  execute();
+    execute();
 }
 
 /**
  * Test IComposerClient::Command::SET_OUTPUT_BUFFER.
  */
 TEST_F(GraphicsComposerHidlCommandTest, SET_OUTPUT_BUFFER) {
-  if (mComposerClient->getMaxVirtualDisplayCount() == 0) {
-    GTEST_SUCCEED() << "no virtual display support";
-    return;
-  }
+    if (mComposerClient->getMaxVirtualDisplayCount() == 0) {
+        GTEST_SUCCEED() << "no virtual display support";
+        return;
+    }
 
-  Display display;
-  PixelFormat format;
-  ASSERT_NO_FATAL_FAILURE(display = mComposerClient->createVirtualDisplay(
-                              64, 64, PixelFormat::IMPLEMENTATION_DEFINED,
-                              kBufferSlotCount, &format));
+    Display display;
+    PixelFormat format;
+    ASSERT_NO_FATAL_FAILURE(
+        display = mComposerClient->createVirtualDisplay(64, 64, PixelFormat::IMPLEMENTATION_DEFINED,
+                                                        kBufferSlotCount, &format));
 
-  const native_handle_t* handle;
-  ASSERT_NO_FATAL_FAILURE(handle = allocate());
+    const native_handle_t* handle;
+    ASSERT_NO_FATAL_FAILURE(handle = allocate());
 
-  mWriter->selectDisplay(display);
-  mWriter->setOutputBuffer(0, handle, -1);
-  execute();
+    mWriter->selectDisplay(display);
+    mWriter->setOutputBuffer(0, handle, -1);
+    execute();
 }
 
 /**
  * Test IComposerClient::Command::VALIDATE_DISPLAY.
  */
 TEST_F(GraphicsComposerHidlCommandTest, VALIDATE_DISPLAY) {
-  mWriter->selectDisplay(mPrimaryDisplay);
-  mWriter->validateDisplay();
-  execute();
+    mWriter->selectDisplay(mPrimaryDisplay);
+    mWriter->validateDisplay();
+    execute();
 }
 
 /**
  * Test IComposerClient::Command::ACCEPT_DISPLAY_CHANGES.
  */
 TEST_F(GraphicsComposerHidlCommandTest, ACCEPT_DISPLAY_CHANGES) {
-  mWriter->selectDisplay(mPrimaryDisplay);
-  mWriter->validateDisplay();
-  mWriter->acceptDisplayChanges();
-  execute();
+    mWriter->selectDisplay(mPrimaryDisplay);
+    mWriter->validateDisplay();
+    mWriter->acceptDisplayChanges();
+    execute();
 }
 
 /**
  * Test IComposerClient::Command::PRESENT_DISPLAY.
  */
 TEST_F(GraphicsComposerHidlCommandTest, PRESENT_DISPLAY) {
-  mWriter->selectDisplay(mPrimaryDisplay);
-  mWriter->validateDisplay();
-  mWriter->presentDisplay();
-  execute();
+    mWriter->selectDisplay(mPrimaryDisplay);
+    mWriter->validateDisplay();
+    mWriter->presentDisplay();
+    execute();
 }
 
 /**
  * Test IComposerClient::Command::SET_LAYER_CURSOR_POSITION.
  */
 TEST_F(GraphicsComposerHidlCommandTest, SET_LAYER_CURSOR_POSITION) {
-  Layer layer;
-  ASSERT_NO_FATAL_FAILURE(
-      layer = mComposerClient->createLayer(mPrimaryDisplay, kBufferSlotCount));
+    Layer layer;
+    ASSERT_NO_FATAL_FAILURE(layer =
+                                mComposerClient->createLayer(mPrimaryDisplay, kBufferSlotCount));
 
-  mWriter->selectDisplay(mPrimaryDisplay);
-  mWriter->selectLayer(layer);
-  mWriter->setLayerCursorPosition(1, 1);
-  mWriter->setLayerCursorPosition(0, 0);
-  execute();
+    mWriter->selectDisplay(mPrimaryDisplay);
+    mWriter->selectLayer(layer);
+    mWriter->setLayerCursorPosition(1, 1);
+    mWriter->setLayerCursorPosition(0, 0);
+    execute();
 }
 
 /**
  * Test IComposerClient::Command::SET_LAYER_BUFFER.
  */
 TEST_F(GraphicsComposerHidlCommandTest, SET_LAYER_BUFFER) {
-  auto handle = allocate();
-  ASSERT_NE(nullptr, handle);
+    auto handle = allocate();
+    ASSERT_NE(nullptr, handle);
 
-  Layer layer;
-  ASSERT_NO_FATAL_FAILURE(
-      layer = mComposerClient->createLayer(mPrimaryDisplay, kBufferSlotCount));
+    Layer layer;
+    ASSERT_NO_FATAL_FAILURE(layer =
+                                mComposerClient->createLayer(mPrimaryDisplay, kBufferSlotCount));
 
-  mWriter->selectDisplay(mPrimaryDisplay);
-  mWriter->selectLayer(layer);
-  mWriter->setLayerBuffer(0, handle, -1);
-  execute();
+    mWriter->selectDisplay(mPrimaryDisplay);
+    mWriter->selectLayer(layer);
+    mWriter->setLayerBuffer(0, handle, -1);
+    execute();
 }
 
 /**
  * Test IComposerClient::Command::SET_LAYER_SURFACE_DAMAGE.
  */
 TEST_F(GraphicsComposerHidlCommandTest, SET_LAYER_SURFACE_DAMAGE) {
-  Layer layer;
-  ASSERT_NO_FATAL_FAILURE(
-      layer = mComposerClient->createLayer(mPrimaryDisplay, kBufferSlotCount));
+    Layer layer;
+    ASSERT_NO_FATAL_FAILURE(layer =
+                                mComposerClient->createLayer(mPrimaryDisplay, kBufferSlotCount));
 
-  IComposerClient::Rect empty{0, 0, 0, 0};
-  IComposerClient::Rect unit{0, 0, 1, 1};
+    IComposerClient::Rect empty{0, 0, 0, 0};
+    IComposerClient::Rect unit{0, 0, 1, 1};
 
-  mWriter->selectDisplay(mPrimaryDisplay);
-  mWriter->selectLayer(layer);
-  mWriter->setLayerSurfaceDamage(std::vector<IComposerClient::Rect>(1, empty));
-  mWriter->setLayerSurfaceDamage(std::vector<IComposerClient::Rect>(1, unit));
-  mWriter->setLayerSurfaceDamage(std::vector<IComposerClient::Rect>());
-  execute();
+    mWriter->selectDisplay(mPrimaryDisplay);
+    mWriter->selectLayer(layer);
+    mWriter->setLayerSurfaceDamage(std::vector<IComposerClient::Rect>(1, empty));
+    mWriter->setLayerSurfaceDamage(std::vector<IComposerClient::Rect>(1, unit));
+    mWriter->setLayerSurfaceDamage(std::vector<IComposerClient::Rect>());
+    execute();
 }
 
 /**
  * Test IComposerClient::Command::SET_LAYER_BLEND_MODE.
  */
 TEST_F(GraphicsComposerHidlCommandTest, SET_LAYER_BLEND_MODE) {
-  Layer layer;
-  ASSERT_NO_FATAL_FAILURE(
-      layer = mComposerClient->createLayer(mPrimaryDisplay, kBufferSlotCount));
+    Layer layer;
+    ASSERT_NO_FATAL_FAILURE(layer =
+                                mComposerClient->createLayer(mPrimaryDisplay, kBufferSlotCount));
 
-  mWriter->selectDisplay(mPrimaryDisplay);
-  mWriter->selectLayer(layer);
-  mWriter->setLayerBlendMode(IComposerClient::BlendMode::NONE);
-  mWriter->setLayerBlendMode(IComposerClient::BlendMode::PREMULTIPLIED);
-  mWriter->setLayerBlendMode(IComposerClient::BlendMode::COVERAGE);
-  execute();
+    mWriter->selectDisplay(mPrimaryDisplay);
+    mWriter->selectLayer(layer);
+    mWriter->setLayerBlendMode(IComposerClient::BlendMode::NONE);
+    mWriter->setLayerBlendMode(IComposerClient::BlendMode::PREMULTIPLIED);
+    mWriter->setLayerBlendMode(IComposerClient::BlendMode::COVERAGE);
+    execute();
 }
 
 /**
  * Test IComposerClient::Command::SET_LAYER_COLOR.
  */
 TEST_F(GraphicsComposerHidlCommandTest, SET_LAYER_COLOR) {
-  Layer layer;
-  ASSERT_NO_FATAL_FAILURE(
-      layer = mComposerClient->createLayer(mPrimaryDisplay, kBufferSlotCount));
+    Layer layer;
+    ASSERT_NO_FATAL_FAILURE(layer =
+                                mComposerClient->createLayer(mPrimaryDisplay, kBufferSlotCount));
 
-  mWriter->selectDisplay(mPrimaryDisplay);
-  mWriter->selectLayer(layer);
-  mWriter->setLayerColor(IComposerClient::Color{0xff, 0xff, 0xff, 0xff});
-  mWriter->setLayerColor(IComposerClient::Color{0, 0, 0, 0});
-  execute();
+    mWriter->selectDisplay(mPrimaryDisplay);
+    mWriter->selectLayer(layer);
+    mWriter->setLayerColor(IComposerClient::Color{0xff, 0xff, 0xff, 0xff});
+    mWriter->setLayerColor(IComposerClient::Color{0, 0, 0, 0});
+    execute();
 }
 
 /**
  * Test IComposerClient::Command::SET_LAYER_COMPOSITION_TYPE.
  */
 TEST_F(GraphicsComposerHidlCommandTest, SET_LAYER_COMPOSITION_TYPE) {
-  Layer layer;
-  ASSERT_NO_FATAL_FAILURE(
-      layer = mComposerClient->createLayer(mPrimaryDisplay, kBufferSlotCount));
+    Layer layer;
+    ASSERT_NO_FATAL_FAILURE(layer =
+                                mComposerClient->createLayer(mPrimaryDisplay, kBufferSlotCount));
 
-  mWriter->selectDisplay(mPrimaryDisplay);
-  mWriter->selectLayer(layer);
-  mWriter->setLayerCompositionType(IComposerClient::Composition::CLIENT);
-  mWriter->setLayerCompositionType(IComposerClient::Composition::DEVICE);
-  mWriter->setLayerCompositionType(IComposerClient::Composition::SOLID_COLOR);
-  mWriter->setLayerCompositionType(IComposerClient::Composition::CURSOR);
-  execute();
+    mWriter->selectDisplay(mPrimaryDisplay);
+    mWriter->selectLayer(layer);
+    mWriter->setLayerCompositionType(IComposerClient::Composition::CLIENT);
+    mWriter->setLayerCompositionType(IComposerClient::Composition::DEVICE);
+    mWriter->setLayerCompositionType(IComposerClient::Composition::SOLID_COLOR);
+    mWriter->setLayerCompositionType(IComposerClient::Composition::CURSOR);
+    execute();
 }
 
 /**
  * Test IComposerClient::Command::SET_LAYER_DATASPACE.
  */
 TEST_F(GraphicsComposerHidlCommandTest, SET_LAYER_DATASPACE) {
-  Layer layer;
-  ASSERT_NO_FATAL_FAILURE(
-      layer = mComposerClient->createLayer(mPrimaryDisplay, kBufferSlotCount));
+    Layer layer;
+    ASSERT_NO_FATAL_FAILURE(layer =
+                                mComposerClient->createLayer(mPrimaryDisplay, kBufferSlotCount));
 
-  mWriter->selectDisplay(mPrimaryDisplay);
-  mWriter->selectLayer(layer);
-  mWriter->setLayerDataspace(Dataspace::UNKNOWN);
-  execute();
+    mWriter->selectDisplay(mPrimaryDisplay);
+    mWriter->selectLayer(layer);
+    mWriter->setLayerDataspace(Dataspace::UNKNOWN);
+    execute();
 }
 
 /**
  * Test IComposerClient::Command::SET_LAYER_DISPLAY_FRAME.
  */
 TEST_F(GraphicsComposerHidlCommandTest, SET_LAYER_DISPLAY_FRAME) {
-  Layer layer;
-  ASSERT_NO_FATAL_FAILURE(
-      layer = mComposerClient->createLayer(mPrimaryDisplay, kBufferSlotCount));
+    Layer layer;
+    ASSERT_NO_FATAL_FAILURE(layer =
+                                mComposerClient->createLayer(mPrimaryDisplay, kBufferSlotCount));
 
-  mWriter->selectDisplay(mPrimaryDisplay);
-  mWriter->selectLayer(layer);
-  mWriter->setLayerDisplayFrame(IComposerClient::Rect{0, 0, 1, 1});
-  execute();
+    mWriter->selectDisplay(mPrimaryDisplay);
+    mWriter->selectLayer(layer);
+    mWriter->setLayerDisplayFrame(IComposerClient::Rect{0, 0, 1, 1});
+    execute();
 }
 
 /**
  * Test IComposerClient::Command::SET_LAYER_PLANE_ALPHA.
  */
 TEST_F(GraphicsComposerHidlCommandTest, SET_LAYER_PLANE_ALPHA) {
-  Layer layer;
-  ASSERT_NO_FATAL_FAILURE(
-      layer = mComposerClient->createLayer(mPrimaryDisplay, kBufferSlotCount));
+    Layer layer;
+    ASSERT_NO_FATAL_FAILURE(layer =
+                                mComposerClient->createLayer(mPrimaryDisplay, kBufferSlotCount));
 
-  mWriter->selectDisplay(mPrimaryDisplay);
-  mWriter->selectLayer(layer);
-  mWriter->setLayerPlaneAlpha(0.0f);
-  mWriter->setLayerPlaneAlpha(1.0f);
-  execute();
+    mWriter->selectDisplay(mPrimaryDisplay);
+    mWriter->selectLayer(layer);
+    mWriter->setLayerPlaneAlpha(0.0f);
+    mWriter->setLayerPlaneAlpha(1.0f);
+    execute();
 }
 
 /**
  * Test IComposerClient::Command::SET_LAYER_SIDEBAND_STREAM.
  */
 TEST_F(GraphicsComposerHidlCommandTest, SET_LAYER_SIDEBAND_STREAM) {
-  if (!mComposer->hasCapability(IComposer::Capability::SIDEBAND_STREAM)) {
-    GTEST_SUCCEED() << "no sideband stream support";
-    return;
-  }
+    if (!mComposer->hasCapability(IComposer::Capability::SIDEBAND_STREAM)) {
+        GTEST_SUCCEED() << "no sideband stream support";
+        return;
+    }
 
-  auto handle = allocate();
-  ASSERT_NE(nullptr, handle);
+    auto handle = allocate();
+    ASSERT_NE(nullptr, handle);
 
-  Layer layer;
-  ASSERT_NO_FATAL_FAILURE(
-      layer = mComposerClient->createLayer(mPrimaryDisplay, kBufferSlotCount));
+    Layer layer;
+    ASSERT_NO_FATAL_FAILURE(layer =
+                                mComposerClient->createLayer(mPrimaryDisplay, kBufferSlotCount));
 
-  mWriter->selectDisplay(mPrimaryDisplay);
-  mWriter->selectLayer(layer);
-  mWriter->setLayerSidebandStream(handle);
-  execute();
+    mWriter->selectDisplay(mPrimaryDisplay);
+    mWriter->selectLayer(layer);
+    mWriter->setLayerSidebandStream(handle);
+    execute();
 }
 
 /**
  * Test IComposerClient::Command::SET_LAYER_SOURCE_CROP.
  */
 TEST_F(GraphicsComposerHidlCommandTest, SET_LAYER_SOURCE_CROP) {
-  Layer layer;
-  ASSERT_NO_FATAL_FAILURE(
-      layer = mComposerClient->createLayer(mPrimaryDisplay, kBufferSlotCount));
+    Layer layer;
+    ASSERT_NO_FATAL_FAILURE(layer =
+                                mComposerClient->createLayer(mPrimaryDisplay, kBufferSlotCount));
 
-  mWriter->selectDisplay(mPrimaryDisplay);
-  mWriter->selectLayer(layer);
-  mWriter->setLayerSourceCrop(IComposerClient::FRect{0.0f, 0.0f, 1.0f, 1.0f});
-  execute();
+    mWriter->selectDisplay(mPrimaryDisplay);
+    mWriter->selectLayer(layer);
+    mWriter->setLayerSourceCrop(IComposerClient::FRect{0.0f, 0.0f, 1.0f, 1.0f});
+    execute();
 }
 
 /**
  * Test IComposerClient::Command::SET_LAYER_TRANSFORM.
  */
 TEST_F(GraphicsComposerHidlCommandTest, SET_LAYER_TRANSFORM) {
-  Layer layer;
-  ASSERT_NO_FATAL_FAILURE(
-      layer = mComposerClient->createLayer(mPrimaryDisplay, kBufferSlotCount));
+    Layer layer;
+    ASSERT_NO_FATAL_FAILURE(layer =
+                                mComposerClient->createLayer(mPrimaryDisplay, kBufferSlotCount));
 
-  mWriter->selectDisplay(mPrimaryDisplay);
-  mWriter->selectLayer(layer);
-  mWriter->setLayerTransform(static_cast<Transform>(0));
-  mWriter->setLayerTransform(Transform::FLIP_H);
-  mWriter->setLayerTransform(Transform::FLIP_V);
-  mWriter->setLayerTransform(Transform::ROT_90);
-  mWriter->setLayerTransform(Transform::ROT_180);
-  mWriter->setLayerTransform(Transform::ROT_270);
-  mWriter->setLayerTransform(
-      static_cast<Transform>(Transform::FLIP_H | Transform::ROT_90));
-  mWriter->setLayerTransform(
-      static_cast<Transform>(Transform::FLIP_V | Transform::ROT_90));
-  execute();
+    mWriter->selectDisplay(mPrimaryDisplay);
+    mWriter->selectLayer(layer);
+    mWriter->setLayerTransform(static_cast<Transform>(0));
+    mWriter->setLayerTransform(Transform::FLIP_H);
+    mWriter->setLayerTransform(Transform::FLIP_V);
+    mWriter->setLayerTransform(Transform::ROT_90);
+    mWriter->setLayerTransform(Transform::ROT_180);
+    mWriter->setLayerTransform(Transform::ROT_270);
+    mWriter->setLayerTransform(static_cast<Transform>(Transform::FLIP_H | Transform::ROT_90));
+    mWriter->setLayerTransform(static_cast<Transform>(Transform::FLIP_V | Transform::ROT_90));
+    execute();
 }
 
 /**
  * Test IComposerClient::Command::SET_LAYER_VISIBLE_REGION.
  */
 TEST_F(GraphicsComposerHidlCommandTest, SET_LAYER_VISIBLE_REGION) {
-  Layer layer;
-  ASSERT_NO_FATAL_FAILURE(
-      layer = mComposerClient->createLayer(mPrimaryDisplay, kBufferSlotCount));
+    Layer layer;
+    ASSERT_NO_FATAL_FAILURE(layer =
+                                mComposerClient->createLayer(mPrimaryDisplay, kBufferSlotCount));
 
-  IComposerClient::Rect empty{0, 0, 0, 0};
-  IComposerClient::Rect unit{0, 0, 1, 1};
+    IComposerClient::Rect empty{0, 0, 0, 0};
+    IComposerClient::Rect unit{0, 0, 1, 1};
 
-  mWriter->selectDisplay(mPrimaryDisplay);
-  mWriter->selectLayer(layer);
-  mWriter->setLayerVisibleRegion(std::vector<IComposerClient::Rect>(1, empty));
-  mWriter->setLayerVisibleRegion(std::vector<IComposerClient::Rect>(1, unit));
-  mWriter->setLayerVisibleRegion(std::vector<IComposerClient::Rect>());
-  execute();
+    mWriter->selectDisplay(mPrimaryDisplay);
+    mWriter->selectLayer(layer);
+    mWriter->setLayerVisibleRegion(std::vector<IComposerClient::Rect>(1, empty));
+    mWriter->setLayerVisibleRegion(std::vector<IComposerClient::Rect>(1, unit));
+    mWriter->setLayerVisibleRegion(std::vector<IComposerClient::Rect>());
+    execute();
 }
 
 /**
  * Test IComposerClient::Command::SET_LAYER_Z_ORDER.
  */
 TEST_F(GraphicsComposerHidlCommandTest, SET_LAYER_Z_ORDER) {
-  Layer layer;
-  ASSERT_NO_FATAL_FAILURE(
-      layer = mComposerClient->createLayer(mPrimaryDisplay, kBufferSlotCount));
+    Layer layer;
+    ASSERT_NO_FATAL_FAILURE(layer =
+                                mComposerClient->createLayer(mPrimaryDisplay, kBufferSlotCount));
 
-  mWriter->selectDisplay(mPrimaryDisplay);
-  mWriter->selectLayer(layer);
-  mWriter->setLayerZOrder(10);
-  mWriter->setLayerZOrder(0);
-  execute();
+    mWriter->selectDisplay(mPrimaryDisplay);
+    mWriter->selectLayer(layer);
+    mWriter->setLayerZOrder(10);
+    mWriter->setLayerZOrder(0);
+    execute();
 }
 
-}  // namespace anonymous
-}  // namespace tests
+}  // namespace
+}  // namespace vts
 }  // namespace V2_1
 }  // namespace composer
 }  // namespace graphics
@@ -704,7 +693,7 @@
 }  // namespace android
 
 int main(int argc, char** argv) {
-    using android::hardware::graphics::composer::V2_1::tests::GraphicsComposerHidlEnvironment;
+    using android::hardware::graphics::composer::V2_1::vts::GraphicsComposerHidlEnvironment;
     ::testing::AddGlobalTestEnvironment(GraphicsComposerHidlEnvironment::Instance());
     ::testing::InitGoogleTest(&argc, argv);
     GraphicsComposerHidlEnvironment::Instance()->init(&argc, argv);
diff --git a/graphics/composer/2.2/default/Android.bp b/graphics/composer/2.2/default/Android.bp
new file mode 100644
index 0000000..906479e
--- /dev/null
+++ b/graphics/composer/2.2/default/Android.bp
@@ -0,0 +1,31 @@
+cc_binary {
+    name: "android.hardware.graphics.composer@2.2-service",
+    defaults: ["hidl_defaults"],
+    vendor: true,
+    relative_install_path: "hw",
+    srcs: ["service.cpp"],
+    init_rc: ["android.hardware.graphics.composer@2.2-service.rc"],
+    header_libs: [
+        "android.hardware.graphics.composer@2.2-passthrough",
+    ],
+    shared_libs: [
+        "android.hardware.graphics.composer@2.1",
+        "android.hardware.graphics.composer@2.2",
+        "android.hardware.graphics.mapper@2.0",
+        "libbase",
+        "libbinder",
+        "libcutils",
+        "libfmq",
+        "libhardware",
+        "libhidlbase",
+        "libhidltransport",
+        "libhwc2on1adapter",
+        "libhwc2onfbadapter",
+        "liblog",
+        "libsync",
+        "libutils",
+    ],
+    cflags: [
+        "-DLOG_TAG=\"ComposerHal\""
+    ],
+}
diff --git a/graphics/composer/2.2/default/OWNERS b/graphics/composer/2.2/default/OWNERS
new file mode 100644
index 0000000..4714be2
--- /dev/null
+++ b/graphics/composer/2.2/default/OWNERS
@@ -0,0 +1,5 @@
+# Graphics team
+courtneygo@google.com
+jessehall@google.com
+olv@google.com
+stoza@google.com
diff --git a/graphics/composer/2.2/default/android.hardware.graphics.composer@2.2-service.rc b/graphics/composer/2.2/default/android.hardware.graphics.composer@2.2-service.rc
new file mode 100644
index 0000000..a41d902
--- /dev/null
+++ b/graphics/composer/2.2/default/android.hardware.graphics.composer@2.2-service.rc
@@ -0,0 +1,6 @@
+service vendor.hwcomposer-2-2 /vendor/bin/hw/android.hardware.graphics.composer@2.2-service
+    class hal animation
+    user system
+    group graphics drmrpc
+    capabilities SYS_NICE
+    onrestart restart surfaceflinger
diff --git a/graphics/composer/2.2/default/service.cpp b/graphics/composer/2.2/default/service.cpp
new file mode 100644
index 0000000..8c5ef18
--- /dev/null
+++ b/graphics/composer/2.2/default/service.cpp
@@ -0,0 +1,55 @@
+/*
+ * Copyright 2018 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 <sched.h>
+
+#include <android/hardware/graphics/composer/2.2/IComposer.h>
+#include <binder/ProcessState.h>
+#include <composer-passthrough/2.2/HwcLoader.h>
+#include <hidl/HidlTransportSupport.h>
+
+using android::hardware::graphics::composer::V2_2::IComposer;
+using android::hardware::graphics::composer::V2_2::passthrough::HwcLoader;
+
+int main() {
+    // the conventional HAL might start binder services
+    android::ProcessState::initWithDriver("/dev/vndbinder");
+    android::ProcessState::self()->setThreadPoolMaxThreadCount(4);
+    android::ProcessState::self()->startThreadPool();
+
+    // same as SF main thread
+    struct sched_param param = {0};
+    param.sched_priority = 2;
+    if (sched_setscheduler(0, SCHED_FIFO | SCHED_RESET_ON_FORK, &param) != 0) {
+        ALOGE("Couldn't set SCHED_FIFO: %d", errno);
+    }
+
+    android::hardware::configureRpcThreadpool(4, true /* will join */);
+
+    android::sp<IComposer> composer = HwcLoader::load();
+    if (composer == nullptr) {
+        return 1;
+    }
+    if (composer->registerAsService() != android::NO_ERROR) {
+        ALOGE("failed to register service");
+        return 1;
+    }
+
+    android::hardware::joinRpcThreadpool();
+
+    ALOGE("service is terminating");
+    return 1;
+}
diff --git a/graphics/composer/2.2/utils/hal/Android.bp b/graphics/composer/2.2/utils/hal/Android.bp
new file mode 100644
index 0000000..10dcae4
--- /dev/null
+++ b/graphics/composer/2.2/utils/hal/Android.bp
@@ -0,0 +1,35 @@
+//
+// Copyright (C) 2018 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.
+
+cc_library_headers {
+    name: "android.hardware.graphics.composer@2.2-hal",
+    defaults: ["hidl_defaults"],
+    vendor_available: true,
+    shared_libs: [
+        "android.hardware.graphics.composer@2.2",
+    ],
+    export_shared_lib_headers: [
+        "android.hardware.graphics.composer@2.2",
+    ],
+    header_libs: [
+        "android.hardware.graphics.composer@2.2-command-buffer",
+        "android.hardware.graphics.composer@2.1-hal",
+    ],
+    export_header_lib_headers: [
+        "android.hardware.graphics.composer@2.2-command-buffer",
+        "android.hardware.graphics.composer@2.1-hal",
+    ],
+    export_include_dirs: ["include"],
+}
diff --git a/graphics/composer/2.2/utils/hal/include/composer-hal/2.2/Composer.h b/graphics/composer/2.2/utils/hal/include/composer-hal/2.2/Composer.h
new file mode 100644
index 0000000..58bbaa5
--- /dev/null
+++ b/graphics/composer/2.2/utils/hal/include/composer-hal/2.2/Composer.h
@@ -0,0 +1,74 @@
+/*
+ * Copyright 2018 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
+
+#ifndef LOG_TAG
+#warning "Composer.h included without LOG_TAG"
+#endif
+
+#include <android/hardware/graphics/composer/2.2/IComposer.h>
+#include <composer-hal/2.1/Composer.h>
+#include <composer-hal/2.2/ComposerClient.h>
+
+namespace android {
+namespace hardware {
+namespace graphics {
+namespace composer {
+namespace V2_2 {
+namespace hal {
+
+namespace detail {
+
+// ComposerImpl implements V2_*::IComposer on top of V2_*::ComposerHal
+template <typename Interface, typename Hal>
+class ComposerImpl : public V2_1::hal::detail::ComposerImpl<Interface, Hal> {
+   public:
+    static std::unique_ptr<ComposerImpl> create(std::unique_ptr<Hal> hal) {
+        return std::make_unique<ComposerImpl>(std::move(hal));
+    }
+
+    ComposerImpl(std::unique_ptr<Hal> hal) : BaseType2_1(std::move(hal)) {}
+
+   protected:
+    V2_1::IComposerClient* createClient() override {
+        auto client = ComposerClient::create(mHal.get());
+        if (!client) {
+            return nullptr;
+        }
+
+        auto clientDestroyed = [this]() { onClientDestroyed(); };
+        client->setOnClientDestroyed(clientDestroyed);
+
+        return client.release();
+    }
+
+   private:
+    using BaseType2_1 = V2_1::hal::detail::ComposerImpl<Interface, Hal>;
+    using BaseType2_1::mHal;
+    using BaseType2_1::onClientDestroyed;
+};
+
+}  // namespace detail
+
+using Composer = detail::ComposerImpl<IComposer, ComposerHal>;
+
+}  // namespace hal
+}  // namespace V2_2
+}  // namespace composer
+}  // namespace graphics
+}  // namespace hardware
+}  // namespace android
diff --git a/graphics/composer/2.2/utils/hal/include/composer-hal/2.2/ComposerClient.h b/graphics/composer/2.2/utils/hal/include/composer-hal/2.2/ComposerClient.h
new file mode 100644
index 0000000..d550f83
--- /dev/null
+++ b/graphics/composer/2.2/utils/hal/include/composer-hal/2.2/ComposerClient.h
@@ -0,0 +1,162 @@
+/*
+ * Copyright 2018 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
+
+#ifndef LOG_TAG
+#warning "ComposerClient.h included without LOG_TAG"
+#endif
+
+#include <android/hardware/graphics/composer/2.2/IComposerClient.h>
+#include <composer-hal/2.1/ComposerClient.h>
+#include <composer-hal/2.2/ComposerCommandEngine.h>
+#include <composer-hal/2.2/ComposerHal.h>
+#include <composer-hal/2.2/ComposerResources.h>
+
+namespace android {
+namespace hardware {
+namespace graphics {
+namespace composer {
+namespace V2_2 {
+namespace hal {
+
+namespace detail {
+
+// ComposerClientImpl implements V2_*::IComposerClient on top of V2_*::ComposerHal
+template <typename Interface, typename Hal>
+class ComposerClientImpl : public V2_1::hal::detail::ComposerClientImpl<Interface, Hal> {
+   public:
+    static std::unique_ptr<ComposerClientImpl> create(Hal* hal) {
+        auto client = std::make_unique<ComposerClientImpl>(hal);
+        return client->init() ? std::move(client) : nullptr;
+    }
+
+    ComposerClientImpl(Hal* hal) : BaseType2_1(hal) {}
+
+    // IComposerClient 2.2 interface
+
+    Return<void> getPerFrameMetadataKeys(
+        Display display, IComposerClient::getPerFrameMetadataKeys_cb hidl_cb) override {
+        std::vector<IComposerClient::PerFrameMetadataKey> keys;
+        Error error = mHal->getPerFrameMetadataKeys(display, &keys);
+        hidl_cb(error, keys);
+        return Void();
+    }
+
+    Return<void> getReadbackBufferAttributes(
+        Display display, IComposerClient::getReadbackBufferAttributes_cb hidl_cb) override {
+        PixelFormat format = static_cast<PixelFormat>(0);
+        Dataspace dataspace = Dataspace::UNKNOWN;
+        Error error = mHal->getReadbackBufferAttributes(display, &format, &dataspace);
+        hidl_cb(error, format, dataspace);
+        return Void();
+    }
+
+    Return<void> getReadbackBufferFence(
+        Display display, IComposerClient::getReadbackBufferFence_cb hidl_cb) override {
+        base::unique_fd fenceFd;
+        Error error = mHal->getReadbackBufferFence(display, &fenceFd);
+        if (error != Error::NONE) {
+            hidl_cb(error, nullptr);
+            return Void();
+        }
+
+        NATIVE_HANDLE_DECLARE_STORAGE(fenceStorage, 1, 0);
+        hidl_cb(error, getFenceHandle(fenceFd, fenceStorage));
+        return Void();
+    }
+
+    Return<Error> setReadbackBuffer(Display display, const hidl_handle& buffer,
+                                    const hidl_handle& releaseFence) override {
+        base::unique_fd fenceFd;
+        Error error = getFenceFd(releaseFence, &fenceFd);
+        if (error != Error::NONE) {
+            return error;
+        }
+
+        auto resources = static_cast<ComposerResources*>(mResources.get());
+        const native_handle_t* readbackBuffer;
+        ComposerResources::ReplacedBufferHandle replacedReadbackBuffer;
+        error = resources->getDisplayReadbackBuffer(display, buffer.getNativeHandle(),
+                                                    &readbackBuffer, &replacedReadbackBuffer);
+        if (error != Error::NONE) {
+            return error;
+        }
+
+        return mHal->setReadbackBuffer(display, readbackBuffer, std::move(fenceFd));
+    }
+
+    Return<Error> setPowerMode_2_2(Display display, IComposerClient::PowerMode mode) override {
+        return mHal->setPowerMode_2_2(display, mode);
+    }
+
+   protected:
+    std::unique_ptr<V2_1::hal::ComposerResources> createResources() override {
+        return ComposerResources::create();
+    }
+
+    std::unique_ptr<V2_1::hal::ComposerCommandEngine> createCommandEngine() override {
+        return std::make_unique<ComposerCommandEngine>(
+            mHal, static_cast<ComposerResources*>(mResources.get()));
+    }
+
+    // convert fenceFd to or from hidl_handle
+    static Error getFenceFd(const hidl_handle& fenceHandle, base::unique_fd* outFenceFd) {
+        auto handle = fenceHandle.getNativeHandle();
+        if (handle && handle->numFds > 1) {
+            ALOGE("invalid fence handle with %d fds", handle->numFds);
+            return Error::BAD_PARAMETER;
+        }
+
+        int fenceFd = (handle && handle->numFds == 1) ? handle->data[0] : -1;
+        if (fenceFd >= 0) {
+            fenceFd = dup(fenceFd);
+            if (fenceFd < 0) {
+                return Error::NO_RESOURCES;
+            }
+        }
+
+        outFenceFd->reset(fenceFd);
+
+        return Error::NONE;
+    }
+
+    static hidl_handle getFenceHandle(const base::unique_fd& fenceFd, char* handleStorage) {
+        native_handle_t* handle = nullptr;
+        if (fenceFd >= 0) {
+            handle = native_handle_init(handleStorage, 1, 0);
+            handle->data[0] = fenceFd;
+        }
+
+        return hidl_handle(handle);
+    }
+
+   private:
+    using BaseType2_1 = V2_1::hal::detail::ComposerClientImpl<Interface, Hal>;
+    using BaseType2_1::mHal;
+    using BaseType2_1::mResources;
+};
+
+}  // namespace detail
+
+using ComposerClient = detail::ComposerClientImpl<IComposerClient, ComposerHal>;
+
+}  // namespace hal
+}  // namespace V2_2
+}  // namespace composer
+}  // namespace graphics
+}  // namespace hardware
+}  // namespace android
diff --git a/graphics/composer/2.2/utils/hal/include/composer-hal/2.2/ComposerCommandEngine.h b/graphics/composer/2.2/utils/hal/include/composer-hal/2.2/ComposerCommandEngine.h
new file mode 100644
index 0000000..adcac46
--- /dev/null
+++ b/graphics/composer/2.2/utils/hal/include/composer-hal/2.2/ComposerCommandEngine.h
@@ -0,0 +1,103 @@
+/*
+ * Copyright 2018 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
+
+#ifndef LOG_TAG
+#warning "ComposerCommandEngine.h included without LOG_TAG"
+#endif
+
+#include <composer-command-buffer/2.2/ComposerCommandBuffer.h>
+#include <composer-hal/2.1/ComposerCommandEngine.h>
+#include <composer-hal/2.2/ComposerHal.h>
+#include <composer-hal/2.2/ComposerResources.h>
+
+namespace android {
+namespace hardware {
+namespace graphics {
+namespace composer {
+namespace V2_2 {
+namespace hal {
+
+class ComposerCommandEngine : public V2_1::hal::ComposerCommandEngine {
+   public:
+    ComposerCommandEngine(ComposerHal* hal, ComposerResources* resources)
+        : BaseType2_1(hal, resources), mHal(hal) {}
+
+   protected:
+    bool executeCommand(V2_1::IComposerClient::Command command, uint16_t length) override {
+        switch (static_cast<IComposerClient::Command>(command)) {
+            case IComposerClient::Command::SET_PER_FRAME_METADATA:
+                return executeSetPerFrameMetadata(length);
+            case IComposerClient::Command::SET_LAYER_FLOAT_COLOR:
+                return executeSetLayerFloatColor(length);
+            default:
+                return BaseType2_1::executeCommand(command, length);
+        }
+    }
+
+    bool executeSetPerFrameMetadata(uint16_t length) {
+        // (key, value) pairs
+        if (length % 2 != 0) {
+            return false;
+        }
+
+        std::vector<IComposerClient::PerFrameMetadata> metadata;
+        metadata.reserve(length / 2);
+        while (length > 0) {
+            metadata.emplace_back(IComposerClient::PerFrameMetadata{
+                static_cast<IComposerClient::PerFrameMetadataKey>(readSigned()), readFloat()});
+            length -= 2;
+        }
+
+        auto err = mHal->setPerFrameMetadata(mCurrentDisplay, metadata);
+        if (err != Error::NONE) {
+            mWriter.setError(getCommandLoc(), err);
+        }
+
+        return true;
+    }
+
+    bool executeSetLayerFloatColor(uint16_t length) {
+        if (length != CommandWriterBase::kSetLayerFloatColorLength) {
+            return false;
+        }
+
+        auto err = mHal->setLayerFloatColor(mCurrentDisplay, mCurrentLayer, readFloatColor());
+        if (err != Error::NONE) {
+            mWriter.setError(getCommandLoc(), err);
+        }
+
+        return true;
+    }
+
+    IComposerClient::FloatColor readFloatColor() {
+        return IComposerClient::FloatColor{readFloat(), readFloat(), readFloat(), readFloat()};
+    }
+
+   private:
+    using BaseType2_1 = V2_1::hal::ComposerCommandEngine;
+    using BaseType2_1::mWriter;
+
+    ComposerHal* mHal;
+};
+
+}  // namespace hal
+}  // namespace V2_2
+}  // namespace composer
+}  // namespace graphics
+}  // namespace hardware
+}  // namespace android
diff --git a/graphics/composer/2.2/utils/hal/include/composer-hal/2.2/ComposerHal.h b/graphics/composer/2.2/utils/hal/include/composer-hal/2.2/ComposerHal.h
new file mode 100644
index 0000000..30b3643
--- /dev/null
+++ b/graphics/composer/2.2/utils/hal/include/composer-hal/2.2/ComposerHal.h
@@ -0,0 +1,66 @@
+/*
+ * Copyright 2018 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-base/unique_fd.h>
+#include <android/hardware/graphics/composer/2.2/IComposer.h>
+#include <android/hardware/graphics/composer/2.2/IComposerClient.h>
+#include <composer-hal/2.1/ComposerHal.h>
+
+namespace android {
+namespace hardware {
+namespace graphics {
+namespace composer {
+namespace V2_2 {
+namespace hal {
+
+using common::V1_0::Dataspace;
+using common::V1_0::PixelFormat;
+using V2_1::Display;
+using V2_1::Error;
+using V2_1::Layer;
+
+class ComposerHal : public V2_1::hal::ComposerHal {
+   public:
+    // superceded by setPowerMode_2_2
+    Error setPowerMode(Display display, V2_1::IComposerClient::PowerMode mode) override {
+        return setPowerMode_2_2(display, static_cast<IComposerClient::PowerMode>(mode));
+    }
+
+    virtual Error getPerFrameMetadataKeys(
+        Display display, std::vector<IComposerClient::PerFrameMetadataKey>* outKeys) = 0;
+    virtual Error setPerFrameMetadata(
+        Display display, const std::vector<IComposerClient::PerFrameMetadata>& metadata) = 0;
+
+    virtual Error getReadbackBufferAttributes(Display display, PixelFormat* outFormat,
+                                              Dataspace* outDataspace) = 0;
+    virtual Error setReadbackBuffer(Display display, const native_handle_t* bufferHandle,
+                                    base::unique_fd fenceFd) = 0;
+    virtual Error getReadbackBufferFence(Display display, base::unique_fd* outFenceFd) = 0;
+
+    virtual Error setPowerMode_2_2(Display display, IComposerClient::PowerMode mode) = 0;
+
+    virtual Error setLayerFloatColor(Display display, Layer layer,
+                                     IComposerClient::FloatColor color) = 0;
+};
+
+}  // namespace hal
+}  // namespace V2_2
+}  // namespace composer
+}  // namespace graphics
+}  // namespace hardware
+}  // namespace android
diff --git a/graphics/composer/2.2/utils/hal/include/composer-hal/2.2/ComposerResources.h b/graphics/composer/2.2/utils/hal/include/composer-hal/2.2/ComposerResources.h
new file mode 100644
index 0000000..85b6651
--- /dev/null
+++ b/graphics/composer/2.2/utils/hal/include/composer-hal/2.2/ComposerResources.h
@@ -0,0 +1,105 @@
+/*
+ * Copyright 2018 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
+
+#ifndef LOG_TAG
+#warning "ComposerResources.h included without LOG_TAG"
+#endif
+
+#include <composer-hal/2.1/ComposerResources.h>
+
+namespace android {
+namespace hardware {
+namespace graphics {
+namespace composer {
+namespace V2_2 {
+namespace hal {
+
+using V2_1::hal::ComposerHandleCache;
+using V2_1::hal::ComposerHandleImporter;
+
+class ComposerDisplayResource : public V2_1::hal::ComposerDisplayResource {
+   public:
+    ComposerDisplayResource(DisplayType type, ComposerHandleImporter& importer,
+                            uint32_t outputBufferCacheSize)
+        : V2_1::hal::ComposerDisplayResource(type, importer, outputBufferCacheSize),
+          mReadbackBufferCache(importer, ComposerHandleCache::HandleType::BUFFER, 1) {}
+
+    Error getReadbackBuffer(const native_handle_t* inHandle, const native_handle_t** outHandle,
+                            const native_handle** outReplacedHandle) {
+        const uint32_t slot = 0;
+        const bool fromCache = false;
+        return mReadbackBufferCache.getHandle(slot, fromCache, inHandle, outHandle,
+                                              outReplacedHandle);
+    }
+
+   protected:
+    ComposerHandleCache mReadbackBufferCache;
+};
+
+class ComposerResources : public V2_1::hal::ComposerResources {
+   public:
+    static std::unique_ptr<ComposerResources> create() {
+        auto resources = std::make_unique<ComposerResources>();
+        return resources->init() ? std::move(resources) : nullptr;
+    }
+
+    Error getDisplayReadbackBuffer(Display display, const native_handle_t* rawHandle,
+                                   const native_handle_t** outHandle,
+                                   ReplacedBufferHandle* outReplacedHandle) {
+        // import buffer
+        const native_handle_t* importedHandle;
+        Error error = mImporter.importBuffer(rawHandle, &importedHandle);
+        if (error != Error::NONE) {
+            return error;
+        }
+
+        std::lock_guard<std::mutex> lock(mDisplayResourcesMutex);
+
+        auto iter = mDisplayResources.find(display);
+        if (iter == mDisplayResources.end()) {
+            mImporter.freeBuffer(importedHandle);
+            return Error::BAD_DISPLAY;
+        }
+        ComposerDisplayResource& displayResource =
+            *static_cast<ComposerDisplayResource*>(iter->second.get());
+
+        // update cache
+        const native_handle_t* replacedHandle;
+        error = displayResource.getReadbackBuffer(importedHandle, outHandle, &replacedHandle);
+        if (error != Error::NONE) {
+            mImporter.freeBuffer(importedHandle);
+            return error;
+        }
+
+        outReplacedHandle->reset(&mImporter, replacedHandle);
+        return Error::NONE;
+    }
+
+   protected:
+    std::unique_ptr<V2_1::hal::ComposerDisplayResource> createDisplayResource(
+        ComposerDisplayResource::DisplayType type, uint32_t outputBufferCacheSize) override {
+        return std::make_unique<ComposerDisplayResource>(type, mImporter, outputBufferCacheSize);
+    }
+};
+
+}  // namespace hal
+}  // namespace V2_2
+}  // namespace composer
+}  // namespace graphics
+}  // namespace hardware
+}  // namespace android
diff --git a/graphics/composer/2.2/utils/passthrough/Android.bp b/graphics/composer/2.2/utils/passthrough/Android.bp
new file mode 100644
index 0000000..318ce91
--- /dev/null
+++ b/graphics/composer/2.2/utils/passthrough/Android.bp
@@ -0,0 +1,14 @@
+cc_library_headers {
+    name: "android.hardware.graphics.composer@2.2-passthrough",
+    defaults: ["hidl_defaults"],
+    vendor: true,
+    header_libs: [
+        "android.hardware.graphics.composer@2.1-passthrough",
+        "android.hardware.graphics.composer@2.2-hal",
+    ],
+    export_header_lib_headers: [
+        "android.hardware.graphics.composer@2.1-passthrough",
+        "android.hardware.graphics.composer@2.2-hal",
+    ],
+    export_include_dirs: ["include"],
+}
diff --git a/graphics/composer/2.2/utils/passthrough/include/composer-passthrough/2.2/HwcHal.h b/graphics/composer/2.2/utils/passthrough/include/composer-passthrough/2.2/HwcHal.h
new file mode 100644
index 0000000..b251351
--- /dev/null
+++ b/graphics/composer/2.2/utils/passthrough/include/composer-passthrough/2.2/HwcHal.h
@@ -0,0 +1,208 @@
+/*
+ * Copyright 2018 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
+
+#ifndef LOG_TAG
+#warning "HwcHal.h included without LOG_TAG"
+#endif
+
+#include <type_traits>
+
+#include <composer-hal/2.2/ComposerHal.h>
+#include <composer-passthrough/2.1/HwcHal.h>
+
+namespace android {
+namespace hardware {
+namespace graphics {
+namespace composer {
+namespace V2_2 {
+namespace passthrough {
+
+namespace detail {
+
+using common::V1_0::Dataspace;
+using common::V1_0::PixelFormat;
+using V2_1::Display;
+using V2_1::Error;
+using V2_1::Layer;
+
+// HwcHalImpl implements V2_*::hal::ComposerHal on top of hwcomposer2
+template <typename Hal>
+class HwcHalImpl : public V2_1::passthrough::detail::HwcHalImpl<Hal> {
+   public:
+    // XXX when can we return Error::UNSUPPORTED?
+
+    Error getPerFrameMetadataKeys(
+        Display display, std::vector<IComposerClient::PerFrameMetadataKey>* outKeys) override {
+        if (!mDispatch.getPerFrameMetadataKeys) {
+            return Error::UNSUPPORTED;
+        }
+
+        uint32_t count = 0;
+        int32_t error = mDispatch.getPerFrameMetadataKeys(mDevice, display, &count, nullptr);
+        if (error != HWC2_ERROR_NONE) {
+            return static_cast<Error>(error);
+        }
+
+        std::vector<IComposerClient::PerFrameMetadataKey> keys(count);
+        error = mDispatch.getPerFrameMetadataKeys(
+            mDevice, display, &count,
+            reinterpret_cast<std::underlying_type<IComposerClient::PerFrameMetadataKey>::type*>(
+                keys.data()));
+        if (error != HWC2_ERROR_NONE) {
+            return static_cast<Error>(error);
+        }
+
+        keys.resize(count);
+        *outKeys = std::move(keys);
+        return Error::NONE;
+    }
+
+    Error setPerFrameMetadata(
+        Display display, const std::vector<IComposerClient::PerFrameMetadata>& metadata) override {
+        if (!mDispatch.setPerFrameMetadata) {
+            return Error::UNSUPPORTED;
+        }
+
+        std::vector<int32_t> keys;
+        std::vector<float> values;
+        keys.reserve(metadata.size());
+        values.reserve(metadata.size());
+        for (const auto& m : metadata) {
+            keys.push_back(static_cast<int32_t>(m.key));
+            values.push_back(m.value);
+        }
+
+        int32_t error = mDispatch.setPerFrameMetadata(mDevice, display, metadata.size(),
+                                                      keys.data(), values.data());
+        return static_cast<Error>(error);
+    }
+
+    Error getReadbackBufferAttributes(Display display, PixelFormat* outFormat,
+                                      Dataspace* outDataspace) override {
+        if (!mDispatch.getReadbackBufferAttributes) {
+            return Error::UNSUPPORTED;
+        }
+
+        int32_t format = 0;
+        int32_t dataspace = 0;
+        int32_t error =
+            mDispatch.getReadbackBufferAttributes(mDevice, display, &format, &dataspace);
+        if (error == HWC2_ERROR_NONE) {
+            *outFormat = static_cast<PixelFormat>(format);
+            *outDataspace = static_cast<Dataspace>(dataspace);
+        }
+        return static_cast<Error>(error);
+    }
+
+    Error setReadbackBuffer(Display display, const native_handle_t* bufferHandle,
+                            base::unique_fd fenceFd) override {
+        if (!mDispatch.setReadbackBuffer) {
+            return Error::UNSUPPORTED;
+        }
+
+        int32_t error =
+            mDispatch.setReadbackBuffer(mDevice, display, bufferHandle, fenceFd.release());
+        return static_cast<Error>(error);
+    }
+
+    Error getReadbackBufferFence(Display display, base::unique_fd* outFenceFd) override {
+        if (!mDispatch.getReadbackBufferFence) {
+            return Error::UNSUPPORTED;
+        }
+
+        int32_t fenceFd = -1;
+        int32_t error = mDispatch.getReadbackBufferFence(mDevice, display, &fenceFd);
+        outFenceFd->reset(fenceFd);
+        return static_cast<Error>(error);
+    }
+
+    Error setPowerMode_2_2(Display display, IComposerClient::PowerMode mode) override {
+        if (mode == IComposerClient::PowerMode::ON_SUSPEND) {
+            return Error::UNSUPPORTED;
+        }
+        return setPowerMode(display, static_cast<V2_1::IComposerClient::PowerMode>(mode));
+    }
+
+    Error setLayerFloatColor(Display display, Layer layer,
+                             IComposerClient::FloatColor color) override {
+        if (!mDispatch.setLayerFloatColor) {
+            return Error::UNSUPPORTED;
+        }
+
+        int32_t error = mDispatch.setLayerFloatColor(
+            mDevice, display, layer, hwc_float_color{color.r, color.g, color.b, color.a});
+        return static_cast<Error>(error);
+    }
+
+   protected:
+    template <typename T>
+    bool initOptionalDispatch(hwc2_function_descriptor_t desc, T* outPfn) {
+        auto pfn = mDevice->getFunction(mDevice, desc);
+        if (pfn) {
+            *outPfn = reinterpret_cast<T>(pfn);
+            return true;
+        } else {
+            return false;
+        }
+    }
+
+    bool initDispatch() override {
+        if (!BaseType2_1::initDispatch()) {
+            return false;
+        }
+
+        initOptionalDispatch(HWC2_FUNCTION_SET_LAYER_FLOAT_COLOR, &mDispatch.setLayerFloatColor);
+
+        initOptionalDispatch(HWC2_FUNCTION_SET_PER_FRAME_METADATA, &mDispatch.setPerFrameMetadata);
+        initOptionalDispatch(HWC2_FUNCTION_GET_PER_FRAME_METADATA_KEYS,
+                             &mDispatch.getPerFrameMetadataKeys);
+
+        initOptionalDispatch(HWC2_FUNCTION_SET_READBACK_BUFFER, &mDispatch.setReadbackBuffer);
+        initOptionalDispatch(HWC2_FUNCTION_GET_READBACK_BUFFER_ATTRIBUTES,
+                             &mDispatch.getReadbackBufferAttributes);
+        initOptionalDispatch(HWC2_FUNCTION_GET_READBACK_BUFFER_FENCE,
+                             &mDispatch.getReadbackBufferFence);
+
+        return true;
+    }
+
+    struct {
+        HWC2_PFN_SET_LAYER_FLOAT_COLOR setLayerFloatColor;
+        HWC2_PFN_SET_PER_FRAME_METADATA setPerFrameMetadata;
+        HWC2_PFN_GET_PER_FRAME_METADATA_KEYS getPerFrameMetadataKeys;
+        HWC2_PFN_SET_READBACK_BUFFER setReadbackBuffer;
+        HWC2_PFN_GET_READBACK_BUFFER_ATTRIBUTES getReadbackBufferAttributes;
+        HWC2_PFN_GET_READBACK_BUFFER_FENCE getReadbackBufferFence;
+    } mDispatch = {};
+
+   private:
+    using BaseType2_1 = V2_1::passthrough::detail::HwcHalImpl<Hal>;
+    using BaseType2_1::mDevice;
+    using BaseType2_1::setPowerMode;
+};
+
+}  // namespace detail
+
+using HwcHal = detail::HwcHalImpl<hal::ComposerHal>;
+
+}  // namespace passthrough
+}  // namespace V2_2
+}  // namespace composer
+}  // namespace graphics
+}  // namespace hardware
+}  // namespace android
diff --git a/graphics/composer/2.2/utils/passthrough/include/composer-passthrough/2.2/HwcLoader.h b/graphics/composer/2.2/utils/passthrough/include/composer-passthrough/2.2/HwcLoader.h
new file mode 100644
index 0000000..cb4a238
--- /dev/null
+++ b/graphics/composer/2.2/utils/passthrough/include/composer-passthrough/2.2/HwcLoader.h
@@ -0,0 +1,79 @@
+/*
+ * Copyright 2018 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
+
+#ifndef LOG_TAG
+#warning "HwcLoader.h included without LOG_TAG"
+#endif
+
+#include <composer-hal/2.2/Composer.h>
+#include <composer-hal/2.2/ComposerHal.h>
+#include <composer-passthrough/2.1/HwcLoader.h>
+#include <composer-passthrough/2.2/HwcHal.h>
+
+namespace android {
+namespace hardware {
+namespace graphics {
+namespace composer {
+namespace V2_2 {
+namespace passthrough {
+
+class HwcLoader : public V2_1::passthrough::HwcLoader {
+   public:
+    static IComposer* load() {
+        const hw_module_t* module = loadModule();
+        if (!module) {
+            return nullptr;
+        }
+
+        auto hal = createHalWithAdapter(module);
+        if (!hal) {
+            return nullptr;
+        }
+
+        return createComposer(std::move(hal)).release();
+    }
+
+    // create a ComposerHal instance
+    static std::unique_ptr<hal::ComposerHal> createHal(const hw_module_t* module) {
+        auto hal = std::make_unique<HwcHal>();
+        return hal->initWithModule(module) ? std::move(hal) : nullptr;
+    }
+
+    // create a ComposerHal instance, insert an adapter if necessary
+    static std::unique_ptr<hal::ComposerHal> createHalWithAdapter(const hw_module_t* module) {
+        bool adapted;
+        hwc2_device_t* device = openDeviceWithAdapter(module, &adapted);
+        if (!device) {
+            return nullptr;
+        }
+        auto hal = std::make_unique<HwcHal>();
+        return hal->initWithDevice(std::move(device), !adapted) ? std::move(hal) : nullptr;
+    }
+
+    // create an IComposer instance
+    static std::unique_ptr<IComposer> createComposer(std::unique_ptr<hal::ComposerHal> hal) {
+        return hal::Composer::create(std::move(hal));
+    }
+};
+
+}  // namespace passthrough
+}  // namespace V2_2
+}  // namespace composer
+}  // namespace graphics
+}  // namespace hardware
+}  // namespace android
diff --git a/graphics/composer/2.2/utils/vts/Android.bp b/graphics/composer/2.2/utils/vts/Android.bp
new file mode 100644
index 0000000..641fdcb
--- /dev/null
+++ b/graphics/composer/2.2/utils/vts/Android.bp
@@ -0,0 +1,39 @@
+//
+// Copyright (C) 2018 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.
+//
+
+cc_library_static {
+    name: "android.hardware.graphics.composer@2.2-vts",
+    defaults: ["hidl_defaults"],
+    srcs: [
+        "ComposerVts.cpp",
+    ],
+    static_libs: [
+        "VtsHalHidlTargetTestBase",
+        "android.hardware.graphics.composer@2.1",
+        "android.hardware.graphics.composer@2.1-vts",
+        "android.hardware.graphics.composer@2.2",
+    ],
+    header_libs: [
+        "android.hardware.graphics.composer@2.1-command-buffer",
+        "android.hardware.graphics.composer@2.2-command-buffer",
+    ],
+    cflags: [
+        "-O0",
+        "-g",
+        "-DLOG_TAG=\"ComposerVts\"",
+    ],
+    export_include_dirs: ["include"],
+}
diff --git a/graphics/composer/2.2/vts/functional/VtsHalGraphicsComposerTestUtils.cpp b/graphics/composer/2.2/utils/vts/ComposerVts.cpp
similarity index 96%
rename from graphics/composer/2.2/vts/functional/VtsHalGraphicsComposerTestUtils.cpp
rename to graphics/composer/2.2/utils/vts/ComposerVts.cpp
index 00946ce..b536f67 100644
--- a/graphics/composer/2.2/vts/functional/VtsHalGraphicsComposerTestUtils.cpp
+++ b/graphics/composer/2.2/utils/vts/ComposerVts.cpp
@@ -14,22 +14,22 @@
  * limitations under the License.
  */
 
-#include <VtsHalHidlTargetTestBase.h>
-#include <hidl/HidlTransportUtils.h>
+#include <composer-vts/2.2/ComposerVts.h>
 
+#include <VtsHalHidlTargetTestBase.h>
 #include <composer-command-buffer/2.2/ComposerCommandBuffer.h>
-#include "2.2/VtsHalGraphicsComposerTestUtils.h"
+#include <hidl/HidlTransportUtils.h>
 
 namespace android {
 namespace hardware {
 namespace graphics {
 namespace composer {
 namespace V2_2 {
-namespace tests {
+namespace vts {
 
-using android::hardware::graphics::composer::V2_2::IComposerClient;
-using android::hardware::details::getDescriptor;
 using android::hardware::details::canCastInterface;
+using android::hardware::details::getDescriptor;
+using android::hardware::graphics::composer::V2_2::IComposerClient;
 
 std::unique_ptr<ComposerClient_v2_2> Composer_v2_2::createClient_v2_2() {
     std::unique_ptr<ComposerClient_v2_2> client;
@@ -56,7 +56,7 @@
     return keys;
 }
 
-void ComposerClient_v2_2::execute_v2_2(V2_1::tests::TestCommandReader* reader,
+void ComposerClient_v2_2::execute_v2_2(V2_1::vts::TestCommandReader* reader,
                                        V2_2::CommandWriterBase* writer) {
     bool queueChanged = false;
     uint32_t commandLength = 0;
@@ -119,7 +119,7 @@
     *outFence = 0;
 }
 
-}  // namespace tests
+}  // namespace vts
 }  // namespace V2_2
 }  // namespace composer
 }  // namespace graphics
diff --git a/graphics/composer/2.2/vts/functional/include/2.2/VtsHalGraphicsComposerTestUtils.h b/graphics/composer/2.2/utils/vts/include/composer-vts/2.2/ComposerVts.h
similarity index 82%
rename from graphics/composer/2.2/vts/functional/include/2.2/VtsHalGraphicsComposerTestUtils.h
rename to graphics/composer/2.2/utils/vts/include/composer-vts/2.2/ComposerVts.h
index c5756ed..eced69f 100644
--- a/graphics/composer/2.2/vts/functional/include/2.2/VtsHalGraphicsComposerTestUtils.h
+++ b/graphics/composer/2.2/utils/vts/include/composer-vts/2.2/ComposerVts.h
@@ -22,11 +22,11 @@
 #include <unordered_set>
 #include <vector>
 
-#include <VtsHalGraphicsComposerTestUtils.h>
 #include <VtsHalHidlTargetTestBase.h>
 #include <android/hardware/graphics/composer/2.2/IComposer.h>
 #include <android/hardware/graphics/composer/2.2/IComposerClient.h>
 #include <composer-command-buffer/2.2/ComposerCommandBuffer.h>
+#include <composer-vts/2.1/ComposerVts.h>
 #include <utils/StrongPointer.h>
 
 namespace android {
@@ -34,7 +34,7 @@
 namespace graphics {
 namespace composer {
 namespace V2_2 {
-namespace tests {
+namespace vts {
 
 using android::hardware::graphics::common::V1_0::ColorMode;
 using android::hardware::graphics::common::V1_0::Dataspace;
@@ -47,22 +47,22 @@
 
 // Only thing I need for Composer_v2_2 is to create a v2_2 ComposerClient
 // Everything else is the same
-class Composer_v2_2 : public V2_1::tests::Composer {
+class Composer_v2_2 : public V2_1::vts::Composer {
    public:
-    Composer_v2_2() : V2_1::tests::Composer(){};
-    explicit Composer_v2_2(const std::string& name) : V2_1::tests::Composer(name){};
+    Composer_v2_2() : V2_1::vts::Composer(){};
+    explicit Composer_v2_2(const std::string& name) : V2_1::vts::Composer(name){};
 
     std::unique_ptr<ComposerClient_v2_2> createClient_v2_2();
 };
 
 // A wrapper to IComposerClient.
 class ComposerClient_v2_2
-    : public android::hardware::graphics::composer::V2_1::tests::ComposerClient {
+    : public android::hardware::graphics::composer::V2_1::vts::ComposerClient {
    public:
     ComposerClient_v2_2(const sp<IComposerClient>& client)
-        : V2_1::tests::ComposerClient(client), mClient_v2_2(client){};
+        : V2_1::vts::ComposerClient(client), mClient_v2_2(client){};
 
-    void execute_v2_2(V2_1::tests::TestCommandReader* reader, V2_2::CommandWriterBase* writer);
+    void execute_v2_2(V2_1::vts::TestCommandReader* reader, V2_2::CommandWriterBase* writer);
 
     std::vector<IComposerClient::PerFrameMetadataKey> getPerFrameMetadataKeys(Display display);
 
@@ -76,7 +76,7 @@
     sp<V2_2::IComposerClient> mClient_v2_2;
 };
 
-}  // namespace tests
+}  // namespace vts
 }  // namespace V2_2
 }  // namespace composer
 }  // namespace graphics
diff --git a/graphics/composer/2.2/vts/functional/Android.bp b/graphics/composer/2.2/vts/functional/Android.bp
index 78322a1..7747900 100644
--- a/graphics/composer/2.2/vts/functional/Android.bp
+++ b/graphics/composer/2.2/vts/functional/Android.bp
@@ -14,37 +14,6 @@
 // limitations under the License.
 //
 
-cc_library_static {
-    name: "libVtsHalGraphicsComposerTestUtils@2.2",
-    defaults: ["hidl_defaults"],
-    srcs: [
-        "VtsHalGraphicsComposerTestUtils.cpp",
-    ],
-    shared_libs: [
-        "android.hardware.graphics.composer@2.1",
-        "android.hardware.graphics.composer@2.2",
-        "libfmq",
-        "libsync",
-    ],
-    static_libs: [
-        "libVtsHalGraphicsComposerTestUtils",
-        "VtsHalHidlTargetTestBase",
-    ],
-    header_libs: [
-        "android.hardware.graphics.composer@2.1-command-buffer",
-        "android.hardware.graphics.composer@2.2-command-buffer",
-    ],
-    cflags: [
-        "-Wall",
-        "-Wextra",
-        "-Werror",
-        "-O0",
-        "-g",
-        "-DLOG_TAG=\"GraphicsComposerTestUtils@2.2\"",
-    ],
-    export_include_dirs: ["include"],
-}
-
 cc_test {
     name: "VtsHalGraphicsComposerV2_2TargetTest",
     defaults: ["VtsHalTargetTestDefaults"],
@@ -58,14 +27,13 @@
     ],
     static_libs: [
         "android.hardware.graphics.allocator@2.0",
-        "android.hardware.graphics.composer@2.2",
         "android.hardware.graphics.composer@2.1",
+        "android.hardware.graphics.composer@2.1-vts",
+        "android.hardware.graphics.composer@2.2",
+        "android.hardware.graphics.composer@2.2-vts",
         "android.hardware.graphics.mapper@2.0",
         "android.hardware.graphics.mapper@2.0-vts",
         "android.hardware.graphics.mapper@2.1",
-        "libVtsHalGraphicsComposerTestUtils",
-        "libVtsHalGraphicsComposerTestUtils@2.2",
-        "libnativehelper",
     ],
     header_libs: [
         "android.hardware.graphics.composer@2.1-command-buffer",
diff --git a/graphics/composer/2.2/vts/functional/VtsHalGraphicsComposerV2_2TargetTest.cpp b/graphics/composer/2.2/vts/functional/VtsHalGraphicsComposerV2_2TargetTest.cpp
index 6fbdd3c..c494329 100644
--- a/graphics/composer/2.2/vts/functional/VtsHalGraphicsComposerV2_2TargetTest.cpp
+++ b/graphics/composer/2.2/vts/functional/VtsHalGraphicsComposerV2_2TargetTest.cpp
@@ -16,23 +16,20 @@
 
 #define LOG_TAG "graphics_composer_hidl_hal_test@2.2"
 
+#include <VtsHalHidlTargetTestBase.h>
 #include <android-base/logging.h>
 #include <android/hardware/graphics/mapper/2.1/IMapper.h>
+#include <composer-vts/2.1/GraphicsComposerCallback.h>
+#include <composer-vts/2.1/TestCommandReader.h>
+#include <composer-vts/2.2/ComposerVts.h>
 #include <mapper-vts/2.0/MapperVts.h>
-#include <sync/sync.h>
-#include "2.2/VtsHalGraphicsComposerTestUtils.h"
-#include "GraphicsComposerCallback.h"
-#include "TestCommandReader.h"
-#include "VtsHalGraphicsComposerTestUtils.h"
-
-#include <VtsHalHidlTargetTestBase.h>
 
 namespace android {
 namespace hardware {
 namespace graphics {
 namespace composer {
 namespace V2_2 {
-namespace tests {
+namespace vts {
 namespace {
 
 using android::hardware::graphics::common::V1_0::BufferUsage;
@@ -71,7 +68,7 @@
                 GraphicsComposerHidlEnvironment::Instance()->getServiceName<IComposer>()));
         ASSERT_NO_FATAL_FAILURE(mComposerClient = mComposer->createClient_v2_2());
 
-        mComposerCallback = new V2_1::tests::GraphicsComposerCallback;
+        mComposerCallback = new V2_1::vts::GraphicsComposerCallback;
         mComposerClient->registerCallback(mComposerCallback);
 
         // assume the first display is primary and is never removed
@@ -95,7 +92,7 @@
 
     std::unique_ptr<Composer_v2_2> mComposer;
     std::unique_ptr<ComposerClient_v2_2> mComposerClient;
-    sp<V2_1::tests::GraphicsComposerCallback> mComposerCallback;
+    sp<V2_1::vts::GraphicsComposerCallback> mComposerCallback;
     // the first display and is assumed never to be removed
     Display mPrimaryDisplay;
 
@@ -122,7 +119,7 @@
         ASSERT_NO_FATAL_FAILURE(mGralloc = std::make_unique<Gralloc>());
 
         mWriter = std::make_unique<V2_2::CommandWriterBase>(1024);
-        mReader = std::make_unique<V2_1::tests::TestCommandReader>();
+        mReader = std::make_unique<V2_1::vts::TestCommandReader>();
     }
 
     void TearDown() override { ASSERT_NO_FATAL_FAILURE(GraphicsComposerHidlTest::TearDown()); }
@@ -142,7 +139,7 @@
     void execute() { mComposerClient->execute_v2_2(mReader.get(), mWriter.get()); }
 
     std::unique_ptr<V2_2::CommandWriterBase> mWriter;
-    std::unique_ptr<V2_1::tests::TestCommandReader> mReader;
+    std::unique_ptr<V2_1::vts::TestCommandReader> mReader;
 
    private:
     std::unique_ptr<Gralloc> mGralloc;
@@ -239,7 +236,7 @@
 }
 
 }  // namespace
-}  // namespace tests
+}  // namespace vts
 }  // namespace V2_2
 }  // namespace composer
 }  // namespace graphics
@@ -247,7 +244,7 @@
 }  // namespace android
 
 int main(int argc, char** argv) {
-    using android::hardware::graphics::composer::V2_2::tests::GraphicsComposerHidlEnvironment;
+    using android::hardware::graphics::composer::V2_2::vts::GraphicsComposerHidlEnvironment;
     ::testing::AddGlobalTestEnvironment(GraphicsComposerHidlEnvironment::Instance());
     ::testing::InitGoogleTest(&argc, argv);
     GraphicsComposerHidlEnvironment::Instance()->init(&argc, argv);
diff --git a/health/1.0/vts/functional/VtsHalHealthV1_0TargetTest.cpp b/health/1.0/vts/functional/VtsHalHealthV1_0TargetTest.cpp
index 324eb9f..335d15d 100644
--- a/health/1.0/vts/functional/VtsHalHealthV1_0TargetTest.cpp
+++ b/health/1.0/vts/functional/VtsHalHealthV1_0TargetTest.cpp
@@ -19,7 +19,9 @@
 #include <android/hardware/health/1.0/IHealth.h>
 #include <android/hardware/health/1.0/types.h>
 #include <log/log.h>
+
 #include <VtsHalHidlTargetTestBase.h>
+#include <VtsHalHidlTargetTestEnvBase.h>
 
 using HealthConfig = ::android::hardware::health::V1_0::HealthConfig;
 using HealthInfo = ::android::hardware::health::V1_0::HealthInfo;
@@ -28,10 +30,25 @@
 
 using ::android::sp;
 
+// Test environment for Health HIDL HAL.
+class HealthHidlEnvironment : public ::testing::VtsHalHidlTargetTestEnvBase {
+   public:
+    // get the test environment singleton
+    static HealthHidlEnvironment* Instance() {
+        static HealthHidlEnvironment* instance = new HealthHidlEnvironment;
+        return instance;
+    }
+
+    virtual void registerTestServices() override { registerTestService<IHealth>(); }
+   private:
+    HealthHidlEnvironment() {}
+};
+
 class HealthHidlTest : public ::testing::VtsHalHidlTargetTestBase {
    public:
     virtual void SetUp() override {
-        health = ::testing::VtsHalHidlTargetTestBase::getService<IHealth>();
+        health = ::testing::VtsHalHidlTargetTestBase::getService<IHealth>(
+            HealthHidlEnvironment::Instance()->getServiceName<IHealth>());
         ASSERT_NE(health, nullptr);
         health->init(config,
                      [&](const auto& halConfigOut) { config = halConfigOut; });
@@ -57,7 +74,9 @@
 }
 
 int main(int argc, char **argv) {
+    ::testing::AddGlobalTestEnvironment(HealthHidlEnvironment::Instance());
     ::testing::InitGoogleTest(&argc, argv);
+    HealthHidlEnvironment::Instance()->init(&argc, argv);
     int status = RUN_ALL_TESTS();
     ALOGI("Test result = %d", status);
     return status;
diff --git a/neuralnetworks/1.0/vts/functional/Android.bp b/neuralnetworks/1.0/vts/functional/Android.bp
index e33ee77..54dd14a 100644
--- a/neuralnetworks/1.0/vts/functional/Android.bp
+++ b/neuralnetworks/1.0/vts/functional/Android.bp
@@ -14,22 +14,49 @@
 // limitations under the License.
 //
 
+cc_library_static {
+    name: "VtsHalNeuralnetworksTest_utils",
+    srcs: [
+        "Callbacks.cpp",
+        "Models.cpp",
+        "GeneratedTestHarness.cpp",
+    ],
+    defaults: ["VtsHalTargetTestDefaults"],
+    export_include_dirs: ["."],
+    static_libs: [
+        "android.hardware.neuralnetworks@1.0",
+        "android.hardware.neuralnetworks@1.1",
+        "android.hidl.allocator@1.0",
+        "android.hidl.memory@1.0",
+        "libhidlmemory",
+        "libneuralnetworks_utils",
+    ],
+    header_libs: [
+        "libneuralnetworks_headers",
+        "libneuralnetworks_generated_test_harness_headers",
+        "libneuralnetworks_generated_tests",
+    ],
+}
+
 cc_test {
     name: "VtsHalNeuralnetworksV1_0TargetTest",
     srcs: [
-        "Callbacks.cpp",
-        "GeneratedTestHarness.cpp",
-        "Models.cpp",
-        "VtsHalNeuralnetworksV1_0TargetTest.cpp",
+        "VtsHalNeuralnetworksV1_0.cpp",
+        "VtsHalNeuralnetworksV1_0BasicTest.cpp",
+        "VtsHalNeuralnetworksV1_0GeneratedTest.cpp",
     ],
     defaults: ["VtsHalTargetTestDefaults"],
     static_libs: [
         "android.hardware.neuralnetworks@1.0",
+        "android.hardware.neuralnetworks@1.1",
         "android.hidl.allocator@1.0",
         "android.hidl.memory@1.0",
         "libhidlmemory",
+        "libneuralnetworks_utils",
+        "VtsHalNeuralnetworksTest_utils",
     ],
     header_libs: [
+        "libneuralnetworks_headers",
         "libneuralnetworks_generated_test_harness_headers",
         "libneuralnetworks_generated_tests",
     ],
diff --git a/neuralnetworks/1.0/vts/functional/GeneratedTestHarness.cpp b/neuralnetworks/1.0/vts/functional/GeneratedTestHarness.cpp
index d740b5f..f0ce938 100644
--- a/neuralnetworks/1.0/vts/functional/GeneratedTestHarness.cpp
+++ b/neuralnetworks/1.0/vts/functional/GeneratedTestHarness.cpp
@@ -16,9 +16,15 @@
 
 #include "Callbacks.h"
 #include "TestHarness.h"
-#include "VtsHalNeuralnetworksV1_0TargetTest.h"
+#include "Utils.h"
 
 #include <android-base/logging.h>
+#include <android/hardware/neuralnetworks/1.0/IDevice.h>
+#include <android/hardware/neuralnetworks/1.0/IExecutionCallback.h>
+#include <android/hardware/neuralnetworks/1.0/IPreparedModel.h>
+#include <android/hardware/neuralnetworks/1.0/IPreparedModelCallback.h>
+#include <android/hardware/neuralnetworks/1.0/types.h>
+#include <android/hidl/allocator/1.0/IAllocator.h>
 #include <android/hidl/memory/1.0/IMemory.h>
 #include <hidlmemory/mapping.h>
 #include <iostream>
@@ -26,11 +32,6 @@
 namespace android {
 namespace hardware {
 namespace neuralnetworks {
-namespace V1_0 {
-namespace vts {
-namespace functional {
-// allocator helper
-hidl_memory allocateSharedMemory(int64_t size, const std::string& type = "ashmem");
 
 namespace generated_tests {
 using ::android::hardware::neuralnetworks::V1_0::implementation::ExecutionCallback;
@@ -64,54 +65,11 @@
 
 // Top level driver for models and examples generated by test_generator.py
 // Test driver for those generated from ml/nn/runtime/test/spec
-void Execute(const sp<IDevice>& device, std::function<Model(void)> create_model,
-             std::function<bool(int)> is_ignored,
-             const std::vector<MixedTypedExampleType>& examples) {
+void EvaluatePreparedModel(sp<IPreparedModel>& preparedModel, std::function<bool(int)> is_ignored,
+                           const std::vector<MixedTypedExampleType>& examples,
+                           float fpRange = 1e-5f) {
     const uint32_t INPUT = 0;
     const uint32_t OUTPUT = 1;
-    Model model = create_model();
-
-    // see if service can handle model
-    ErrorStatus supportedStatus;
-    bool fullySupportsModel = false;
-    Return<void> supportedCall = device->getSupportedOperations(
-        model, [&](ErrorStatus status, const hidl_vec<bool>& supported) {
-            supportedStatus = status;
-            ASSERT_NE(0ul, supported.size());
-            fullySupportsModel =
-                std::all_of(supported.begin(), supported.end(), [](bool valid) { return valid; });
-        });
-    ASSERT_TRUE(supportedCall.isOk());
-    ASSERT_EQ(ErrorStatus::NONE, supportedStatus);
-
-    // launch prepare model
-    sp<PreparedModelCallback> preparedModelCallback = new PreparedModelCallback();
-    ASSERT_NE(nullptr, preparedModelCallback.get());
-    Return<ErrorStatus> prepareLaunchStatus = device->prepareModel(model, preparedModelCallback);
-    ASSERT_TRUE(prepareLaunchStatus.isOk());
-
-    // retrieve prepared model
-    preparedModelCallback->wait();
-    ErrorStatus prepareReturnStatus = preparedModelCallback->getStatus();
-    sp<IPreparedModel> preparedModel = preparedModelCallback->getPreparedModel();
-    if (fullySupportsModel) {
-        EXPECT_EQ(ErrorStatus::NONE, prepareReturnStatus);
-    } else {
-        EXPECT_TRUE(prepareReturnStatus == ErrorStatus::NONE ||
-                    prepareReturnStatus == ErrorStatus::GENERAL_FAILURE);
-    }
-
-    // early termination if vendor service cannot fully prepare model
-    if (!fullySupportsModel && prepareReturnStatus == ErrorStatus::GENERAL_FAILURE) {
-        ASSERT_EQ(nullptr, preparedModel.get());
-        LOG(INFO) << "NN VTS: Early termination of test because vendor service cannot "
-                     "prepare model that it does not support.";
-        std::cout << "[          ]   Early termination of test because vendor service cannot "
-                     "prepare model that it does not support."
-                  << std::endl;
-        return;
-    }
-    ASSERT_NE(nullptr, preparedModel.get());
 
     int example_no = 1;
     for (auto& example : examples) {
@@ -167,8 +125,8 @@
                 offset += i.location.length;
             }
         }
-        std::vector<hidl_memory> pools = {allocateSharedMemory(inputSize),
-                                          allocateSharedMemory(outputSize)};
+        std::vector<hidl_memory> pools = {nn::allocateSharedMemory(inputSize),
+                                          nn::allocateSharedMemory(outputSize)};
         ASSERT_NE(0ull, pools[INPUT].size());
         ASSERT_NE(0ull, pools[OUTPUT].size());
 
@@ -217,15 +175,113 @@
         MixedTyped filtered_test = filter(test, is_ignored);
 
         // We want "close-enough" results for float
-        compare(filtered_golden, filtered_test);
+        compare(filtered_golden, filtered_test, fpRange);
     }
 }
 
+void Execute(sp<V1_0::IDevice>& device, std::function<V1_0::Model(void)> create_model,
+             std::function<bool(int)> is_ignored,
+             const std::vector<MixedTypedExampleType>& examples) {
+    V1_0::Model model = create_model();
+
+    // see if service can handle model
+    bool fullySupportsModel = false;
+    ErrorStatus supportedStatus;
+    sp<PreparedModelCallback> preparedModelCallback = new PreparedModelCallback();
+    ASSERT_NE(nullptr, preparedModelCallback.get());
+
+    Return<void> supportedCall = device->getSupportedOperations(
+        model, [&](ErrorStatus status, const hidl_vec<bool>& supported) {
+            supportedStatus = status;
+            ASSERT_NE(0ul, supported.size());
+            fullySupportsModel =
+                std::all_of(supported.begin(), supported.end(), [](bool valid) { return valid; });
+        });
+    ASSERT_TRUE(supportedCall.isOk());
+    ASSERT_EQ(ErrorStatus::NONE, supportedStatus);
+    Return<ErrorStatus> prepareLaunchStatus = device->prepareModel(model, preparedModelCallback);
+    ASSERT_TRUE(prepareLaunchStatus.isOk());
+
+    // retrieve prepared model
+    preparedModelCallback->wait();
+    ErrorStatus prepareReturnStatus = preparedModelCallback->getStatus();
+    sp<IPreparedModel> preparedModel = preparedModelCallback->getPreparedModel();
+    if (fullySupportsModel) {
+        EXPECT_EQ(ErrorStatus::NONE, prepareReturnStatus);
+    } else {
+        EXPECT_TRUE(prepareReturnStatus == ErrorStatus::NONE ||
+                    prepareReturnStatus == ErrorStatus::GENERAL_FAILURE);
+    }
+
+    // early termination if vendor service cannot fully prepare model
+    if (!fullySupportsModel && prepareReturnStatus == ErrorStatus::GENERAL_FAILURE) {
+        ASSERT_EQ(nullptr, preparedModel.get());
+        LOG(INFO) << "NN VTS: Early termination of test because vendor service cannot "
+                     "prepare model that it does not support.";
+        std::cout << "[          ]   Early termination of test because vendor service cannot "
+                     "prepare model that it does not support."
+                  << std::endl;
+        return;
+    }
+    ASSERT_NE(nullptr, preparedModel.get());
+
+    EvaluatePreparedModel(preparedModel, is_ignored, examples);
+}
+
+void Execute(sp<V1_1::IDevice>& device, std::function<V1_1::Model(void)> create_model,
+             std::function<bool(int)> is_ignored,
+             const std::vector<MixedTypedExampleType>& examples) {
+    V1_1::Model model = create_model();
+
+    // see if service can handle model
+    bool fullySupportsModel = false;
+    ErrorStatus supportedStatus;
+    sp<PreparedModelCallback> preparedModelCallback = new PreparedModelCallback();
+    ASSERT_NE(nullptr, preparedModelCallback.get());
+
+    Return<void> supportedCall = device->getSupportedOperations_1_1(
+        model, [&](ErrorStatus status, const hidl_vec<bool>& supported) {
+            supportedStatus = status;
+            ASSERT_NE(0ul, supported.size());
+            fullySupportsModel =
+                std::all_of(supported.begin(), supported.end(), [](bool valid) { return valid; });
+        });
+    ASSERT_TRUE(supportedCall.isOk());
+    ASSERT_EQ(ErrorStatus::NONE, supportedStatus);
+    Return<ErrorStatus> prepareLaunchStatus =
+        device->prepareModel_1_1(model, preparedModelCallback);
+    ASSERT_TRUE(prepareLaunchStatus.isOk());
+
+    // retrieve prepared model
+    preparedModelCallback->wait();
+    ErrorStatus prepareReturnStatus = preparedModelCallback->getStatus();
+    sp<IPreparedModel> preparedModel = preparedModelCallback->getPreparedModel();
+    if (fullySupportsModel) {
+        EXPECT_EQ(ErrorStatus::NONE, prepareReturnStatus);
+    } else {
+        EXPECT_TRUE(prepareReturnStatus == ErrorStatus::NONE ||
+                    prepareReturnStatus == ErrorStatus::GENERAL_FAILURE);
+    }
+
+    // early termination if vendor service cannot fully prepare model
+    if (!fullySupportsModel && prepareReturnStatus == ErrorStatus::GENERAL_FAILURE) {
+        ASSERT_EQ(nullptr, preparedModel.get());
+        LOG(INFO) << "NN VTS: Early termination of test because vendor service cannot "
+                     "prepare model that it does not support.";
+        std::cout << "[          ]   Early termination of test because vendor service cannot "
+                     "prepare model that it does not support."
+                  << std::endl;
+        return;
+    }
+    ASSERT_NE(nullptr, preparedModel.get());
+
+    // If in relaxed mode, set the error range to be 5ULP of FP16.
+    float fpRange = !model.relaxComputationFloat32toFloat16 ? 1e-5f : 5.0f * 0.0009765625f;
+    EvaluatePreparedModel(preparedModel, is_ignored, examples, fpRange);
+}
+
 }  // namespace generated_tests
 
-}  // namespace functional
-}  // namespace vts
-}  // namespace V1_0
 }  // namespace neuralnetworks
 }  // namespace hardware
 }  // namespace android
diff --git a/neuralnetworks/1.0/vts/functional/Models.cpp b/neuralnetworks/1.0/vts/functional/Models.cpp
index 8ce4f25..180286a 100644
--- a/neuralnetworks/1.0/vts/functional/Models.cpp
+++ b/neuralnetworks/1.0/vts/functional/Models.cpp
@@ -17,19 +17,22 @@
 #define LOG_TAG "neuralnetworks_hidl_hal_test"
 
 #include "Models.h"
+#include "Utils.h"
+
+#include <android-base/logging.h>
+#include <android/hidl/allocator/1.0/IAllocator.h>
 #include <android/hidl/memory/1.0/IMemory.h>
 #include <hidlmemory/mapping.h>
 #include <vector>
 
+using ::android::sp;
+
 namespace android {
 namespace hardware {
 namespace neuralnetworks {
-namespace V1_0 {
-namespace vts {
-namespace functional {
 
 // create a valid model
-Model createValidTestModel() {
+V1_1::Model createValidTestModel_1_1() {
     const std::vector<float> operand2Data = {5.0f, 6.0f, 7.0f, 8.0f};
     const uint32_t size = operand2Data.size() * sizeof(float);
 
@@ -103,39 +106,34 @@
 }
 
 // create first invalid model
-Model createInvalidTestModel1() {
-    Model model = createValidTestModel();
+V1_1::Model createInvalidTestModel1_1_1() {
+    Model model = createValidTestModel_1_1();
     model.operations[0].type = static_cast<OperationType>(0xDEADBEEF); /* INVALID */
     return model;
 }
 
 // create second invalid model
-Model createInvalidTestModel2() {
-    Model model = createValidTestModel();
+V1_1::Model createInvalidTestModel2_1_1() {
+    Model model = createValidTestModel_1_1();
     const uint32_t operand1 = 0;
     const uint32_t operand5 = 4;  // INVALID OPERAND
     model.inputIndexes = std::vector<uint32_t>({operand1, operand5 /* INVALID OPERAND */});
     return model;
 }
 
-// allocator helper
-hidl_memory allocateSharedMemory(int64_t size, const std::string& type = "ashmem") {
-    hidl_memory memory;
+V1_0::Model createValidTestModel_1_0() {
+    V1_1::Model model = createValidTestModel_1_1();
+    return nn::convertToV1_0(model);
+}
 
-    sp<IAllocator> allocator = IAllocator::getService(type);
-    if (!allocator.get()) {
-        return {};
-    }
+V1_0::Model createInvalidTestModel1_1_0() {
+    V1_1::Model model = createInvalidTestModel1_1_1();
+    return nn::convertToV1_0(model);
+}
 
-    Return<void> ret = allocator->allocate(size, [&](bool success, const hidl_memory& mem) {
-        ASSERT_TRUE(success);
-        memory = mem;
-    });
-    if (!ret.isOk()) {
-        return {};
-    }
-
-    return memory;
+V1_0::Model createInvalidTestModel2_1_0() {
+    V1_1::Model model = createInvalidTestModel2_1_1();
+    return nn::convertToV1_0(model);
 }
 
 // create a valid request
@@ -154,8 +152,8 @@
     std::vector<RequestArgument> outputs = {{
         .location = {.poolIndex = OUTPUT, .offset = 0, .length = outputSize}, .dimensions = {},
     }};
-    std::vector<hidl_memory> pools = {allocateSharedMemory(inputSize),
-                                      allocateSharedMemory(outputSize)};
+    std::vector<hidl_memory> pools = {nn::allocateSharedMemory(inputSize),
+                                      nn::allocateSharedMemory(outputSize)};
     if (pools[INPUT].size() == 0 || pools[OUTPUT].size() == 0) {
         return {};
     }
@@ -199,9 +197,6 @@
     return request;
 }
 
-}  // namespace functional
-}  // namespace vts
-}  // namespace V1_0
 }  // namespace neuralnetworks
 }  // namespace hardware
 }  // namespace android
diff --git a/neuralnetworks/1.0/vts/functional/Models.h b/neuralnetworks/1.0/vts/functional/Models.h
index e0d57d5..9398235 100644
--- a/neuralnetworks/1.0/vts/functional/Models.h
+++ b/neuralnetworks/1.0/vts/functional/Models.h
@@ -16,28 +16,27 @@
 
 #define LOG_TAG "neuralnetworks_hidl_hal_test"
 
-#include "VtsHalNeuralnetworksV1_0TargetTest.h"
+#include <android/hardware/neuralnetworks/1.1/types.h>
 
 namespace android {
 namespace hardware {
 namespace neuralnetworks {
-namespace V1_0 {
-namespace vts {
-namespace functional {
 
-// create the model
-Model createValidTestModel();
-Model createInvalidTestModel1();
-Model createInvalidTestModel2();
+// create V1_1 model
+V1_1::Model createValidTestModel_1_1();
+V1_1::Model createInvalidTestModel1_1_1();
+V1_1::Model createInvalidTestModel2_1_1();
+
+// create V1_0 model
+V1_0::Model createValidTestModel_1_0();
+V1_0::Model createInvalidTestModel1_1_0();
+V1_0::Model createInvalidTestModel2_1_0();
 
 // create the request
-Request createValidTestRequest();
-Request createInvalidTestRequest1();
-Request createInvalidTestRequest2();
+V1_0::Request createValidTestRequest();
+V1_0::Request createInvalidTestRequest1();
+V1_0::Request createInvalidTestRequest2();
 
-}  // namespace functional
-}  // namespace vts
-}  // namespace V1_0
 }  // namespace neuralnetworks
 }  // namespace hardware
 }  // namespace android
diff --git a/neuralnetworks/1.0/vts/functional/VtsHalNeuralnetworksV1_0.cpp b/neuralnetworks/1.0/vts/functional/VtsHalNeuralnetworksV1_0.cpp
new file mode 100644
index 0000000..b14fb2c
--- /dev/null
+++ b/neuralnetworks/1.0/vts/functional/VtsHalNeuralnetworksV1_0.cpp
@@ -0,0 +1,73 @@
+/*
+ * Copyright (C) 2018 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 LOG_TAG "neuralnetworks_hidl_hal_test"
+
+#include "VtsHalNeuralnetworksV1_0.h"
+#include "Utils.h"
+
+#include <android-base/logging.h>
+
+using ::android::hardware::hidl_memory;
+using ::android::hidl::allocator::V1_0::IAllocator;
+using ::android::hidl::memory::V1_0::IMemory;
+using ::android::sp;
+
+namespace android {
+namespace hardware {
+namespace neuralnetworks {
+namespace V1_0 {
+namespace vts {
+namespace functional {
+
+// allocator helper
+hidl_memory allocateSharedMemory(int64_t size) {
+    return nn::allocateSharedMemory(size);
+}
+
+// A class for test environment setup
+NeuralnetworksHidlEnvironment::NeuralnetworksHidlEnvironment() {}
+
+NeuralnetworksHidlEnvironment::~NeuralnetworksHidlEnvironment() {}
+
+NeuralnetworksHidlEnvironment* NeuralnetworksHidlEnvironment::getInstance() {
+    // This has to return a "new" object because it is freed inside
+    // ::testing::AddGlobalTestEnvironment when the gtest is being torn down
+    static NeuralnetworksHidlEnvironment* instance = new NeuralnetworksHidlEnvironment();
+    return instance;
+}
+
+void NeuralnetworksHidlEnvironment::registerTestServices() {
+    registerTestService<V1_0::IDevice>();
+}
+
+// The main test class for NEURALNETWORK HIDL HAL.
+NeuralnetworksHidlTest::~NeuralnetworksHidlTest() {}
+
+void NeuralnetworksHidlTest::SetUp() {
+    device = ::testing::VtsHalHidlTargetTestBase::getService<V1_0::IDevice>(
+        NeuralnetworksHidlEnvironment::getInstance());
+    ASSERT_NE(nullptr, device.get());
+}
+
+void NeuralnetworksHidlTest::TearDown() {}
+
+}  // namespace functional
+}  // namespace vts
+}  // namespace V1_0
+}  // namespace neuralnetworks
+}  // namespace hardware
+}  // namespace android
diff --git a/neuralnetworks/1.0/vts/functional/VtsHalNeuralnetworksV1_0TargetTest.h b/neuralnetworks/1.0/vts/functional/VtsHalNeuralnetworksV1_0.h
similarity index 69%
rename from neuralnetworks/1.0/vts/functional/VtsHalNeuralnetworksV1_0TargetTest.h
rename to neuralnetworks/1.0/vts/functional/VtsHalNeuralnetworksV1_0.h
index 5cd209a..fbb1607 100644
--- a/neuralnetworks/1.0/vts/functional/VtsHalNeuralnetworksV1_0TargetTest.h
+++ b/neuralnetworks/1.0/vts/functional/VtsHalNeuralnetworksV1_0.h
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2017 The Android Open Source Project
+ * Copyright (C) 2018 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.
@@ -29,23 +29,6 @@
 #include <gtest/gtest.h>
 #include <string>
 
-using ::android::hardware::neuralnetworks::V1_0::IDevice;
-using ::android::hardware::neuralnetworks::V1_0::IPreparedModel;
-using ::android::hardware::neuralnetworks::V1_0::Capabilities;
-using ::android::hardware::neuralnetworks::V1_0::DeviceStatus;
-using ::android::hardware::neuralnetworks::V1_0::FusedActivationFunc;
-using ::android::hardware::neuralnetworks::V1_0::Model;
-using ::android::hardware::neuralnetworks::V1_0::OperationType;
-using ::android::hardware::neuralnetworks::V1_0::PerformanceInfo;
-using ::android::hardware::Return;
-using ::android::hardware::Void;
-using ::android::hardware::hidl_memory;
-using ::android::hardware::hidl_string;
-using ::android::hardware::hidl_vec;
-using ::android::hidl::allocator::V1_0::IAllocator;
-using ::android::hidl::memory::V1_0::IMemory;
-using ::android::sp;
-
 namespace android {
 namespace hardware {
 namespace neuralnetworks {
@@ -53,6 +36,8 @@
 namespace vts {
 namespace functional {
 
+hidl_memory allocateSharedMemory(int64_t size);
+
 // A class for test environment setup
 class NeuralnetworksHidlEnvironment : public ::testing::VtsHalHidlTargetTestEnvBase {
     NeuralnetworksHidlEnvironment();
@@ -74,25 +59,22 @@
     void SetUp() override;
     void TearDown() override;
 
-    sp<IPreparedModel> doPrepareModelShortcut();
-
-    sp<IDevice> device;
+    sp<V1_0::IDevice> device;
 };
-
 }  // namespace functional
 }  // namespace vts
 
 // pretty-print values for error messages
 
-template<typename CharT, typename Traits>
+template <typename CharT, typename Traits>
 ::std::basic_ostream<CharT, Traits>& operator<<(::std::basic_ostream<CharT, Traits>& os,
-                                                ErrorStatus errorStatus) {
+                                                V1_0::ErrorStatus errorStatus) {
     return os << toString(errorStatus);
 }
 
-template<typename CharT, typename Traits>
+template <typename CharT, typename Traits>
 ::std::basic_ostream<CharT, Traits>& operator<<(::std::basic_ostream<CharT, Traits>& os,
-                                                DeviceStatus deviceStatus) {
+                                                V1_0::DeviceStatus deviceStatus) {
     return os << toString(deviceStatus);
 }
 
diff --git a/neuralnetworks/1.0/vts/functional/VtsHalNeuralnetworksV1_0TargetTest.cpp b/neuralnetworks/1.0/vts/functional/VtsHalNeuralnetworksV1_0BasicTest.cpp
similarity index 80%
rename from neuralnetworks/1.0/vts/functional/VtsHalNeuralnetworksV1_0TargetTest.cpp
rename to neuralnetworks/1.0/vts/functional/VtsHalNeuralnetworksV1_0BasicTest.cpp
index b99e20e..e838997 100644
--- a/neuralnetworks/1.0/vts/functional/VtsHalNeuralnetworksV1_0TargetTest.cpp
+++ b/neuralnetworks/1.0/vts/functional/VtsHalNeuralnetworksV1_0BasicTest.cpp
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2017 The Android Open Source Project
+ * Copyright (C) 2018 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.
@@ -16,7 +16,7 @@
 
 #define LOG_TAG "neuralnetworks_hidl_hal_test"
 
-#include "VtsHalNeuralnetworksV1_0TargetTest.h"
+#include "VtsHalNeuralnetworksV1_0.h"
 
 #include "Callbacks.h"
 #include "Models.h"
@@ -26,51 +26,34 @@
 #include <android/hidl/memory/1.0/IMemory.h>
 #include <hidlmemory/mapping.h>
 
+using ::android::hardware::neuralnetworks::V1_0::IDevice;
+using ::android::hardware::neuralnetworks::V1_0::IPreparedModel;
+using ::android::hardware::neuralnetworks::V1_0::Capabilities;
+using ::android::hardware::neuralnetworks::V1_0::DeviceStatus;
+using ::android::hardware::neuralnetworks::V1_0::FusedActivationFunc;
+using ::android::hardware::neuralnetworks::V1_0::Model;
+using ::android::hardware::neuralnetworks::V1_0::OperationType;
+using ::android::hardware::neuralnetworks::V1_0::PerformanceInfo;
+using ::android::hardware::Return;
+using ::android::hardware::Void;
+using ::android::hardware::hidl_memory;
+using ::android::hardware::hidl_string;
+using ::android::hardware::hidl_vec;
+using ::android::hidl::allocator::V1_0::IAllocator;
+using ::android::hidl::memory::V1_0::IMemory;
+using ::android::sp;
+
 namespace android {
 namespace hardware {
 namespace neuralnetworks {
 namespace V1_0 {
 namespace vts {
 namespace functional {
-
 using ::android::hardware::neuralnetworks::V1_0::implementation::ExecutionCallback;
 using ::android::hardware::neuralnetworks::V1_0::implementation::PreparedModelCallback;
-using ::generated_tests::MixedTypedExampleType;
 
-namespace generated_tests {
-extern void Execute(const sp<IDevice>&, std::function<Model(void)>, std::function<bool(int)>,
-                    const std::vector<MixedTypedExampleType>&);
-}
-
-// A class for test environment setup
-NeuralnetworksHidlEnvironment::NeuralnetworksHidlEnvironment() {}
-
-NeuralnetworksHidlEnvironment::~NeuralnetworksHidlEnvironment() {}
-
-NeuralnetworksHidlEnvironment* NeuralnetworksHidlEnvironment::getInstance() {
-    // This has to return a "new" object because it is freed inside
-    // ::testing::AddGlobalTestEnvironment when the gtest is being torn down
-    static NeuralnetworksHidlEnvironment* instance = new NeuralnetworksHidlEnvironment();
-    return instance;
-}
-
-void NeuralnetworksHidlEnvironment::registerTestServices() {
-    registerTestService<IDevice>();
-}
-
-// The main test class for NEURALNETWORK HIDL HAL.
-NeuralnetworksHidlTest::~NeuralnetworksHidlTest() {}
-
-void NeuralnetworksHidlTest::SetUp() {
-    device = ::testing::VtsHalHidlTargetTestBase::getService<IDevice>(
-        NeuralnetworksHidlEnvironment::getInstance());
-    ASSERT_NE(nullptr, device.get());
-}
-
-void NeuralnetworksHidlTest::TearDown() {}
-
-sp<IPreparedModel> NeuralnetworksHidlTest::doPrepareModelShortcut() {
-    Model model = createValidTestModel();
+inline sp<IPreparedModel> doPrepareModelShortcut(sp<IDevice>& device) {
+    Model model = createValidTestModel_1_0();
 
     sp<PreparedModelCallback> preparedModelCallback = new PreparedModelCallback();
     if (preparedModelCallback == nullptr) {
@@ -116,7 +99,7 @@
 
 // supported operations positive test
 TEST_F(NeuralnetworksHidlTest, SupportedOperationsPositiveTest) {
-    Model model = createValidTestModel();
+    Model model = createValidTestModel_1_0();
     Return<void> ret = device->getSupportedOperations(
         model, [&](ErrorStatus status, const hidl_vec<bool>& supported) {
             EXPECT_EQ(ErrorStatus::NONE, status);
@@ -127,7 +110,7 @@
 
 // supported operations negative test 1
 TEST_F(NeuralnetworksHidlTest, SupportedOperationsNegativeTest1) {
-    Model model = createInvalidTestModel1();
+    Model model = createInvalidTestModel1_1_0();
     Return<void> ret = device->getSupportedOperations(
         model, [&](ErrorStatus status, const hidl_vec<bool>& supported) {
             EXPECT_EQ(ErrorStatus::INVALID_ARGUMENT, status);
@@ -138,7 +121,7 @@
 
 // supported operations negative test 2
 TEST_F(NeuralnetworksHidlTest, SupportedOperationsNegativeTest2) {
-    Model model = createInvalidTestModel2();
+    Model model = createInvalidTestModel2_1_0();
     Return<void> ret = device->getSupportedOperations(
         model, [&](ErrorStatus status, const hidl_vec<bool>& supported) {
             EXPECT_EQ(ErrorStatus::INVALID_ARGUMENT, status);
@@ -149,7 +132,7 @@
 
 // prepare simple model positive test
 TEST_F(NeuralnetworksHidlTest, SimplePrepareModelPositiveTest) {
-    Model model = createValidTestModel();
+    Model model = createValidTestModel_1_0();
     sp<PreparedModelCallback> preparedModelCallback = new PreparedModelCallback();
     ASSERT_NE(nullptr, preparedModelCallback.get());
     Return<ErrorStatus> prepareLaunchStatus = device->prepareModel(model, preparedModelCallback);
@@ -165,7 +148,7 @@
 
 // prepare simple model negative test 1
 TEST_F(NeuralnetworksHidlTest, SimplePrepareModelNegativeTest1) {
-    Model model = createInvalidTestModel1();
+    Model model = createInvalidTestModel1_1_0();
     sp<PreparedModelCallback> preparedModelCallback = new PreparedModelCallback();
     ASSERT_NE(nullptr, preparedModelCallback.get());
     Return<ErrorStatus> prepareLaunchStatus = device->prepareModel(model, preparedModelCallback);
@@ -181,7 +164,7 @@
 
 // prepare simple model negative test 2
 TEST_F(NeuralnetworksHidlTest, SimplePrepareModelNegativeTest2) {
-    Model model = createInvalidTestModel2();
+    Model model = createInvalidTestModel2_1_0();
     sp<PreparedModelCallback> preparedModelCallback = new PreparedModelCallback();
     ASSERT_NE(nullptr, preparedModelCallback.get());
     Return<ErrorStatus> prepareLaunchStatus = device->prepareModel(model, preparedModelCallback);
@@ -201,7 +184,7 @@
     std::vector<float> expectedData = {6.0f, 8.0f, 10.0f, 12.0f};
     const uint32_t OUTPUT = 1;
 
-    sp<IPreparedModel> preparedModel = doPrepareModelShortcut();
+    sp<IPreparedModel> preparedModel = doPrepareModelShortcut(device);
     ASSERT_NE(nullptr, preparedModel.get());
     Request request = createValidTestRequest();
 
@@ -235,7 +218,7 @@
 
 // execute simple graph negative test 1
 TEST_F(NeuralnetworksHidlTest, SimpleExecuteGraphNegativeTest1) {
-    sp<IPreparedModel> preparedModel = doPrepareModelShortcut();
+    sp<IPreparedModel> preparedModel = doPrepareModelShortcut(device);
     ASSERT_NE(nullptr, preparedModel.get());
     Request request = createInvalidTestRequest1();
 
@@ -252,7 +235,7 @@
 
 // execute simple graph negative test 2
 TEST_F(NeuralnetworksHidlTest, SimpleExecuteGraphNegativeTest2) {
-    sp<IPreparedModel> preparedModel = doPrepareModelShortcut();
+    sp<IPreparedModel> preparedModel = doPrepareModelShortcut(device);
     ASSERT_NE(nullptr, preparedModel.get());
     Request request = createInvalidTestRequest2();
 
@@ -267,16 +250,6 @@
     EXPECT_EQ(ErrorStatus::INVALID_ARGUMENT, executionReturnStatus);
 }
 
-// Mixed-typed examples
-typedef MixedTypedExampleType MixedTypedExample;
-
-// in frameworks/ml/nn/runtime/tests/generated/
-#include "all_generated_vts_tests.cpp"
-
-// TODO: Add tests for execution failure, or wait_for/wait_until timeout.
-//       Discussion:
-//       https://googleplex-android-review.git.corp.google.com/#/c/platform/hardware/interfaces/+/2654636/5/neuralnetworks/1.0/vts/functional/VtsHalNeuralnetworksV1_0TargetTest.cpp@222
-
 }  // namespace functional
 }  // namespace vts
 }  // namespace V1_0
diff --git a/neuralnetworks/1.0/vts/functional/VtsHalNeuralnetworksV1_0GeneratedTest.cpp b/neuralnetworks/1.0/vts/functional/VtsHalNeuralnetworksV1_0GeneratedTest.cpp
new file mode 100644
index 0000000..b99aef7
--- /dev/null
+++ b/neuralnetworks/1.0/vts/functional/VtsHalNeuralnetworksV1_0GeneratedTest.cpp
@@ -0,0 +1,72 @@
+/*
+ * Copyright (C) 2018 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 LOG_TAG "neuralnetworks_hidl_hal_test"
+
+#include "VtsHalNeuralnetworksV1_0.h"
+
+#include "Callbacks.h"
+#include "TestHarness.h"
+
+#include <android-base/logging.h>
+#include <android/hidl/memory/1.0/IMemory.h>
+#include <hidlmemory/mapping.h>
+
+using ::android::hardware::neuralnetworks::V1_0::IDevice;
+using ::android::hardware::neuralnetworks::V1_0::IPreparedModel;
+using ::android::hardware::neuralnetworks::V1_0::Capabilities;
+using ::android::hardware::neuralnetworks::V1_0::DeviceStatus;
+using ::android::hardware::neuralnetworks::V1_0::FusedActivationFunc;
+using ::android::hardware::neuralnetworks::V1_0::Model;
+using ::android::hardware::neuralnetworks::V1_0::OperationType;
+using ::android::hardware::neuralnetworks::V1_0::PerformanceInfo;
+using ::android::hardware::Return;
+using ::android::hardware::Void;
+using ::android::hardware::hidl_memory;
+using ::android::hardware::hidl_string;
+using ::android::hardware::hidl_vec;
+using ::android::hidl::allocator::V1_0::IAllocator;
+using ::android::hidl::memory::V1_0::IMemory;
+using ::android::sp;
+
+namespace android {
+namespace hardware {
+namespace neuralnetworks {
+
+namespace generated_tests {
+using ::generated_tests::MixedTypedExampleType;
+extern void Execute(sp<IDevice>&, std::function<Model(void)>, std::function<bool(int)>,
+                    const std::vector<MixedTypedExampleType>&);
+}  // namespace generated_tests
+
+namespace V1_0 {
+namespace vts {
+namespace functional {
+using ::android::hardware::neuralnetworks::V1_0::implementation::ExecutionCallback;
+using ::android::hardware::neuralnetworks::V1_0::implementation::PreparedModelCallback;
+
+// Mixed-typed examples
+typedef generated_tests::MixedTypedExampleType MixedTypedExample;
+
+// in frameworks/ml/nn/runtime/tests/generated/
+#include "all_generated_V1_0_vts_tests.cpp"
+
+}  // namespace functional
+}  // namespace vts
+}  // namespace V1_0
+}  // namespace neuralnetworks
+}  // namespace hardware
+}  // namespace android
diff --git a/neuralnetworks/1.1/types.hal b/neuralnetworks/1.1/types.hal
index 18863d3..fae5dd0 100644
--- a/neuralnetworks/1.1/types.hal
+++ b/neuralnetworks/1.1/types.hal
@@ -330,4 +330,12 @@
      * equals OperandLifeTime::CONSTANT_REFERENCE.
      */
     vec<memory> pools;
+
+    /**
+     * 'true' indicates TENSOR_FLOAT32 may be calculated with range and/or
+     * precision as low as that of the IEEE 754 16-bit floating-point format.
+     * 'false' indicates TENSOR_FLOAT32 must be calculated using at least the
+     * range and precision of the IEEE 754 32-bit floating-point format.
+     */
+    bool relaxComputationFloat32toFloat16;
 };
diff --git a/neuralnetworks/1.1/vts/OWNERS b/neuralnetworks/1.1/vts/OWNERS
new file mode 100644
index 0000000..7f75ab3
--- /dev/null
+++ b/neuralnetworks/1.1/vts/OWNERS
@@ -0,0 +1,10 @@
+# Neuralnetworks team
+butlermichael@google.com
+dgross@google.com
+jeanluc@google.com
+miaowang@google.com
+yangni@google.com
+
+# VTS team
+yim@google.com
+yuexima@google.com
diff --git a/neuralnetworks/1.1/vts/functional/Android.bp b/neuralnetworks/1.1/vts/functional/Android.bp
new file mode 100644
index 0000000..623b441
--- /dev/null
+++ b/neuralnetworks/1.1/vts/functional/Android.bp
@@ -0,0 +1,39 @@
+//
+// Copyright (C) 2018 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.
+//
+
+cc_test {
+    name: "VtsHalNeuralnetworksV1_1TargetTest",
+    srcs: [
+        "VtsHalNeuralnetworksV1_1.cpp",
+        "VtsHalNeuralnetworksV1_1BasicTest.cpp",
+        "VtsHalNeuralnetworksV1_1GeneratedTest.cpp",
+    ],
+    defaults: ["VtsHalTargetTestDefaults"],
+    static_libs: [
+        "android.hardware.neuralnetworks@1.0",
+        "android.hardware.neuralnetworks@1.1",
+        "android.hidl.allocator@1.0",
+        "android.hidl.memory@1.0",
+        "libhidlmemory",
+        "libneuralnetworks_utils",
+        "VtsHalNeuralnetworksTest_utils",
+    ],
+    header_libs: [
+        "libneuralnetworks_headers",
+        "libneuralnetworks_generated_test_harness_headers",
+        "libneuralnetworks_generated_tests",
+    ],
+}
diff --git a/neuralnetworks/1.1/vts/functional/VtsHalNeuralnetworksV1_1.cpp b/neuralnetworks/1.1/vts/functional/VtsHalNeuralnetworksV1_1.cpp
new file mode 100644
index 0000000..b1d3be7
--- /dev/null
+++ b/neuralnetworks/1.1/vts/functional/VtsHalNeuralnetworksV1_1.cpp
@@ -0,0 +1,74 @@
+/*
+ * Copyright (C) 2018 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 LOG_TAG "neuralnetworks_hidl_hal_test"
+
+#include "VtsHalNeuralnetworksV1_1.h"
+#include "Utils.h"
+
+#include <android-base/logging.h>
+#include <hidlmemory/mapping.h>
+
+using ::android::hardware::hidl_memory;
+using ::android::hidl::allocator::V1_0::IAllocator;
+using ::android::hidl::memory::V1_0::IMemory;
+using ::android::sp;
+
+namespace android {
+namespace hardware {
+namespace neuralnetworks {
+namespace V1_1 {
+namespace vts {
+namespace functional {
+
+// allocator helper
+hidl_memory allocateSharedMemory(int64_t size) {
+    return nn::allocateSharedMemory(size);
+}
+
+// A class for test environment setup
+NeuralnetworksHidlEnvironment::NeuralnetworksHidlEnvironment() {}
+
+NeuralnetworksHidlEnvironment::~NeuralnetworksHidlEnvironment() {}
+
+NeuralnetworksHidlEnvironment* NeuralnetworksHidlEnvironment::getInstance() {
+    // This has to return a "new" object because it is freed inside
+    // ::testing::AddGlobalTestEnvironment when the gtest is being torn down
+    static NeuralnetworksHidlEnvironment* instance = new NeuralnetworksHidlEnvironment();
+    return instance;
+}
+
+void NeuralnetworksHidlEnvironment::registerTestServices() {
+    registerTestService<V1_1::IDevice>();
+}
+
+// The main test class for NEURALNETWORK HIDL HAL.
+NeuralnetworksHidlTest::~NeuralnetworksHidlTest() {}
+
+void NeuralnetworksHidlTest::SetUp() {
+    device = ::testing::VtsHalHidlTargetTestBase::getService<V1_1::IDevice>(
+        NeuralnetworksHidlEnvironment::getInstance());
+    ASSERT_NE(nullptr, device.get());
+}
+
+void NeuralnetworksHidlTest::TearDown() {}
+
+}  // namespace functional
+}  // namespace vts
+}  // namespace V1_1
+}  // namespace neuralnetworks
+}  // namespace hardware
+}  // namespace android
diff --git a/neuralnetworks/1.0/vts/functional/VtsHalNeuralnetworksV1_0TargetTest.h b/neuralnetworks/1.1/vts/functional/VtsHalNeuralnetworksV1_1.h
similarity index 61%
copy from neuralnetworks/1.0/vts/functional/VtsHalNeuralnetworksV1_0TargetTest.h
copy to neuralnetworks/1.1/vts/functional/VtsHalNeuralnetworksV1_1.h
index 5cd209a..426246c 100644
--- a/neuralnetworks/1.0/vts/functional/VtsHalNeuralnetworksV1_0TargetTest.h
+++ b/neuralnetworks/1.1/vts/functional/VtsHalNeuralnetworksV1_1.h
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2017 The Android Open Source Project
+ * Copyright (C) 2018 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.
@@ -14,14 +14,14 @@
  * limitations under the License.
  */
 
-#ifndef VTS_HAL_NEURALNETWORKS_V1_0_TARGET_TESTS_H
-#define VTS_HAL_NEURALNETWORKS_V1_0_TARGET_TESTS_H
+#ifndef VTS_HAL_NEURALNETWORKS_V1_1_H
+#define VTS_HAL_NEURALNETWORKS_V1_1_H
 
-#include <android/hardware/neuralnetworks/1.0/IDevice.h>
 #include <android/hardware/neuralnetworks/1.0/IExecutionCallback.h>
 #include <android/hardware/neuralnetworks/1.0/IPreparedModel.h>
 #include <android/hardware/neuralnetworks/1.0/IPreparedModelCallback.h>
-#include <android/hardware/neuralnetworks/1.0/types.h>
+#include <android/hardware/neuralnetworks/1.1/IDevice.h>
+#include <android/hardware/neuralnetworks/1.1/types.h>
 #include <android/hidl/allocator/1.0/IAllocator.h>
 
 #include <VtsHalHidlTargetTestBase.h>
@@ -29,29 +29,13 @@
 #include <gtest/gtest.h>
 #include <string>
 
-using ::android::hardware::neuralnetworks::V1_0::IDevice;
-using ::android::hardware::neuralnetworks::V1_0::IPreparedModel;
-using ::android::hardware::neuralnetworks::V1_0::Capabilities;
-using ::android::hardware::neuralnetworks::V1_0::DeviceStatus;
-using ::android::hardware::neuralnetworks::V1_0::FusedActivationFunc;
-using ::android::hardware::neuralnetworks::V1_0::Model;
-using ::android::hardware::neuralnetworks::V1_0::OperationType;
-using ::android::hardware::neuralnetworks::V1_0::PerformanceInfo;
-using ::android::hardware::Return;
-using ::android::hardware::Void;
-using ::android::hardware::hidl_memory;
-using ::android::hardware::hidl_string;
-using ::android::hardware::hidl_vec;
-using ::android::hidl::allocator::V1_0::IAllocator;
-using ::android::hidl::memory::V1_0::IMemory;
-using ::android::sp;
-
 namespace android {
 namespace hardware {
 namespace neuralnetworks {
-namespace V1_0 {
+namespace V1_1 {
 namespace vts {
 namespace functional {
+hidl_memory allocateSharedMemory(int64_t size);
 
 // A class for test environment setup
 class NeuralnetworksHidlEnvironment : public ::testing::VtsHalHidlTargetTestEnvBase {
@@ -74,31 +58,28 @@
     void SetUp() override;
     void TearDown() override;
 
-    sp<IPreparedModel> doPrepareModelShortcut();
-
-    sp<IDevice> device;
+    sp<V1_1::IDevice> device;
 };
-
 }  // namespace functional
 }  // namespace vts
 
 // pretty-print values for error messages
 
-template<typename CharT, typename Traits>
+template <typename CharT, typename Traits>
 ::std::basic_ostream<CharT, Traits>& operator<<(::std::basic_ostream<CharT, Traits>& os,
-                                                ErrorStatus errorStatus) {
+                                                V1_0::ErrorStatus errorStatus) {
     return os << toString(errorStatus);
 }
 
-template<typename CharT, typename Traits>
+template <typename CharT, typename Traits>
 ::std::basic_ostream<CharT, Traits>& operator<<(::std::basic_ostream<CharT, Traits>& os,
-                                                DeviceStatus deviceStatus) {
+                                                V1_0::DeviceStatus deviceStatus) {
     return os << toString(deviceStatus);
 }
 
-}  // namespace V1_0
+}  // namespace V1_1
 }  // namespace neuralnetworks
 }  // namespace hardware
 }  // namespace android
 
-#endif  // VTS_HAL_NEURALNETWORKS_V1_0_TARGET_TESTS_H
+#endif  // VTS_HAL_NEURALNETWORKS_V1_1_H
diff --git a/neuralnetworks/1.0/vts/functional/VtsHalNeuralnetworksV1_0TargetTest.cpp b/neuralnetworks/1.1/vts/functional/VtsHalNeuralnetworksV1_1BasicTest.cpp
similarity index 74%
copy from neuralnetworks/1.0/vts/functional/VtsHalNeuralnetworksV1_0TargetTest.cpp
copy to neuralnetworks/1.1/vts/functional/VtsHalNeuralnetworksV1_1BasicTest.cpp
index b99e20e..51eff2a 100644
--- a/neuralnetworks/1.0/vts/functional/VtsHalNeuralnetworksV1_0TargetTest.cpp
+++ b/neuralnetworks/1.1/vts/functional/VtsHalNeuralnetworksV1_1BasicTest.cpp
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2017 The Android Open Source Project
+ * Copyright (C) 2018 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.
@@ -16,67 +16,58 @@
 
 #define LOG_TAG "neuralnetworks_hidl_hal_test"
 
-#include "VtsHalNeuralnetworksV1_0TargetTest.h"
+#include "VtsHalNeuralnetworksV1_1.h"
 
 #include "Callbacks.h"
 #include "Models.h"
 #include "TestHarness.h"
 
 #include <android-base/logging.h>
+#include <android/hardware/neuralnetworks/1.1/IDevice.h>
+#include <android/hardware/neuralnetworks/1.1/types.h>
 #include <android/hidl/memory/1.0/IMemory.h>
 #include <hidlmemory/mapping.h>
 
+using ::android::hardware::neuralnetworks::V1_0::IPreparedModel;
+using ::android::hardware::neuralnetworks::V1_0::Capabilities;
+using ::android::hardware::neuralnetworks::V1_0::DeviceStatus;
+using ::android::hardware::neuralnetworks::V1_0::ErrorStatus;
+using ::android::hardware::neuralnetworks::V1_0::FusedActivationFunc;
+using ::android::hardware::neuralnetworks::V1_0::Operand;
+using ::android::hardware::neuralnetworks::V1_0::OperandLifeTime;
+using ::android::hardware::neuralnetworks::V1_0::OperandType;
+using ::android::hardware::neuralnetworks::V1_0::Request;
+using ::android::hardware::neuralnetworks::V1_1::IDevice;
+using ::android::hardware::neuralnetworks::V1_1::Model;
+using ::android::hardware::neuralnetworks::V1_1::Operation;
+using ::android::hardware::neuralnetworks::V1_1::OperationType;
+using ::android::hardware::Return;
+using ::android::hardware::Void;
+using ::android::hardware::hidl_memory;
+using ::android::hardware::hidl_string;
+using ::android::hardware::hidl_vec;
+using ::android::hidl::allocator::V1_0::IAllocator;
+using ::android::hidl::memory::V1_0::IMemory;
+using ::android::sp;
+
 namespace android {
 namespace hardware {
 namespace neuralnetworks {
-namespace V1_0 {
+namespace V1_1 {
 namespace vts {
 namespace functional {
-
 using ::android::hardware::neuralnetworks::V1_0::implementation::ExecutionCallback;
 using ::android::hardware::neuralnetworks::V1_0::implementation::PreparedModelCallback;
-using ::generated_tests::MixedTypedExampleType;
 
-namespace generated_tests {
-extern void Execute(const sp<IDevice>&, std::function<Model(void)>, std::function<bool(int)>,
-                    const std::vector<MixedTypedExampleType>&);
-}
-
-// A class for test environment setup
-NeuralnetworksHidlEnvironment::NeuralnetworksHidlEnvironment() {}
-
-NeuralnetworksHidlEnvironment::~NeuralnetworksHidlEnvironment() {}
-
-NeuralnetworksHidlEnvironment* NeuralnetworksHidlEnvironment::getInstance() {
-    // This has to return a "new" object because it is freed inside
-    // ::testing::AddGlobalTestEnvironment when the gtest is being torn down
-    static NeuralnetworksHidlEnvironment* instance = new NeuralnetworksHidlEnvironment();
-    return instance;
-}
-
-void NeuralnetworksHidlEnvironment::registerTestServices() {
-    registerTestService<IDevice>();
-}
-
-// The main test class for NEURALNETWORK HIDL HAL.
-NeuralnetworksHidlTest::~NeuralnetworksHidlTest() {}
-
-void NeuralnetworksHidlTest::SetUp() {
-    device = ::testing::VtsHalHidlTargetTestBase::getService<IDevice>(
-        NeuralnetworksHidlEnvironment::getInstance());
-    ASSERT_NE(nullptr, device.get());
-}
-
-void NeuralnetworksHidlTest::TearDown() {}
-
-sp<IPreparedModel> NeuralnetworksHidlTest::doPrepareModelShortcut() {
-    Model model = createValidTestModel();
+inline sp<IPreparedModel> doPrepareModelShortcut(sp<IDevice>& device) {
+    Model model = createValidTestModel_1_1();
 
     sp<PreparedModelCallback> preparedModelCallback = new PreparedModelCallback();
     if (preparedModelCallback == nullptr) {
         return nullptr;
     }
-    Return<ErrorStatus> prepareLaunchStatus = device->prepareModel(model, preparedModelCallback);
+    Return<ErrorStatus> prepareLaunchStatus =
+        device->prepareModel_1_1(model, preparedModelCallback);
     if (!prepareLaunchStatus.isOk() || prepareLaunchStatus != ErrorStatus::NONE) {
         return nullptr;
     }
@@ -116,8 +107,8 @@
 
 // supported operations positive test
 TEST_F(NeuralnetworksHidlTest, SupportedOperationsPositiveTest) {
-    Model model = createValidTestModel();
-    Return<void> ret = device->getSupportedOperations(
+    Model model = createValidTestModel_1_1();
+    Return<void> ret = device->getSupportedOperations_1_1(
         model, [&](ErrorStatus status, const hidl_vec<bool>& supported) {
             EXPECT_EQ(ErrorStatus::NONE, status);
             EXPECT_EQ(model.operations.size(), supported.size());
@@ -127,8 +118,8 @@
 
 // supported operations negative test 1
 TEST_F(NeuralnetworksHidlTest, SupportedOperationsNegativeTest1) {
-    Model model = createInvalidTestModel1();
-    Return<void> ret = device->getSupportedOperations(
+    Model model = createInvalidTestModel1_1_1();
+    Return<void> ret = device->getSupportedOperations_1_1(
         model, [&](ErrorStatus status, const hidl_vec<bool>& supported) {
             EXPECT_EQ(ErrorStatus::INVALID_ARGUMENT, status);
             (void)supported;
@@ -138,8 +129,8 @@
 
 // supported operations negative test 2
 TEST_F(NeuralnetworksHidlTest, SupportedOperationsNegativeTest2) {
-    Model model = createInvalidTestModel2();
-    Return<void> ret = device->getSupportedOperations(
+    Model model = createInvalidTestModel2_1_1();
+    Return<void> ret = device->getSupportedOperations_1_1(
         model, [&](ErrorStatus status, const hidl_vec<bool>& supported) {
             EXPECT_EQ(ErrorStatus::INVALID_ARGUMENT, status);
             (void)supported;
@@ -149,10 +140,11 @@
 
 // prepare simple model positive test
 TEST_F(NeuralnetworksHidlTest, SimplePrepareModelPositiveTest) {
-    Model model = createValidTestModel();
+    Model model = createValidTestModel_1_1();
     sp<PreparedModelCallback> preparedModelCallback = new PreparedModelCallback();
     ASSERT_NE(nullptr, preparedModelCallback.get());
-    Return<ErrorStatus> prepareLaunchStatus = device->prepareModel(model, preparedModelCallback);
+    Return<ErrorStatus> prepareLaunchStatus =
+        device->prepareModel_1_1(model, preparedModelCallback);
     ASSERT_TRUE(prepareLaunchStatus.isOk());
     EXPECT_EQ(ErrorStatus::NONE, static_cast<ErrorStatus>(prepareLaunchStatus));
 
@@ -165,10 +157,11 @@
 
 // prepare simple model negative test 1
 TEST_F(NeuralnetworksHidlTest, SimplePrepareModelNegativeTest1) {
-    Model model = createInvalidTestModel1();
+    Model model = createInvalidTestModel1_1_1();
     sp<PreparedModelCallback> preparedModelCallback = new PreparedModelCallback();
     ASSERT_NE(nullptr, preparedModelCallback.get());
-    Return<ErrorStatus> prepareLaunchStatus = device->prepareModel(model, preparedModelCallback);
+    Return<ErrorStatus> prepareLaunchStatus =
+        device->prepareModel_1_1(model, preparedModelCallback);
     ASSERT_TRUE(prepareLaunchStatus.isOk());
     EXPECT_EQ(ErrorStatus::INVALID_ARGUMENT, static_cast<ErrorStatus>(prepareLaunchStatus));
 
@@ -181,10 +174,11 @@
 
 // prepare simple model negative test 2
 TEST_F(NeuralnetworksHidlTest, SimplePrepareModelNegativeTest2) {
-    Model model = createInvalidTestModel2();
+    Model model = createInvalidTestModel2_1_1();
     sp<PreparedModelCallback> preparedModelCallback = new PreparedModelCallback();
     ASSERT_NE(nullptr, preparedModelCallback.get());
-    Return<ErrorStatus> prepareLaunchStatus = device->prepareModel(model, preparedModelCallback);
+    Return<ErrorStatus> prepareLaunchStatus =
+        device->prepareModel_1_1(model, preparedModelCallback);
     ASSERT_TRUE(prepareLaunchStatus.isOk());
     EXPECT_EQ(ErrorStatus::INVALID_ARGUMENT, static_cast<ErrorStatus>(prepareLaunchStatus));
 
@@ -201,7 +195,7 @@
     std::vector<float> expectedData = {6.0f, 8.0f, 10.0f, 12.0f};
     const uint32_t OUTPUT = 1;
 
-    sp<IPreparedModel> preparedModel = doPrepareModelShortcut();
+    sp<IPreparedModel> preparedModel = doPrepareModelShortcut(device);
     ASSERT_NE(nullptr, preparedModel.get());
     Request request = createValidTestRequest();
 
@@ -235,7 +229,7 @@
 
 // execute simple graph negative test 1
 TEST_F(NeuralnetworksHidlTest, SimpleExecuteGraphNegativeTest1) {
-    sp<IPreparedModel> preparedModel = doPrepareModelShortcut();
+    sp<IPreparedModel> preparedModel = doPrepareModelShortcut(device);
     ASSERT_NE(nullptr, preparedModel.get());
     Request request = createInvalidTestRequest1();
 
@@ -252,7 +246,7 @@
 
 // execute simple graph negative test 2
 TEST_F(NeuralnetworksHidlTest, SimpleExecuteGraphNegativeTest2) {
-    sp<IPreparedModel> preparedModel = doPrepareModelShortcut();
+    sp<IPreparedModel> preparedModel = doPrepareModelShortcut(device);
     ASSERT_NE(nullptr, preparedModel.get());
     Request request = createInvalidTestRequest2();
 
@@ -267,24 +261,14 @@
     EXPECT_EQ(ErrorStatus::INVALID_ARGUMENT, executionReturnStatus);
 }
 
-// Mixed-typed examples
-typedef MixedTypedExampleType MixedTypedExample;
-
-// in frameworks/ml/nn/runtime/tests/generated/
-#include "all_generated_vts_tests.cpp"
-
-// TODO: Add tests for execution failure, or wait_for/wait_until timeout.
-//       Discussion:
-//       https://googleplex-android-review.git.corp.google.com/#/c/platform/hardware/interfaces/+/2654636/5/neuralnetworks/1.0/vts/functional/VtsHalNeuralnetworksV1_0TargetTest.cpp@222
-
 }  // namespace functional
 }  // namespace vts
-}  // namespace V1_0
+}  // namespace V1_1
 }  // namespace neuralnetworks
 }  // namespace hardware
 }  // namespace android
 
-using android::hardware::neuralnetworks::V1_0::vts::functional::NeuralnetworksHidlEnvironment;
+using android::hardware::neuralnetworks::V1_1::vts::functional::NeuralnetworksHidlEnvironment;
 
 int main(int argc, char** argv) {
     ::testing::AddGlobalTestEnvironment(NeuralnetworksHidlEnvironment::getInstance());
diff --git a/neuralnetworks/1.1/vts/functional/VtsHalNeuralnetworksV1_1GeneratedTest.cpp b/neuralnetworks/1.1/vts/functional/VtsHalNeuralnetworksV1_1GeneratedTest.cpp
new file mode 100644
index 0000000..025d9fe
--- /dev/null
+++ b/neuralnetworks/1.1/vts/functional/VtsHalNeuralnetworksV1_1GeneratedTest.cpp
@@ -0,0 +1,80 @@
+/*
+ * Copyright (C) 2018 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 LOG_TAG "neuralnetworks_hidl_hal_test"
+
+#include "VtsHalNeuralnetworksV1_1.h"
+
+#include "Callbacks.h"
+#include "TestHarness.h"
+
+#include <android-base/logging.h>
+#include <android/hardware/neuralnetworks/1.1/IDevice.h>
+#include <android/hardware/neuralnetworks/1.1/types.h>
+#include <android/hidl/memory/1.0/IMemory.h>
+#include <hidlmemory/mapping.h>
+
+using ::android::hardware::neuralnetworks::V1_0::IPreparedModel;
+using ::android::hardware::neuralnetworks::V1_0::Capabilities;
+using ::android::hardware::neuralnetworks::V1_0::DeviceStatus;
+using ::android::hardware::neuralnetworks::V1_0::ErrorStatus;
+using ::android::hardware::neuralnetworks::V1_0::FusedActivationFunc;
+using ::android::hardware::neuralnetworks::V1_0::Operand;
+using ::android::hardware::neuralnetworks::V1_0::OperandLifeTime;
+using ::android::hardware::neuralnetworks::V1_0::OperandType;
+using ::android::hardware::neuralnetworks::V1_0::Request;
+using ::android::hardware::neuralnetworks::V1_1::IDevice;
+using ::android::hardware::neuralnetworks::V1_1::Model;
+using ::android::hardware::neuralnetworks::V1_1::Operation;
+using ::android::hardware::neuralnetworks::V1_1::OperationType;
+using ::android::hardware::Return;
+using ::android::hardware::Void;
+using ::android::hardware::hidl_memory;
+using ::android::hardware::hidl_string;
+using ::android::hardware::hidl_vec;
+using ::android::hidl::allocator::V1_0::IAllocator;
+using ::android::hidl::memory::V1_0::IMemory;
+using ::android::sp;
+
+namespace android {
+namespace hardware {
+namespace neuralnetworks {
+
+namespace generated_tests {
+using ::generated_tests::MixedTypedExampleType;
+extern void Execute(sp<V1_1::IDevice>&, std::function<Model(void)>, std::function<bool(int)>,
+                    const std::vector<MixedTypedExampleType>&);
+}  // namespace generated_tests
+
+namespace V1_1 {
+namespace vts {
+namespace functional {
+using ::android::hardware::neuralnetworks::V1_0::implementation::ExecutionCallback;
+using ::android::hardware::neuralnetworks::V1_0::implementation::PreparedModelCallback;
+
+// Mixed-typed examples
+typedef generated_tests::MixedTypedExampleType MixedTypedExample;
+
+// in frameworks/ml/nn/runtime/tests/generated/
+#include "all_generated_V1_0_vts_tests.cpp"
+#include "all_generated_V1_1_vts_tests.cpp"
+
+}  // namespace functional
+}  // namespace vts
+}  // namespace V1_1
+}  // namespace neuralnetworks
+}  // namespace hardware
+}  // namespace android
diff --git a/nfc/1.0/vts/functional/VtsHalNfcV1_0TargetTest.cpp b/nfc/1.0/vts/functional/VtsHalNfcV1_0TargetTest.cpp
index 2f00fbb..e17c961 100644
--- a/nfc/1.0/vts/functional/VtsHalNfcV1_0TargetTest.cpp
+++ b/nfc/1.0/vts/functional/VtsHalNfcV1_0TargetTest.cpp
@@ -24,6 +24,7 @@
 
 #include <VtsHalHidlTargetCallbackBase.h>
 #include <VtsHalHidlTargetTestBase.h>
+#include <VtsHalHidlTargetTestEnvBase.h>
 
 using ::android::hardware::nfc::V1_0::INfc;
 using ::android::hardware::nfc::V1_0::INfcClientCallback;
@@ -93,11 +94,26 @@
     };
 };
 
+// Test environment for Nfc HIDL HAL.
+class NfcHidlEnvironment : public ::testing::VtsHalHidlTargetTestEnvBase {
+ public:
+  // get the test environment singleton
+  static NfcHidlEnvironment* Instance() {
+    static NfcHidlEnvironment* instance = new NfcHidlEnvironment;
+    return instance;
+  }
+
+  virtual void registerTestServices() override { registerTestService<INfc>(); }
+ private:
+  NfcHidlEnvironment() {}
+};
+
 // The main test class for NFC HIDL HAL.
 class NfcHidlTest : public ::testing::VtsHalHidlTargetTestBase {
  public:
   virtual void SetUp() override {
-    nfc_ = ::testing::VtsHalHidlTargetTestBase::getService<INfc>();
+    nfc_ = ::testing::VtsHalHidlTargetTestBase::getService<INfc>(
+        NfcHidlEnvironment::Instance()->getServiceName<INfc>());
     ASSERT_NE(nfc_, nullptr);
 
     nfc_cb_ = new NfcClientCallback();
@@ -163,15 +179,6 @@
   sp<NfcClientCallback> nfc_cb_;
 };
 
-// A class for test environment setup (kept since this file is a template).
-class NfcHidlEnvironment : public ::testing::Environment {
- public:
-  virtual void SetUp() {}
-  virtual void TearDown() {}
-
- private:
-};
-
 /*
  * OpenAndClose:
  * Makes an open call, waits for NfcEvent.OPEN_CPLT
@@ -586,8 +593,9 @@
 }
 
 int main(int argc, char** argv) {
-  ::testing::AddGlobalTestEnvironment(new NfcHidlEnvironment);
+  ::testing::AddGlobalTestEnvironment(NfcHidlEnvironment::Instance());
   ::testing::InitGoogleTest(&argc, argv);
+  NfcHidlEnvironment::Instance()->init(&argc, argv);
 
   std::system("svc nfc disable"); /* Turn off NFC */
   sleep(5);
diff --git a/nfc/1.1/vts/functional/VtsHalNfcV1_1TargetTest.cpp b/nfc/1.1/vts/functional/VtsHalNfcV1_1TargetTest.cpp
index a5b40d4..bef412b 100644
--- a/nfc/1.1/vts/functional/VtsHalNfcV1_1TargetTest.cpp
+++ b/nfc/1.1/vts/functional/VtsHalNfcV1_1TargetTest.cpp
@@ -25,6 +25,7 @@
 
 #include <VtsHalHidlTargetCallbackBase.h>
 #include <VtsHalHidlTargetTestBase.h>
+#include <VtsHalHidlTargetTestEnvBase.h>
 
 using ::android::hardware::nfc::V1_1::INfc;
 using ::android::hardware::nfc::V1_1::INfcClientCallback;
@@ -78,6 +79,20 @@
     };
 };
 
+// Test environment for Nfc HIDL HAL.
+class NfcHidlEnvironment : public ::testing::VtsHalHidlTargetTestEnvBase {
+   public:
+    // get the test environment singleton
+    static NfcHidlEnvironment* Instance() {
+        static NfcHidlEnvironment* instance = new NfcHidlEnvironment;
+        return instance;
+    }
+
+    virtual void registerTestServices() override { registerTestService<INfc>(); }
+   private:
+    NfcHidlEnvironment() {}
+};
+
 // The main test class for NFC HIDL HAL.
 class NfcHidlTest : public ::testing::VtsHalHidlTargetTestBase {
    public:
@@ -127,15 +142,6 @@
     sp<NfcClientCallback> nfc_cb_;
 };
 
-// A class for test environment setup (kept since this file is a template).
-class NfcHidlEnvironment : public ::testing::Environment {
-   public:
-    virtual void SetUp() {}
-    virtual void TearDown() {}
-
-   private:
-};
-
 /*
  * factoryReset
  * calls factoryReset()
@@ -204,8 +210,9 @@
 }
 
 int main(int argc, char** argv) {
-    ::testing::AddGlobalTestEnvironment(new NfcHidlEnvironment);
+    ::testing::AddGlobalTestEnvironment(NfcHidlEnvironment::Instance());
     ::testing::InitGoogleTest(&argc, argv);
+    NfcHidlEnvironment::Instance()->init(&argc, argv);
 
     std::system("svc nfc disable"); /* Turn off NFC */
     sleep(5);
diff --git a/radio/1.0/types.hal b/radio/1.0/types.hal
index 4d22bc0..6787a82 100644
--- a/radio/1.0/types.hal
+++ b/radio/1.0/types.hal
@@ -1292,10 +1292,9 @@
                                           // from cell to device.
                                           // Approximate distance is calculated using
                                           // 300m/us * timingAdvance.
-                                          // Range: 0 to 0x7FFFFFFE
-                                          // INT_MAX : 0x7FFFFFFF denotes invalid value.
-                                          // Reference: 3GPP 36.321 section 6.1.3.5
-                                          // also: http://www.cellular-planningoptimization.com/2010/02/timing-advance-with-calculation.html
+                                          // Range: 0 to 1282 inclusive.
+                                          // INT_MAX : 0x7FFFFFFF denotes unknown value.
+                                          // Reference: 3GPP 36.213 section 4.2.3
 };
 
 struct TdScdmaSignalStrength {
diff --git a/radio/1.2/Android.bp b/radio/1.2/Android.bp
index 48ac5a1..a9c80b7 100644
--- a/radio/1.2/Android.bp
+++ b/radio/1.2/Android.bp
@@ -28,11 +28,13 @@
         "CellIdentityGsm",
         "CellIdentityLte",
         "CellIdentityOperatorNames",
+        "CellIdentityTdscdma",
         "CellIdentityWcdma",
         "CellInfo",
         "CellInfoCdma",
         "CellInfoGsm",
         "CellInfoLte",
+        "CellInfoTdscdma",
         "CellInfoWcdma",
         "DataRequestReason",
         "IncrementalResultsPeriodicityRange",
@@ -44,6 +46,9 @@
         "PhysicalChannelConfig",
         "RadioConst",
         "ScanIntervalRange",
+        "SignalStrength",
+        "TdscdmaSignalStrength",
+        "WcdmaSignalStrength",
     ],
     gen_java: true,
 }
diff --git a/radio/1.2/IRadio.hal b/radio/1.2/IRadio.hal
index 67ce56c..6463b0f 100644
--- a/radio/1.2/IRadio.hal
+++ b/radio/1.2/IRadio.hal
@@ -50,7 +50,7 @@
      *
      * @param serial Serial number of request.
      * @param indicationFilter 32-bit bitmap of IndicationFilter. Bits set to 1 indicate the
-     *        indications are enabled. See @1.2::IndicationFilter for the definition of each bit.
+     *     indications are enabled. See @1.2::IndicationFilter for the definition of each bit.
      *
      * Response callback is IRadioResponse.setIndicationFilterResponse()
      */
@@ -68,16 +68,16 @@
      *
      * @param serial Serial number of request.
      * @param hysteresisMs A hysteresis time in milliseconds to prevent flapping. A value of 0
-     *                     disables hysteresis.
+     *     disables hysteresis.
      * @param hysteresisDb An interval in dB defining the required magnitude change between reports.
-     *                     hysteresisDb must be smaller than the smallest threshold delta. An
-     *                     interval value of 0 disables hysteresis.
+     *     hysteresisDb must be smaller than the smallest threshold delta. An
+     *     interval value of 0 disables hysteresis.
      * @param thresholdsDbm A vector of trigger thresholds in dBm. A vector size of 0 disables the
-     *                      use of thresholds for reporting.
-     * @param ran The type of network for which to apply these thresholds.
+     *     use of thresholds for reporting.
+     * @param accessNetwork The type of network for which to apply these thresholds.
      */
     oneway setSignalStrengthReportingCriteria(int32_t serial, int32_t hysteresisMs,
-            int32_t hysteresisDb, vec<int32_t> thresholdsDbm, RadioAccessNetworks ran);
+            int32_t hysteresisDb, vec<int32_t> thresholdsDbm, AccessNetwork accessNetwork);
 
     /**
      * Sets the link capacity reporting criteria.
@@ -91,23 +91,22 @@
      *
      * @param serial Serial number of request.
      * @param hysteresisMs A hysteresis time in milliseconds to prevent flapping. A value of 0
-     *                     disables hysteresis.
+     *     disables hysteresis.
      * @param hysteresisDlKbps An interval in kbps defining the required magnitude change between DL
-     *                         reports. hysteresisDlKbps must be smaller than the smallest threshold
-     *                         delta. A value of 0 disables hysteresis.
+     *     reports. hysteresisDlKbps must be smaller than the smallest threshold delta. A value of 0
+     *     disables hysteresis.
      * @param hysteresisUlKbps An interval in kbps defining the required magnitude change between UL
-     *                         reports. hysteresisUlKbps must be smaller than the smallest threshold
-     *                         delta. A value of 0 disables hysteresis.
+     *     reports. hysteresisUlKbps must be smaller than the smallest threshold delta. A value of 0
+     *     disables hysteresis.
      * @param thresholdsDownlinkKbps A vector of trigger thresholds in kbps for downlink reports. A
-     *                               vector size of 0 disables the use of DL thresholds for
-     *                               reporting.
+     *     vector size of 0 disables the use of DL thresholds for reporting.
      * @param thresholdsUplinkKbps A vector of trigger thresholds in kbps for uplink reports. A
-     *                             vector size of 0 disables the use of UL thresholds for reporting.
-     * @param ran The type of network for which to apply these thresholds.
+     *     vector size of 0 disables the use of UL thresholds for reporting.
+     * @param accessNetwork The type of network for which to apply these thresholds.
      */
     oneway setLinkCapacityReportingCriteria(int32_t serial, int32_t hysteresisMs,
             int32_t hysteresisDlKbps, int32_t hysteresisUlKbps, vec<int32_t> thresholdsDownlinkKbps,
-            vec<int32_t> thresholdsUplinkKbps, RadioAccessNetworks ran);
+            vec<int32_t> thresholdsUplinkKbps, AccessNetwork accessNetwork);
 
     /**
      * Setup a packet data connection. If DataCallResponse.status returns DataCallFailCause:NONE,
diff --git a/radio/1.2/IRadioIndication.hal b/radio/1.2/IRadioIndication.hal
index a124557..3d93b98 100644
--- a/radio/1.2/IRadioIndication.hal
+++ b/radio/1.2/IRadioIndication.hal
@@ -34,7 +34,7 @@
      * Same information as returned by getCellInfoList() in 1.0::IRadio.
      *
      * @param type Type of radio indication
-     * @param records Current cell information known to radio
+     * @param records Current cell information
      */
      oneway cellInfoList_1_2(RadioIndicationType type, vec<CellInfo> records);
 
@@ -50,7 +50,7 @@
      * suppressed by @1.2::IRadio.setIndicationFilter_1_2().
      *
      * @param type Type of radio indication
-     * @param lce LinkCapacityEstimate information as defined in types.hal
+     * @param lce LinkCapacityEstimate
      */
     oneway currentLinkCapacityEstimate(RadioIndicationType type, LinkCapacityEstimate lce);
 
@@ -58,8 +58,16 @@
      * Indicates physical channel configurations.
      *
      * @param type Type of radio indication
-     * @param configs List of PhysicalChannelConfigs as defined in types.hal
+     * @param configs Vector of PhysicalChannelConfigs
      */
     oneway currentPhysicalChannelConfigs(RadioIndicationType type,
             vec<PhysicalChannelConfig> configs);
+
+    /**
+     * Indicates current signal strength of the radio.
+     *
+     * @param type Type of radio indication
+     * @param signalStrength SignalStrength information
+     */
+    oneway currentSignalStrength_1_2(RadioIndicationType type, SignalStrength signalStrength);
 };
diff --git a/radio/1.2/IRadioResponse.hal b/radio/1.2/IRadioResponse.hal
index 93ec4d7..f26c9ec 100644
--- a/radio/1.2/IRadioResponse.hal
+++ b/radio/1.2/IRadioResponse.hal
@@ -88,4 +88,14 @@
      *   RadioError:CANCELLED
      */
     oneway getCurrentCallsResponse_1_2(RadioResponseInfo info, vec<Call> calls);
+
+    /**
+     * @param signalStrength Current signal strength
+     *
+     * Valid errors returned:
+     *   RadioError:NONE
+     *   RadioError:RADIO_NOT_AVAILABLE
+     *   RadioError:INTERNAL_ERR
+     */
+    oneway getSignalStrengthResponse_1_2(RadioResponseInfo info, SignalStrength signalStrength);
 };
diff --git a/radio/1.2/types.hal b/radio/1.2/types.hal
index c353645..b68895e 100644
--- a/radio/1.2/types.hal
+++ b/radio/1.2/types.hal
@@ -17,12 +17,13 @@
 package android.hardware.radio@1.2;
 
 import @1.0::Call;
-import @1.0::CdmaSignalStrength;
 import @1.0::CardState;
 import @1.0::CardStatus;
+import @1.0::CdmaSignalStrength;
 import @1.0::CellIdentityCdma;
 import @1.0::CellIdentityGsm;
 import @1.0::CellIdentityLte;
+import @1.0::CellIdentityTdscdma;
 import @1.0::CellIdentityWcdma;
 import @1.0::CellInfoTdscdma;
 import @1.0::CellInfoType;
@@ -30,10 +31,12 @@
 import @1.0::GsmSignalStrength;
 import @1.0::LteSignalStrength;
 import @1.0::RadioConst;
+import @1.0::RadioError;
+import @1.0::SignalStrength;
+import @1.0::TdScdmaSignalStrength;
 import @1.0::TimeStampType;
 import @1.0::WcdmaSignalStrength;
 import @1.1::RadioAccessSpecifier;
-import @1.0::RadioError;
 import @1.1::ScanStatus;
 import @1.1::ScanType;
 
@@ -251,6 +254,15 @@
     int32_t bandwidth;
 };
 
+struct CellIdentityTdscdma {
+    @1.0::CellIdentityTdscdma base;
+    /**
+     * 16-bit UMTS Absolute RF Channel Number defined in TS 25.102 5.4.4; this value must be valid.
+     */
+    int32_t uarfcn;
+    CellIdentityOperatorNames operatorNames;
+};
+
 struct CellIdentityWcdma {
     @1.0::CellIdentityWcdma base;
     CellIdentityOperatorNames operatorNames;
@@ -277,6 +289,11 @@
     LteSignalStrength signalStrengthLte;
 };
 
+struct CellInfoTdscdma {
+    CellIdentityTdscdma cellIdentityTdscdma;
+    TdscdmaSignalStrength signalStrengthTdscdma;
+};
+
 struct CellInfo {
     /**
      * Cell type for selecting from union CellInfo.
@@ -344,11 +361,17 @@
 
 struct LinkCapacityEstimate {
     /**
-     * Estimated downlink capacity in kbps.
+     * Estimated downlink capacity in kbps. This bandwidth estimate shall be the estimated
+     * maximum sustainable link bandwidth (as would be measured at the Upper PDCP or SNDCP SAP).
+     * If the DL Aggregate Maximum Bit Rate is known, this value shall not exceed the DL-AMBR
+     * for the Internet PDN connection.
      */
     uint32_t downlinkCapacityKbps;
     /**
-     * Estimated uplink capacity in kbps.
+     * Estimated uplink capacity in kbps. This bandwidth estimate shall be the estimated
+     * maximum sustainable link bandwidth (as would be measured at the Upper PDCP or SNDCP SAP).
+     * If the UL Aggregate Maximum Bit Rate is known, this value shall not exceed the UL-AMBR
+     * for the Internet PDN connection.
      */
     uint32_t uplinkCapacityKbps;
 };
@@ -397,3 +420,45 @@
     @1.0::Call base;
     AudioQuality audioQuality;
 };
+
+struct WcdmaSignalStrength {
+    @1.0::WcdmaSignalStrength base;
+    /**
+     * CPICH RSCP as defined in TS 25.215 5.1.1
+     * Valid values are (0-96, 255) as defined in TS 27.007 8.69
+     */
+    uint32_t rscp;
+    /**
+     * Ec/No value as defined in TS 25.215 5.1.5
+     * Valid values are (0-49, 255) as defined in TS 27.007 8.69
+     */
+    uint32_t ecno;
+
+};
+
+struct TdscdmaSignalStrength {
+    /**
+     * UTRA carrier RSSI as defined in TS 25.225 5.1.4
+     * Valid values are (0-96, 99) as defined in TS 27.007 8.69
+     */
+    uint32_t signalStrength;
+    /**
+     * Transport Channel BER as defined in TS 25.225 5.2.5
+     * Valid values are (0-49, 99) as defined in TS 27.007 8.69
+     */
+    uint32_t bitErrorRate;
+    /**
+     * P-CCPCH RSCP as defined in TS 25.225 5.1.1
+     * Valid values are (0-96, 255) as defined in TS 27.007 8.69
+     */
+    uint32_t rscp;
+};
+
+struct SignalStrength {
+    GsmSignalStrength gsm;
+    CdmaSignalStrength cdma;
+    EvdoSignalStrength evdo;
+    LteSignalStrength lte;
+    TdScdmaSignalStrength tdScdma;
+    WcdmaSignalStrength wcdma;
+};
diff --git a/radio/1.2/vts/functional/radio_hidl_hal_api.cpp b/radio/1.2/vts/functional/radio_hidl_hal_api.cpp
index 64a598a..06a7f77 100644
--- a/radio/1.2/vts/functional/radio_hidl_hal_api.cpp
+++ b/radio/1.2/vts/functional/radio_hidl_hal_api.cpp
@@ -43,13 +43,9 @@
 
     ALOGI("startNetworkScan, rspInfo.error = %s\n", toString(radioRsp_v1_2->rspInfo.error).c_str());
     if (cardStatus.cardState == CardState::ABSENT) {
-        ASSERT_TRUE(CheckAnyOfErrors(radioRsp_v1_2->rspInfo.error,
-                                     {RadioError::SIM_ABSENT, RadioError::REQUEST_NOT_SUPPORTED,
-                                      RadioError::OPERATION_NOT_ALLOWED}));
+        ASSERT_TRUE(CheckAnyOfErrors(radioRsp_v1_2->rspInfo.error, {RadioError::SIM_ABSENT}));
     } else if (cardStatus.cardState == CardState::PRESENT) {
-        ASSERT_TRUE(CheckAnyOfErrors(radioRsp_v1_2->rspInfo.error,
-                                     {RadioError::NONE, RadioError::REQUEST_NOT_SUPPORTED,
-                                      RadioError::OPERATION_NOT_ALLOWED}));
+        ASSERT_TRUE(CheckAnyOfErrors(radioRsp_v1_2->rspInfo.error, {RadioError::NONE}));
     }
 }
 
@@ -73,12 +69,10 @@
           toString(radioRsp_v1_2->rspInfo.error).c_str());
     if (cardStatus.cardState == CardState::ABSENT) {
         ASSERT_TRUE(CheckAnyOfErrors(radioRsp_v1_2->rspInfo.error,
-                                     {RadioError::SIM_ABSENT, RadioError::REQUEST_NOT_SUPPORTED,
-                                      RadioError::INVALID_ARGUMENTS}));
+                                     {RadioError::SIM_ABSENT, RadioError::INVALID_ARGUMENTS}));
     } else if (cardStatus.cardState == CardState::PRESENT) {
         ASSERT_TRUE(
-            CheckAnyOfErrors(radioRsp_v1_2->rspInfo.error,
-                             {RadioError::INVALID_ARGUMENTS, RadioError::REQUEST_NOT_SUPPORTED}));
+            CheckAnyOfErrors(radioRsp_v1_2->rspInfo.error, {RadioError::INVALID_ARGUMENTS}));
     }
 }
 
@@ -110,15 +104,11 @@
     ALOGI("startNetworkScan_InvalidInterval1, rspInfo.error = %s\n",
           toString(radioRsp_v1_2->rspInfo.error).c_str());
     if (cardStatus.cardState == CardState::ABSENT) {
-        ASSERT_TRUE(CheckAnyOfErrors(
-            radioRsp_v1_2->rspInfo.error,
-            {RadioError::SIM_ABSENT, RadioError::INVALID_ARGUMENTS,
-             RadioError::REQUEST_NOT_SUPPORTED, RadioError::OPERATION_NOT_ALLOWED}));
+        ASSERT_TRUE(CheckAnyOfErrors(radioRsp_v1_2->rspInfo.error,
+                                     {RadioError::SIM_ABSENT, RadioError::INVALID_ARGUMENTS}));
     } else if (cardStatus.cardState == CardState::PRESENT) {
         ASSERT_TRUE(
-            CheckAnyOfErrors(radioRsp_v1_2->rspInfo.error,
-                             {RadioError::INVALID_ARGUMENTS, RadioError::REQUEST_NOT_SUPPORTED,
-                              RadioError::OPERATION_NOT_ALLOWED}));
+            CheckAnyOfErrors(radioRsp_v1_2->rspInfo.error, {RadioError::INVALID_ARGUMENTS}));
     }
 }
 
@@ -150,15 +140,11 @@
     ALOGI("startNetworkScan_InvalidInterval2, rspInfo.error = %s\n",
           toString(radioRsp_v1_2->rspInfo.error).c_str());
     if (cardStatus.cardState == CardState::ABSENT) {
-        ASSERT_TRUE(CheckAnyOfErrors(
-            radioRsp_v1_2->rspInfo.error,
-            {RadioError::SIM_ABSENT, RadioError::INVALID_ARGUMENTS,
-             RadioError::REQUEST_NOT_SUPPORTED, RadioError::OPERATION_NOT_ALLOWED}));
+        ASSERT_TRUE(CheckAnyOfErrors(radioRsp_v1_2->rspInfo.error,
+                                     {RadioError::SIM_ABSENT, RadioError::INVALID_ARGUMENTS}));
     } else if (cardStatus.cardState == CardState::PRESENT) {
         ASSERT_TRUE(
-            CheckAnyOfErrors(radioRsp_v1_2->rspInfo.error,
-                             {RadioError::INVALID_ARGUMENTS, RadioError::REQUEST_NOT_SUPPORTED,
-                              RadioError::OPERATION_NOT_ALLOWED}));
+            CheckAnyOfErrors(radioRsp_v1_2->rspInfo.error, {RadioError::INVALID_ARGUMENTS}));
     }
 }
 
@@ -190,15 +176,11 @@
     ALOGI("startNetworkScan_InvalidMaxSearchTime1, rspInfo.error = %s\n",
           toString(radioRsp_v1_2->rspInfo.error).c_str());
     if (cardStatus.cardState == CardState::ABSENT) {
-        ASSERT_TRUE(CheckAnyOfErrors(
-            radioRsp_v1_2->rspInfo.error,
-            {RadioError::SIM_ABSENT, RadioError::INVALID_ARGUMENTS,
-             RadioError::REQUEST_NOT_SUPPORTED, RadioError::OPERATION_NOT_ALLOWED}));
+        ASSERT_TRUE(CheckAnyOfErrors(radioRsp_v1_2->rspInfo.error,
+                                     {RadioError::SIM_ABSENT, RadioError::INVALID_ARGUMENTS}));
     } else if (cardStatus.cardState == CardState::PRESENT) {
         ASSERT_TRUE(
-            CheckAnyOfErrors(radioRsp_v1_2->rspInfo.error,
-                             {RadioError::INVALID_ARGUMENTS, RadioError::REQUEST_NOT_SUPPORTED,
-                              RadioError::OPERATION_NOT_ALLOWED}));
+            CheckAnyOfErrors(radioRsp_v1_2->rspInfo.error, {RadioError::INVALID_ARGUMENTS}));
     }
 }
 
@@ -230,15 +212,11 @@
     ALOGI("startNetworkScan_InvalidMaxSearchTime2, rspInfo.error = %s\n",
           toString(radioRsp_v1_2->rspInfo.error).c_str());
     if (cardStatus.cardState == CardState::ABSENT) {
-        ASSERT_TRUE(CheckAnyOfErrors(
-            radioRsp_v1_2->rspInfo.error,
-            {RadioError::SIM_ABSENT, RadioError::INVALID_ARGUMENTS,
-             RadioError::REQUEST_NOT_SUPPORTED, RadioError::OPERATION_NOT_ALLOWED}));
+        ASSERT_TRUE(CheckAnyOfErrors(radioRsp_v1_2->rspInfo.error,
+                                     {RadioError::SIM_ABSENT, RadioError::INVALID_ARGUMENTS}));
     } else if (cardStatus.cardState == CardState::PRESENT) {
         ASSERT_TRUE(
-            CheckAnyOfErrors(radioRsp_v1_2->rspInfo.error,
-                             {RadioError::INVALID_ARGUMENTS, RadioError::REQUEST_NOT_SUPPORTED,
-                              RadioError::OPERATION_NOT_ALLOWED}));
+            CheckAnyOfErrors(radioRsp_v1_2->rspInfo.error, {RadioError::INVALID_ARGUMENTS}));
     }
 }
 
@@ -270,15 +248,11 @@
     ALOGI("startNetworkScan_InvalidPeriodicity1, rspInfo.error = %s\n",
           toString(radioRsp_v1_2->rspInfo.error).c_str());
     if (cardStatus.cardState == CardState::ABSENT) {
-        ASSERT_TRUE(CheckAnyOfErrors(
-            radioRsp_v1_2->rspInfo.error,
-            {RadioError::SIM_ABSENT, RadioError::INVALID_ARGUMENTS,
-             RadioError::REQUEST_NOT_SUPPORTED, RadioError::OPERATION_NOT_ALLOWED}));
+        ASSERT_TRUE(CheckAnyOfErrors(radioRsp_v1_2->rspInfo.error,
+                                     {RadioError::SIM_ABSENT, RadioError::INVALID_ARGUMENTS}));
     } else if (cardStatus.cardState == CardState::PRESENT) {
         ASSERT_TRUE(
-            CheckAnyOfErrors(radioRsp_v1_2->rspInfo.error,
-                             {RadioError::INVALID_ARGUMENTS, RadioError::REQUEST_NOT_SUPPORTED,
-                              RadioError::OPERATION_NOT_ALLOWED}));
+            CheckAnyOfErrors(radioRsp_v1_2->rspInfo.error, {RadioError::INVALID_ARGUMENTS}));
     }
 }
 
@@ -310,15 +284,11 @@
     ALOGI("startNetworkScan_InvalidPeriodicity2, rspInfo.error = %s\n",
           toString(radioRsp_v1_2->rspInfo.error).c_str());
     if (cardStatus.cardState == CardState::ABSENT) {
-        ASSERT_TRUE(CheckAnyOfErrors(
-            radioRsp_v1_2->rspInfo.error,
-            {RadioError::SIM_ABSENT, RadioError::INVALID_ARGUMENTS,
-             RadioError::REQUEST_NOT_SUPPORTED, RadioError::OPERATION_NOT_ALLOWED}));
+        ASSERT_TRUE(CheckAnyOfErrors(radioRsp_v1_2->rspInfo.error,
+                                     {RadioError::SIM_ABSENT, RadioError::INVALID_ARGUMENTS}));
     } else if (cardStatus.cardState == CardState::PRESENT) {
         ASSERT_TRUE(
-            CheckAnyOfErrors(radioRsp_v1_2->rspInfo.error,
-                             {RadioError::INVALID_ARGUMENTS, RadioError::REQUEST_NOT_SUPPORTED,
-                              RadioError::OPERATION_NOT_ALLOWED}));
+            CheckAnyOfErrors(radioRsp_v1_2->rspInfo.error, {RadioError::INVALID_ARGUMENTS}));
     }
 }
 
@@ -350,14 +320,10 @@
     ALOGI("startNetworkScan_InvalidArgument, rspInfo.error = %s\n",
           toString(radioRsp_v1_2->rspInfo.error).c_str());
     if (cardStatus.cardState == CardState::ABSENT) {
-        ASSERT_TRUE(CheckAnyOfErrors(
-            radioRsp_v1_2->rspInfo.error,
-            {RadioError::NONE, RadioError::SIM_ABSENT, RadioError::REQUEST_NOT_SUPPORTED,
-             RadioError::OPERATION_NOT_ALLOWED}));
-    } else if (cardStatus.cardState == CardState::PRESENT) {
         ASSERT_TRUE(CheckAnyOfErrors(radioRsp_v1_2->rspInfo.error,
-                                     {RadioError::NONE, RadioError::REQUEST_NOT_SUPPORTED,
-                                      RadioError::OPERATION_NOT_ALLOWED}));
+                                     {RadioError::NONE, RadioError::SIM_ABSENT}));
+    } else if (cardStatus.cardState == CardState::PRESENT) {
+        ASSERT_TRUE(CheckAnyOfErrors(radioRsp_v1_2->rspInfo.error, {RadioError::NONE}));
     }
 }
 
@@ -390,13 +356,9 @@
     ALOGI("startNetworkScan_InvalidArgument, rspInfo.error = %s\n",
           toString(radioRsp_v1_2->rspInfo.error).c_str());
     if (cardStatus.cardState == CardState::ABSENT) {
-        ASSERT_TRUE(CheckAnyOfErrors(
-            radioRsp_v1_2->rspInfo.error,
-            {RadioError::NONE, RadioError::SIM_ABSENT, RadioError::REQUEST_NOT_SUPPORTED,
-             RadioError::OPERATION_NOT_ALLOWED}));
-    } else if (cardStatus.cardState == CardState::PRESENT) {
         ASSERT_TRUE(CheckAnyOfErrors(radioRsp_v1_2->rspInfo.error,
-                                     {RadioError::NONE, RadioError::REQUEST_NOT_SUPPORTED,
-                                      RadioError::OPERATION_NOT_ALLOWED}));
+                                     {RadioError::NONE, RadioError::SIM_ABSENT}));
+    } else if (cardStatus.cardState == CardState::PRESENT) {
+        ASSERT_TRUE(CheckAnyOfErrors(radioRsp_v1_2->rspInfo.error, {RadioError::NONE}));
     }
 }
diff --git a/soundtrigger/2.0/vts/functional/VtsHalSoundtriggerV2_0TargetTest.cpp b/soundtrigger/2.0/vts/functional/VtsHalSoundtriggerV2_0TargetTest.cpp
index 97956c5..59ac13e 100644
--- a/soundtrigger/2.0/vts/functional/VtsHalSoundtriggerV2_0TargetTest.cpp
+++ b/soundtrigger/2.0/vts/functional/VtsHalSoundtriggerV2_0TargetTest.cpp
@@ -30,6 +30,7 @@
 #include <android/hardware/soundtrigger/2.0/types.h>
 
 #include <VtsHalHidlTargetTestBase.h>
+#include <VtsHalHidlTargetTestEnvBase.h>
 
 #define SHORT_TIMEOUT_PERIOD (1)
 
@@ -85,12 +86,27 @@
   int mCount;
 };
 
+// Test environment for SoundTrigger HIDL HAL.
+class SoundTriggerHidlEnvironment : public ::testing::VtsHalHidlTargetTestEnvBase {
+   public:
+    // get the test environment singleton
+    static SoundTriggerHidlEnvironment* Instance() {
+        static SoundTriggerHidlEnvironment* instance = new SoundTriggerHidlEnvironment;
+        return instance;
+    }
+
+    virtual void registerTestServices() override { registerTestService<ISoundTriggerHw>(); }
+
+   private:
+    SoundTriggerHidlEnvironment() {}
+};
+
 // The main test class for Sound Trigger HIDL HAL.
 class SoundTriggerHidlTest : public ::testing::VtsHalHidlTargetTestBase {
  public:
   virtual void SetUp() override {
-      mSoundTriggerHal =
-          ::testing::VtsHalHidlTargetTestBase::getService<ISoundTriggerHw>();
+      mSoundTriggerHal = ::testing::VtsHalHidlTargetTestBase::getService<ISoundTriggerHw>(
+          SoundTriggerHidlEnvironment::Instance()->getServiceName<ISoundTriggerHw>());
       ASSERT_NE(nullptr, mSoundTriggerHal.get());
       mCallback = new SoundTriggerHwCallback(*this);
       ASSERT_NE(nullptr, mCallback.get());
@@ -142,15 +158,6 @@
   sp<SoundTriggerHwCallback> mCallback;
 };
 
-// A class for test environment setup (kept since this file is a template).
-class SoundTriggerHidlEnvironment : public ::testing::Environment {
- public:
-  virtual void SetUp() {}
-  virtual void TearDown() {}
-
- private:
-};
-
 /**
  * Test ISoundTriggerHw::getProperties() method
  *
@@ -318,11 +325,11 @@
     EXPECT_TRUE(hidlReturn == 0 || hidlReturn == -ENOSYS);
 }
 
-
 int main(int argc, char** argv) {
-  ::testing::AddGlobalTestEnvironment(new SoundTriggerHidlEnvironment);
-  ::testing::InitGoogleTest(&argc, argv);
-  int status = RUN_ALL_TESTS();
-  ALOGI("Test result = %d", status);
-  return status;
+    ::testing::AddGlobalTestEnvironment(SoundTriggerHidlEnvironment::Instance());
+    ::testing::InitGoogleTest(&argc, argv);
+    SoundTriggerHidlEnvironment::Instance()->init(&argc, argv);
+    int status = RUN_ALL_TESTS();
+    ALOGI("Test result = %d", status);
+    return status;
 }
diff --git a/soundtrigger/2.1/vts/functional/VtsHalSoundtriggerV2_1TargetTest.cpp b/soundtrigger/2.1/vts/functional/VtsHalSoundtriggerV2_1TargetTest.cpp
index fdd5f0d..0a2eeac 100644
--- a/soundtrigger/2.1/vts/functional/VtsHalSoundtriggerV2_1TargetTest.cpp
+++ b/soundtrigger/2.1/vts/functional/VtsHalSoundtriggerV2_1TargetTest.cpp
@@ -33,6 +33,7 @@
 #include <hidlmemory/mapping.h>
 
 #include <VtsHalHidlTargetTestBase.h>
+#include <VtsHalHidlTargetTestEnvBase.h>
 
 #define SHORT_TIMEOUT_PERIOD (1)
 
@@ -93,11 +94,27 @@
     int mCount;
 };
 
+// Test environment for SoundTrigger HIDL HAL.
+class SoundTriggerHidlEnvironment : public ::testing::VtsHalHidlTargetTestEnvBase {
+   public:
+    // get the test environment singleton
+    static SoundTriggerHidlEnvironment* Instance() {
+        static SoundTriggerHidlEnvironment* instance = new SoundTriggerHidlEnvironment;
+        return instance;
+    }
+
+    virtual void registerTestServices() override { registerTestService<ISoundTriggerHw>(); }
+
+   private:
+    SoundTriggerHidlEnvironment() {}
+};
+
 // The main test class for Sound Trigger HIDL HAL.
 class SoundTriggerHidlTest : public ::testing::VtsHalHidlTargetTestBase {
    public:
     virtual void SetUp() override {
-        mSoundTriggerHal = ::testing::VtsHalHidlTargetTestBase::getService<ISoundTriggerHw>();
+        mSoundTriggerHal = ::testing::VtsHalHidlTargetTestBase::getService<ISoundTriggerHw>(
+            SoundTriggerHidlEnvironment::Instance()->getServiceName<ISoundTriggerHw>());
         ASSERT_NE(nullptr, mSoundTriggerHal.get());
         mCallback = new SoundTriggerHwCallback(*this);
         ASSERT_NE(nullptr, mCallback.get());
@@ -480,3 +497,12 @@
     EXPECT_TRUE(hidlReturn.isOk());
     EXPECT_TRUE(hidlReturn == 0 || hidlReturn == -ENOSYS);
 }
+
+int main(int argc, char** argv) {
+    ::testing::AddGlobalTestEnvironment(SoundTriggerHidlEnvironment::Instance());
+    ::testing::InitGoogleTest(&argc, argv);
+    SoundTriggerHidlEnvironment::Instance()->init(&argc, argv);
+    int status = RUN_ALL_TESTS();
+    ALOGI("Test result = %d", status);
+    return status;
+}
diff --git a/thermal/1.0/vts/functional/VtsHalThermalV1_0TargetTest.cpp b/thermal/1.0/vts/functional/VtsHalThermalV1_0TargetTest.cpp
index dfa11a1..6f059ef 100644
--- a/thermal/1.0/vts/functional/VtsHalThermalV1_0TargetTest.cpp
+++ b/thermal/1.0/vts/functional/VtsHalThermalV1_0TargetTest.cpp
@@ -21,10 +21,11 @@
 
 #define LOG_TAG "thermal_hidl_hal_test"
 
+#include <VtsHalHidlTargetTestBase.h>
+#include <VtsHalHidlTargetTestEnvBase.h>
 #include <android-base/logging.h>
 #include <android/hardware/thermal/1.0/IThermal.h>
 #include <android/hardware/thermal/1.0/types.h>
-#include <VtsHalHidlTargetTestBase.h>
 #include <unistd.h>
 
 using ::android::hardware::hidl_string;
@@ -45,11 +46,26 @@
 #define MAX_DEVICE_TEMPERATURE 200
 #define MAX_FAN_SPEED 20000
 
+// Test environment for Thermal HIDL HAL.
+class ThermalHidlEnvironment : public ::testing::VtsHalHidlTargetTestEnvBase {
+ public:
+  // get the test environment singleton
+  static ThermalHidlEnvironment* Instance() {
+    static ThermalHidlEnvironment* instance = new ThermalHidlEnvironment;
+    return instance;
+  }
+
+  virtual void registerTestServices() override { registerTestService<IThermal>(); }
+ private:
+  ThermalHidlEnvironment() {}
+};
+
 // The main test class for THERMAL HIDL HAL.
 class ThermalHidlTest : public ::testing::VtsHalHidlTargetTestBase {
  public:
   virtual void SetUp() override {
-    thermal_ = ::testing::VtsHalHidlTargetTestBase::getService<IThermal>();
+    thermal_ = ::testing::VtsHalHidlTargetTestBase::getService<IThermal>(
+        ThermalHidlEnvironment::Instance()->getServiceName<IThermal>());
     ASSERT_NE(thermal_, nullptr);
     baseSize_ = 0;
     names_.clear();
@@ -207,7 +223,9 @@
 }
 
 int main(int argc, char** argv) {
+  ::testing::AddGlobalTestEnvironment(ThermalHidlEnvironment::Instance());
   ::testing::InitGoogleTest(&argc, argv);
+  ThermalHidlEnvironment::Instance()->init(&argc, argv);
   int status = RUN_ALL_TESTS();
   LOG(INFO) << "Test result = " << status;
   return status;
diff --git a/thermal/1.1/vts/functional/VtsHalThermalV1_1TargetTest.cpp b/thermal/1.1/vts/functional/VtsHalThermalV1_1TargetTest.cpp
index 6c1599b..91c8b6e 100644
--- a/thermal/1.1/vts/functional/VtsHalThermalV1_1TargetTest.cpp
+++ b/thermal/1.1/vts/functional/VtsHalThermalV1_1TargetTest.cpp
@@ -20,6 +20,7 @@
 
 #include <VtsHalHidlTargetCallbackBase.h>
 #include <VtsHalHidlTargetTestBase.h>
+#include <VtsHalHidlTargetTestEnvBase.h>
 
 using ::android::hardware::thermal::V1_0::Temperature;
 using ::android::hardware::thermal::V1_0::TemperatureType;
@@ -62,11 +63,26 @@
     }
 };
 
+// Test environment for Thermal HIDL HAL.
+class ThermalHidlEnvironment : public ::testing::VtsHalHidlTargetTestEnvBase {
+   public:
+    // get the test environment singleton
+    static ThermalHidlEnvironment* Instance() {
+        static ThermalHidlEnvironment* instance = new ThermalHidlEnvironment;
+        return instance;
+    }
+
+    virtual void registerTestServices() override { registerTestService<IThermal>(); }
+   private:
+    ThermalHidlEnvironment() {}
+};
+
 // The main test class for THERMAL HIDL HAL 1.1.
 class ThermalHidlTest : public ::testing::VtsHalHidlTargetTestBase {
    public:
     virtual void SetUp() override {
-        mThermal = ::testing::VtsHalHidlTargetTestBase::getService<IThermal>();
+        mThermal = ::testing::VtsHalHidlTargetTestBase::getService<IThermal>(
+            ThermalHidlEnvironment::Instance()->getServiceName<IThermal>());
         ASSERT_NE(mThermal, nullptr);
         mThermalCallback = new(std::nothrow) ThermalCallback();
         ASSERT_NE(mThermalCallback, nullptr);
@@ -99,7 +115,9 @@
 }
 
 int main(int argc, char** argv) {
+    ::testing::AddGlobalTestEnvironment(ThermalHidlEnvironment::Instance());
     ::testing::InitGoogleTest(&argc, argv);
+    ThermalHidlEnvironment::Instance()->init(&argc, argv);
     int status = RUN_ALL_TESTS();
     cout << "Test result = " << status << std::endl;
     return status;
diff --git a/wifi/1.0/vts/functional/Android.bp b/wifi/1.0/vts/functional/Android.bp
index ea27f02..b2f76a3 100644
--- a/wifi/1.0/vts/functional/Android.bp
+++ b/wifi/1.0/vts/functional/Android.bp
@@ -20,7 +20,8 @@
     srcs: [
         "wifi_hidl_call_util_selftest.cpp",
         "wifi_hidl_test.cpp",
-        "wifi_hidl_test_utils.cpp"],
+        "wifi_hidl_test_utils.cpp",
+    ],
     export_include_dirs: [
         "."
     ],
diff --git a/wifi/1.0/vts/functional/VtsHalWifiV1_0TargetTest.cpp b/wifi/1.0/vts/functional/VtsHalWifiV1_0TargetTest.cpp
index beac039..e7b8593 100644
--- a/wifi/1.0/vts/functional/VtsHalWifiV1_0TargetTest.cpp
+++ b/wifi/1.0/vts/functional/VtsHalWifiV1_0TargetTest.cpp
@@ -16,16 +16,31 @@
 
 #include <android-base/logging.h>
 
-#include <VtsHalHidlTargetTestBase.h>
-
 #include "wifi_hidl_test_utils.h"
 
-WifiHidlEnvironment* gEnv;
+class WifiVtsHidlEnvironment_1_0 : public WifiHidlEnvironment {
+   public:
+    // get the test environment singleton
+    static WifiVtsHidlEnvironment_1_0* Instance() {
+        static WifiVtsHidlEnvironment_1_0* instance =
+            new WifiVtsHidlEnvironment_1_0;
+        return instance;
+    }
+
+    virtual void registerTestServices() override {
+        registerTestService<android::hardware::wifi::V1_0::IWifi>();
+    }
+
+   private:
+    WifiVtsHidlEnvironment_1_0() {}
+};
+
+WifiHidlEnvironment* gEnv = WifiVtsHidlEnvironment_1_0::Instance();
 
 int main(int argc, char** argv) {
-    gEnv = new WifiHidlEnvironment();
     ::testing::AddGlobalTestEnvironment(gEnv);
     ::testing::InitGoogleTest(&argc, argv);
+    gEnv->init(&argc, argv);
     int status = gEnv->initFromOptions(argc, argv);
     if (status == 0) {
         status = RUN_ALL_TESTS();
diff --git a/wifi/1.0/vts/functional/wifi_hidl_test_utils.cpp b/wifi/1.0/vts/functional/wifi_hidl_test_utils.cpp
index 313bdd8..97a371b 100644
--- a/wifi/1.0/vts/functional/wifi_hidl_test_utils.cpp
+++ b/wifi/1.0/vts/functional/wifi_hidl_test_utils.cpp
@@ -35,6 +35,8 @@
 using ::android::hardware::hidl_string;
 using ::android::hardware::hidl_vec;
 
+extern WifiHidlEnvironment* gEnv;
+
 namespace {
 constexpr uint32_t kHalStartRetryMaxCount = 5;
 constexpr uint32_t kHalStartRetryIntervalInMs = 2;
@@ -86,7 +88,8 @@
 }  // namespace
 
 sp<IWifi> getWifi() {
-    sp<IWifi> wifi = ::testing::VtsHalHidlTargetTestBase::getService<IWifi>();
+    sp<IWifi> wifi = ::testing::VtsHalHidlTargetTestBase::getService<IWifi>(
+        gEnv->getServiceName<IWifi>());
     return wifi;
 }
 
diff --git a/wifi/1.0/vts/functional/wifi_hidl_test_utils.h b/wifi/1.0/vts/functional/wifi_hidl_test_utils.h
index c4a19dd..2b1c8ec 100644
--- a/wifi/1.0/vts/functional/wifi_hidl_test_utils.h
+++ b/wifi/1.0/vts/functional/wifi_hidl_test_utils.h
@@ -26,6 +26,7 @@
 
 #include <getopt.h>
 
+#include <VtsHalHidlTargetTestEnvBase.h>
 // Helper functions to obtain references to the various HIDL interface objects.
 // Note: We only have a single instance of each of these objects currently.
 // These helper functions should be modified to return vectors if we support
@@ -47,9 +48,9 @@
 // Used to trigger IWifi.stop() at the end of every test.
 void stopWifi();
 
-class WifiHidlEnvironment : public ::testing::Environment {
+class WifiHidlEnvironment : public ::testing::VtsHalHidlTargetTestEnvBase {
    protected:
-    virtual void SetUp() override {
+    virtual void HidlSetUp() override {
         stopWifi();
         sleep(5);
     }
diff --git a/wifi/1.1/vts/functional/VtsHalWifiV1_1TargetTest.cpp b/wifi/1.1/vts/functional/VtsHalWifiV1_1TargetTest.cpp
index 9b92b57..a0f97f8 100644
--- a/wifi/1.1/vts/functional/VtsHalWifiV1_1TargetTest.cpp
+++ b/wifi/1.1/vts/functional/VtsHalWifiV1_1TargetTest.cpp
@@ -15,17 +15,32 @@
  */
 
 #include <android-base/logging.h>
-
-#include <VtsHalHidlTargetTestBase.h>
+#include <android/hardware/wifi/1.1/IWifi.h>
 
 #include "wifi_hidl_test_utils.h"
 
-WifiHidlEnvironment* gEnv;
+class WifiHidlEnvironment_1_1 : public WifiHidlEnvironment {
+   public:
+    // get the test environment singleton
+    static WifiHidlEnvironment_1_1* Instance() {
+        static WifiHidlEnvironment_1_1* instance = new WifiHidlEnvironment_1_1;
+        return instance;
+    }
+
+    virtual void registerTestServices() override {
+        registerTestService<android::hardware::wifi::V1_1::IWifi>();
+    }
+
+   private:
+    WifiHidlEnvironment_1_1() {}
+};
+
+WifiHidlEnvironment* gEnv = WifiHidlEnvironment_1_1::Instance();
 
 int main(int argc, char** argv) {
-    gEnv = new WifiHidlEnvironment();
     ::testing::AddGlobalTestEnvironment(gEnv);
     ::testing::InitGoogleTest(&argc, argv);
+    gEnv->init(&argc, argv);
     int status = gEnv->initFromOptions(argc, argv);
     if (status == 0) {
         int status = RUN_ALL_TESTS();
diff --git a/wifi/hostapd/1.0/vts/functional/VtsHalWifiHostapdV1_0TargetTest.cpp b/wifi/hostapd/1.0/vts/functional/VtsHalWifiHostapdV1_0TargetTest.cpp
index 64e6fbe..0303b20 100644
--- a/wifi/hostapd/1.0/vts/functional/VtsHalWifiHostapdV1_0TargetTest.cpp
+++ b/wifi/hostapd/1.0/vts/functional/VtsHalWifiHostapdV1_0TargetTest.cpp
@@ -15,20 +15,34 @@
  */
 
 #include <android-base/logging.h>
-
-#include <VtsHalHidlTargetTestBase.h>
+#include <android/hardware/wifi/1.0/IWifi.h>
 
 #include "hostapd_hidl_test_utils.h"
 
-class HostapdHidlEnvironment : public ::testing::Environment {
+class WifiHostapdHidlEnvironment_1_0 : public WifiHostapdHidlEnvironment {
    public:
-    virtual void SetUp() override { stopHostapd(); }
-    virtual void TearDown() override { startHostapdAndWaitForHidlService(); }
+    // get the test environment singleton
+    static WifiHostapdHidlEnvironment_1_0* Instance() {
+        static WifiHostapdHidlEnvironment_1_0* instance =
+            new WifiHostapdHidlEnvironment_1_0;
+        return instance;
+    }
+
+    virtual void registerTestServices() override {
+        registerTestService<::android::hardware::wifi::V1_0::IWifi>();
+        registerTestService<android::hardware::wifi::hostapd::V1_0::IHostapd>();
+    }
+
+   private:
+    WifiHostapdHidlEnvironment_1_0() {}
 };
 
+WifiHostapdHidlEnvironment* gEnv = WifiHostapdHidlEnvironment_1_0::Instance();
+
 int main(int argc, char** argv) {
-    ::testing::AddGlobalTestEnvironment(new HostapdHidlEnvironment);
+    ::testing::AddGlobalTestEnvironment(gEnv);
     ::testing::InitGoogleTest(&argc, argv);
+    gEnv->init(&argc, argv);
     int status = RUN_ALL_TESTS();
     LOG(INFO) << "Test result = " << status;
     return status;
diff --git a/wifi/hostapd/1.0/vts/functional/hostapd_hidl_test_utils.cpp b/wifi/hostapd/1.0/vts/functional/hostapd_hidl_test_utils.cpp
index 0915150..e5ba8ef 100644
--- a/wifi/hostapd/1.0/vts/functional/hostapd_hidl_test_utils.cpp
+++ b/wifi/hostapd/1.0/vts/functional/hostapd_hidl_test_utils.cpp
@@ -42,9 +42,9 @@
 using ::android::hidl::manager::V1_0::IServiceNotification;
 using ::android::wifi_system::HostapdManager;
 
-namespace {
-const char kHostapdServiceName[] = "default";
+extern WifiHostapdHidlEnvironment* gEnv;
 
+namespace {
 // Helper function to initialize the driver and firmware to AP mode
 // using the vendor HAL HIDL interface.
 void initilializeDriverAndFirmware() {
@@ -120,16 +120,17 @@
 
     android::sp<ServiceNotificationListener> notification_listener =
         new ServiceNotificationListener();
+    string service_name = gEnv->getServiceName<IHostapd>();
     ASSERT_TRUE(notification_listener->registerForHidlServiceNotifications(
-        kHostapdServiceName));
+        service_name));
 
     HostapdManager hostapd_manager;
     ASSERT_TRUE(hostapd_manager.StartHostapd());
 
-    ASSERT_TRUE(
-        notification_listener->waitForHidlService(200, kHostapdServiceName));
+    ASSERT_TRUE(notification_listener->waitForHidlService(200, service_name));
 }
 
 sp<IHostapd> getHostapd() {
-    return ::testing::VtsHalHidlTargetTestBase::getService<IHostapd>();
+    return ::testing::VtsHalHidlTargetTestBase::getService<IHostapd>(
+        gEnv->getServiceName<IHostapd>());
 }
diff --git a/wifi/hostapd/1.0/vts/functional/hostapd_hidl_test_utils.h b/wifi/hostapd/1.0/vts/functional/hostapd_hidl_test_utils.h
index 74ed284..1b92477 100644
--- a/wifi/hostapd/1.0/vts/functional/hostapd_hidl_test_utils.h
+++ b/wifi/hostapd/1.0/vts/functional/hostapd_hidl_test_utils.h
@@ -19,6 +19,8 @@
 
 #include <android/hardware/wifi/hostapd/1.0/IHostapd.h>
 
+#include <VtsHalHidlTargetTestEnvBase.h>
+
 // Used to stop the android wifi framework before every test.
 void stopWifiFramework();
 void startWifiFramework();
@@ -33,4 +35,13 @@
 // multiple instances.
 android::sp<android::hardware::wifi::hostapd::V1_0::IHostapd> getHostapd();
 
+class WifiHostapdHidlEnvironment
+    : public ::testing::VtsHalHidlTargetTestEnvBase {
+   public:
+    virtual void HidlSetUp() override { stopHostapd(); }
+    virtual void HidlTearDown() override {
+        startHostapdAndWaitForHidlService();
+    }
+};
+
 #endif /* HOSTAPD_HIDL_TEST_UTILS_H */
diff --git a/wifi/offload/1.0/vts/functional/VtsHalWifiOffloadV1_0TargetTest.cpp b/wifi/offload/1.0/vts/functional/VtsHalWifiOffloadV1_0TargetTest.cpp
index 90c36dd..dbe4e74 100644
--- a/wifi/offload/1.0/vts/functional/VtsHalWifiOffloadV1_0TargetTest.cpp
+++ b/wifi/offload/1.0/vts/functional/VtsHalWifiOffloadV1_0TargetTest.cpp
@@ -23,6 +23,7 @@
 
 #include <VtsHalHidlTargetCallbackBase.h>
 #include <VtsHalHidlTargetTestBase.h>
+#include <VtsHalHidlTargetTestEnvBase.h>
 
 #include <vector>
 
@@ -68,12 +69,33 @@
     OffloadStatus error_code_;
 };
 
+// Test environment for Weaver HIDL HAL.
+class WifiOffloadHidlEnvironment
+    : public ::testing::VtsHalHidlTargetTestEnvBase {
+   public:
+    // get the test environment singleton
+    static WifiOffloadHidlEnvironment* Instance() {
+        static WifiOffloadHidlEnvironment* instance =
+            new WifiOffloadHidlEnvironment;
+        return instance;
+    }
+
+    virtual void registerTestServices() override {
+        registerTestService<IOffload>();
+    }
+
+   private:
+    WifiOffloadHidlEnvironment() {}
+};
+
 // The main test class for WifiOffload HIDL HAL.
 class WifiOffloadHidlTest : public ::testing::VtsHalHidlTargetTestBase {
    public:
     virtual void SetUp() override {
         wifi_offload_ =
-            ::testing::VtsHalHidlTargetTestBase::getService<IOffload>();
+            ::testing::VtsHalHidlTargetTestBase::getService<IOffload>(
+                WifiOffloadHidlEnvironment::Instance()
+                    ->getServiceName<IOffload>());
         ASSERT_NE(wifi_offload_, nullptr);
 
         wifi_offload_cb_ = new OffloadCallback();
@@ -209,17 +231,10 @@
     ASSERT_EQ(true, res.no_timeout);
 }
 
-// A class for test environment setup
-class WifiOffloadHalHidlEnvironment : public ::testing::Environment {
-   public:
-    virtual void SetUp() {}
-    virtual void TearDown() {}
-};
-
 int main(int argc, char** argv) {
-    ::testing::AddGlobalTestEnvironment(new WifiOffloadHalHidlEnvironment);
+    ::testing::AddGlobalTestEnvironment(WifiOffloadHidlEnvironment::Instance());
     ::testing::InitGoogleTest(&argc, argv);
-
+    WifiOffloadHidlEnvironment::Instance()->init(&argc, argv);
     int status = RUN_ALL_TESTS();
     LOG(INFO) << "Test result = " << status;
 
diff --git a/wifi/supplicant/1.0/vts/functional/VtsHalWifiSupplicantV1_0TargetTest.cpp b/wifi/supplicant/1.0/vts/functional/VtsHalWifiSupplicantV1_0TargetTest.cpp
index 7fa20c9..adf2a85 100644
--- a/wifi/supplicant/1.0/vts/functional/VtsHalWifiSupplicantV1_0TargetTest.cpp
+++ b/wifi/supplicant/1.0/vts/functional/VtsHalWifiSupplicantV1_0TargetTest.cpp
@@ -16,21 +16,34 @@
 
 #include <android-base/logging.h>
 
-#include <VtsHalHidlTargetTestBase.h>
-
 #include "supplicant_hidl_test_utils.h"
+#include "wifi_hidl_test_utils.h"
 
-class SupplicantHidlEnvironment : public ::testing::Environment {
+class WifiSupplicantHidlEnvironment_1_0 : public WifiSupplicantHidlEnvironment {
    public:
-    virtual void SetUp() override {
-        stopSupplicant();
+    // get the test environment singleton
+    static WifiSupplicantHidlEnvironment_1_0* Instance() {
+        static WifiSupplicantHidlEnvironment_1_0* instance =
+            new WifiSupplicantHidlEnvironment_1_0;
+        return instance;
     }
-    virtual void TearDown() override { startSupplicantAndWaitForHidlService(); }
+    virtual void registerTestServices() override {
+        registerTestService<::android::hardware::wifi::V1_0::IWifi>();
+        registerTestService<
+            ::android::hardware::wifi::supplicant::V1_0::ISupplicant>();
+    }
+
+   private:
+    WifiSupplicantHidlEnvironment_1_0() {}
 };
 
+WifiSupplicantHidlEnvironment* gEnv =
+    WifiSupplicantHidlEnvironment_1_0::Instance();
+
 int main(int argc, char** argv) {
-    ::testing::AddGlobalTestEnvironment(new SupplicantHidlEnvironment);
+    ::testing::AddGlobalTestEnvironment(gEnv);
     ::testing::InitGoogleTest(&argc, argv);
+    gEnv->init(&argc, argv);
     int status = RUN_ALL_TESTS();
     LOG(INFO) << "Test result = " << status;
     return status;
diff --git a/wifi/supplicant/1.0/vts/functional/supplicant_hidl_test_utils.cpp b/wifi/supplicant/1.0/vts/functional/supplicant_hidl_test_utils.cpp
index 3b75508..6dd64ec 100644
--- a/wifi/supplicant/1.0/vts/functional/supplicant_hidl_test_utils.cpp
+++ b/wifi/supplicant/1.0/vts/functional/supplicant_hidl_test_utils.cpp
@@ -14,8 +14,8 @@
  * limitations under the License.
  */
 
-#include <android-base/logging.h>
 #include <VtsHalHidlTargetTestBase.h>
+#include <android-base/logging.h>
 
 #include <android/hidl/manager/1.0/IServiceManager.h>
 #include <android/hidl/manager/1.0/IServiceNotification.h>
@@ -49,8 +49,9 @@
 using ::android::wifi_system::InterfaceTool;
 using ::android::wifi_system::SupplicantManager;
 
+extern WifiSupplicantHidlEnvironment* gEnv;
+
 namespace {
-const char kSupplicantServiceName[] = "default";
 
 // Helper function to initialize the driver and firmware to STA mode
 // using the vendor HAL HIDL interface.
@@ -153,19 +154,20 @@
 
     android::sp<ServiceNotificationListener> notification_listener =
         new ServiceNotificationListener();
+    string service_name = gEnv->getServiceName<ISupplicant>();
     ASSERT_TRUE(notification_listener->registerForHidlServiceNotifications(
-        kSupplicantServiceName));
+        service_name));
 
     SupplicantManager supplicant_manager;
     ASSERT_TRUE(supplicant_manager.StartSupplicant());
     ASSERT_TRUE(supplicant_manager.IsSupplicantRunning());
 
-    ASSERT_TRUE(
-        notification_listener->waitForHidlService(200, kSupplicantServiceName));
+    ASSERT_TRUE(notification_listener->waitForHidlService(200, service_name));
 }
 
 sp<ISupplicant> getSupplicant() {
-    return ::testing::VtsHalHidlTargetTestBase::getService<ISupplicant>();
+    return ::testing::VtsHalHidlTargetTestBase::getService<ISupplicant>(
+        gEnv->getServiceName<ISupplicant>());
 }
 
 sp<ISupplicantStaIface> getSupplicantStaIface() {
diff --git a/wifi/supplicant/1.0/vts/functional/supplicant_hidl_test_utils.h b/wifi/supplicant/1.0/vts/functional/supplicant_hidl_test_utils.h
index 38143e4..4426ab6 100644
--- a/wifi/supplicant/1.0/vts/functional/supplicant_hidl_test_utils.h
+++ b/wifi/supplicant/1.0/vts/functional/supplicant_hidl_test_utils.h
@@ -22,6 +22,8 @@
 #include <android/hardware/wifi/supplicant/1.0/ISupplicantStaIface.h>
 #include <android/hardware/wifi/supplicant/1.0/ISupplicantStaNetwork.h>
 
+#include <VtsHalHidlTargetTestEnvBase.h>
+
 // Used to stop the android wifi framework before every test.
 void stopWifiFramework();
 void startWifiFramework();
@@ -45,4 +47,13 @@
 
 bool turnOnExcessiveLogging();
 
+class WifiSupplicantHidlEnvironment
+    : public ::testing::VtsHalHidlTargetTestEnvBase {
+   public:
+    virtual void HidlSetUp() override { stopSupplicant(); }
+    virtual void HidlTearDown() override {
+        startSupplicantAndWaitForHidlService();
+    }
+};
+
 #endif /* SUPPLICANT_HIDL_TEST_UTILS_H */
diff --git a/wifi/supplicant/1.1/vts/functional/Android.bp b/wifi/supplicant/1.1/vts/functional/Android.bp
index 9375cf5..188dba3 100644
--- a/wifi/supplicant/1.1/vts/functional/Android.bp
+++ b/wifi/supplicant/1.1/vts/functional/Android.bp
@@ -48,6 +48,7 @@
         "android.hardware.wifi.supplicant@1.0",
         "android.hardware.wifi.supplicant@1.1",
         "android.hardware.wifi@1.0",
+        "android.hardware.wifi@1.1",
         "libcrypto",
         "libgmock",
         "libwifi-system",
diff --git a/wifi/supplicant/1.1/vts/functional/VtsHalWifiSupplicantV1_1TargetTest.cpp b/wifi/supplicant/1.1/vts/functional/VtsHalWifiSupplicantV1_1TargetTest.cpp
index b5e369a..3d24fc3 100644
--- a/wifi/supplicant/1.1/vts/functional/VtsHalWifiSupplicantV1_1TargetTest.cpp
+++ b/wifi/supplicant/1.1/vts/functional/VtsHalWifiSupplicantV1_1TargetTest.cpp
@@ -15,20 +15,37 @@
  */
 
 #include <android-base/logging.h>
-
-#include <VtsHalHidlTargetTestBase.h>
+#include <android/hardware/wifi/1.1/IWifi.h>
+#include <android/hardware/wifi/supplicant/1.1/ISupplicant.h>
 
 #include "supplicant_hidl_test_utils.h"
+#include "wifi_hidl_test_utils.h"
 
-class SupplicantHidlEnvironment : public ::testing::Environment {
+class WifiSupplicantHidlEnvironment_1_1 : public WifiSupplicantHidlEnvironment {
    public:
-    virtual void SetUp() override { stopSupplicant(); }
-    virtual void TearDown() override { startSupplicantAndWaitForHidlService(); }
+    // get the test environment singleton
+    static WifiSupplicantHidlEnvironment_1_1* Instance() {
+        static WifiSupplicantHidlEnvironment_1_1* instance =
+            new WifiSupplicantHidlEnvironment_1_1;
+        return instance;
+    }
+    virtual void registerTestServices() override {
+        registerTestService<::android::hardware::wifi::V1_1::IWifi>();
+        registerTestService<
+            ::android::hardware::wifi::supplicant::V1_1::ISupplicant>();
+    }
+
+   private:
+    WifiSupplicantHidlEnvironment_1_1() {}
 };
 
+WifiSupplicantHidlEnvironment* gEnv =
+    WifiSupplicantHidlEnvironment_1_1::Instance();
+
 int main(int argc, char** argv) {
-    ::testing::AddGlobalTestEnvironment(new SupplicantHidlEnvironment);
+    ::testing::AddGlobalTestEnvironment(gEnv);
     ::testing::InitGoogleTest(&argc, argv);
+    gEnv->init(&argc, argv);
     int status = RUN_ALL_TESTS();
     LOG(INFO) << "Test result = " << status;
     return status;