Merge "Add Speed_Display_Units property in DefaultHal" into qt-dev
diff --git a/audio/common/5.0/types.hal b/audio/common/5.0/types.hal
index e1279ee..33a8d62 100644
--- a/audio/common/5.0/types.hal
+++ b/audio/common/5.0/types.hal
@@ -331,7 +331,13 @@
 
 /**
  * A channel mask per se only defines the presence or absence of a channel, not
- * the order.  See AUDIO_INTERLEAVE_* for the platform convention of order.
+ * the order.
+ *
+ * The channel order convention is that channels are interleaved in order from
+ * least significant channel mask bit to most significant channel mask bit,
+ * with unused bits skipped. For example for stereo, LEFT would be first,
+ * followed by RIGHT.
+ * Any exceptions to this convention are noted at the appropriate API.
  *
  * AudioChannelMask is an opaque type and its internal layout should not be
  * assumed as it may change in the future.  Instead, always use functions
diff --git a/audio/common/all-versions/util/include/common/all-versions/HidlSupport.h b/audio/common/all-versions/util/include/common/all-versions/HidlSupport.h
new file mode 100644
index 0000000..b514a43
--- /dev/null
+++ b/audio/common/all-versions/util/include/common/all-versions/HidlSupport.h
@@ -0,0 +1,34 @@
+/*
+ * Copyright (C) 2019 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef android_hardware_audio_common_HidlSupport_H_
+#define android_hardware_audio_common_HidlSupport_H_
+
+
+#include <hidl/HidlSupport.h>
+#include <algorithm>
+
+namespace android::hardware::audio::common::utils {
+
+template <typename Enum>
+bool isValidHidlEnum(Enum e) {
+    hidl_enum_range<Enum> values;
+    return std::find(values.begin(), values.end(), e) != values.end();
+}
+
+} // namespace android::hardware::audio::common::utils
+
+#endif  // android_hardware_audio_common_HidlSupport_H_
diff --git a/audio/core/all-versions/default/StreamIn.cpp b/audio/core/all-versions/default/StreamIn.cpp
index daba6f7..d316f83 100644
--- a/audio/core/all-versions/default/StreamIn.cpp
+++ b/audio/core/all-versions/default/StreamIn.cpp
@@ -19,6 +19,7 @@
 #include "core/default/StreamIn.h"
 #include "core/default/Conversions.h"
 #include "core/default/Util.h"
+#include "common/all-versions/HidlSupport.h"
 
 //#define LOG_NDEBUG 0
 #define ATRACE_TAG ATRACE_TAG_AUDIO
@@ -27,6 +28,7 @@
 #include <hardware/audio.h>
 #include <utils/Trace.h>
 #include <memory>
+#include <cmath>
 
 namespace android {
 namespace hardware {
@@ -501,6 +503,10 @@
     if (mStream->set_microphone_direction == nullptr) {
         return Result::NOT_SUPPORTED;
     }
+    if (!common::utils::isValidHidlEnum(direction)) {
+        ALOGE("%s: Invalid direction %d", __func__, direction);
+        return Result::INVALID_ARGUMENTS;
+    }
     return Stream::analyzeStatus(
             "set_microphone_direction",
             mStream->set_microphone_direction(
@@ -511,6 +517,10 @@
     if (mStream->set_microphone_field_dimension == nullptr) {
         return Result::NOT_SUPPORTED;
     }
+    if (std::isnan(zoom) || zoom < -1 || zoom > 1) {
+        ALOGE("%s: Invalid zoom %f", __func__, zoom);
+        return Result::INVALID_ARGUMENTS;
+    }
     return Stream::analyzeStatus("set_microphone_field_dimension",
                                  mStream->set_microphone_field_dimension(mStream, zoom));
 }
diff --git a/automotive/evs/1.0/vts/functional/FrameHandler.cpp b/automotive/evs/1.0/vts/functional/FrameHandler.cpp
index d44ba41..bc3790f 100644
--- a/automotive/evs/1.0/vts/functional/FrameHandler.cpp
+++ b/automotive/evs/1.0/vts/functional/FrameHandler.cpp
@@ -137,6 +137,10 @@
         // Signal that the last frame has been received and the stream is stopped
         timeToStop = true;
     } else {
+        // Store a dimension of a received frame.
+        mFrameWidth = bufferArg.width;
+        mFrameHeight = bufferArg.height;
+
         // If we were given an opened display at construction time, then send the received
         // image back down the camera.
         if (mDisplay.get()) {
@@ -299,3 +303,13 @@
 
     return success;
 }
+
+void FrameHandler::getFrameDimension(unsigned* width, unsigned* height) {
+    if (width) {
+        *width = mFrameWidth;
+    }
+
+    if (height) {
+        *height = mFrameHeight;
+    }
+}
diff --git a/automotive/evs/1.0/vts/functional/FrameHandler.h b/automotive/evs/1.0/vts/functional/FrameHandler.h
index 17a3980..3f6103d 100644
--- a/automotive/evs/1.0/vts/functional/FrameHandler.h
+++ b/automotive/evs/1.0/vts/functional/FrameHandler.h
@@ -61,6 +61,7 @@
 
     void waitForFrameCount(unsigned frameCount);
     void getFramesCounters(unsigned* received, unsigned* displayed);
+    void getFrameDimension(unsigned* width, unsigned* height);
 
 private:
     // Implementation for ::android::hardware::automotive::evs::V1_0::ICarCameraStream
@@ -85,6 +86,8 @@
     bool                        mRunning = false;
     unsigned                    mFramesReceived = 0;    // Simple counter -- rolls over eventually!
     unsigned                    mFramesDisplayed = 0;   // Simple counter -- rolls over eventually!
+    unsigned                    mFrameWidth = 0;
+    unsigned                    mFrameHeight = 0;
 };
 
 
diff --git a/automotive/evs/1.0/vts/functional/VtsHalEvsV1_0TargetTest.cpp b/automotive/evs/1.0/vts/functional/VtsHalEvsV1_0TargetTest.cpp
index d904ad0..f7580f0 100644
--- a/automotive/evs/1.0/vts/functional/VtsHalEvsV1_0TargetTest.cpp
+++ b/automotive/evs/1.0/vts/functional/VtsHalEvsV1_0TargetTest.cpp
@@ -84,9 +84,12 @@
 public:
     virtual void SetUp() override {
         // Make sure we can connect to the enumerator
-        pEnumerator = getService<IEvsEnumerator>(
-            EvsHidlEnvironment::Instance()->getServiceName<IEvsEnumerator>(kEnumeratorName));
+        string service_name =
+            EvsHidlEnvironment::Instance()->getServiceName<IEvsEnumerator>(kEnumeratorName);
+        pEnumerator = getService<IEvsEnumerator>(service_name);
         ASSERT_NE(pEnumerator.get(), nullptr);
+
+        mIsHwModule = !service_name.compare(kEnumeratorName);
     }
 
     virtual void TearDown() override {}
@@ -114,12 +117,13 @@
 
     sp<IEvsEnumerator>          pEnumerator;    // Every test needs access to the service
     std::vector <CameraDesc>    cameraInfo;     // Empty unless/until loadCameraList() is called
+    bool                        mIsHwModule;    // boolean to tell current module under testing
+                                                // is HW module implementation.
 };
 
 
-//
-// Tests start here...
-//
+// Test cases, their implementations, and corresponding requirements are
+// documented at go/aae-evs-public-api-test.
 
 /*
  * CameraOpenClean:
@@ -180,9 +184,14 @@
         ASSERT_NE(pCam, pCam2);
         ASSERT_NE(pCam2, nullptr);
 
-        // Verify that the old camera rejects calls
-        Return<EvsResult> badResult = pCam->setMaxFramesInFlight(2);
-        EXPECT_EQ(EvsResult::OWNERSHIP_LOST, EvsResult(badResult));
+        Return<EvsResult> result = pCam->setMaxFramesInFlight(2);
+        if (mIsHwModule) {
+            // Verify that the old camera rejects calls via HW module.
+            EXPECT_EQ(EvsResult::OWNERSHIP_LOST, EvsResult(result));
+        } else {
+            // default implementation supports multiple clients.
+            EXPECT_EQ(EvsResult::OK, EvsResult(result));
+        }
 
         // Close the superceded camera
         pEnumerator->closeCamera(pCam);
@@ -194,7 +203,8 @@
                              }
         );
 
-        // Leave the second camera dangling so it gets cleaned up by the destructor path
+        // Close the second camera instance
+        pEnumerator->closeCamera(pCam2);
     }
 
     // Sleep here to ensure the destructor cleanup has time to run so we don't break follow on tests
@@ -343,6 +353,11 @@
         printf("Measured time to first frame %0.2f ms\n", timeToFirstFrame * kNanoToMilliseconds);
         ALOGI("Measured time to first frame %0.2f ms", timeToFirstFrame * kNanoToMilliseconds);
 
+        // Check aspect ratio
+        unsigned width = 0, height = 0;
+        frameHandler->getFrameDimension(&width, &height);
+        EXPECT_GE(width, height);
+
         // Wait a bit, then ensure we get at least the required minimum number of frames
         sleep(5);
         nsecs_t end = systemTime(SYSTEM_TIME_MONOTONIC);
@@ -496,6 +511,96 @@
     pEnumerator->closeDisplay(pDisplay);
 }
 
+
+/*
+ * MultiCameraStream:
+ * Verify that each client can start and stop video streams on the same
+ * underlying camera.
+ */
+TEST_F(EvsHidlTest, MultiCameraStream) {
+    ALOGI("Starting MultiCameraStream test");
+
+    if (mIsHwModule) {
+        // This test is not for HW module implementation.
+        return;
+    }
+
+    // Get the camera list
+    loadCameraList();
+
+    // Test each reported camera
+    for (auto&& cam: cameraInfo) {
+        // Create two camera clients.
+        sp <IEvsCamera> pCam0 = pEnumerator->openCamera(cam.cameraId);
+        ASSERT_NE(pCam0, nullptr);
+
+        sp <IEvsCamera> pCam1 = pEnumerator->openCamera(cam.cameraId);
+        ASSERT_NE(pCam1, nullptr);
+
+        // Set up per-client frame receiver objects which will fire up its own thread
+        sp<FrameHandler> frameHandler0 = new FrameHandler(pCam0, cam,
+                                                          nullptr,
+                                                          FrameHandler::eAutoReturn);
+        ASSERT_NE(frameHandler0, nullptr);
+
+        sp<FrameHandler> frameHandler1 = new FrameHandler(pCam1, cam,
+                                                          nullptr,
+                                                          FrameHandler::eAutoReturn);
+        ASSERT_NE(frameHandler1, nullptr);
+
+        // Start the camera's video stream via client 0
+        bool startResult = false;
+        startResult = frameHandler0->startStream() &&
+                      frameHandler1->startStream();
+        ASSERT_TRUE(startResult);
+
+        // Ensure the stream starts
+        frameHandler0->waitForFrameCount(1);
+        frameHandler1->waitForFrameCount(1);
+
+        nsecs_t firstFrame = systemTime(SYSTEM_TIME_MONOTONIC);
+
+        // Wait a bit, then ensure both clients get at least the required minimum number of frames
+        sleep(5);
+        nsecs_t end = systemTime(SYSTEM_TIME_MONOTONIC);
+        unsigned framesReceived0 = 0, framesReceived1 = 0;
+        frameHandler0->getFramesCounters(&framesReceived0, nullptr);
+        frameHandler1->getFramesCounters(&framesReceived1, nullptr);
+        framesReceived0 = framesReceived0 - 1;    // Back out the first frame we already waited for
+        framesReceived1 = framesReceived1 - 1;    // Back out the first frame we already waited for
+        nsecs_t runTime = end - firstFrame;
+        float framesPerSecond0 = framesReceived0 / (runTime * kNanoToSeconds);
+        float framesPerSecond1 = framesReceived1 / (runTime * kNanoToSeconds);
+        printf("Measured camera rate %3.2f fps and %3.2f fps\n", framesPerSecond0, framesPerSecond1);
+        ALOGI("Measured camera rate %3.2f fps and %3.2f fps", framesPerSecond0, framesPerSecond1);
+        EXPECT_GE(framesPerSecond0, kMinimumFramesPerSecond);
+        EXPECT_GE(framesPerSecond1, kMinimumFramesPerSecond);
+
+        // Shutdown one client
+        frameHandler0->shutdown();
+
+        // Read frame counters again
+        frameHandler0->getFramesCounters(&framesReceived0, nullptr);
+        frameHandler1->getFramesCounters(&framesReceived1, nullptr);
+
+        // Wait a bit again
+        sleep(5);
+        unsigned framesReceivedAfterStop0 = 0, framesReceivedAfterStop1 = 0;
+        frameHandler0->getFramesCounters(&framesReceivedAfterStop0, nullptr);
+        frameHandler1->getFramesCounters(&framesReceivedAfterStop1, nullptr);
+        EXPECT_EQ(framesReceived0, framesReceivedAfterStop0);
+        EXPECT_LT(framesReceived1, framesReceivedAfterStop1);
+
+        // Shutdown another
+        frameHandler1->shutdown();
+
+        // Explicitly release the camera
+        pEnumerator->closeCamera(pCam0);
+        pEnumerator->closeCamera(pCam1);
+    }
+}
+
+
 int main(int argc, char** argv) {
     ::testing::AddGlobalTestEnvironment(EvsHidlEnvironment::Instance());
     ::testing::InitGoogleTest(&argc, argv);
diff --git a/automotive/vehicle/2.0/default/common/include/vhal_v2_0/VmsUtils.h b/automotive/vehicle/2.0/default/common/include/vhal_v2_0/VmsUtils.h
index 7082566..f064367 100644
--- a/automotive/vehicle/2.0/default/common/include/vhal_v2_0/VmsUtils.h
+++ b/automotive/vehicle/2.0/default/common/include/vhal_v2_0/VmsUtils.h
@@ -60,6 +60,8 @@
 };
 
 struct VmsLayerAndPublisher {
+    VmsLayerAndPublisher(VmsLayer layer, int publisher_id)
+        : layer(layer), publisher_id(publisher_id) {}
     VmsLayer layer;
     int publisher_id;
 };
@@ -162,12 +164,16 @@
 std::unique_ptr<VehiclePropValue> createSubscriptionsRequest();
 
 // Creates a VehiclePropValue containing a message of type VmsMessageType.DATA.
-// Returns a nullptr if the byte string in bytes is empty.
+// Returns a nullptr if the vms_packet string in bytes is empty or if the layer_publisher
+// information in VmsLayerAndPublisher format is missing the later or publisher
+// information.
 //
 // For example, to build a VehiclePropValue message containing a proto, the caller
-// should convert the proto to a byte string using the SerializeToString proto
-// API, then use this inteface to build the VehicleProperty.
-std::unique_ptr<VehiclePropValue> createDataMessage(const std::string& bytes);
+// should first convert the proto to a byte string (vms_packet) using the
+// SerializeToString proto API. Then, it use this interface to build the VehicleProperty
+// by passing publisher and layer information (layer_publisher) and the vms_packet.
+std::unique_ptr<VehiclePropValue> createDataMessageWithLayerPublisherInfo(
+        const VmsLayerAndPublisher& layer_publisher, const std::string& vms_packet);
 
 // Creates a VehiclePropValue containing a message of type
 // VmsMessageType.PUBLISHER_ID_REQUEST with the given publisher information.
diff --git a/automotive/vehicle/2.0/default/common/src/VmsUtils.cpp b/automotive/vehicle/2.0/default/common/src/VmsUtils.cpp
index 111f6ea..a5fcbaf 100644
--- a/automotive/vehicle/2.0/default/common/src/VmsUtils.cpp
+++ b/automotive/vehicle/2.0/default/common/src/VmsUtils.cpp
@@ -126,10 +126,13 @@
     return result;
 }
 
-std::unique_ptr<VehiclePropValue> createDataMessage(const std::string& bytes) {
-    auto result = createBaseVmsMessage(kMessageTypeSize);
-    result->value.int32Values = hidl_vec<int32_t>{toInt(VmsMessageType::DATA)};
-    result->value.bytes = std::vector<uint8_t>(bytes.begin(), bytes.end());
+std::unique_ptr<VehiclePropValue> createDataMessageWithLayerPublisherInfo(
+        const VmsLayerAndPublisher& layer_publisher, const std::string& vms_packet) {
+    auto result = createBaseVmsMessage(kMessageTypeSize + kLayerAndPublisherSize);
+    result->value.int32Values = hidl_vec<int32_t>{
+            toInt(VmsMessageType::DATA), layer_publisher.layer.type, layer_publisher.layer.subtype,
+            layer_publisher.layer.version, layer_publisher.publisher_id};
+    result->value.bytes = std::vector<uint8_t>(vms_packet.begin(), vms_packet.end());
     return result;
 }
 
diff --git a/automotive/vehicle/2.0/default/tests/VmsUtils_test.cpp b/automotive/vehicle/2.0/default/tests/VmsUtils_test.cpp
index 2b3efc7..3716738 100644
--- a/automotive/vehicle/2.0/default/tests/VmsUtils_test.cpp
+++ b/automotive/vehicle/2.0/default/tests/VmsUtils_test.cpp
@@ -139,12 +139,23 @@
 }
 
 TEST(VmsUtilsTest, dataMessage) {
-    std::string bytes = "aaa";
-    auto message = createDataMessage(bytes);
+    const std::string bytes = "aaa";
+    const VmsLayerAndPublisher layer_and_publisher(VmsLayer(2, 0, 1), 123);
+    auto message = createDataMessageWithLayerPublisherInfo(layer_and_publisher, bytes);
     ASSERT_NE(message, nullptr);
     EXPECT_TRUE(isValidVmsMessage(*message));
     EXPECT_EQ(message->prop, toInt(VehicleProperty::VEHICLE_MAP_SERVICE));
-    EXPECT_EQ(message->value.int32Values.size(), 0x1ul);
+    EXPECT_EQ(message->value.int32Values.size(), 0x5ul);
+    EXPECT_EQ(message->value.int32Values[0], toInt(VmsMessageType::DATA));
+
+    // Layer
+    EXPECT_EQ(message->value.int32Values[1], 2);
+    EXPECT_EQ(message->value.int32Values[2], 0);
+    EXPECT_EQ(message->value.int32Values[3], 1);
+
+    // Publisher ID
+    EXPECT_EQ(message->value.int32Values[4], 123);
+
     EXPECT_EQ(parseMessageType(*message), VmsMessageType::DATA);
     EXPECT_EQ(message->value.bytes.size(), bytes.size());
     EXPECT_EQ(memcmp(message->value.bytes.data(), bytes.data(), bytes.size()), 0);
@@ -164,8 +175,9 @@
 }
 
 TEST(VmsUtilsTest, parseDataMessage) {
-    std::string bytes = "aaa";
-    auto message = createDataMessage(bytes);
+    const std::string bytes = "aaa";
+    const VmsLayerAndPublisher layer_and_publisher(VmsLayer(1, 0, 1), 123);
+    auto message = createDataMessageWithLayerPublisherInfo(layer_and_publisher, bytes);
     auto data_str = parseData(*message);
     ASSERT_FALSE(data_str.empty());
     EXPECT_EQ(data_str, bytes);
diff --git a/automotive/vehicle/2.0/types.hal b/automotive/vehicle/2.0/types.hal
index e36468a..f6ebcdd 100644
--- a/automotive/vehicle/2.0/types.hal
+++ b/automotive/vehicle/2.0/types.hal
@@ -641,7 +641,9 @@
     /**
      * Night mode
      *
-     * True indicates that night mode is currently enabled.
+     * True indicates that the night mode sensor has detected that the car cabin environment has
+     * low light. The platform could use this, for example, to enable appropriate UI for
+     * better viewing in dark or low light environments.
      *
      * @change_mode VehiclePropertyChangeMode:ON_CHANGE
      * @access VehiclePropertyAccess:READ
@@ -983,6 +985,10 @@
      *
      * Indicates whether the vehicle is displaying temperature to the user as
      * Celsius or Fahrenheit.
+     * VehiclePropConfig.configArray is used to indicate the supported temperature display units.
+     * For example: configArray[0] = CELSIUS
+     *              configArray[1] = FAHRENHEIT
+     *
      * This parameter MAY be used for displaying any HVAC temperature in the system.
      * Values must be one of VehicleUnit::CELSIUS or VehicleUnit::FAHRENHEIT
      * Note that internally, all temperatures are represented in floating point Celsius.
@@ -1329,6 +1335,8 @@
      * int32Values[2] : target display defined in VehicleDisplay. Events not
      *                  tied to specific display must be sent to
      *                  VehicleDisplay#MAIN.
+     * int32Values[3] : [optional] Number of ticks. The value must be equal or
+     *                  greater than 1. When omitted, Android will default to 1.
      *
      * @change_mode VehiclePropertyChangeMode:ON_CHANGE
      * @access VehiclePropertyAccess:READ
@@ -2792,6 +2800,14 @@
      */
     int32_t areaId;
 
+    /**
+     * If the property has @data_enum, leave the range to zero.
+     *
+     * Range will be ignored in the following cases:
+     *    - The VehiclePropertyType is not INT32, INT64 or FLOAT.
+     *    - Both of min value and max value are zero.
+     */
+
     int32_t minInt32Value;
     int32_t maxInt32Value;
 
@@ -3271,16 +3287,6 @@
  */
 enum VmsMessageType : int32_t {
     /**
-     * A notification indicating that the sender has been reset.
-     *
-     * The receiving party must reset its internal state and respond to the
-     * sender with a START_SESSION message as acknowledgement.
-     *
-     * This message type uses enum VmsStartSessionMessageIntegerValuesIndex.
-     */
-    START_SESSION = 17,
-
-    /**
      * A request from the subscribers to the VMS service to subscribe to a layer.
      *
      * This message type uses enum VmsMessageWithLayerIntegerValuesIndex.
@@ -3396,6 +3402,16 @@
      */
     PUBLISHER_INFORMATION_RESPONSE = 16,
 
+    /**
+     * A notification indicating that the sender has been reset.
+     *
+     * The receiving party must reset its internal state and respond to the
+     * sender with a START_SESSION message as acknowledgement.
+     *
+     * This message type uses enum VmsStartSessionMessageIntegerValuesIndex.
+     */
+    START_SESSION = 17,
+
     LAST_VMS_MESSAGE_TYPE = START_SESSION,
 };
 
diff --git a/camera/common/1.0/default/Android.bp b/camera/common/1.0/default/Android.bp
index 21f81f5..3e5c6d7 100644
--- a/camera/common/1.0/default/Android.bp
+++ b/camera/common/1.0/default/Android.bp
@@ -20,6 +20,7 @@
         "libhardware",
         "libcamera_metadata",
         "android.hardware.graphics.mapper@2.0",
+        "android.hardware.graphics.mapper@3.0",
         "libexif",
     ],
     include_dirs: ["system/media/private/camera/include"],
diff --git a/camera/common/1.0/default/HandleImporter.cpp b/camera/common/1.0/default/HandleImporter.cpp
index 21706a8..b8c40e9 100644
--- a/camera/common/1.0/default/HandleImporter.cpp
+++ b/camera/common/1.0/default/HandleImporter.cpp
@@ -25,7 +25,9 @@
 namespace V1_0 {
 namespace helper {
 
-using MapperError = android::hardware::graphics::mapper::V2_0::Error;
+using MapperErrorV2 = android::hardware::graphics::mapper::V2_0::Error;
+using MapperErrorV3 = android::hardware::graphics::mapper::V3_0::Error;
+using IMapperV3 = android::hardware::graphics::mapper::V3_0::IMapper;
 
 HandleImporter::HandleImporter() : mInitialized(false) {}
 
@@ -34,8 +36,14 @@
         return;
     }
 
-    mMapper = IMapper::getService();
-    if (mMapper == nullptr) {
+    mMapperV3 = IMapperV3::getService();
+    if (mMapperV3 != nullptr) {
+        mInitialized = true;
+        return;
+    }
+
+    mMapperV2 = IMapper::getService();
+    if (mMapperV2 == nullptr) {
         ALOGE("%s: cannnot acccess graphics mapper HAL!", __FUNCTION__);
         return;
     }
@@ -45,10 +53,90 @@
 }
 
 void HandleImporter::cleanup() {
-    mMapper.clear();
+    mMapperV3.clear();
+    mMapperV2.clear();
     mInitialized = false;
 }
 
+template<class M, class E>
+bool HandleImporter::importBufferInternal(const sp<M> mapper, buffer_handle_t& handle) {
+    E error;
+    buffer_handle_t importedHandle;
+    auto ret = mapper->importBuffer(
+        hidl_handle(handle),
+        [&](const auto& tmpError, const auto& tmpBufferHandle) {
+            error = tmpError;
+            importedHandle = static_cast<buffer_handle_t>(tmpBufferHandle);
+        });
+
+    if (!ret.isOk()) {
+        ALOGE("%s: mapper importBuffer failed: %s",
+                __FUNCTION__, ret.description().c_str());
+        return false;
+    }
+
+    if (error != E::NONE) {
+        return false;
+    }
+
+    handle = importedHandle;
+    return true;
+}
+
+template<class M, class E>
+YCbCrLayout HandleImporter::lockYCbCrInternal(const sp<M> mapper, buffer_handle_t& buf,
+        uint64_t cpuUsage, const IMapper::Rect& accessRegion) {
+    hidl_handle acquireFenceHandle;
+    auto buffer = const_cast<native_handle_t*>(buf);
+    YCbCrLayout layout = {};
+
+    typename M::Rect accessRegionCopy = {accessRegion.left, accessRegion.top,
+            accessRegion.width, accessRegion.height};
+    mapper->lockYCbCr(buffer, cpuUsage, accessRegionCopy, acquireFenceHandle,
+            [&](const auto& tmpError, const auto& tmpLayout) {
+                if (tmpError == E::NONE) {
+                    // Member by member copy from different versions of YCbCrLayout.
+                    layout.y = tmpLayout.y;
+                    layout.cb = tmpLayout.cb;
+                    layout.cr = tmpLayout.cr;
+                    layout.yStride = tmpLayout.yStride;
+                    layout.cStride = tmpLayout.cStride;
+                    layout.chromaStep = tmpLayout.chromaStep;
+                } else {
+                    ALOGE("%s: failed to lockYCbCr error %d!", __FUNCTION__, tmpError);
+                }
+           });
+    return layout;
+}
+
+template<class M, class E>
+int HandleImporter::unlockInternal(const sp<M> mapper, buffer_handle_t& buf) {
+    int releaseFence = -1;
+    auto buffer = const_cast<native_handle_t*>(buf);
+
+    mapper->unlock(
+        buffer, [&](const auto& tmpError, const auto& tmpReleaseFence) {
+            if (tmpError == E::NONE) {
+                auto fenceHandle = tmpReleaseFence.getNativeHandle();
+                if (fenceHandle) {
+                    if (fenceHandle->numInts != 0 || fenceHandle->numFds != 1) {
+                        ALOGE("%s: bad release fence numInts %d numFds %d",
+                                __FUNCTION__, fenceHandle->numInts, fenceHandle->numFds);
+                        return;
+                    }
+                    releaseFence = dup(fenceHandle->data[0]);
+                    if (releaseFence < 0) {
+                        ALOGE("%s: bad release fence FD %d",
+                                __FUNCTION__, releaseFence);
+                    }
+                }
+            } else {
+                ALOGE("%s: failed to unlock error %d!", __FUNCTION__, tmpError);
+            }
+        });
+    return releaseFence;
+}
+
 // 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.
@@ -63,33 +151,16 @@
         initializeLocked();
     }
 
-    if (mMapper == nullptr) {
-        ALOGE("%s: mMapper is null!", __FUNCTION__);
-        return false;
+    if (mMapperV3 != nullptr) {
+        return importBufferInternal<IMapperV3, MapperErrorV3>(mMapperV3, handle);
     }
 
-    MapperError error;
-    buffer_handle_t importedHandle;
-    auto ret = mMapper->importBuffer(
-        hidl_handle(handle),
-        [&](const auto& tmpError, const auto& tmpBufferHandle) {
-            error = tmpError;
-            importedHandle = static_cast<buffer_handle_t>(tmpBufferHandle);
-        });
-
-    if (!ret.isOk()) {
-        ALOGE("%s: mapper importBuffer failed: %s",
-                __FUNCTION__, ret.description().c_str());
-        return false;
+    if (mMapperV2 != nullptr) {
+        return importBufferInternal<IMapper, MapperErrorV2>(mMapperV2, handle);
     }
 
-    if (error != MapperError::NONE) {
-        return false;
-    }
-
-    handle = importedHandle;
-
-    return true;
+    ALOGE("%s: mMapperV3 and mMapperV2 are both null!", __FUNCTION__);
+    return false;
 }
 
 void HandleImporter::freeBuffer(buffer_handle_t handle) {
@@ -98,15 +169,23 @@
     }
 
     Mutex::Autolock lock(mLock);
-    if (mMapper == nullptr) {
-        ALOGE("%s: mMapper is null!", __FUNCTION__);
+    if (mMapperV3 == nullptr && mMapperV2 == nullptr) {
+        ALOGE("%s: mMapperV3 and mMapperV2 are both null!", __FUNCTION__);
         return;
     }
 
-    auto ret = mMapper->freeBuffer(const_cast<native_handle_t*>(handle));
-    if (!ret.isOk()) {
-        ALOGE("%s: mapper freeBuffer failed: %s",
-                __FUNCTION__, ret.description().c_str());
+    if (mMapperV3 != nullptr) {
+        auto ret = mMapperV3->freeBuffer(const_cast<native_handle_t*>(handle));
+        if (!ret.isOk()) {
+            ALOGE("%s: mapper freeBuffer failed: %s",
+                    __FUNCTION__, ret.description().c_str());
+        }
+    } else {
+        auto ret = mMapperV2->freeBuffer(const_cast<native_handle_t*>(handle));
+        if (!ret.isOk()) {
+            ALOGE("%s: mapper freeBuffer failed: %s",
+                    __FUNCTION__, ret.description().c_str());
+        }
     }
 }
 
@@ -138,91 +217,82 @@
         buffer_handle_t& buf, uint64_t cpuUsage, size_t size) {
     Mutex::Autolock lock(mLock);
     void *ret = 0;
-    IMapper::Rect accessRegion { 0, 0, static_cast<int>(size), 1 };
 
     if (!mInitialized) {
         initializeLocked();
     }
 
-    if (mMapper == nullptr) {
-        ALOGE("%s: mMapper is null!", __FUNCTION__);
+    if (mMapperV3 == nullptr && mMapperV2 == nullptr) {
+        ALOGE("%s: mMapperV3 and mMapperV2 are both null!", __FUNCTION__);
         return ret;
     }
 
     hidl_handle acquireFenceHandle;
     auto buffer = const_cast<native_handle_t*>(buf);
-    mMapper->lock(buffer, cpuUsage, accessRegion, acquireFenceHandle,
-            [&](const auto& tmpError, const auto& tmpPtr) {
-                if (tmpError == MapperError::NONE) {
-                    ret = tmpPtr;
-                } else {
-                    ALOGE("%s: failed to lock error %d!",
-                          __FUNCTION__, tmpError);
-                }
-           });
+    if (mMapperV3 != nullptr) {
+        IMapperV3::Rect accessRegion { 0, 0, static_cast<int>(size), 1 };
+        // No need to use bytesPerPixel and bytesPerStride because we are using
+        // an 1-D buffer and accressRegion.
+        mMapperV3->lock(buffer, cpuUsage, accessRegion, acquireFenceHandle,
+                [&](const auto& tmpError, const auto& tmpPtr, const auto& /*bytesPerPixel*/,
+                        const auto& /*bytesPerStride*/) {
+                    if (tmpError == MapperErrorV3::NONE) {
+                        ret = tmpPtr;
+                    } else {
+                        ALOGE("%s: failed to lock error %d!",
+                              __FUNCTION__, tmpError);
+                    }
+               });
+    } else {
+        IMapper::Rect accessRegion { 0, 0, static_cast<int>(size), 1 };
+        mMapperV2->lock(buffer, cpuUsage, accessRegion, acquireFenceHandle,
+                [&](const auto& tmpError, const auto& tmpPtr) {
+                    if (tmpError == MapperErrorV2::NONE) {
+                        ret = tmpPtr;
+                    } else {
+                        ALOGE("%s: failed to lock error %d!",
+                              __FUNCTION__, tmpError);
+                    }
+               });
+    }
 
     ALOGV("%s: ptr %p size: %zu", __FUNCTION__, ret, size);
     return ret;
 }
 
-
 YCbCrLayout HandleImporter::lockYCbCr(
         buffer_handle_t& buf, uint64_t cpuUsage,
         const IMapper::Rect& accessRegion) {
     Mutex::Autolock lock(mLock);
-    YCbCrLayout layout = {};
 
     if (!mInitialized) {
         initializeLocked();
     }
 
-    if (mMapper == nullptr) {
-        ALOGE("%s: mMapper is null!", __FUNCTION__);
-        return layout;
+    if (mMapperV3 != nullptr) {
+        return lockYCbCrInternal<IMapperV3, MapperErrorV3>(
+                mMapperV3, buf, cpuUsage, accessRegion);
     }
 
-    hidl_handle acquireFenceHandle;
-    auto buffer = const_cast<native_handle_t*>(buf);
-    mMapper->lockYCbCr(buffer, cpuUsage, accessRegion, acquireFenceHandle,
-            [&](const auto& tmpError, const auto& tmpLayout) {
-                if (tmpError == MapperError::NONE) {
-                    layout = tmpLayout;
-                } else {
-                    ALOGE("%s: failed to lockYCbCr error %d!", __FUNCTION__, tmpError);
-                }
-           });
+    if (mMapperV2 != nullptr) {
+        return lockYCbCrInternal<IMapper, MapperErrorV2>(
+                mMapperV2, buf, cpuUsage, accessRegion);
+    }
 
-    ALOGV("%s: layout y %p cb %p cr %p y_str %d c_str %d c_step %d",
-            __FUNCTION__, layout.y, layout.cb, layout.cr,
-            layout.yStride, layout.cStride, layout.chromaStep);
-    return layout;
+    ALOGE("%s: mMapperV3 and mMapperV2 are both null!", __FUNCTION__);
+    return {};
 }
 
 int HandleImporter::unlock(buffer_handle_t& buf) {
-    int releaseFence = -1;
-    auto buffer = const_cast<native_handle_t*>(buf);
-    mMapper->unlock(
-        buffer, [&](const auto& tmpError, const auto& tmpReleaseFence) {
-            if (tmpError == MapperError::NONE) {
-                auto fenceHandle = tmpReleaseFence.getNativeHandle();
-                if (fenceHandle) {
-                    if (fenceHandle->numInts != 0 || fenceHandle->numFds != 1) {
-                        ALOGE("%s: bad release fence numInts %d numFds %d",
-                                __FUNCTION__, fenceHandle->numInts, fenceHandle->numFds);
-                        return;
-                    }
-                    releaseFence = dup(fenceHandle->data[0]);
-                    if (releaseFence <= 0) {
-                        ALOGE("%s: bad release fence FD %d",
-                                __FUNCTION__, releaseFence);
-                    }
-                }
-            } else {
-                ALOGE("%s: failed to unlock error %d!", __FUNCTION__, tmpError);
-            }
-        });
+    if (mMapperV3 != nullptr) {
+        return unlockInternal<IMapperV3, MapperErrorV3>(mMapperV3, buf);
+    }
+    if (mMapperV2 != nullptr) {
+        return unlockInternal<IMapper, MapperErrorV2>(mMapperV2, buf);
+    }
 
-    return releaseFence;
+    ALOGE("%s: mMapperV3 and mMapperV2 are both null!", __FUNCTION__);
+    return -1;
 }
 
 } // namespace helper
diff --git a/camera/common/1.0/default/OWNERS b/camera/common/1.0/default/OWNERS
index 70128c7..f48a95c 100644
--- a/camera/common/1.0/default/OWNERS
+++ b/camera/common/1.0/default/OWNERS
@@ -1 +1 @@
-include platform/frameworks/av:camera/OWNERS
+include platform/frameworks/av:/camera/OWNERS
diff --git a/camera/common/1.0/default/include/HandleImporter.h b/camera/common/1.0/default/include/HandleImporter.h
index f9cd9fb..a93d455 100644
--- a/camera/common/1.0/default/include/HandleImporter.h
+++ b/camera/common/1.0/default/include/HandleImporter.h
@@ -19,6 +19,7 @@
 
 #include <utils/Mutex.h>
 #include <android/hardware/graphics/mapper/2.0/IMapper.h>
+#include <android/hardware/graphics/mapper/3.0/IMapper.h>
 #include <cutils/native_handle.h>
 
 using android::hardware::graphics::mapper::V2_0::IMapper;
@@ -57,10 +58,18 @@
     void initializeLocked();
     void cleanup();
 
+    template<class M, class E>
+    bool importBufferInternal(const sp<M> mapper, buffer_handle_t& handle);
+    template<class M, class E>
+    YCbCrLayout lockYCbCrInternal(const sp<M> mapper, buffer_handle_t& buf, uint64_t cpuUsage,
+            const IMapper::Rect& accessRegion);
+    template<class M, class E>
+    int unlockInternal(const sp<M> mapper, buffer_handle_t& buf);
+
     Mutex mLock;
     bool mInitialized;
-    sp<IMapper> mMapper;
-
+    sp<IMapper> mMapperV2;
+    sp<graphics::mapper::V3_0::IMapper> mMapperV3;
 };
 
 } // namespace helper
diff --git a/camera/device/1.0/default/Android.bp b/camera/device/1.0/default/Android.bp
index 4a7fc9c..aa3b941 100644
--- a/camera/device/1.0/default/Android.bp
+++ b/camera/device/1.0/default/Android.bp
@@ -15,6 +15,7 @@
         "android.hardware.camera.common@1.0",
         "android.hardware.graphics.allocator@2.0",
         "android.hardware.graphics.mapper@2.0",
+        "android.hardware.graphics.mapper@3.0",
         "android.hardware.graphics.common@1.0",
         "android.hidl.allocator@1.0",
         "android.hidl.memory@1.0",
diff --git a/camera/device/3.2/default/Android.bp b/camera/device/3.2/default/Android.bp
index 325c008..edb008e 100644
--- a/camera/device/3.2/default/Android.bp
+++ b/camera/device/3.2/default/Android.bp
@@ -13,6 +13,7 @@
         "android.hardware.camera.device@3.2",
         "android.hardware.camera.provider@2.4",
         "android.hardware.graphics.mapper@2.0",
+        "android.hardware.graphics.mapper@3.0",
         "liblog",
         "libhardware",
         "libcamera_metadata",
diff --git a/camera/device/3.3/default/Android.bp b/camera/device/3.3/default/Android.bp
index b1e9b46..39d379d 100644
--- a/camera/device/3.3/default/Android.bp
+++ b/camera/device/3.3/default/Android.bp
@@ -15,6 +15,7 @@
         "android.hardware.camera.device@3.3",
         "android.hardware.camera.provider@2.4",
         "android.hardware.graphics.mapper@2.0",
+        "android.hardware.graphics.mapper@3.0",
         "liblog",
         "libhardware",
         "libcamera_metadata",
diff --git a/camera/device/3.4/default/Android.bp b/camera/device/3.4/default/Android.bp
index 272bf42..c22b13c 100644
--- a/camera/device/3.4/default/Android.bp
+++ b/camera/device/3.4/default/Android.bp
@@ -48,6 +48,7 @@
         "android.hardware.camera.device@3.4",
         "android.hardware.camera.provider@2.4",
         "android.hardware.graphics.mapper@2.0",
+        "android.hardware.graphics.mapper@3.0",
         "liblog",
         "libhardware",
         "libcamera_metadata",
@@ -84,6 +85,7 @@
         "android.hardware.camera.device@3.4",
         "android.hardware.camera.provider@2.4",
         "android.hardware.graphics.mapper@2.0",
+        "android.hardware.graphics.mapper@3.0",
         "liblog",
         "libhardware",
         "libcamera_metadata",
diff --git a/camera/device/3.4/default/CameraDeviceSession.cpp b/camera/device/3.4/default/CameraDeviceSession.cpp
index 03b6050..b4ebe22 100644
--- a/camera/device/3.4/default/CameraDeviceSession.cpp
+++ b/camera/device/3.4/default/CameraDeviceSession.cpp
@@ -75,7 +75,7 @@
 void CameraDeviceSession::configureStreams_3_4_Impl(
         const StreamConfiguration& requestedConfiguration,
         ICameraDeviceSession::configureStreams_3_4_cb _hidl_cb,
-        uint32_t streamConfigCounter)  {
+        uint32_t streamConfigCounter, bool useOverriddenFields)  {
     Status status = initStatus();
     HalStreamConfiguration outStreams;
 
@@ -133,7 +133,8 @@
     mStreamConfigCounter = streamConfigCounter;
     hidl_vec<camera3_stream_t*> streams;
     stream_list.session_parameters = paramBuffer;
-    if (!preProcessConfigurationLocked_3_4(requestedConfiguration, &stream_list, &streams)) {
+    if (!preProcessConfigurationLocked_3_4(requestedConfiguration,
+            useOverriddenFields, &stream_list, &streams)) {
         _hidl_cb(Status::INTERNAL_ERROR, outStreams);
         return;
     }
@@ -164,7 +165,7 @@
 }
 
 bool CameraDeviceSession::preProcessConfigurationLocked_3_4(
-        const StreamConfiguration& requestedConfiguration,
+        const StreamConfiguration& requestedConfiguration, bool useOverriddenFields,
         camera3_stream_configuration_t *stream_list /*out*/,
         hidl_vec<camera3_stream_t*> *streams /*out*/) {
 
@@ -189,19 +190,31 @@
                     mStreamMap[id].data_space);
             mCirculatingBuffers.emplace(stream.mId, CirculatingBuffers{});
         } else {
-            // width/height/format must not change, but usage/rotation might need to change
+            // width/height/format must not change, but usage/rotation might need to change.
+            // format and data_space may change.
             if (mStreamMap[id].stream_type !=
                     (int) requestedConfiguration.streams[i].v3_2.streamType ||
                     mStreamMap[id].width != requestedConfiguration.streams[i].v3_2.width ||
                     mStreamMap[id].height != requestedConfiguration.streams[i].v3_2.height ||
-                    mStreamMap[id].format != (int) requestedConfiguration.streams[i].v3_2.format ||
-                    mStreamMap[id].data_space !=
-                            mapToLegacyDataspace( static_cast<android_dataspace_t> (
-                                    requestedConfiguration.streams[i].v3_2.dataSpace)) ||
                     mPhysicalCameraIdMap[id] != requestedConfiguration.streams[i].physicalCameraId) {
                 ALOGE("%s: stream %d configuration changed!", __FUNCTION__, id);
                 return false;
             }
+            if (useOverriddenFields) {
+                android_dataspace_t requestedDataSpace =
+                        mapToLegacyDataspace(static_cast<android_dataspace_t>(
+                        requestedConfiguration.streams[i].v3_2.dataSpace));
+                if (mStreamMap[id].format != (int) requestedConfiguration.streams[i].v3_2.format ||
+                        mStreamMap[id].data_space != requestedDataSpace) {
+                    ALOGE("%s: stream %d configuration changed!", __FUNCTION__, id);
+                    return false;
+                }
+            } else {
+                mStreamMap[id].format =
+                        (int) requestedConfiguration.streams[i].v3_2.format;
+                mStreamMap[id].data_space = (android_dataspace_t)
+                        requestedConfiguration.streams[i].v3_2.dataSpace;
+            }
             mStreamMap[id].rotation = (int) requestedConfiguration.streams[i].v3_2.rotation;
             mStreamMap[id].usage = (uint32_t) requestedConfiguration.streams[i].v3_2.usage;
         }
diff --git a/camera/device/3.4/default/include/device_v3_4_impl/CameraDeviceSession.h b/camera/device/3.4/default/include/device_v3_4_impl/CameraDeviceSession.h
index 1db7b41..280c4be 100644
--- a/camera/device/3.4/default/include/device_v3_4_impl/CameraDeviceSession.h
+++ b/camera/device/3.4/default/include/device_v3_4_impl/CameraDeviceSession.h
@@ -80,7 +80,7 @@
             ICameraDeviceSession::configureStreams_3_4_cb _hidl_cb);
 
     bool preProcessConfigurationLocked_3_4(
-            const StreamConfiguration& requestedConfiguration,
+            const StreamConfiguration& requestedConfiguration, bool useOverriddenFields,
             camera3_stream_configuration_t *stream_list /*out*/,
             hidl_vec<camera3_stream_t*> *streams /*out*/);
     void postProcessConfigurationLocked_3_4(const StreamConfiguration& requestedConfiguration);
@@ -91,7 +91,7 @@
             const StreamConfiguration& requestedConfiguration,
             ICameraDeviceSession::configureStreams_3_4_cb _hidl_cb,
             // Optional argument for ICameraDeviceSession@3.5 impl
-            uint32_t streamConfigCounter = 0);
+            uint32_t streamConfigCounter = 0, bool useOverriddenFields = true);
 
     Return<void> processCaptureRequest_3_4(
             const hidl_vec<V3_4::CaptureRequest>& requests,
diff --git a/camera/device/3.5/ICameraDeviceSession.hal b/camera/device/3.5/ICameraDeviceSession.hal
index d0cfe39..c868e1e 100644
--- a/camera/device/3.5/ICameraDeviceSession.hal
+++ b/camera/device/3.5/ICameraDeviceSession.hal
@@ -36,6 +36,12 @@
      *
      * - a streamConfigCounter counter is provided to check for race condition
      *   between configureStreams_3_5 and signalStreamFlush call.
+     * - In case the HAL overrides dataspace or format for
+     *   IMPLEMENTATION_DEFINED pixel format, camera framework must use original
+     *   dataspace and format in subsequent configureStreams_3_5 calls for the same
+     *   stream. HAL is allowed to change the overriding behavior of format or
+     *   dataspace for reconfiguration of the same stream depending on the stream
+     *   combination.
      *
      * @return status Status code for the operation, one of:
      *     OK:
diff --git a/camera/device/3.5/default/Android.bp b/camera/device/3.5/default/Android.bp
index 7a48865..26b3b67 100644
--- a/camera/device/3.5/default/Android.bp
+++ b/camera/device/3.5/default/Android.bp
@@ -49,6 +49,7 @@
         "android.hardware.camera.device@3.5",
         "android.hardware.camera.provider@2.4",
         "android.hardware.graphics.mapper@2.0",
+        "android.hardware.graphics.mapper@3.0",
         "liblog",
         "libhardware",
         "libcamera_metadata",
@@ -82,6 +83,7 @@
         "android.hardware.camera.device@3.5",
         "android.hardware.camera.provider@2.4",
         "android.hardware.graphics.mapper@2.0",
+	"android.hardware.graphics.mapper@3.0",
         "liblog",
         "libhardware",
         "libcamera_metadata",
diff --git a/camera/device/3.5/default/CameraDeviceSession.cpp b/camera/device/3.5/default/CameraDeviceSession.cpp
index e812e50..44d067d 100644
--- a/camera/device/3.5/default/CameraDeviceSession.cpp
+++ b/camera/device/3.5/default/CameraDeviceSession.cpp
@@ -66,7 +66,7 @@
         const StreamConfiguration& requestedConfiguration,
         ICameraDeviceSession::configureStreams_3_5_cb _hidl_cb)  {
     configureStreams_3_4_Impl(requestedConfiguration.v3_4, _hidl_cb,
-            requestedConfiguration.streamConfigCounter);
+            requestedConfiguration.streamConfigCounter, false /*useOverriddenFields*/);
     return Void();
 }
 
diff --git a/camera/provider/2.4/default/Android.bp b/camera/provider/2.4/default/Android.bp
index 9d73934..cb78fcb 100644
--- a/camera/provider/2.4/default/Android.bp
+++ b/camera/provider/2.4/default/Android.bp
@@ -12,6 +12,7 @@
         "android.hardware.camera.device@3.5",
         "android.hardware.camera.provider@2.4",
         "android.hardware.graphics.mapper@2.0",
+        "android.hardware.graphics.mapper@3.0",
         "android.hidl.allocator@1.0",
         "android.hidl.memory@1.0",
         "camera.device@1.0-impl",
@@ -50,6 +51,7 @@
         "android.hardware.camera.device@3.5",
         "android.hardware.camera.provider@2.4",
         "android.hardware.graphics.mapper@2.0",
+        "android.hardware.graphics.mapper@3.0",
         "android.hidl.allocator@1.0",
         "android.hidl.memory@1.0",
         "camera.device@3.3-impl",
diff --git a/camera/provider/2.4/vts/functional/Android.bp b/camera/provider/2.4/vts/functional/Android.bp
index 5fb1fd8..2c3ed37 100644
--- a/camera/provider/2.4/vts/functional/Android.bp
+++ b/camera/provider/2.4/vts/functional/Android.bp
@@ -42,8 +42,10 @@
         "android.hardware.camera.provider@2.4",
         "android.hardware.camera.provider@2.5",
         "android.hardware.graphics.allocator@2.0",
+        "android.hardware.graphics.allocator@3.0",
         "android.hardware.graphics.common@1.0",
         "android.hardware.graphics.mapper@2.0",
+        "android.hardware.graphics.mapper@3.0",
         "android.hidl.allocator@1.0",
         "libgrallocusage",
         "libhidlmemory",
diff --git a/camera/provider/2.4/vts/functional/VtsHalCameraProviderV2_4TargetTest.cpp b/camera/provider/2.4/vts/functional/VtsHalCameraProviderV2_4TargetTest.cpp
index 33d23a0..c94c825 100644
--- a/camera/provider/2.4/vts/functional/VtsHalCameraProviderV2_4TargetTest.cpp
+++ b/camera/provider/2.4/vts/functional/VtsHalCameraProviderV2_4TargetTest.cpp
@@ -54,8 +54,10 @@
 #include <ui/GraphicBuffer.h>
 
 #include <android/hardware/graphics/allocator/2.0/IAllocator.h>
+#include <android/hardware/graphics/allocator/3.0/IAllocator.h>
 #include <android/hardware/graphics/mapper/2.0/IMapper.h>
 #include <android/hardware/graphics/mapper/2.0/types.h>
+#include <android/hardware/graphics/mapper/3.0/IMapper.h>
 #include <android/hidl/allocator/1.0/IAllocator.h>
 #include <android/hidl/memory/1.0/IMapper.h>
 #include <android/hidl/memory/1.0/IMemory.h>
@@ -1231,7 +1233,14 @@
     }
 
     if (mUseHalBufManager) {
-        returnStreamBuffers(results.outputBuffers);
+        // Don't return buffers of bufId 0 (empty buffer)
+        std::vector<StreamBuffer> buffers;
+        for (const auto& sb : results.outputBuffers) {
+            if (sb.bufferId != 0) {
+                buffers.push_back(sb);
+            }
+        }
+        returnStreamBuffers(buffers);
     }
     return notify;
 }
@@ -6104,36 +6113,66 @@
 
     sp<android::hardware::graphics::allocator::V2_0::IAllocator> allocator =
         android::hardware::graphics::allocator::V2_0::IAllocator::getService();
-    ASSERT_NE(nullptr, allocator.get());
+    sp<android::hardware::graphics::allocator::V3_0::IAllocator> allocatorV3 =
+        android::hardware::graphics::allocator::V3_0::IAllocator::getService();
 
+    sp<android::hardware::graphics::mapper::V3_0::IMapper> mapperV3 =
+        android::hardware::graphics::mapper::V3_0::IMapper::getService();
     sp<android::hardware::graphics::mapper::V2_0::IMapper> mapper =
         android::hardware::graphics::mapper::V2_0::IMapper::getService();
-    ASSERT_NE(mapper.get(), nullptr);
-
-    android::hardware::graphics::mapper::V2_0::IMapper::BufferDescriptorInfo descriptorInfo {};
-    descriptorInfo.width = width;
-    descriptorInfo.height = height;
-    descriptorInfo.layerCount = 1;
-    descriptorInfo.format = format;
-    descriptorInfo.usage = usage;
-
     ::android::hardware::hidl_vec<uint32_t> descriptor;
-    auto ret = mapper->createDescriptor(
-        descriptorInfo, [&descriptor](android::hardware::graphics::mapper::V2_0::Error err,
-                            ::android::hardware::hidl_vec<uint32_t> desc) {
-            ASSERT_EQ(err, android::hardware::graphics::mapper::V2_0::Error::NONE);
-            descriptor = desc;
-        });
-    ASSERT_TRUE(ret.isOk());
+    if (mapperV3 != nullptr && allocatorV3 != nullptr) {
+        android::hardware::graphics::mapper::V3_0::IMapper::BufferDescriptorInfo descriptorInfo {};
+        descriptorInfo.width = width;
+        descriptorInfo.height = height;
+        descriptorInfo.layerCount = 1;
+        descriptorInfo.format =
+                static_cast<android::hardware::graphics::common::V1_2::PixelFormat>(format);
+        descriptorInfo.usage = usage;
 
-    ret = allocator->allocate(descriptor, 1u,
-        [&](android::hardware::graphics::mapper::V2_0::Error err, uint32_t /*stride*/,
-            const ::android::hardware::hidl_vec<::android::hardware::hidl_handle>& buffers) {
-            ASSERT_EQ(android::hardware::graphics::mapper::V2_0::Error::NONE, err);
-            ASSERT_EQ(buffers.size(), 1u);
-            *buffer_handle = buffers[0];
-        });
-    ASSERT_TRUE(ret.isOk());
+        auto ret = mapperV3->createDescriptor(
+            descriptorInfo, [&descriptor](android::hardware::graphics::mapper::V3_0::Error err,
+                                ::android::hardware::hidl_vec<uint32_t> desc) {
+                ASSERT_EQ(err, android::hardware::graphics::mapper::V3_0::Error::NONE);
+                descriptor = desc;
+            });
+        ASSERT_TRUE(ret.isOk());
+
+        ret = allocatorV3->allocate(descriptor, 1u,
+            [&](android::hardware::graphics::mapper::V3_0::Error err, uint32_t /*stride*/,
+                const ::android::hardware::hidl_vec<::android::hardware::hidl_handle>& buffers) {
+                ASSERT_EQ(android::hardware::graphics::mapper::V3_0::Error::NONE, err);
+                ASSERT_EQ(buffers.size(), 1u);
+                *buffer_handle = buffers[0];
+            });
+        ASSERT_TRUE(ret.isOk());
+    } else {
+        ASSERT_NE(mapper.get(), nullptr);
+        ASSERT_NE(allocator.get(), nullptr);
+        android::hardware::graphics::mapper::V2_0::IMapper::BufferDescriptorInfo descriptorInfo {};
+        descriptorInfo.width = width;
+        descriptorInfo.height = height;
+        descriptorInfo.layerCount = 1;
+        descriptorInfo.format = format;
+        descriptorInfo.usage = usage;
+
+        auto ret = mapper->createDescriptor(
+            descriptorInfo, [&descriptor](android::hardware::graphics::mapper::V2_0::Error err,
+                                ::android::hardware::hidl_vec<uint32_t> desc) {
+                ASSERT_EQ(err, android::hardware::graphics::mapper::V2_0::Error::NONE);
+                descriptor = desc;
+            });
+        ASSERT_TRUE(ret.isOk());
+
+        ret = allocator->allocate(descriptor, 1u,
+            [&](android::hardware::graphics::mapper::V2_0::Error err, uint32_t /*stride*/,
+                const ::android::hardware::hidl_vec<::android::hardware::hidl_handle>& buffers) {
+                ASSERT_EQ(android::hardware::graphics::mapper::V2_0::Error::NONE, err);
+                ASSERT_EQ(buffers.size(), 1u);
+                *buffer_handle = buffers[0];
+            });
+        ASSERT_TRUE(ret.isOk());
+    }
 }
 
 void CameraHidlTest::verifyRecommendedConfigs(const CameraMetadata& chars) {
diff --git a/current.txt b/current.txt
index d97c0b3..47e7d72 100644
--- a/current.txt
+++ b/current.txt
@@ -410,7 +410,9 @@
 ed9da80ec0c96991fd03f0a46107815d0e50f764656e49dba4980fa5c31d5bc3 android.hardware.radio@1.0::types
 1d19720d4fd38b1095f0f555a4bd92b3b12c9b1d0f560b0e9a474cd6dcc20db6 android.hardware.radio@1.2::IRadio
 cd1757867a5e3a3faa362e785239515870d1a3c9ce756c6f0cf0f0fd8aac2547 android.hardware.radio@1.2::types
+722b3595548ed7f1953b6e0143dc842d4d6e290ff009a134eb518d7c17a09347 android.hardware.radio@1.2::types # b/112486807
 e78cf871f9fd1c072874e481e06e18e2681763cf2aa38c1fd777d53bab4eb69b android.hardware.sensors@1.0::types
+c28859a334c1f540dea0a7d4f0baef0551ba76a3232f53c936196543ee35bc4d android.hardware.sensors@1.0::types # b/133264933
 3d01e29e8129186f7567c4f9c8bee7480a0768e587b1be9b28adb0a6cbec6bf2 android.hardware.tv.cec@1.0::types
 1722ad002317b1fae1400de709e90f442d94ef22864e05f7a12af48c32e8edc8 android.hardware.usb@1.1::types
 29c8da7a13c40d488f569c812441d5754ee45bdcdb8ce6564f524b708d10a057 android.hardware.vibrator@1.1::types
@@ -427,6 +429,7 @@
 1b0500367ed2b32a841667ac3200edf3d3a164e8004aca445ff1b085ac831e93 android.hardware.audio@5.0::IStreamOutCallback
 83e365479cc77d8717c155e1787ee668cd2ae4c557b467cf75b8e7cd53697ad8 android.hardware.audio@5.0::types
 07d17800b298331e90d4ea5d8ba19a1ae3fe9c1dbff08d9f75fd3ade09496d67 android.hardware.audio.common@5.0::types
+b3c1ec989f317b9a36eac10f4e7b66aad2997302156899481553a67476e148dd android.hardware.audio.common@5.0::types # b/133453897
 f269297866765b95ddd1825676cc8a772f0c7c9863286df596fc302781a42ff5 android.hardware.audio.effect@5.0::IAcousticEchoCancelerEffect
 fa187b602d8939644ef708ed7627f2e3deac97899a4bda1de07f2ff126abe243 android.hardware.audio.effect@5.0::IAutomaticGainControlEffect
 e1bf864ccb8458c0da1dcc74a2e748b1dca8ac360df590591cf82d98292d7981 android.hardware.audio.effect@5.0::IBassBoostEffect
@@ -452,6 +455,7 @@
 09ab9b24994429d9bb32a3fb420b6f6be3e47eb655139a2c08c4e80d3f33ff95 android.hardware.camera.device@3.5::ICameraDevice
 06237de53c42890029e3f8fe7d1480d078469c0d07608e51c37b4d485d342992 android.hardware.camera.device@3.5::ICameraDeviceCallback
 08c68b196e2fc4e5ba67ba0d0917bde828a87cbe2cffec19d04733972da9eb49 android.hardware.camera.device@3.5::ICameraDeviceSession
+feabf0b7caa947757bf74375aceb4919a5aa99dd6a36216843553b6adec7eb5d android.hardware.camera.device@3.5::ICameraDeviceSession # b/131864007
 f9b8b388c0c76669e4b9189e4943efd2982f9bda5c10e276f96cc91bc8e818d6 android.hardware.camera.device@3.5::types
 f727d5f350f55a6d3354aad2feb64e43200de77c10d9d642465566bc260bb8ec android.hardware.camera.metadata@3.4::types
 0fb39a7809ad1c52b3efbbed5ef4749b06c2a4f1f19cdc3efa2e3d9b28f1205c android.hardware.camera.provider@2.5::ICameraProvider
@@ -526,6 +530,7 @@
 a1c6b0761bcb89d6bf15a156f9306b8090b3a916a15fea1689b4b0c1738e382f android.hardware.radio@1.3::IRadio
 e9d0f11a52715f5a29d89e2d8e2e21db1e16a43174af6b9d51a62d705cda1455 android.hardware.radio@1.3::IRadioIndication
 d233f0da44f55fdef0a95db5229231412787bb67695cd1ea197ce89a3c2908b9 android.hardware.radio@1.3::IRadioResponse
+f5fbe4f28a9e346be36063eca4e6c864114a1a6fb64884db03fdd825791ad9b8 android.hardware.radio@1.3::IRadioResponse # b/132818184 for Android Q
 750a363c8cec70baa1aac19e275c15233c5898e93c6bb5155fa2ca7f365490dc android.hardware.radio@1.3::types
 ef4ab741f7e7762fb45e2e24ca83871f72006ce05f57aa9addc574893dd29872 android.hardware.radio@1.4::IRadio
 33d9e6895cca98aa56296bb01720d18b8acd0e4de4960beb712e63ad147438a5 android.hardware.radio@1.4::IRadioIndication
@@ -541,6 +546,7 @@
 08d439c463e4044fa78874037d8e8379aa3cabecde32f08a775897eea5a538af android.hardware.secure_element@1.1::ISecureElement
 b53ac9d61c24efb16a2d63a861cef20680f6d57adb244a03b9778c675550628b android.hardware.secure_element@1.1::ISecureElementHalCallback
 3702b1c52c0bb3427244618e9e7975c05228bf4ceb8720da7a93603a71cb0368 android.hardware.sensors@2.0::ISensors
+c36670945ea09d92ae90a557147352ed9bd5223f957d347b367c2acb6f94870f android.hardware.sensors@2.0::ISensors # b/135216821
 ae5faa38538a9f50eb71eb7f9b998271124d2c64b761cb11c4d820c7732b4ddc android.hardware.sensors@2.0::ISensorsCallback
 3a98242a57d0820dacaca0f7db52bec433eae1f21c498763c6f1ece611c3967b android.hardware.sensors@2.0::types
 ce4b98211959449361146d4b1e5554dc841ceb4d4577154d7b2fb6d1eb504f76 android.hardware.soundtrigger@2.2::ISoundTriggerHw
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
index 581dc96..90d9b98 100644
--- 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
@@ -80,7 +80,8 @@
 
     Return<void> createClient(IComposer::createClient_cb hidl_cb) override {
         std::unique_lock<std::mutex> lock(mClientMutex);
-        if (!waitForClientDestroyedLocked(lock)) {
+        bool destroyed = waitForClientDestroyedLocked(lock);
+        if (!destroyed) {
             hidl_cb(Error::NO_RESOURCES, nullptr);
             return Void();
         }
@@ -108,12 +109,10 @@
             // 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) {
+            mClientDestroyedCondition.wait_for(lock, 1s,
+                                               [this]() -> bool { return mClient == nullptr; });
+            if (mClient != nullptr) {
                 ALOGD("previous client was not destroyed");
-            } else {
-                mClient.clear();
             }
         }
 
diff --git a/graphics/composer/2.1/utils/vts/Android.bp b/graphics/composer/2.1/utils/vts/Android.bp
index 846cfdf..fcb327f 100644
--- a/graphics/composer/2.1/utils/vts/Android.bp
+++ b/graphics/composer/2.1/utils/vts/Android.bp
@@ -25,6 +25,8 @@
     static_libs: [
         "VtsHalHidlTargetTestBase",
         "android.hardware.graphics.composer@2.1",
+        "android.hardware.graphics.mapper@2.0-vts",
+        "android.hardware.graphics.mapper@3.0-vts",
     ],
     header_libs: [
         "android.hardware.graphics.composer@2.1-command-buffer",
diff --git a/graphics/composer/2.1/utils/vts/ComposerVts.cpp b/graphics/composer/2.1/utils/vts/ComposerVts.cpp
index 7ba67d4..c5d5823 100644
--- a/graphics/composer/2.1/utils/vts/ComposerVts.cpp
+++ b/graphics/composer/2.1/utils/vts/ComposerVts.cpp
@@ -315,6 +315,77 @@
     writer->reset();
 }
 
+Gralloc::Gralloc() {
+    [this] {
+        ASSERT_NO_FATAL_FAILURE(mGralloc3 = std::make_shared<Gralloc3>("default", "default",
+                                                                       /*errOnFailure=*/false));
+        if (mGralloc3->getAllocator() == nullptr || mGralloc3->getMapper() == nullptr) {
+            mGralloc3 = nullptr;
+            ASSERT_NO_FATAL_FAILURE(mGralloc2 = std::make_shared<Gralloc2>());
+        }
+    }();
+}
+
+const native_handle_t* Gralloc::allocate(uint32_t width, uint32_t height, uint32_t layerCount,
+                                         PixelFormat format, uint64_t usage, bool import,
+                                         uint32_t* outStride) {
+    if (mGralloc3) {
+        IMapper3::BufferDescriptorInfo info{};
+        info.width = width;
+        info.height = height;
+        info.layerCount = layerCount;
+        info.format = static_cast<android::hardware::graphics::common::V1_2::PixelFormat>(format);
+        info.usage = usage;
+        return mGralloc3->allocate(info, import, outStride);
+    } else {
+        IMapper2::BufferDescriptorInfo info{};
+        info.width = width;
+        info.height = height;
+        info.layerCount = layerCount;
+        info.format = format;
+        info.usage = usage;
+        return mGralloc2->allocate(info, import, outStride);
+    }
+}
+
+void* Gralloc::lock(const native_handle_t* bufferHandle, uint64_t cpuUsage,
+                    const AccessRegion& accessRegionRect, int acquireFence) {
+    if (mGralloc3) {
+        IMapper3::Rect accessRegion;
+        accessRegion.left = accessRegionRect.left;
+        accessRegion.top = accessRegionRect.top;
+        accessRegion.width = accessRegionRect.width;
+        accessRegion.height = accessRegionRect.height;
+        int32_t bytesPerPixel;
+        int32_t bytesPerStride;
+        return mGralloc3->lock(bufferHandle, cpuUsage, accessRegion, acquireFence, &bytesPerPixel,
+                               &bytesPerStride);
+    } else {
+        IMapper2::Rect accessRegion;
+        accessRegion.left = accessRegionRect.left;
+        accessRegion.top = accessRegionRect.top;
+        accessRegion.width = accessRegionRect.width;
+        accessRegion.height = accessRegionRect.height;
+        return mGralloc2->lock(bufferHandle, cpuUsage, accessRegion, acquireFence);
+    }
+}
+
+int Gralloc::unlock(const native_handle_t* bufferHandle) {
+    if (mGralloc3) {
+        return mGralloc3->unlock(bufferHandle);
+    } else {
+        return mGralloc2->unlock(bufferHandle);
+    }
+}
+
+void Gralloc::freeBuffer(const native_handle_t* bufferHandle) {
+    if (mGralloc3) {
+        mGralloc3->freeBuffer(bufferHandle);
+    } else {
+        mGralloc2->freeBuffer(bufferHandle);
+    }
+}
+
 }  // namespace vts
 }  // namespace V2_1
 }  // namespace composer
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
index c97be76..7811048 100644
--- 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
@@ -25,8 +25,12 @@
 #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 <mapper-vts/2.0/MapperVts.h>
+#include <mapper-vts/3.0/MapperVts.h>
 #include <utils/StrongPointer.h>
 
+#include "gtest/gtest.h"
+
 namespace android {
 namespace hardware {
 namespace graphics {
@@ -38,6 +42,10 @@
 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 IMapper2 = android::hardware::graphics::mapper::V2_0::IMapper;
+using IMapper3 = android::hardware::graphics::mapper::V3_0::IMapper;
+using Gralloc2 = android::hardware::graphics::mapper::V2_0::vts::Gralloc;
+using Gralloc3 = android::hardware::graphics::mapper::V3_0::vts::Gralloc;
 
 class ComposerClient;
 
@@ -119,6 +127,34 @@
     const sp<IComposerClient> mClient;
 };
 
+class AccessRegion {
+  public:
+    int32_t left;
+    int32_t top;
+    int32_t width;
+    int32_t height;
+};
+
+class Gralloc {
+  public:
+    explicit Gralloc();
+
+    const native_handle_t* allocate(uint32_t width, uint32_t height, uint32_t layerCount,
+                                    PixelFormat format, uint64_t usage, bool import = true,
+                                    uint32_t* outStride = nullptr);
+
+    void* lock(const native_handle_t* bufferHandle, uint64_t cpuUsage,
+               const AccessRegion& accessRegionRect, int acquireFence);
+
+    int unlock(const native_handle_t* bufferHandle);
+
+    void freeBuffer(const native_handle_t* bufferHandle);
+
+  protected:
+    std::shared_ptr<Gralloc2> mGralloc2 = nullptr;
+    std::shared_ptr<Gralloc3> mGralloc3 = nullptr;
+};
+
 }  // namespace vts
 }  // namespace V2_1
 }  // namespace composer
diff --git a/graphics/composer/2.1/vts/functional/Android.bp b/graphics/composer/2.1/vts/functional/Android.bp
index c98cc0d..d54da60 100644
--- a/graphics/composer/2.1/vts/functional/Android.bp
+++ b/graphics/composer/2.1/vts/functional/Android.bp
@@ -26,10 +26,13 @@
     ],
     static_libs: [
         "android.hardware.graphics.allocator@2.0",
+        "android.hardware.graphics.allocator@3.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",
+        "android.hardware.graphics.mapper@3.0",
+        "android.hardware.graphics.mapper@3.0-vts",
     ],
     header_libs: [
         "android.hardware.graphics.composer@2.1-command-buffer",
diff --git a/graphics/composer/2.1/vts/functional/VtsHalGraphicsComposerV2_1TargetTest.cpp b/graphics/composer/2.1/vts/functional/VtsHalGraphicsComposerV2_1TargetTest.cpp
index 3c408b7..30b9694 100644
--- a/graphics/composer/2.1/vts/functional/VtsHalGraphicsComposerV2_1TargetTest.cpp
+++ b/graphics/composer/2.1/vts/functional/VtsHalGraphicsComposerV2_1TargetTest.cpp
@@ -21,6 +21,7 @@
 #include <composer-vts/2.1/GraphicsComposerCallback.h>
 #include <composer-vts/2.1/TestCommandReader.h>
 #include <mapper-vts/2.0/MapperVts.h>
+#include <mapper-vts/3.0/MapperVts.h>
 
 #include <VtsHalHidlTargetTestBase.h>
 #include <VtsHalHidlTargetTestEnvBase.h>
@@ -47,8 +48,6 @@
 using android::hardware::graphics::common::V1_0::Dataspace;
 using android::hardware::graphics::common::V1_0::PixelFormat;
 using android::hardware::graphics::common::V1_0::Transform;
-using android::hardware::graphics::mapper::V2_0::IMapper;
-using android::hardware::graphics::mapper::V2_0::vts::Gralloc;
 using GrallocError = android::hardware::graphics::mapper::V2_0::Error;
 
 // Test environment for graphics.composer
@@ -669,7 +668,6 @@
         ASSERT_NO_FATAL_FAILURE(GraphicsComposerHidlTest::SetUp());
 
         ASSERT_NO_FATAL_FAILURE(mGralloc = std::make_unique<Gralloc>());
-
         Config activeConfig = mComposerClient->getActiveConfig(mPrimaryDisplay);
         mDisplayWidth = mComposerClient->getDisplayAttribute(mPrimaryDisplay, activeConfig,
                                                              IComposerClient::Attribute::WIDTH);
@@ -685,16 +683,10 @@
     }
 
     const native_handle_t* allocate() {
-        IMapper::BufferDescriptorInfo info{};
-        info.width = mDisplayWidth;
-        info.height = mDisplayHeight;
-        info.layerCount = 1;
-        info.format = PixelFormat::RGBA_8888;
-        info.usage =
-            static_cast<uint64_t>(BufferUsage::CPU_WRITE_OFTEN | BufferUsage::CPU_READ_OFTEN |
-                                  BufferUsage::COMPOSER_OVERLAY);
-
-        return mGralloc->allocate(info);
+        uint64_t usage =
+                static_cast<uint64_t>(BufferUsage::CPU_WRITE_OFTEN | BufferUsage::CPU_READ_OFTEN |
+                                      BufferUsage::COMPOSER_OVERLAY);
+        return mGralloc->allocate(mDisplayWidth, mDisplayHeight, 1, PixelFormat::RGBA_8888, usage);
     }
 
     void execute() { mComposerClient->execute(mReader.get(), mWriter.get()); }
@@ -705,7 +697,7 @@
     int32_t mDisplayHeight;
 
    private:
-    std::unique_ptr<Gralloc> mGralloc;
+     std::unique_ptr<Gralloc> mGralloc;
 };
 
 /**
diff --git a/graphics/composer/2.2/utils/vts/Android.bp b/graphics/composer/2.2/utils/vts/Android.bp
index c6b524d..dd979cb 100644
--- a/graphics/composer/2.2/utils/vts/Android.bp
+++ b/graphics/composer/2.2/utils/vts/Android.bp
@@ -25,6 +25,10 @@
         "android.hardware.graphics.composer@2.1",
         "android.hardware.graphics.composer@2.1-vts",
         "android.hardware.graphics.composer@2.2",
+        "android.hardware.graphics.mapper@2.1",
+        "android.hardware.graphics.mapper@2.1-vts",
+        "android.hardware.graphics.mapper@3.0",
+        "android.hardware.graphics.mapper@3.0-vts",
     ],
     export_static_lib_headers: [
         "android.hardware.graphics.composer@2.1-vts",
diff --git a/graphics/composer/2.2/utils/vts/ComposerVts.cpp b/graphics/composer/2.2/utils/vts/ComposerVts.cpp
index da99460..cd6772a 100644
--- a/graphics/composer/2.2/utils/vts/ComposerVts.cpp
+++ b/graphics/composer/2.2/utils/vts/ComposerVts.cpp
@@ -180,6 +180,48 @@
     return matrix;
 }
 
+Gralloc::Gralloc() {
+    [this] {
+        ALOGD("Attempting to initialize gralloc3");
+        ASSERT_NO_FATAL_FAILURE(mGralloc3 = std::make_shared<Gralloc3>("default", "default",
+                                                                       /*errOnFailure=*/false));
+        if (mGralloc3->getMapper() == nullptr || mGralloc3->getAllocator() == nullptr) {
+            mGralloc3 = nullptr;
+            ALOGD("Failed to create gralloc3, initializing gralloc2_1");
+            mGralloc2_1 = std::make_shared<Gralloc2_1>(/*errOnFailure*/ false);
+            if (!mGralloc2_1->getMapper()) {
+                mGralloc2_1 = nullptr;
+                ALOGD("Failed to create gralloc2_1, initializing gralloc2");
+                ASSERT_NO_FATAL_FAILURE(mGralloc2 = std::make_shared<Gralloc2>());
+            }
+        }
+    }();
+}
+
+bool Gralloc::validateBufferSize(const native_handle_t* bufferHandle, uint32_t width,
+                                 uint32_t height, uint32_t layerCount, PixelFormat format,
+                                 uint64_t usage, uint32_t stride) {
+    if (mGralloc3) {
+        IMapper3::BufferDescriptorInfo info{};
+        info.width = width;
+        info.height = height;
+        info.layerCount = layerCount;
+        info.format = static_cast<android::hardware::graphics::common::V1_2::PixelFormat>(format);
+        info.usage = usage;
+        return mGralloc3->validateBufferSize(bufferHandle, info, stride);
+    } else if (mGralloc2_1) {
+        IMapper2_1::BufferDescriptorInfo info{};
+        info.width = width;
+        info.height = height;
+        info.layerCount = layerCount;
+        info.format = static_cast<android::hardware::graphics::common::V1_1::PixelFormat>(format);
+        info.usage = usage;
+        return mGralloc2_1->validateBufferSize(bufferHandle, info, stride);
+    } else {
+        return true;
+    }
+}
+
 }  // namespace vts
 }  // namespace V2_2
 }  // namespace composer
diff --git a/graphics/composer/2.2/utils/vts/include/composer-vts/2.2/ComposerVts.h b/graphics/composer/2.2/utils/vts/include/composer-vts/2.2/ComposerVts.h
index 2633021..8fa9b7b 100644
--- a/graphics/composer/2.2/utils/vts/include/composer-vts/2.2/ComposerVts.h
+++ b/graphics/composer/2.2/utils/vts/include/composer-vts/2.2/ComposerVts.h
@@ -27,6 +27,7 @@
 #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 <mapper-vts/2.1/MapperVts.h>
 #include <utils/StrongPointer.h>
 
 namespace android {
@@ -41,6 +42,11 @@
 using common::V1_1::Dataspace;
 using common::V1_1::PixelFormat;
 using common::V1_1::RenderIntent;
+using IMapper2_1 = android::hardware::graphics::mapper::V2_1::IMapper;
+using IMapper3 = android::hardware::graphics::mapper::V3_0::IMapper;
+using Gralloc2 = android::hardware::graphics::mapper::V2_0::vts::Gralloc;
+using Gralloc2_1 = android::hardware::graphics::mapper::V2_1::vts::Gralloc;
+using Gralloc3 = android::hardware::graphics::mapper::V3_0::vts::Gralloc;
 
 class ComposerClient;
 
@@ -84,6 +90,26 @@
     const sp<IComposerClient> mClient;
 };
 
+class Gralloc : public V2_1::vts::Gralloc {
+  public:
+    Gralloc();
+    const native_handle_t* allocate(uint32_t width, uint32_t height, uint32_t layerCount,
+                                    PixelFormat format, uint64_t usage, bool import = true,
+                                    uint32_t* outStride = nullptr) {
+        return V2_1::vts::Gralloc::allocate(
+                width, height, layerCount,
+                static_cast<android::hardware::graphics::common::V1_0::PixelFormat>(format), usage,
+                import, outStride);
+    }
+
+    bool validateBufferSize(const native_handle_t* bufferHandle, uint32_t width, uint32_t height,
+                            uint32_t layerCount, PixelFormat format, uint64_t usage,
+                            uint32_t stride);
+
+  protected:
+    std::shared_ptr<Gralloc2_1> mGralloc2_1 = nullptr;
+};
+
 }  // namespace vts
 }  // namespace V2_2
 }  // namespace composer
diff --git a/graphics/composer/2.2/vts/functional/Android.bp b/graphics/composer/2.2/vts/functional/Android.bp
index b62f302..9f7e1cd 100644
--- a/graphics/composer/2.2/vts/functional/Android.bp
+++ b/graphics/composer/2.2/vts/functional/Android.bp
@@ -25,11 +25,13 @@
     // TODO(b/64437680): Assume these libs are always available on the device.
     shared_libs: [
         "libfmq",
+        "libhidlbase",
         "libhidltransport",
         "libsync",
     ],
     static_libs: [
         "android.hardware.graphics.allocator@2.0",
+        "android.hardware.graphics.allocator@3.0",
         "android.hardware.graphics.common@1.1",
         "android.hardware.graphics.composer@2.1",
         "android.hardware.graphics.composer@2.1-vts",
@@ -39,6 +41,8 @@
         "android.hardware.graphics.mapper@2.0-vts",
         "android.hardware.graphics.mapper@2.1",
         "android.hardware.graphics.mapper@2.1-vts",
+        "android.hardware.graphics.mapper@3.0",
+        "android.hardware.graphics.mapper@3.0-vts",
     ],
     header_libs: [
         "android.hardware.graphics.composer@2.1-command-buffer",
diff --git a/graphics/composer/2.2/vts/functional/VtsHalGraphicsComposerV2_2ReadbackTest.cpp b/graphics/composer/2.2/vts/functional/VtsHalGraphicsComposerV2_2ReadbackTest.cpp
index da8858e..0648b34 100644
--- a/graphics/composer/2.2/vts/functional/VtsHalGraphicsComposerV2_2ReadbackTest.cpp
+++ b/graphics/composer/2.2/vts/functional/VtsHalGraphicsComposerV2_2ReadbackTest.cpp
@@ -39,9 +39,9 @@
 using common::V1_1::Dataspace;
 using common::V1_1::PixelFormat;
 using mapper::V2_1::IMapper;
-using mapper::V2_1::vts::Gralloc;
 using V2_1::Display;
 using V2_1::Layer;
+using V2_1::vts::AccessRegion;
 using V2_1::vts::TestCommandReader;
 
 static const IComposerClient::Color BLACK = {0, 0, 0, 0xff};
@@ -296,14 +296,13 @@
         mComposerClient = client;
         mGralloc = gralloc;
 
-        mPixelFormat = pixelFormat;
+        mFormat = pixelFormat;
         mDataspace = dataspace;
 
-        mInfo.width = width;
-        mInfo.height = height;
-        mInfo.layerCount = 1;
-        mInfo.format = mPixelFormat;
-        mInfo.usage = static_cast<uint64_t>(BufferUsage::CPU_READ_OFTEN | BufferUsage::GPU_TEXTURE);
+        mWidth = width;
+        mHeight = height;
+        mLayerCount = 1;
+        mUsage = static_cast<uint64_t>(BufferUsage::CPU_READ_OFTEN | BufferUsage::GPU_TEXTURE);
 
         mAccessRegion.top = 0;
         mAccessRegion.left = 0;
@@ -322,8 +321,10 @@
             mGralloc->freeBuffer(mBufferHandle);
             mBufferHandle = nullptr;
         }
-        mBufferHandle = mGralloc->allocate(mInfo, /*import*/ true, &mStride);
-        ASSERT_NE(false, mGralloc->validateBufferSize(mBufferHandle, mInfo, mStride));
+        mBufferHandle = mGralloc->allocate(mWidth, mHeight, mLayerCount, mFormat, mUsage,
+                                           /*import*/ true, &mStride);
+        ASSERT_NE(false, mGralloc->validateBufferSize(mBufferHandle, mWidth, mHeight, mLayerCount,
+                                                      mFormat, mUsage, mStride));
         ASSERT_NO_FATAL_FAILURE(mComposerClient->setReadbackBuffer(mDisplay, mBufferHandle, -1));
     }
 
@@ -332,13 +333,13 @@
         int32_t fenceHandle;
         ASSERT_NO_FATAL_FAILURE(mComposerClient->getReadbackBufferFence(mDisplay, &fenceHandle));
 
-        void* bufData = mGralloc->lock(mBufferHandle, mInfo.usage, mAccessRegion, fenceHandle);
-        ASSERT_TRUE(mPixelFormat == PixelFormat::RGB_888 || mPixelFormat == PixelFormat::RGBA_8888);
-        int32_t bytesPerPixel = GraphicsComposerReadbackTest::GetBytesPerPixel(mPixelFormat);
+        void* bufData = mGralloc->lock(mBufferHandle, mUsage, mAccessRegion, fenceHandle);
+        ASSERT_TRUE(mFormat == PixelFormat::RGB_888 || mFormat == PixelFormat::RGBA_8888);
+        int32_t bytesPerPixel = GraphicsComposerReadbackTest::GetBytesPerPixel(mFormat);
         ASSERT_NE(-1, bytesPerPixel);
-        for (int row = 0; row < mInfo.height; row++) {
-            for (int col = 0; col < mInfo.width; col++) {
-                int pixel = row * mInfo.width + col;
+        for (int row = 0; row < mHeight; row++) {
+            for (int col = 0; col < mWidth; col++) {
+                int pixel = row * mWidth + col;
                 int offset = (row * mStride + col) * bytesPerPixel;
                 uint8_t* pixelColor = (uint8_t*)bufData + offset;
 
@@ -354,12 +355,16 @@
         }
     }
 
-   protected:
-    IMapper::BufferDescriptorInfo mInfo;
-    IMapper::Rect mAccessRegion;
+    uint32_t mWidth;
+    uint32_t mHeight;
+    uint32_t mLayerCount;
+    PixelFormat mFormat;
+    uint64_t mUsage;
+    AccessRegion mAccessRegion;
+
+  protected:
     uint32_t mStride;
     const native_handle_t* mBufferHandle = nullptr;
-    PixelFormat mPixelFormat;
     Dataspace mDataspace;
     Display mDisplay;
     std::shared_ptr<Gralloc> mGralloc;
@@ -392,13 +397,12 @@
         : TestLayer{client, display} {
         mGralloc = gralloc;
         mComposition = composition;
-        mInfo.width = width;
-        mInfo.height = height;
-        mInfo.layerCount = 1;
-        mInfo.format = format;
-        mInfo.usage =
-            static_cast<uint64_t>(BufferUsage::CPU_READ_OFTEN | BufferUsage::CPU_WRITE_OFTEN |
-                                  BufferUsage::COMPOSER_OVERLAY);
+        mWidth = width;
+        mHeight = height;
+        mLayerCount = 1;
+        mFormat = format;
+        mUsage = static_cast<uint64_t>(BufferUsage::CPU_READ_OFTEN | BufferUsage::CPU_WRITE_OFTEN |
+                                       BufferUsage::COMPOSER_OVERLAY);
 
         mAccessRegion.top = 0;
         mAccessRegion.left = 0;
@@ -423,9 +427,9 @@
     }
 
     void fillBuffer(std::vector<IComposerClient::Color> expectedColors) {
-        void* bufData = mGralloc->lock(mBufferHandle, mInfo.usage, mAccessRegion, -1);
+        void* bufData = mGralloc->lock(mBufferHandle, mUsage, mAccessRegion, -1);
         ASSERT_NO_FATAL_FAILURE(GraphicsComposerReadbackTest::fillBuffer(
-            mInfo.width, mInfo.height, mStride, bufData, mInfo.format, expectedColors));
+                mWidth, mHeight, mStride, bufData, mFormat, expectedColors));
         mFillFence = mGralloc->unlock(mBufferHandle);
         if (mFillFence != -1) {
             sync_wait(mFillFence, -1);
@@ -437,10 +441,12 @@
             mGralloc->freeBuffer(mBufferHandle);
             mBufferHandle = nullptr;
         }
-        mBufferHandle = mGralloc->allocate(mInfo, /*import*/ true, &mStride);
+        mBufferHandle = mGralloc->allocate(mWidth, mHeight, mLayerCount, mFormat, mUsage,
+                                           /*import*/ true, &mStride);
         ASSERT_NE(nullptr, mBufferHandle);
         ASSERT_NO_FATAL_FAILURE(fillBuffer(colors));
-        ASSERT_NE(false, mGralloc->validateBufferSize(mBufferHandle, mInfo, mStride));
+        ASSERT_NE(false, mGralloc->validateBufferSize(mBufferHandle, mWidth, mHeight, mLayerCount,
+                                                      mFormat, mUsage, mStride));
     }
 
     void setToClientComposition(const std::shared_ptr<CommandWriterBase>& writer) {
@@ -448,11 +454,15 @@
         writer->setLayerCompositionType(IComposerClient::Composition::CLIENT);
     }
 
-    IMapper::BufferDescriptorInfo mInfo;
-    IMapper::Rect mAccessRegion;
+    AccessRegion mAccessRegion;
     uint32_t mStride;
+    uint32_t mWidth;
+    uint32_t mHeight;
+    uint32_t mLayerCount;
+    PixelFormat mFormat;
 
-   protected:
+  protected:
+    uint64_t mUsage;
     IComposerClient::Composition mComposition;
     std::shared_ptr<Gralloc> mGralloc;
     int32_t mFillFence;
@@ -568,14 +578,11 @@
     layer->write(mWriter);
 
     // This following buffer call should have no effect
-    IMapper::BufferDescriptorInfo bufferInfo{};
-    bufferInfo.width = mDisplayWidth;
-    bufferInfo.height = mDisplayHeight;
-    bufferInfo.layerCount = 1;
-    bufferInfo.format = PixelFormat::RGBA_8888;
-    bufferInfo.usage =
-        static_cast<uint64_t>(BufferUsage::CPU_READ_OFTEN | BufferUsage::CPU_WRITE_OFTEN);
-    const native_handle_t* bufferHandle = mGralloc->allocate(bufferInfo);
+    PixelFormat format = PixelFormat::RGBA_8888;
+    uint64_t usage =
+            static_cast<uint64_t>(BufferUsage::CPU_READ_OFTEN | BufferUsage::CPU_WRITE_OFTEN);
+    const native_handle_t* bufferHandle =
+            mGralloc->allocate(mDisplayWidth, mDisplayHeight, 1, format, usage);
     mWriter->setLayerBuffer(0, bufferHandle, -1);
 
     // expected color for each pixel
@@ -642,23 +649,20 @@
 
         // create client target buffer
         uint32_t clientStride;
-        IMapper::BufferDescriptorInfo clientInfo;
-        clientInfo.width = layer->mInfo.width;
-        clientInfo.height = layer->mInfo.height;
-        clientInfo.layerCount = layer->mInfo.layerCount;
-        clientInfo.format = PixelFormat::RGBA_8888;
-        clientInfo.usage =
-            static_cast<uint64_t>(BufferUsage::CPU_READ_OFTEN | BufferUsage::CPU_WRITE_OFTEN |
-                                  BufferUsage::COMPOSER_CLIENT_TARGET);
+        PixelFormat clientFormat = PixelFormat::RGBA_8888;
+        uint64_t clientUsage =
+                static_cast<uint64_t>(BufferUsage::CPU_READ_OFTEN | BufferUsage::CPU_WRITE_OFTEN |
+                                      BufferUsage::COMPOSER_CLIENT_TARGET);
         const native_handle_t* clientBufferHandle =
-            mGralloc->allocate(clientInfo, /*import*/ true, &clientStride);
+                mGralloc->allocate(layer->mWidth, layer->mHeight, layer->mLayerCount, clientFormat,
+                                   clientUsage, /*import*/ true, &clientStride);
         ASSERT_NE(nullptr, clientBufferHandle);
 
         void* clientBufData =
-            mGralloc->lock(clientBufferHandle, clientInfo.usage, layer->mAccessRegion, -1);
+                mGralloc->lock(clientBufferHandle, clientUsage, layer->mAccessRegion, -1);
 
-        ASSERT_NO_FATAL_FAILURE(fillBuffer(clientInfo.width, clientInfo.height, clientStride,
-                                           clientBufData, clientInfo.format, expectedColors));
+        ASSERT_NO_FATAL_FAILURE(fillBuffer(layer->mWidth, layer->mHeight, clientStride,
+                                           clientBufData, clientFormat, expectedColors));
         int clientFence = mGralloc->unlock(clientBufferHandle);
         if (clientFence != -1) {
             sync_wait(clientFence, -1);
@@ -706,14 +710,13 @@
     auto deviceLayer =
         std::make_shared<TestBufferLayer>(mComposerClient, mGralloc, mPrimaryDisplay, mDisplayWidth,
                                           mDisplayHeight / 2, PixelFormat::RGBA_8888);
-    std::vector<IComposerClient::Color> deviceColors(deviceLayer->mInfo.width *
-                                                     deviceLayer->mInfo.height);
-    fillColorsArea(deviceColors, deviceLayer->mInfo.width,
-                   {0, 0, static_cast<int32_t>(deviceLayer->mInfo.width),
-                    static_cast<int32_t>(deviceLayer->mInfo.height)},
+    std::vector<IComposerClient::Color> deviceColors(deviceLayer->mWidth * deviceLayer->mHeight);
+    fillColorsArea(deviceColors, deviceLayer->mWidth,
+                   {0, 0, static_cast<int32_t>(deviceLayer->mWidth),
+                    static_cast<int32_t>(deviceLayer->mHeight)},
                    GREEN);
-    deviceLayer->setDisplayFrame({0, 0, static_cast<int32_t>(deviceLayer->mInfo.width),
-                                  static_cast<int32_t>(deviceLayer->mInfo.height)});
+    deviceLayer->setDisplayFrame({0, 0, static_cast<int32_t>(deviceLayer->mWidth),
+                                  static_cast<int32_t>(deviceLayer->mHeight)});
     deviceLayer->setZOrder(10);
     ASSERT_NO_FATAL_FAILURE(deviceLayer->setBuffer(deviceColors));
     deviceLayer->write(mWriter);
@@ -728,30 +731,25 @@
     execute();
     ASSERT_EQ(0, mReader->mErrors.size());
 
-    IMapper::BufferDescriptorInfo clientInfo;
-    clientInfo.width = mDisplayWidth;
-    clientInfo.height = mDisplayHeight;
-    clientInfo.layerCount = 1;
-    clientInfo.format = PixelFormat::RGBA_8888;
-    clientInfo.usage =
-        static_cast<uint64_t>(BufferUsage::CPU_READ_OFTEN | BufferUsage::CPU_WRITE_OFTEN |
-                              BufferUsage::COMPOSER_CLIENT_TARGET);
-
+    uint64_t clientUsage =
+            static_cast<uint64_t>(BufferUsage::CPU_READ_OFTEN | BufferUsage::CPU_WRITE_OFTEN |
+                                  BufferUsage::COMPOSER_CLIENT_TARGET);
     uint32_t clientStride;
     const native_handle_t* clientBufferHandle =
-        mGralloc->allocate(clientInfo, /*import*/ true, &clientStride);
+            mGralloc->allocate(mDisplayWidth, mDisplayHeight, 1, PixelFormat::RGBA_8888,
+                               clientUsage, /*import*/ true, &clientStride);
     ASSERT_NE(nullptr, clientBufferHandle);
 
-    IMapper::Rect clientAccessRegion;
+    AccessRegion clientAccessRegion;
     clientAccessRegion.left = 0;
     clientAccessRegion.top = 0;
     clientAccessRegion.width = mDisplayWidth;
     clientAccessRegion.height = mDisplayHeight;
-    void* clientData = mGralloc->lock(clientBufferHandle, clientInfo.usage, clientAccessRegion, -1);
-    std::vector<IComposerClient::Color> clientColors(clientInfo.width * clientInfo.height);
-    fillColorsArea(clientColors, clientInfo.width, clientFrame, RED);
-    ASSERT_NO_FATAL_FAILURE(fillBuffer(clientInfo.width, clientInfo.height, clientStride,
-                                       clientData, clientInfo.format, clientColors));
+    void* clientData = mGralloc->lock(clientBufferHandle, clientUsage, clientAccessRegion, -1);
+    std::vector<IComposerClient::Color> clientColors(mDisplayWidth * mDisplayHeight);
+    fillColorsArea(clientColors, mDisplayWidth, clientFrame, RED);
+    ASSERT_NO_FATAL_FAILURE(fillBuffer(mDisplayWidth, mDisplayHeight, clientStride, clientData,
+                                       PixelFormat::RGBA_8888, clientColors));
     int clientFence = mGralloc->unlock(clientBufferHandle);
     if (clientFence != -1) {
         sync_wait(clientFence, -1);
diff --git a/graphics/composer/2.2/vts/functional/VtsHalGraphicsComposerV2_2TargetTest.cpp b/graphics/composer/2.2/vts/functional/VtsHalGraphicsComposerV2_2TargetTest.cpp
index 9c80f4d..51832f9 100644
--- a/graphics/composer/2.2/vts/functional/VtsHalGraphicsComposerV2_2TargetTest.cpp
+++ b/graphics/composer/2.2/vts/functional/VtsHalGraphicsComposerV2_2TargetTest.cpp
@@ -40,7 +40,6 @@
 using common::V1_1::PixelFormat;
 using common::V1_1::RenderIntent;
 using mapper::V2_0::IMapper;
-using mapper::V2_0::vts::Gralloc;
 
 // Test environment for graphics.composer
 class GraphicsComposerHidlEnvironment : public ::testing::VtsHalHidlTargetTestEnvBase {
@@ -171,15 +170,10 @@
     }
 
     const native_handle_t* allocate() {
-        IMapper::BufferDescriptorInfo info{};
-        info.width = 64;
-        info.height = 64;
-        info.layerCount = 1;
-        info.format = static_cast<common::V1_0::PixelFormat>(PixelFormat::RGBA_8888);
-        info.usage =
-            static_cast<uint64_t>(BufferUsage::CPU_WRITE_OFTEN | BufferUsage::CPU_READ_OFTEN);
-
-        return mGralloc->allocate(info);
+        uint64_t usage =
+                static_cast<uint64_t>(BufferUsage::CPU_WRITE_OFTEN | BufferUsage::CPU_READ_OFTEN);
+        return mGralloc->allocate(/*width*/ 64, /*height*/ 64, /*layerCount*/ 1,
+                                  PixelFormat::RGBA_8888, usage);
     }
 
     void execute() { mComposerClient->execute(mReader.get(), mWriter.get()); }
@@ -456,18 +450,15 @@
         return;
     }
 
-    IMapper::BufferDescriptorInfo info{};
-    info.width = mDisplayWidth;
-    info.height = mDisplayHeight;
-    info.layerCount = 1;
-    info.format = static_cast<common::V1_0::PixelFormat>(mReadbackPixelFormat);
     // BufferUsage::COMPOSER_OUTPUT is missing
-    info.usage = static_cast<uint64_t>(BufferUsage::COMPOSER_OVERLAY | BufferUsage::CPU_READ_OFTEN);
+    uint64_t usage =
+            static_cast<uint64_t>(BufferUsage::COMPOSER_OVERLAY | BufferUsage::CPU_READ_OFTEN);
 
     std::unique_ptr<Gralloc> gralloc;
     const native_handle_t* buffer;
     ASSERT_NO_FATAL_FAILURE(gralloc = std::make_unique<Gralloc>());
-    ASSERT_NO_FATAL_FAILURE(buffer = gralloc->allocate(info));
+    ASSERT_NO_FATAL_FAILURE(buffer = gralloc->allocate(mDisplayWidth, mDisplayHeight, 1,
+                                                       mReadbackPixelFormat, usage));
 
     mComposerClient->setReadbackBuffer(mPrimaryDisplay, buffer, -1);
 }
@@ -483,17 +474,14 @@
         return;
     }
 
-    IMapper::BufferDescriptorInfo info{};
-    info.width = mDisplayWidth;
-    info.height = mDisplayHeight;
-    info.layerCount = 1;
-    info.format = static_cast<common::V1_0::PixelFormat>(mReadbackPixelFormat);
-    info.usage = static_cast<uint64_t>(BufferUsage::COMPOSER_OVERLAY | BufferUsage::CPU_READ_OFTEN);
+    uint64_t usage =
+            static_cast<uint64_t>(BufferUsage::COMPOSER_OVERLAY | BufferUsage::CPU_READ_OFTEN);
 
     std::unique_ptr<Gralloc> gralloc;
     const native_handle_t* buffer;
     ASSERT_NO_FATAL_FAILURE(gralloc = std::make_unique<Gralloc>());
-    ASSERT_NO_FATAL_FAILURE(buffer = gralloc->allocate(info));
+    ASSERT_NO_FATAL_FAILURE(buffer = gralloc->allocate(mDisplayWidth, mDisplayHeight, 1,
+                                                       mReadbackPixelFormat, usage));
 
     Error error = mComposerClient->getRaw()->setReadbackBuffer(mInvalidDisplayId, buffer, nullptr);
     ASSERT_EQ(Error::BAD_DISPLAY, error);
diff --git a/graphics/composer/2.3/utils/vts/Android.bp b/graphics/composer/2.3/utils/vts/Android.bp
index 19438cb..2fe6cd6 100644
--- a/graphics/composer/2.3/utils/vts/Android.bp
+++ b/graphics/composer/2.3/utils/vts/Android.bp
@@ -27,6 +27,12 @@
         "android.hardware.graphics.composer@2.2",
         "android.hardware.graphics.composer@2.2-vts",
         "android.hardware.graphics.composer@2.3",
+	"android.hardware.graphics.mapper@2.0",
+	"android.hardware.graphics.mapper@2.0-vts",
+	"android.hardware.graphics.mapper@2.1",
+	"android.hardware.graphics.mapper@2.1-vts",
+	"android.hardware.graphics.mapper@3.0",
+	"android.hardware.graphics.mapper@3.0-vts",
     ],
     header_libs: [
         "android.hardware.graphics.composer@2.1-command-buffer",
diff --git a/graphics/composer/2.3/vts/functional/Android.bp b/graphics/composer/2.3/vts/functional/Android.bp
index 7548cb5..2766638 100644
--- a/graphics/composer/2.3/vts/functional/Android.bp
+++ b/graphics/composer/2.3/vts/functional/Android.bp
@@ -22,11 +22,13 @@
     // TODO(b/64437680): Assume these libs are always available on the device.
     shared_libs: [
         "libfmq",
+        "libhidlbase",
         "libhidltransport",
         "libsync",
     ],
     static_libs: [
         "android.hardware.graphics.allocator@2.0",
+        "android.hardware.graphics.allocator@3.0",
         "android.hardware.graphics.composer@2.1",
         "android.hardware.graphics.composer@2.1-vts",
         "android.hardware.graphics.composer@2.2",
@@ -36,6 +38,9 @@
         "android.hardware.graphics.mapper@2.0",
         "android.hardware.graphics.mapper@2.0-vts",
         "android.hardware.graphics.mapper@2.1",
+        "android.hardware.graphics.mapper@2.1-vts",
+        "android.hardware.graphics.mapper@3.0",
+        "android.hardware.graphics.mapper@3.0-vts",
     ],
     header_libs: [
         "android.hardware.graphics.composer@2.1-command-buffer",
diff --git a/graphics/composer/2.3/vts/functional/VtsHalGraphicsComposerV2_3TargetTest.cpp b/graphics/composer/2.3/vts/functional/VtsHalGraphicsComposerV2_3TargetTest.cpp
index d51c30a..dafe587 100644
--- a/graphics/composer/2.3/vts/functional/VtsHalGraphicsComposerV2_3TargetTest.cpp
+++ b/graphics/composer/2.3/vts/functional/VtsHalGraphicsComposerV2_3TargetTest.cpp
@@ -41,7 +41,7 @@
 using common::V1_2::Dataspace;
 using common::V1_2::PixelFormat;
 using mapper::V2_0::IMapper;
-using mapper::V2_0::vts::Gralloc;
+using V2_2::vts::Gralloc;
 
 // Test environment for graphics.composer
 class GraphicsComposerHidlEnvironment : public ::testing::VtsHalHidlTargetTestEnvBase {
@@ -156,15 +156,9 @@
     }
 
     const native_handle_t* allocate() {
-        IMapper::BufferDescriptorInfo info{};
-        info.width = 64;
-        info.height = 64;
-        info.layerCount = 1;
-        info.format = static_cast<common::V1_0::PixelFormat>(PixelFormat::RGBA_8888);
-        info.usage =
-            static_cast<uint64_t>(BufferUsage::CPU_WRITE_OFTEN | BufferUsage::CPU_READ_OFTEN);
-
-        return mGralloc->allocate(info);
+        return mGralloc->allocate(
+                64, 64, 1, static_cast<common::V1_1::PixelFormat>(PixelFormat::RGBA_8888),
+                static_cast<uint64_t>(BufferUsage::CPU_WRITE_OFTEN | BufferUsage::CPU_READ_OFTEN));
     }
 
     void execute() { mComposerClient->execute(mReader.get(), mWriter.get()); }
diff --git a/graphics/mapper/2.1/utils/vts/MapperVts.cpp b/graphics/mapper/2.1/utils/vts/MapperVts.cpp
index 078068e..36f9cbb 100644
--- a/graphics/mapper/2.1/utils/vts/MapperVts.cpp
+++ b/graphics/mapper/2.1/utils/vts/MapperVts.cpp
@@ -43,24 +43,25 @@
                       offsetof(IMapper::BufferDescriptorInfo, usage),
               "");
 
-Gralloc::Gralloc() : V2_0::vts::Gralloc() {
+Gralloc::Gralloc(bool errOnFailure) : V2_0::vts::Gralloc() {
     if (::testing::Test::HasFatalFailure()) {
         return;
     }
-    init();
+    init(errOnFailure);
 }
 
-Gralloc::Gralloc(const std::string& allocatorServiceName, const std::string& mapperServiceName)
+Gralloc::Gralloc(const std::string& allocatorServiceName, const std::string& mapperServiceName,
+                 bool errOnFailure)
     : V2_0::vts::Gralloc(allocatorServiceName, mapperServiceName) {
     if (::testing::Test::HasFatalFailure()) {
         return;
     }
-    init();
+    init(errOnFailure);
 }
 
-void Gralloc::init() {
+void Gralloc::init(bool errOnFailure) {
     mMapperV2_1 = IMapper::castFrom(V2_0::vts::Gralloc::getMapper());
-    ASSERT_NE(nullptr, mMapperV2_1.get()) << "failed to get mapper 2.1 service";
+    if (errOnFailure) ASSERT_NE(nullptr, mMapperV2_1.get()) << "failed to get mapper 2.1 service";
 }
 
 sp<IMapper> Gralloc::getMapper() const {
diff --git a/graphics/mapper/2.1/utils/vts/include/mapper-vts/2.1/MapperVts.h b/graphics/mapper/2.1/utils/vts/include/mapper-vts/2.1/MapperVts.h
index 423d4b3..bc683bb 100644
--- a/graphics/mapper/2.1/utils/vts/include/mapper-vts/2.1/MapperVts.h
+++ b/graphics/mapper/2.1/utils/vts/include/mapper-vts/2.1/MapperVts.h
@@ -32,25 +32,26 @@
 // A wrapper to IAllocator and IMapper.
 class Gralloc : public V2_0::vts::Gralloc {
    public:
-    Gralloc();
-    Gralloc(const std::string& allocatorServiceName, const std::string& mapperServiceName);
+     Gralloc(bool errOnFailure = true);
+     Gralloc(const std::string& allocatorServiceName, const std::string& mapperServiceName,
+             bool errOnFailure = true);
 
-    sp<IMapper> getMapper() const;
+     sp<IMapper> getMapper() const;
 
-    bool validateBufferSize(const native_handle_t* bufferHandle,
-                            const IMapper::BufferDescriptorInfo& descriptorInfo, uint32_t stride);
-    void getTransportSize(const native_handle_t* bufferHandle, uint32_t* outNumFds,
-                          uint32_t* outNumInts);
+     bool validateBufferSize(const native_handle_t* bufferHandle,
+                             const IMapper::BufferDescriptorInfo& descriptorInfo, uint32_t stride);
+     void getTransportSize(const native_handle_t* bufferHandle, uint32_t* outNumFds,
+                           uint32_t* outNumInts);
 
-    BufferDescriptor createDescriptor(const IMapper::BufferDescriptorInfo& descriptorInfo);
+     BufferDescriptor createDescriptor(const IMapper::BufferDescriptorInfo& descriptorInfo);
 
-    const native_handle_t* allocate(const IMapper::BufferDescriptorInfo& descriptorInfo,
-                                    bool import = true, uint32_t* outStride = nullptr);
+     const native_handle_t* allocate(const IMapper::BufferDescriptorInfo& descriptorInfo,
+                                     bool import = true, uint32_t* outStride = nullptr);
 
    protected:
-    void init();
+     void init(bool errOnFailure = true);
 
-    sp<IMapper> mMapperV2_1;
+     sp<IMapper> mMapperV2_1;
 };
 
 }  // namespace vts
diff --git a/graphics/mapper/3.0/utils/vts/MapperVts.cpp b/graphics/mapper/3.0/utils/vts/MapperVts.cpp
index f2b7594..c94e8db 100644
--- a/graphics/mapper/3.0/utils/vts/MapperVts.cpp
+++ b/graphics/mapper/3.0/utils/vts/MapperVts.cpp
@@ -25,8 +25,13 @@
 namespace V3_0 {
 namespace vts {
 
-Gralloc::Gralloc(const std::string& allocatorServiceName, const std::string& mapperServiceName) {
-    init(allocatorServiceName, mapperServiceName);
+Gralloc::Gralloc(const std::string& allocatorServiceName, const std::string& mapperServiceName,
+                 bool errOnFailure) {
+    if (errOnFailure) {
+        init(allocatorServiceName, mapperServiceName);
+    } else {
+        initNoErr(allocatorServiceName, mapperServiceName);
+    }
 }
 
 void Gralloc::init(const std::string& allocatorServiceName, const std::string& mapperServiceName) {
@@ -38,6 +43,16 @@
     ASSERT_FALSE(mMapper->isRemote()) << "mapper is not in passthrough mode";
 }
 
+void Gralloc::initNoErr(const std::string& allocatorServiceName,
+                        const std::string& mapperServiceName) {
+    mAllocator = ::testing::VtsHalHidlTargetTestBase::getService<IAllocator>(allocatorServiceName);
+
+    mMapper = ::testing::VtsHalHidlTargetTestBase::getService<IMapper>(mapperServiceName);
+    if (mMapper.get()) {
+        ASSERT_FALSE(mMapper->isRemote()) << "mapper is not in passthrough mode";
+    }
+}
+
 Gralloc::~Gralloc() {
     for (auto bufferHandle : mClonedBuffers) {
         auto buffer = const_cast<native_handle_t*>(bufferHandle);
diff --git a/graphics/mapper/3.0/utils/vts/include/mapper-vts/3.0/MapperVts.h b/graphics/mapper/3.0/utils/vts/include/mapper-vts/3.0/MapperVts.h
index ba79ca4..1141a88 100644
--- a/graphics/mapper/3.0/utils/vts/include/mapper-vts/3.0/MapperVts.h
+++ b/graphics/mapper/3.0/utils/vts/include/mapper-vts/3.0/MapperVts.h
@@ -36,62 +36,66 @@
 // A wrapper to IAllocator and IMapper.
 class Gralloc {
    public:
-    Gralloc(const std::string& allocatorServiceName = "default",
-            const std::string& mapperServiceName = "default");
-    ~Gralloc();
+     Gralloc(const std::string& allocatorServiceName = "default",
+             const std::string& mapperServiceName = "default", bool errOnFailure = true);
+     ~Gralloc();
 
-    // IAllocator methods
+     // IAllocator methods
 
-    sp<IAllocator> getAllocator() const;
+     sp<IAllocator> getAllocator() const;
 
-    std::string dumpDebugInfo();
+     std::string dumpDebugInfo();
 
-    // When import is false, this simply calls IAllocator::allocate. When import
-    // is true, the returned buffers are also imported into the mapper.
-    //
-    // Either case, the returned buffers must be freed with freeBuffer.
-    std::vector<const native_handle_t*> allocate(const BufferDescriptor& descriptor, uint32_t count,
-                                                 bool import = true, uint32_t* outStride = nullptr);
-    const native_handle_t* allocate(const IMapper::BufferDescriptorInfo& descriptorInfo,
-                                    bool import = true, uint32_t* outStride = nullptr);
+     // When import is false, this simply calls IAllocator::allocate. When import
+     // is true, the returned buffers are also imported into the mapper.
+     //
+     // Either case, the returned buffers must be freed with freeBuffer.
+     std::vector<const native_handle_t*> allocate(const BufferDescriptor& descriptor,
+                                                  uint32_t count, bool import = true,
+                                                  uint32_t* outStride = nullptr);
+     const native_handle_t* allocate(const IMapper::BufferDescriptorInfo& descriptorInfo,
+                                     bool import = true, uint32_t* outStride = nullptr);
 
-    // IMapper methods
+     // IMapper methods
 
-    sp<IMapper> getMapper() const;
+     sp<IMapper> getMapper() const;
 
-    BufferDescriptor createDescriptor(const IMapper::BufferDescriptorInfo& descriptorInfo);
+     BufferDescriptor createDescriptor(const IMapper::BufferDescriptorInfo& descriptorInfo);
 
-    const native_handle_t* importBuffer(const hidl_handle& rawHandle);
-    void freeBuffer(const native_handle_t* bufferHandle);
+     const native_handle_t* importBuffer(const hidl_handle& rawHandle);
+     void freeBuffer(const native_handle_t* bufferHandle);
 
-    // We use fd instead of hidl_handle in these functions to pass fences
-    // in and out of the mapper.  The ownership of the fd is always transferred
-    // with each of these functions.
-    void* lock(const native_handle_t* bufferHandle, uint64_t cpuUsage,
-               const IMapper::Rect& accessRegion, int acquireFence, int32_t* outBytesPerPixel,
-               int32_t* outBytesPerStride);
-    YCbCrLayout lockYCbCr(const native_handle_t* bufferHandle, uint64_t cpuUsage,
-                          const IMapper::Rect& accessRegion, int acquireFence);
-    int unlock(const native_handle_t* bufferHandle);
+     // We use fd instead of hidl_handle in these functions to pass fences
+     // in and out of the mapper.  The ownership of the fd is always transferred
+     // with each of these functions.
+     void* lock(const native_handle_t* bufferHandle, uint64_t cpuUsage,
+                const IMapper::Rect& accessRegion, int acquireFence, int32_t* outBytesPerPixel,
+                int32_t* outBytesPerStride);
+     YCbCrLayout lockYCbCr(const native_handle_t* bufferHandle, uint64_t cpuUsage,
+                           const IMapper::Rect& accessRegion, int acquireFence);
+     int unlock(const native_handle_t* bufferHandle);
 
-    bool validateBufferSize(const native_handle_t* bufferHandle,
-                            const IMapper::BufferDescriptorInfo& descriptorInfo, uint32_t stride);
-    void getTransportSize(const native_handle_t* bufferHandle, uint32_t* outNumFds,
-                          uint32_t* outNumInts);
+     bool validateBufferSize(const native_handle_t* bufferHandle,
+                             const IMapper::BufferDescriptorInfo& descriptorInfo, uint32_t stride);
+     void getTransportSize(const native_handle_t* bufferHandle, uint32_t* outNumFds,
+                           uint32_t* outNumInts);
 
-    bool isSupported(const IMapper::BufferDescriptorInfo& descriptorInfo);
+     bool isSupported(const IMapper::BufferDescriptorInfo& descriptorInfo);
 
    private:
-    void init(const std::string& allocatorServiceName, const std::string& mapperServiceName);
-    const native_handle_t* cloneBuffer(const hidl_handle& rawHandle);
+     void init(const std::string& allocatorServiceName, const std::string& mapperServiceName);
 
-    sp<IAllocator> mAllocator;
-    sp<IMapper> mMapper;
+     // initialize without checking for failure to get service
+     void initNoErr(const std::string& allocatorServiceName, const std::string& mapperServiceName);
+     const native_handle_t* cloneBuffer(const hidl_handle& rawHandle);
 
-    // Keep track of all cloned and imported handles.  When a test fails with
-    // ASSERT_*, the destructor will free the handles for the test.
-    std::unordered_set<const native_handle_t*> mClonedBuffers;
-    std::unordered_set<const native_handle_t*> mImportedBuffers;
+     sp<IAllocator> mAllocator;
+     sp<IMapper> mMapper;
+
+     // Keep track of all cloned and imported handles.  When a test fails with
+     // ASSERT_*, the destructor will free the handles for the test.
+     std::unordered_set<const native_handle_t*> mClonedBuffers;
+     std::unordered_set<const native_handle_t*> mImportedBuffers;
 };
 
 }  // namespace vts
diff --git a/health/storage/1.0/vts/functional/Android.bp b/health/storage/1.0/vts/functional/Android.bp
index 250a7dc..b18e36f 100644
--- a/health/storage/1.0/vts/functional/Android.bp
+++ b/health/storage/1.0/vts/functional/Android.bp
@@ -20,7 +20,8 @@
     srcs: ["VtsHalHealthStorageV1_0TargetTest.cpp"],
     static_libs: ["android.hardware.health.storage@1.0"],
     shared_libs: [
-        "libhidltransport"
+        "libhidlbase",
+        "libhidltransport",
     ],
     test_suites: ["general-tests"],
 }
diff --git a/keymaster/4.0/vts/functional/keymaster_hidl_hal_test.cpp b/keymaster/4.0/vts/functional/keymaster_hidl_hal_test.cpp
index 3d37e9f..6f75a97 100644
--- a/keymaster/4.0/vts/functional/keymaster_hidl_hal_test.cpp
+++ b/keymaster/4.0/vts/functional/keymaster_hidl_hal_test.cpp
@@ -4219,28 +4219,6 @@
 }
 
 /*
- * AttestationTest.RsaAttestationRequiresCorrectAppId
- *
- * Verifies that attesting to RSA requires the correct app ID.
- */
-TEST_F(AttestationTest, RsaAttestationRequiresCorrectAppId) {
-    ASSERT_EQ(ErrorCode::OK,
-              GenerateKey(AuthorizationSetBuilder()
-                                  .Authorization(TAG_NO_AUTH_REQUIRED)
-                                  .RsaSigningKey(2048, 65537)
-                                  .Digest(Digest::NONE)
-                                  .Padding(PaddingMode::NONE)
-                                  .Authorization(TAG_APPLICATION_ID, HidlBuf("lol"))));
-
-    hidl_vec<hidl_vec<uint8_t>> cert_chain;
-    EXPECT_EQ(ErrorCode::ATTESTATION_APPLICATION_ID_MISSING,
-              AttestKey(AuthorizationSetBuilder()
-                                .Authorization(TAG_ATTESTATION_CHALLENGE, HidlBuf("challenge"))
-                                .Authorization(TAG_APPLICATION_ID, HidlBuf("heh")),
-                        &cert_chain));
-}
-
-/*
  * AttestationTest.EcAttestation
  *
  * Verifies that attesting to EC keys works and generates the expected output.
diff --git a/power/stats/1.0/vts/functional/VtsHalPowerStatsV1_0TargetTest.cpp b/power/stats/1.0/vts/functional/VtsHalPowerStatsV1_0TargetTest.cpp
index 9f007e4..835a47b 100644
--- a/power/stats/1.0/vts/functional/VtsHalPowerStatsV1_0TargetTest.cpp
+++ b/power/stats/1.0/vts/functional/VtsHalPowerStatsV1_0TargetTest.cpp
@@ -566,15 +566,16 @@
     thread1.join();
 }
 
-int main(int argc, char** argv) {
-    ::testing::AddGlobalTestEnvironment(PowerStatsHidlEnv::Instance());
-    ::testing::InitGoogleTest(&argc, argv);
-    PowerStatsHidlEnv::Instance()->init(&argc, argv);
-    int status = RUN_ALL_TESTS();
-    LOG(INFO) << "Test result = " << status;
-    return status;
-}
 }  // namespace vts
 }  // namespace stats
 }  // namespace power
 }  // namespace android
+
+int main(int argc, char** argv) {
+    ::testing::AddGlobalTestEnvironment(android::power::stats::vts::PowerStatsHidlEnv::Instance());
+    ::testing::InitGoogleTest(&argc, argv);
+    android::power::stats::vts::PowerStatsHidlEnv::Instance()->init(&argc, argv);
+    int status = RUN_ALL_TESTS();
+    LOG(INFO) << "Test result = " << status;
+    return status;
+}
diff --git a/radio/1.2/types.hal b/radio/1.2/types.hal
index 2dceeb1..dffebd3 100644
--- a/radio/1.2/types.hal
+++ b/radio/1.2/types.hal
@@ -193,7 +193,8 @@
      * the client (in seconds).
      * Expected range for the input is
      * [IncrementalResultsPeriodicityRange:MIN - IncrementalResultsPeriodicityRange:MAX]
-     * This value must be less than or equal to maxSearchTime.
+     * This value must be less than or equal to maxSearchTime. If incremental results are
+     * not requested, implementations may ignore this value.
      */
     int32_t incrementalResultsPeriodicity;
 
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 a3073ac..f11f0d8 100644
--- a/radio/1.2/vts/functional/radio_hidl_hal_api.cpp
+++ b/radio/1.2/vts/functional/radio_hidl_hal_api.cpp
@@ -60,6 +60,11 @@
                                      {RadioError::NONE, RadioError::REQUEST_NOT_SUPPORTED,
                                       RadioError::OPERATION_NOT_ALLOWED}));
     }
+
+    if (radioRsp_v1_2->rspInfo.error == RadioError::NONE) {
+        ALOGI("Stop Network Scan");
+        stopNetworkScan();
+    }
 }
 
 /*
@@ -228,7 +233,7 @@
             .interval = 60,
             .specifiers = {::GERAN_SPECIFIER_P900, ::GERAN_SPECIFIER_850},
             .maxSearchTime = 600,
-            .incrementalResults = false,
+            .incrementalResults = true,
             .incrementalResultsPeriodicity = 0};
 
     Return<void> res = radio_v1_2->startNetworkScan_1_2(serial, request);
@@ -260,7 +265,7 @@
             .interval = 60,
             .specifiers = {::GERAN_SPECIFIER_P900, ::GERAN_SPECIFIER_850},
             .maxSearchTime = 600,
-            .incrementalResults = false,
+            .incrementalResults = true,
             .incrementalResultsPeriodicity = 11};
 
     Return<void> res = radio_v1_2->startNetworkScan_1_2(serial, request);
diff --git a/radio/1.2/vts/functional/radio_hidl_hal_test.cpp b/radio/1.2/vts/functional/radio_hidl_hal_test.cpp
index b34f138..bff7481 100644
--- a/radio/1.2/vts/functional/radio_hidl_hal_test.cpp
+++ b/radio/1.2/vts/functional/radio_hidl_hal_test.cpp
@@ -14,6 +14,7 @@
  * limitations under the License.
  */
 
+#include <android/hardware/radio/1.1/IRadio.h>
 #include <radio_hidl_hal_utils_v1_2.h>
 
 void RadioHidlTest_v1_2::SetUp() {
@@ -84,4 +85,28 @@
     serial = GetRandomSerialNumber();
     radio_v1_2->getIccCardStatus(serial);
     EXPECT_EQ(std::cv_status::no_timeout, wait());
-}
\ No newline at end of file
+}
+
+void RadioHidlTest_v1_2::stopNetworkScan() {
+    sp<::android::hardware::radio::V1_1::IRadio> radio_v1_1;
+
+    radio_v1_1 = ::testing::VtsHalHidlTargetTestBase::getService<
+            ::android::hardware::radio::V1_1::IRadio>(
+            RadioHidlEnvironment::Instance()
+                    ->getServiceName<::android::hardware::radio::V1_1::IRadio>(
+                            hidl_string(RADIO_SERVICE_NAME)));
+    if (radio_v1_1 == NULL) {
+        sleep(60);
+        radio_v1_1 = ::testing::VtsHalHidlTargetTestBase::getService<
+                ::android::hardware::radio::V1_1::IRadio>(
+                RadioHidlEnvironment::Instance()
+                        ->getServiceName<::android::hardware::radio::V1_1::IRadio>(
+                                hidl_string(RADIO_SERVICE_NAME)));
+    }
+    ASSERT_NE(nullptr, radio_v1_1.get());
+
+    serial = GetRandomSerialNumber();
+
+    radio_v1_1->stopNetworkScan(serial);
+    EXPECT_EQ(std::cv_status::no_timeout, wait());
+}
diff --git a/radio/1.2/vts/functional/radio_hidl_hal_utils_v1_2.h b/radio/1.2/vts/functional/radio_hidl_hal_utils_v1_2.h
index 2e65bfb..3f780e5 100644
--- a/radio/1.2/vts/functional/radio_hidl_hal_utils_v1_2.h
+++ b/radio/1.2/vts/functional/radio_hidl_hal_utils_v1_2.h
@@ -622,7 +622,10 @@
     /* Update Sim Card Status */
     void updateSimCardStatus();
 
-   public:
+    /* Stop Network Scan Command */
+    void stopNetworkScan();
+
+  public:
     virtual void SetUp() override;
 
     /* Used as a mechanism to inform the test about data/event callback */
diff --git a/radio/1.3/IRadioResponse.hal b/radio/1.3/IRadioResponse.hal
index c3bbe65..85085e2 100644
--- a/radio/1.3/IRadioResponse.hal
+++ b/radio/1.3/IRadioResponse.hal
@@ -44,6 +44,9 @@
      *   RadioError:NONE
      *   RadioError:RADIO_NOT_AVAILABLE
      *   RadioError:MODEM_ERR
+     *   RadioError:INVALID_STATE: this is for the case that the API is called in a single-sim
+     *              mode, or when there is only one modem available, as this API should only
+     *              be called in multi sim status.
      */
     oneway enableModemResponse(RadioResponseInfo info);
 
diff --git a/radio/1.3/vts/functional/radio_hidl_hal_api.cpp b/radio/1.3/vts/functional/radio_hidl_hal_api.cpp
index 5b7a06d..813dd13 100644
--- a/radio/1.3/vts/functional/radio_hidl_hal_api.cpp
+++ b/radio/1.3/vts/functional/radio_hidl_hal_api.cpp
@@ -35,7 +35,7 @@
           toString(radioRsp_v1_3->rspInfo.error).c_str());
     ASSERT_TRUE(CheckAnyOfErrors(radioRsp_v1_3->rspInfo.error,
                                  {RadioError::NONE, RadioError::RADIO_NOT_AVAILABLE,
-                                  RadioError::MODEM_ERR, RadioError::REQUEST_NOT_SUPPORTED}));
+                                  RadioError::MODEM_ERR, RadioError::INVALID_STATE}));
 
     // checking if getModemStackStatus returns true, as modem was enabled above
     if (RadioError::NONE == radioRsp_v1_3->rspInfo.error) {
@@ -52,7 +52,7 @@
               toString(radioRsp_v1_3->rspInfo.error).c_str());
         ASSERT_TRUE(CheckAnyOfErrors(radioRsp_v1_3->rspInfo.error,
                                      {RadioError::NONE, RadioError::RADIO_NOT_AVAILABLE,
-                                      RadioError::MODEM_ERR, RadioError::REQUEST_NOT_SUPPORTED}));
+                                      RadioError::MODEM_ERR, RadioError::INVALID_STATE}));
         // verify that enableModem did set isEnabled correctly
         EXPECT_EQ(true, radioRsp_v1_3->isModemEnabled);
     }
diff --git a/radio/1.4/vts/functional/Android.bp b/radio/1.4/vts/functional/Android.bp
index 2d0e089..6827132 100644
--- a/radio/1.4/vts/functional/Android.bp
+++ b/radio/1.4/vts/functional/Android.bp
@@ -31,7 +31,9 @@
         "android.hardware.radio@1.2",
         "android.hardware.radio@1.1",
         "android.hardware.radio@1.0",
+        "android.hardware.radio.config@1.0",
+        "android.hardware.radio.config@1.1",
     ],
     header_libs: ["radio.util.header@1.0"],
     test_suites: ["general-tests"]
-}
\ No newline at end of file
+}
diff --git a/radio/1.4/vts/functional/radio_hidl_hal_api.cpp b/radio/1.4/vts/functional/radio_hidl_hal_api.cpp
index 2093c25..696c746 100644
--- a/radio/1.4/vts/functional/radio_hidl_hal_api.cpp
+++ b/radio/1.4/vts/functional/radio_hidl_hal_api.cpp
@@ -119,6 +119,10 @@
 
     network_type_bitmap |= ::android::hardware::radio::V1_4::RadioAccessFamily::LTE;
 
+    // TODO(b/131634656): LTE_CA will be sent to modem as a RAF in Q, but LTE_CA is not a RAF,
+    // we will not send it to modem as a RAF in R.
+    network_type_bitmap |= ::android::hardware::radio::V1_4::RadioAccessFamily::LTE_CA;
+
     Return<void> res = radio_v1_4->setPreferredNetworkTypeBitmap(serial, network_type_bitmap);
 
     ASSERT_OK(res);
diff --git a/radio/1.4/vts/functional/radio_hidl_hal_test.cpp b/radio/1.4/vts/functional/radio_hidl_hal_test.cpp
index 4d80696..d2d21ce 100644
--- a/radio/1.4/vts/functional/radio_hidl_hal_test.cpp
+++ b/radio/1.4/vts/functional/radio_hidl_hal_test.cpp
@@ -47,6 +47,13 @@
     EXPECT_EQ(serial, radioRsp_v1_4->rspInfo.serial);
     EXPECT_EQ(RadioError::NONE, radioRsp_v1_4->rspInfo.error);
 
+    sp<::android::hardware::radio::config::V1_1::IRadioConfig> radioConfig =
+            ::testing::VtsHalHidlTargetTestBase::getService<
+                    ::android::hardware::radio::config::V1_1::IRadioConfig>();
+
+    /* Enforce Vts tesing with RadioConfig is existed. */
+    ASSERT_NE(nullptr, radioConfig.get());
+
     /* Enforce Vts Testing with Sim Status Present only. */
     EXPECT_EQ(CardState::PRESENT, cardStatus.base.base.cardState);
 }
@@ -84,4 +91,4 @@
     serial = GetRandomSerialNumber();
     radio_v1_4->getIccCardStatus(serial);
     EXPECT_EQ(std::cv_status::no_timeout, wait());
-}
\ No newline at end of file
+}
diff --git a/radio/1.4/vts/functional/radio_hidl_hal_utils_v1_4.h b/radio/1.4/vts/functional/radio_hidl_hal_utils_v1_4.h
index de7742c..f662472 100644
--- a/radio/1.4/vts/functional/radio_hidl_hal_utils_v1_4.h
+++ b/radio/1.4/vts/functional/radio_hidl_hal_utils_v1_4.h
@@ -22,6 +22,8 @@
 #include <condition_variable>
 #include <mutex>
 
+#include <android/hardware/radio/config/1.1/IRadioConfig.h>
+
 #include <android/hardware/radio/1.4/IRadio.h>
 #include <android/hardware/radio/1.4/IRadioIndication.h>
 #include <android/hardware/radio/1.4/IRadioResponse.h>
diff --git a/radio/config/1.0/vts/functional/radio_config_response.cpp b/radio/config/1.0/vts/functional/radio_config_response.cpp
index 97e8dca..a92db64 100644
--- a/radio/config/1.0/vts/functional/radio_config_response.cpp
+++ b/radio/config/1.0/vts/functional/radio_config_response.cpp
@@ -21,11 +21,15 @@
 RadioConfigResponse::RadioConfigResponse(RadioConfigHidlTest& parent) : parent(parent) {}
 
 Return<void> RadioConfigResponse::getSimSlotsStatusResponse(
-    const RadioResponseInfo& /* info */,
-    const ::android::hardware::hidl_vec<SimSlotStatus>& /* slotStatus */) {
+        const RadioResponseInfo& info,
+        const ::android::hardware::hidl_vec<SimSlotStatus>& /* slotStatus */) {
+    rspInfo = info;
+    parent.notify();
     return Void();
 }
 
-Return<void> RadioConfigResponse::setSimSlotsMappingResponse(const RadioResponseInfo& /* info */) {
+Return<void> RadioConfigResponse::setSimSlotsMappingResponse(const RadioResponseInfo& info) {
+    rspInfo = info;
+    parent.notify();
     return Void();
-}
\ No newline at end of file
+}
diff --git a/radio/config/1.1/vts/functional/radio_config_hidl_hal_api.cpp b/radio/config/1.1/vts/functional/radio_config_hidl_hal_api.cpp
index 122ce58..5d0e867 100644
--- a/radio/config/1.1/vts/functional/radio_config_hidl_hal_api.cpp
+++ b/radio/config/1.1/vts/functional/radio_config_hidl_hal_api.cpp
@@ -130,7 +130,8 @@
     EXPECT_EQ(std::cv_status::no_timeout, wait());
     EXPECT_EQ(RadioResponseType::SOLICITED, radioConfigRsp->rspInfo.type);
     EXPECT_EQ(serial, radioConfigRsp->rspInfo.serial);
-    ALOGI("getModemsConfig, rspInfo.error = %s\n", toString(radioConfigRsp->rspInfo.error).c_str());
+    ALOGI("setPreferredDataModem, rspInfo.error = %s\n",
+          toString(radioConfigRsp->rspInfo.error).c_str());
 
     ASSERT_TRUE(CheckAnyOfErrors(
             radioConfigRsp->rspInfo.error,
@@ -149,7 +150,8 @@
     EXPECT_EQ(std::cv_status::no_timeout, wait());
     EXPECT_EQ(RadioResponseType::SOLICITED, radioConfigRsp->rspInfo.type);
     EXPECT_EQ(serial, radioConfigRsp->rspInfo.serial);
-    ALOGI("getModemsConfig, rspInfo.error = %s\n", toString(radioConfigRsp->rspInfo.error).c_str());
+    ALOGI("setPreferredDataModem, rspInfo.error = %s\n",
+          toString(radioConfigRsp->rspInfo.error).c_str());
 
     ASSERT_TRUE(CheckAnyOfErrors(radioConfigRsp->rspInfo.error,
                                  {RadioError::INVALID_ARGUMENTS, RadioError::RADIO_NOT_AVAILABLE,
diff --git a/radio/config/1.1/vts/functional/radio_config_hidl_hal_test.cpp b/radio/config/1.1/vts/functional/radio_config_hidl_hal_test.cpp
index a8c257d..39e6487 100644
--- a/radio/config/1.1/vts/functional/radio_config_hidl_hal_test.cpp
+++ b/radio/config/1.1/vts/functional/radio_config_hidl_hal_test.cpp
@@ -34,9 +34,6 @@
     count_ = 0;
 
     radioConfig->setResponseFunctions(radioConfigRsp, nullptr);
-    EXPECT_EQ(RadioResponseType::SOLICITED, radioConfigRsp->rspInfo.type);
-    EXPECT_EQ(serial, radioConfigRsp->rspInfo.serial);
-    EXPECT_EQ(RadioError::NONE, radioConfigRsp->rspInfo.error);
 }
 
 /*
@@ -66,4 +63,4 @@
     }
     count_--;
     return status;
-}
\ No newline at end of file
+}
diff --git a/radio/config/1.1/vts/functional/radio_config_response.cpp b/radio/config/1.1/vts/functional/radio_config_response.cpp
index ce3dfdf..bd8c4cf 100644
--- a/radio/config/1.1/vts/functional/radio_config_response.cpp
+++ b/radio/config/1.1/vts/functional/radio_config_response.cpp
@@ -38,16 +38,21 @@
     return Void();
 }
 
-Return<void> RadioConfigResponse::setPreferredDataModemResponse(
-    const RadioResponseInfo& /* info */) {
+Return<void> RadioConfigResponse::setPreferredDataModemResponse(const RadioResponseInfo& info) {
+    rspInfo = info;
+    parent.notify(info.serial);
     return Void();
 }
 
-Return<void> RadioConfigResponse::getModemsConfigResponse(const RadioResponseInfo& /* info */,
+Return<void> RadioConfigResponse::getModemsConfigResponse(const RadioResponseInfo& info,
                                                           const ModemsConfig& /* mConfig */) {
+    rspInfo = info;
+    parent.notify(info.serial);
     return Void();
 }
 
-Return<void> RadioConfigResponse::setModemsConfigResponse(const RadioResponseInfo& /* info */) {
+Return<void> RadioConfigResponse::setModemsConfigResponse(const RadioResponseInfo& info) {
+    rspInfo = info;
+    parent.notify(info.serial);
     return Void();
 }
diff --git a/radio/config/1.2/vts/functional/Android.bp b/radio/config/1.2/vts/functional/Android.bp
new file mode 100644
index 0000000..0cafc24
--- /dev/null
+++ b/radio/config/1.2/vts/functional/Android.bp
@@ -0,0 +1,35 @@
+//
+// Copyright (C) 2019 The Android Open Source Project
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+//      http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//
+
+cc_test {
+    name: "VtsHalRadioConfigV1_2TargetTest",
+    defaults: ["VtsHalTargetTestDefaults"],
+    srcs: [
+        "radio_config_hidl_hal_api.cpp",
+        "radio_config_hidl_hal_test.cpp",
+        "radio_config_response.cpp",
+        "radio_config_indication.cpp",
+        "VtsHalRadioConfigV1_2TargetTest.cpp",
+    ],
+    static_libs: [
+        "RadioVtsTestUtilBase",
+        "android.hardware.radio.config@1.0",
+        "android.hardware.radio.config@1.1",
+        "android.hardware.radio.config@1.2",
+    ],
+    header_libs: ["radio.util.header@1.0"],
+    test_suites: ["general-tests"],
+}
diff --git a/radio/config/1.2/vts/functional/VtsHalRadioConfigV1_2TargetTest.cpp b/radio/config/1.2/vts/functional/VtsHalRadioConfigV1_2TargetTest.cpp
new file mode 100644
index 0000000..ec6544e
--- /dev/null
+++ b/radio/config/1.2/vts/functional/VtsHalRadioConfigV1_2TargetTest.cpp
@@ -0,0 +1,26 @@
+/*
+ * Copyright (C) 2019 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include <radio_config_hidl_hal_utils.h>
+
+int main(int argc, char** argv) {
+    ::testing::AddGlobalTestEnvironment(RadioConfigHidlEnvironment::Instance());
+    ::testing::InitGoogleTest(&argc, argv);
+    RadioConfigHidlEnvironment::Instance()->init(&argc, argv);
+    int status = RUN_ALL_TESTS();
+    LOG(INFO) << "Test result = " << status;
+    return status;
+}
diff --git a/radio/config/1.2/vts/functional/radio_config_hidl_hal_api.cpp b/radio/config/1.2/vts/functional/radio_config_hidl_hal_api.cpp
new file mode 100644
index 0000000..a3729ac
--- /dev/null
+++ b/radio/config/1.2/vts/functional/radio_config_hidl_hal_api.cpp
@@ -0,0 +1,30 @@
+/*
+ * Copyright (C) 2019 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include <radio_config_hidl_hal_utils.h>
+
+#define ASSERT_OK(ret) ASSERT_TRUE(ret.isOk())
+
+/*
+ * Test IRadioConfig.getSimSlotsStatus()
+ */
+TEST_F(RadioConfigHidlTest, getSimSlotsStatus) {
+    const int serial = GetRandomSerialNumber();
+    Return<void> res = radioConfig->getSimSlotsStatus(serial);
+    ASSERT_OK(res);
+    ALOGI("getIccSlotsStatus, rspInfo.error = %s\n",
+          toString(radioConfigRsp->rspInfo.error).c_str());
+}
diff --git a/radio/config/1.2/vts/functional/radio_config_hidl_hal_test.cpp b/radio/config/1.2/vts/functional/radio_config_hidl_hal_test.cpp
new file mode 100644
index 0000000..cd7a172
--- /dev/null
+++ b/radio/config/1.2/vts/functional/radio_config_hidl_hal_test.cpp
@@ -0,0 +1,66 @@
+/*
+ * Copyright (C) 2019 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include <radio_config_hidl_hal_utils.h>
+
+void RadioConfigHidlTest::SetUp() {
+    radioConfig = ::testing::VtsHalHidlTargetTestBase::getService<IRadioConfig>(
+            RadioConfigHidlEnvironment::Instance()->getServiceName<IRadioConfig>(
+                    hidl_string(RADIO_SERVICE_NAME)));
+    if (radioConfig == NULL) {
+        sleep(60);
+        radioConfig = ::testing::VtsHalHidlTargetTestBase::getService<IRadioConfig>(
+                RadioConfigHidlEnvironment::Instance()->getServiceName<IRadioConfig>(
+                        hidl_string(RADIO_SERVICE_NAME)));
+    }
+    ASSERT_NE(nullptr, radioConfig.get());
+
+    radioConfigRsp = new (std::nothrow) RadioConfigResponse(*this);
+    ASSERT_NE(nullptr, radioConfigRsp.get());
+
+    count_ = 0;
+
+    radioConfig->setResponseFunctions(radioConfigRsp, nullptr);
+}
+
+/*
+ * Notify that the response message is received.
+ */
+void RadioConfigHidlTest::notify(int receivedSerial) {
+    std::unique_lock<std::mutex> lock(mtx_);
+    if (serial == receivedSerial) {
+        count_++;
+        cv_.notify_one();
+    }
+}
+
+/*
+ * Wait till the response message is notified or till TIMEOUT_PERIOD.
+ */
+std::cv_status RadioConfigHidlTest::wait() {
+    std::unique_lock<std::mutex> lock(mtx_);
+
+    std::cv_status status = std::cv_status::no_timeout;
+    auto now = std::chrono::system_clock::now();
+    while (count_ == 0) {
+        status = cv_.wait_until(lock, now + std::chrono::seconds(TIMEOUT_PERIOD));
+        if (status == std::cv_status::timeout) {
+            return status;
+        }
+    }
+    count_--;
+    return status;
+}
diff --git a/radio/config/1.2/vts/functional/radio_config_hidl_hal_utils.h b/radio/config/1.2/vts/functional/radio_config_hidl_hal_utils.h
new file mode 100644
index 0000000..a876766
--- /dev/null
+++ b/radio/config/1.2/vts/functional/radio_config_hidl_hal_utils.h
@@ -0,0 +1,140 @@
+/*
+ * Copyright (C) 2019 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include <android-base/logging.h>
+
+#include <VtsHalHidlTargetTestBase.h>
+#include <VtsHalHidlTargetTestEnvBase.h>
+#include <chrono>
+#include <condition_variable>
+#include <mutex>
+
+#include <android/hardware/radio/config/1.1/IRadioConfig.h>
+#include <android/hardware/radio/config/1.1/types.h>
+#include <android/hardware/radio/config/1.2/IRadioConfigIndication.h>
+#include <android/hardware/radio/config/1.2/IRadioConfigResponse.h>
+#include <android/hardware/radio/config/1.2/types.h>
+
+#include "vts_test_util.h"
+
+using namespace ::android::hardware::radio::config::V1_2;
+
+using ::android::sp;
+using ::android::hardware::hidl_string;
+using ::android::hardware::hidl_vec;
+using ::android::hardware::Return;
+using ::android::hardware::Void;
+using ::android::hardware::radio::config::V1_1::IRadioConfig;
+using ::android::hardware::radio::config::V1_1::ModemsConfig;
+using ::android::hardware::radio::config::V1_1::PhoneCapability;
+using ::android::hardware::radio::config::V1_2::SimSlotStatus;
+using ::android::hardware::radio::V1_0::RadioResponseInfo;
+using ::android::hardware::radio::V1_0::RadioResponseType;
+
+#define TIMEOUT_PERIOD 75
+#define RADIO_SERVICE_NAME "slot1"
+
+class RadioConfigHidlTest;
+
+/* Callback class for radio config response */
+class RadioConfigResponse : public IRadioConfigResponse {
+  protected:
+    RadioConfigHidlTest& parent;
+
+  public:
+    RadioResponseInfo rspInfo;
+    PhoneCapability phoneCap;
+
+    RadioConfigResponse(RadioConfigHidlTest& parent);
+    virtual ~RadioConfigResponse() = default;
+
+    Return<void> getSimSlotsStatusResponse(
+            const RadioResponseInfo& info,
+            const ::android::hardware::hidl_vec<
+                    ::android::hardware::radio::config::V1_0::SimSlotStatus>& slotStatus);
+
+    Return<void> getSimSlotsStatusResponse_1_2(
+            const RadioResponseInfo& info,
+            const ::android::hardware::hidl_vec<SimSlotStatus>& slotStatus);
+
+    Return<void> setSimSlotsMappingResponse(const RadioResponseInfo& info);
+
+    Return<void> getPhoneCapabilityResponse(const RadioResponseInfo& info,
+                                            const PhoneCapability& phoneCapability);
+
+    Return<void> setPreferredDataModemResponse(const RadioResponseInfo& info);
+
+    Return<void> getModemsConfigResponse(const RadioResponseInfo& info,
+                                         const ModemsConfig& mConfig);
+
+    Return<void> setModemsConfigResponse(const RadioResponseInfo& info);
+};
+
+/* Callback class for radio config indication */
+class RadioConfigIndication : public IRadioConfigIndication {
+  protected:
+    RadioConfigHidlTest& parent;
+
+  public:
+    RadioConfigIndication(RadioConfigHidlTest& parent);
+    virtual ~RadioConfigIndication() = default;
+
+    Return<void> simSlotsStatusChanged_1_2(
+            ::android::hardware::radio::V1_0::RadioIndicationType type,
+            const ::android::hardware::hidl_vec<SimSlotStatus>& slotStatus);
+};
+
+// Test environment for Radio HIDL HAL.
+class RadioConfigHidlEnvironment : public ::testing::VtsHalHidlTargetTestEnvBase {
+  public:
+    // get the test environment singleton
+    static RadioConfigHidlEnvironment* Instance() {
+        static RadioConfigHidlEnvironment* instance = new RadioConfigHidlEnvironment;
+        return instance;
+    }
+    virtual void registerTestServices() override { registerTestService<IRadioConfig>(); }
+
+  private:
+    RadioConfigHidlEnvironment() {}
+};
+
+// The main test class for Radio config HIDL.
+class RadioConfigHidlTest : public ::testing::VtsHalHidlTargetTestBase {
+  protected:
+    std::mutex mtx_;
+    std::condition_variable cv_;
+    int count_;
+
+  public:
+    virtual void SetUp() override;
+
+    /* Used as a mechanism to inform the test about data/event callback */
+    void notify(int receivedSerial);
+
+    /* Test code calls this function to wait for response */
+    std::cv_status wait();
+
+    void updateSimCardStatus();
+
+    /* Serial number for radio request */
+    int serial;
+
+    /* radio config service handle */
+    sp<IRadioConfig> radioConfig;
+
+    /* radio config response handle */
+    sp<RadioConfigResponse> radioConfigRsp;
+};
diff --git a/radio/config/1.2/vts/functional/radio_config_indication.cpp b/radio/config/1.2/vts/functional/radio_config_indication.cpp
new file mode 100644
index 0000000..0bacacb
--- /dev/null
+++ b/radio/config/1.2/vts/functional/radio_config_indication.cpp
@@ -0,0 +1,25 @@
+/*
+ * Copyright (C) 2019 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include <radio_config_hidl_hal_utils.h>
+
+RadioConfigIndication::RadioConfigIndication(RadioConfigHidlTest& parent) : parent(parent) {}
+
+Return<void> RadioConfigIndication::simSlotsStatusChanged_1_2(
+        ::android::hardware::radio::V1_0::RadioIndicationType /*type*/,
+        const ::android::hardware::hidl_vec<SimSlotStatus>& /*slotStatus*/) {
+    return Void();
+}
diff --git a/radio/config/1.2/vts/functional/radio_config_response.cpp b/radio/config/1.2/vts/functional/radio_config_response.cpp
new file mode 100644
index 0000000..ec0f886
--- /dev/null
+++ b/radio/config/1.2/vts/functional/radio_config_response.cpp
@@ -0,0 +1,66 @@
+/*
+ * Copyright (C) 2019 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include <radio_config_hidl_hal_utils.h>
+
+using ::android::hardware::radio::V1_0::RadioResponseInfo;
+
+// SimSlotStatus slotStatus;
+
+RadioConfigResponse::RadioConfigResponse(RadioConfigHidlTest& parent) : parent(parent) {}
+
+Return<void> RadioConfigResponse::getSimSlotsStatusResponse(
+        const ::android::hardware::radio::V1_0::RadioResponseInfo& /* info */,
+        const ::android::hardware::hidl_vec<
+                ::android::hardware::radio::config::V1_0::SimSlotStatus>& /* slotStatus */) {
+    return Void();
+}
+
+Return<void> RadioConfigResponse::getSimSlotsStatusResponse_1_2(
+        const ::android::hardware::radio::V1_0::RadioResponseInfo& /* info */,
+        const ::android::hardware::hidl_vec<SimSlotStatus>& /* slotStatus */) {
+    return Void();
+}
+
+Return<void> RadioConfigResponse::setSimSlotsMappingResponse(
+        const ::android::hardware::radio::V1_0::RadioResponseInfo& /* info */) {
+    return Void();
+}
+
+Return<void> RadioConfigResponse::getPhoneCapabilityResponse(
+        const ::android::hardware::radio::V1_0::RadioResponseInfo& info,
+        const PhoneCapability& phoneCapability) {
+    rspInfo = info;
+    phoneCap = phoneCapability;
+    parent.notify(info.serial);
+    return Void();
+}
+
+Return<void> RadioConfigResponse::setPreferredDataModemResponse(
+        const ::android::hardware::radio::V1_0::RadioResponseInfo& /* info */) {
+    return Void();
+}
+
+Return<void> RadioConfigResponse::getModemsConfigResponse(
+        const ::android::hardware::radio::V1_0::RadioResponseInfo& /* info */,
+        const ModemsConfig& /* mConfig */) {
+    return Void();
+}
+
+Return<void> RadioConfigResponse::setModemsConfigResponse(
+        const ::android::hardware::radio::V1_0::RadioResponseInfo& /* info */) {
+    return Void();
+}
diff --git a/sensors/1.0/types.hal b/sensors/1.0/types.hal
index e91820c..cbbe92f 100644
--- a/sensors/1.0/types.hal
+++ b/sensors/1.0/types.hal
@@ -1008,10 +1008,40 @@
     AINFO_VEC3_CALIBRATION,
 
     /**
-     * Location and orientation of sensor element in the device frame: origin is
-     * the geometric center of the mobile device screen surface; the axis
-     * definition corresponds to Android sensor definitions.
-     * float[12]: 3x4 matrix in row major order
+     * Provides the orientation and location of the sensor element in terms of
+     * the Android coordinate system. This data is given as a 3x4 matrix
+     * consisting of a 3x3 rotation matrix (R) concatenated with a 3x1 location
+     * vector (t). The rotation matrix provides the orientation of the Android
+     * device coordinate frame relative to the local coordinate frame of the
+     * sensor. Note that assuming the axes conventions of the sensor are the
+     * same as Android, this is the inverse of the matrix applied to raw
+     * samples read from the sensor to convert them into the Android
+     * representation. The location vector represents the translation from the
+     * origin of the Android sensor coordinate system to the geometric center
+     * of the sensor, specified in millimeters (mm).
+     *
+     * float[12]: 3x4 matrix in row major order [R; t]
+     *
+     * Example:
+     *     This raw buffer: {0, 1, 0, 0, -1, 0, 0, 10, 0, 0, 1, -2.5}
+     *     Corresponds to this 3x4 matrix:
+     *         0 1 0    0
+     *        -1 0 0   10
+     *         0 0 1 -2.5
+     *     The sensor is oriented such that:
+     *         - the device X axis corresponds to the sensor's local -Y axis
+     *         - the device Y axis corresponds to the sensor's local X axis
+     *         - the device Z axis and sensor's local Z axis are equivalent
+     *     In other words, if viewing the origin of the Android coordinate
+     *     system from the positive Z direction, the device coordinate frame is
+     *     to be rotated 90 degrees counter-clockwise about the Z axis to align
+     *     with the sensor's local coordinate frame. Equivalently, a vector in
+     *     the Android coordinate frame may be multiplied with R to rotate it
+     *     90 degrees clockwise (270 degrees counter-clockwise), yielding its
+     *     representation in the sensor's coordinate frame.
+     *     Relative to the origin of the Android coordinate system, the physical
+     *     center of the sensor is located 10mm in the positive Y direction, and
+     *     2.5mm in the negative Z direction.
      */
     AINFO_SENSOR_PLACEMENT,
 
diff --git a/sensors/2.0/ISensors.hal b/sensors/2.0/ISensors.hal
index 3a9af46..a84c56e 100644
--- a/sensors/2.0/ISensors.hal
+++ b/sensors/2.0/ISensors.hal
@@ -99,7 +99,11 @@
      * Lock FMQ. When the HAL reads the data from the Wake Lock FMQ, the HAL
      * decrements its current count of unprocessed WAKE_UP events and releases
      * its wake_lock if the current count of unprocessed WAKE_UP events is
-     * zero.
+     * zero. It is important to note that the HAL must acquire the wake lock and
+     * update its internal state regarding the number of outstanding WAKE_UP
+     * events _before_ posting the event to the Wake Lock FMQ, in order to avoid
+     * a race condition that can lead to loss of wake lock synchronization with
+     * the framework.
      *
      * The framework must use the WakeLockQueueFlagBits::DATA_WRITTEN value to
      * notify the HAL that data has been written to the Wake Lock FMQ and must
diff --git a/sensors/2.0/vts/functional/SensorsHidlEnvironmentV2_0.cpp b/sensors/2.0/vts/functional/SensorsHidlEnvironmentV2_0.cpp
index be7415b..0525bdc 100644
--- a/sensors/2.0/vts/functional/SensorsHidlEnvironmentV2_0.cpp
+++ b/sensors/2.0/vts/functional/SensorsHidlEnvironmentV2_0.cpp
@@ -109,11 +109,15 @@
 void SensorsHidlEnvironmentV2_0::HidlTearDown() {
     mStopThread = true;
 
-    // Wake up the event queue so the poll thread can exit
-    mEventQueueFlag->wake(asBaseType(EventQueueFlagBits::READ_AND_PROCESS));
-    mPollThread.join();
+    if (mEventQueueFlag != nullptr) {
+        // Wake up the event queue so the poll thread can exit
+        mEventQueueFlag->wake(asBaseType(EventQueueFlagBits::READ_AND_PROCESS));
+        if (mPollThread.joinable()) {
+            mPollThread.join();
+        }
 
-    EventFlag::deleteEventFlag(&mEventQueueFlag);
+        EventFlag::deleteEventFlag(&mEventQueueFlag);
+    }
 }
 
 void SensorsHidlEnvironmentV2_0::startPollingThread() {
@@ -135,6 +139,7 @@
     size_t eventsToRead = std::min(availableEvents, mEventBuffer.size());
     if (eventsToRead > 0) {
         if (mEventQueue->read(mEventBuffer.data(), eventsToRead)) {
+            mEventQueueFlag->wake(asBaseType(EventQueueFlagBits::EVENTS_READ));
             for (size_t i = 0; i < eventsToRead; i++) {
                 addEvent(mEventBuffer[i]);
             }
diff --git a/wifi/1.0/vts/functional/wifi_nan_iface_hidl_test.cpp b/wifi/1.0/vts/functional/wifi_nan_iface_hidl_test.cpp
index 85bcccd..64b4fb6 100644
--- a/wifi/1.0/vts/functional/wifi_nan_iface_hidl_test.cpp
+++ b/wifi/1.0/vts/functional/wifi_nan_iface_hidl_test.cpp
@@ -91,12 +91,12 @@
     };
 
     /* Test code calls this function to wait for data/event callback */
+    /* Must set callbackType = INVALID before call this function */
     inline std::cv_status wait(CallbackType waitForCallbackType) {
       std::unique_lock<std::mutex> lock(mtx_);
 
       EXPECT_NE(INVALID, waitForCallbackType); // can't ASSERT in a non-void-returning method
 
-      callbackType = INVALID;
       std::cv_status status = std::cv_status::no_timeout;
       auto now = std::chrono::system_clock::now();
       while (count_ == 0) {
@@ -469,6 +469,7 @@
  */
 TEST_F(WifiNanIfaceHidlTest, getCapabilitiesRequest) {
   uint16_t inputCmdId = 10;
+  callbackType = INVALID;
   ASSERT_EQ(WifiStatusCode::SUCCESS,
         HIDL_INVOKE(iwifiNanIface, getCapabilitiesRequest, inputCmdId).code);
   // wait for a callback
diff --git a/wifi/1.2/vts/functional/wifi_nan_iface_hidl_test.cpp b/wifi/1.2/vts/functional/wifi_nan_iface_hidl_test.cpp
index cc36fae..4dbc82b 100644
--- a/wifi/1.2/vts/functional/wifi_nan_iface_hidl_test.cpp
+++ b/wifi/1.2/vts/functional/wifi_nan_iface_hidl_test.cpp
@@ -100,13 +100,13 @@
     };
 
     /* Test code calls this function to wait for data/event callback */
+    /* Must set callbackType = INVALID before call this function */
     inline std::cv_status wait(CallbackType waitForCallbackType) {
         std::unique_lock<std::mutex> lock(mtx_);
 
         EXPECT_NE(INVALID, waitForCallbackType);  // can't ASSERT in a
                                                   // non-void-returning method
 
-        callbackType = INVALID;
         std::cv_status status = std::cv_status::no_timeout;
         auto now = std::chrono::system_clock::now();
         while (count_ == 0) {
@@ -475,6 +475,7 @@
  */
 TEST_F(WifiNanIfaceHidlTest, enableRequest_1_2InvalidArgs) {
     uint16_t inputCmdId = 10;
+    callbackType = INVALID;
     NanEnableRequest nanEnableRequest = {};
     NanConfigRequestSupplemental nanConfigRequestSupp = {};
     ASSERT_EQ(WifiStatusCode::SUCCESS,
@@ -509,6 +510,7 @@
  */
 TEST_F(WifiNanIfaceHidlTest, configRequest_1_2InvalidArgs) {
     uint16_t inputCmdId = 10;
+    callbackType = INVALID;
     NanConfigRequest nanConfigRequest = {};
     NanConfigRequestSupplemental nanConfigRequestSupp = {};
     ASSERT_EQ(WifiStatusCode::SUCCESS,
diff --git a/wifi/1.3/default/Android.mk b/wifi/1.3/default/Android.mk
index 199ea3b..0a3809c 100644
--- a/wifi/1.3/default/Android.mk
+++ b/wifi/1.3/default/Android.mk
@@ -142,22 +142,24 @@
 LOCAL_SRC_FILES := \
     tests/hidl_struct_util_unit_tests.cpp \
     tests/main.cpp \
+    tests/mock_interface_tool.cpp \
     tests/mock_wifi_feature_flags.cpp \
     tests/mock_wifi_iface_util.cpp \
     tests/mock_wifi_legacy_hal.cpp \
     tests/mock_wifi_mode_controller.cpp \
     tests/ringbuffer_unit_tests.cpp \
     tests/wifi_ap_iface_unit_tests.cpp \
+    tests/wifi_nan_iface_unit_tests.cpp \
     tests/wifi_chip_unit_tests.cpp \
     tests/wifi_iface_util_unit_tests.cpp
 LOCAL_STATIC_LIBRARIES := \
     libgmock \
     libgtest \
-    libhidlbase \
     android.hardware.wifi@1.0-service-lib
 LOCAL_SHARED_LIBRARIES := \
     libbase \
     libcutils \
+    libhidlbase \
     libhidltransport \
     liblog \
     libnl \
diff --git a/wifi/1.3/default/service.cpp b/wifi/1.3/default/service.cpp
index 73015cf..fcbc37c 100644
--- a/wifi/1.3/default/service.cpp
+++ b/wifi/1.3/default/service.cpp
@@ -48,12 +48,14 @@
 
     configureRpcThreadpool(1, true /* callerWillJoin */);
 
+    const auto iface_tool =
+        std::make_shared<android::wifi_system::InterfaceTool>();
     // Setup hwbinder service
     android::sp<android::hardware::wifi::V1_3::IWifi> service =
         new android::hardware::wifi::V1_3::implementation::Wifi(
-            std::make_shared<WifiLegacyHal>(),
+            iface_tool, std::make_shared<WifiLegacyHal>(iface_tool),
             std::make_shared<WifiModeController>(),
-            std::make_shared<WifiIfaceUtil>(),
+            std::make_shared<WifiIfaceUtil>(iface_tool),
             std::make_shared<WifiFeatureFlags>());
     if (kLazyService) {
         LazyServiceRegistrar registrar;
diff --git a/wifi/1.3/default/tests/mock_interface_tool.cpp b/wifi/1.3/default/tests/mock_interface_tool.cpp
new file mode 100644
index 0000000..b99a164
--- /dev/null
+++ b/wifi/1.3/default/tests/mock_interface_tool.cpp
@@ -0,0 +1,29 @@
+/*
+ * Copyright (C) 2019 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+#include <android-base/logging.h>
+#include <android-base/macros.h>
+#include <gmock/gmock.h>
+
+#undef NAN  // This is weird, NAN is defined in bionic/libc/include/math.h:38
+#include "mock_interface_tool.h"
+
+namespace android {
+namespace wifi_system {
+
+MockInterfaceTool::MockInterfaceTool() {}
+
+}  // namespace wifi_system
+}  // namespace android
diff --git a/wifi/1.3/default/tests/mock_interface_tool.h b/wifi/1.3/default/tests/mock_interface_tool.h
new file mode 100644
index 0000000..0f17551
--- /dev/null
+++ b/wifi/1.3/default/tests/mock_interface_tool.h
@@ -0,0 +1,44 @@
+/*
+ * Copyright (C) 2019 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef MOCK_INTERFACE_TOOL_H
+#define MOCK_INTERFACE_TOOL_H
+
+#include <gmock/gmock.h>
+#include <wifi_system/interface_tool.h>
+
+namespace android {
+namespace wifi_system {
+
+class MockInterfaceTool : public InterfaceTool {
+   public:
+    MockInterfaceTool();
+
+    MOCK_METHOD1(GetUpState, bool(const char* if_name));
+    MOCK_METHOD2(SetUpState, bool(const char* if_name, bool request_up));
+    MOCK_METHOD1(SetWifiUpState, bool(bool request_up));
+    MOCK_METHOD2(SetMacAddress,
+                 bool(const char* if_name,
+                      const std::array<uint8_t, ETH_ALEN>& address));
+    MOCK_METHOD1(GetFactoryMacAddress,
+                 std::array<uint8_t, ETH_ALEN>(const char* if_name));
+
+};  // class MockInterfaceTool
+
+}  // namespace wifi_system
+}  // namespace android
+
+#endif  // MOCK_INTERFACE_TOOL_H
diff --git a/wifi/1.3/default/tests/mock_wifi_iface_util.cpp b/wifi/1.3/default/tests/mock_wifi_iface_util.cpp
index 706cb6a..3d877c0 100644
--- a/wifi/1.3/default/tests/mock_wifi_iface_util.cpp
+++ b/wifi/1.3/default/tests/mock_wifi_iface_util.cpp
@@ -28,7 +28,9 @@
 namespace implementation {
 namespace iface_util {
 
-MockWifiIfaceUtil::MockWifiIfaceUtil() : WifiIfaceUtil() {}
+MockWifiIfaceUtil::MockWifiIfaceUtil(
+    const std::weak_ptr<wifi_system::InterfaceTool> iface_tool)
+    : WifiIfaceUtil(iface_tool) {}
 }  // namespace iface_util
 }  // namespace implementation
 }  // namespace V1_3
diff --git a/wifi/1.3/default/tests/mock_wifi_iface_util.h b/wifi/1.3/default/tests/mock_wifi_iface_util.h
index 87ab5db..8ec93eb 100644
--- a/wifi/1.3/default/tests/mock_wifi_iface_util.h
+++ b/wifi/1.3/default/tests/mock_wifi_iface_util.h
@@ -30,12 +30,16 @@
 
 class MockWifiIfaceUtil : public WifiIfaceUtil {
    public:
-    MockWifiIfaceUtil();
+    MockWifiIfaceUtil(
+        const std::weak_ptr<wifi_system::InterfaceTool> iface_tool);
     MOCK_METHOD1(getFactoryMacAddress,
                  std::array<uint8_t, 6>(const std::string&));
     MOCK_METHOD2(setMacAddress,
                  bool(const std::string&, const std::array<uint8_t, 6>&));
     MOCK_METHOD0(getOrCreateRandomMacAddress, std::array<uint8_t, 6>());
+    MOCK_METHOD2(registerIfaceEventHandlers,
+                 void(const std::string&, IfaceEventHandlers));
+    MOCK_METHOD1(unregisterIfaceEventHandlers, void(const std::string&));
 };
 }  // namespace iface_util
 }  // namespace implementation
diff --git a/wifi/1.3/default/tests/mock_wifi_legacy_hal.cpp b/wifi/1.3/default/tests/mock_wifi_legacy_hal.cpp
index 4cd279d..0a202c4 100644
--- a/wifi/1.3/default/tests/mock_wifi_legacy_hal.cpp
+++ b/wifi/1.3/default/tests/mock_wifi_legacy_hal.cpp
@@ -28,7 +28,9 @@
 namespace implementation {
 namespace legacy_hal {
 
-MockWifiLegacyHal::MockWifiLegacyHal() : WifiLegacyHal() {}
+MockWifiLegacyHal::MockWifiLegacyHal(
+    const std::weak_ptr<wifi_system::InterfaceTool> iface_tool)
+    : WifiLegacyHal(iface_tool) {}
 }  // namespace legacy_hal
 }  // namespace implementation
 }  // namespace V1_3
diff --git a/wifi/1.3/default/tests/mock_wifi_legacy_hal.h b/wifi/1.3/default/tests/mock_wifi_legacy_hal.h
index 53fa8d6..81cb1de 100644
--- a/wifi/1.3/default/tests/mock_wifi_legacy_hal.h
+++ b/wifi/1.3/default/tests/mock_wifi_legacy_hal.h
@@ -30,7 +30,8 @@
 
 class MockWifiLegacyHal : public WifiLegacyHal {
    public:
-    MockWifiLegacyHal();
+    MockWifiLegacyHal(
+        const std::weak_ptr<wifi_system::InterfaceTool> iface_tool);
     MOCK_METHOD0(initialize, wifi_error());
     MOCK_METHOD0(start, wifi_error());
     MOCK_METHOD2(stop, wifi_error(std::unique_lock<std::recursive_mutex>*,
diff --git a/wifi/1.3/default/tests/wifi_ap_iface_unit_tests.cpp b/wifi/1.3/default/tests/wifi_ap_iface_unit_tests.cpp
index 28e028b..680f534 100644
--- a/wifi/1.3/default/tests/wifi_ap_iface_unit_tests.cpp
+++ b/wifi/1.3/default/tests/wifi_ap_iface_unit_tests.cpp
@@ -22,6 +22,7 @@
 #undef NAN  // This is weird, NAN is defined in bionic/libc/include/math.h:38
 #include "wifi_ap_iface.h"
 
+#include "mock_interface_tool.h"
 #include "mock_wifi_feature_flags.h"
 #include "mock_wifi_iface_util.h"
 #include "mock_wifi_legacy_hal.h"
@@ -42,10 +43,12 @@
 
 class WifiApIfaceTest : public Test {
    protected:
+    std::shared_ptr<NiceMock<wifi_system::MockInterfaceTool>> iface_tool_{
+        new NiceMock<wifi_system::MockInterfaceTool>};
     std::shared_ptr<NiceMock<legacy_hal::MockWifiLegacyHal>> legacy_hal_{
-        new NiceMock<legacy_hal::MockWifiLegacyHal>};
+        new NiceMock<legacy_hal::MockWifiLegacyHal>(iface_tool_)};
     std::shared_ptr<NiceMock<iface_util::MockWifiIfaceUtil>> iface_util_{
-        new NiceMock<iface_util::MockWifiIfaceUtil>};
+        new NiceMock<iface_util::MockWifiIfaceUtil>(iface_tool_)};
     std::shared_ptr<NiceMock<feature_flags::MockWifiFeatureFlags>>
         feature_flags_{new NiceMock<feature_flags::MockWifiFeatureFlags>};
 };
diff --git a/wifi/1.3/default/tests/wifi_chip_unit_tests.cpp b/wifi/1.3/default/tests/wifi_chip_unit_tests.cpp
index 7928328..d8ce278 100644
--- a/wifi/1.3/default/tests/wifi_chip_unit_tests.cpp
+++ b/wifi/1.3/default/tests/wifi_chip_unit_tests.cpp
@@ -22,6 +22,7 @@
 #undef NAN  // This is weird, NAN is defined in bionic/libc/include/math.h:38
 #include "wifi_chip.h"
 
+#include "mock_interface_tool.h"
 #include "mock_wifi_feature_flags.h"
 #include "mock_wifi_iface_util.h"
 #include "mock_wifi_legacy_hal.h"
@@ -263,12 +264,14 @@
 
     sp<WifiChip> chip_;
     ChipId chip_id_ = kFakeChipId;
+    std::shared_ptr<NiceMock<wifi_system::MockInterfaceTool>> iface_tool_{
+        new NiceMock<wifi_system::MockInterfaceTool>};
     std::shared_ptr<NiceMock<legacy_hal::MockWifiLegacyHal>> legacy_hal_{
-        new NiceMock<legacy_hal::MockWifiLegacyHal>};
+        new NiceMock<legacy_hal::MockWifiLegacyHal>(iface_tool_)};
     std::shared_ptr<NiceMock<mode_controller::MockWifiModeController>>
         mode_controller_{new NiceMock<mode_controller::MockWifiModeController>};
     std::shared_ptr<NiceMock<iface_util::MockWifiIfaceUtil>> iface_util_{
-        new NiceMock<iface_util::MockWifiIfaceUtil>};
+        new NiceMock<iface_util::MockWifiIfaceUtil>(iface_tool_)};
     std::shared_ptr<NiceMock<feature_flags::MockWifiFeatureFlags>>
         feature_flags_{new NiceMock<feature_flags::MockWifiFeatureFlags>};
 
@@ -700,6 +703,72 @@
         });
 }
 
+TEST_F(WifiChipV2_AwareIfaceCombinationTest,
+       InvalidateAndRemoveNanOnStaRemove) {
+    findModeAndConfigureForIfaceType(IfaceType::STA);
+    ASSERT_EQ(createIface(IfaceType::STA), "wlan0");
+
+    // Create NAN iface
+    ASSERT_EQ(createIface(IfaceType::NAN), "wlan0");
+
+    // We should have 1 nan iface.
+    chip_->getNanIfaceNames(
+        [](const WifiStatus& status, const hidl_vec<hidl_string>& iface_names) {
+            ASSERT_EQ(WifiStatusCode::SUCCESS, status.code);
+            ASSERT_EQ(iface_names.size(), 1u);
+            ASSERT_EQ(iface_names[0], "wlan0");
+        });
+    // Retrieve the exact iface object.
+    sp<IWifiNanIface> nan_iface;
+    chip_->getNanIface("wlan0", [&nan_iface](const WifiStatus& status,
+                                             const sp<IWifiNanIface>& iface) {
+        ASSERT_EQ(WifiStatusCode::SUCCESS, status.code);
+        ASSERT_NE(iface.get(), nullptr);
+        nan_iface = iface;
+    });
+
+    // Remove the STA iface.
+    removeIface(IfaceType::STA, "wlan0");
+    // We should have 0 nan iface now.
+    chip_->getNanIfaceNames(
+        [](const WifiStatus& status, const hidl_vec<hidl_string>& iface_names) {
+            ASSERT_EQ(WifiStatusCode::SUCCESS, status.code);
+            ASSERT_EQ(iface_names.size(), 0u);
+        });
+    // Any operation on the nan iface object should return error now.
+    nan_iface->getName(
+        [](const WifiStatus& status, const std::string& /* iface_name */) {
+            ASSERT_EQ(WifiStatusCode::ERROR_WIFI_IFACE_INVALID, status.code);
+        });
+}
+
+TEST_F(WifiChipV2_AwareIfaceCombinationTest,
+       InvalidateAndRemoveRttControllerOnStaRemove) {
+    findModeAndConfigureForIfaceType(IfaceType::STA);
+    ASSERT_EQ(createIface(IfaceType::STA), "wlan0");
+
+    // Create RTT controller
+    sp<IWifiRttController> rtt_controller;
+    chip_->createRttController(
+        NULL, [&rtt_controller](const WifiStatus& status,
+                                const sp<IWifiRttController>& rtt) {
+            if (WifiStatusCode::SUCCESS == status.code) {
+                ASSERT_NE(rtt.get(), nullptr);
+                rtt_controller = rtt;
+            }
+        });
+
+    // Remove the STA iface.
+    removeIface(IfaceType::STA, "wlan0");
+
+    // Any operation on the rtt controller object should return error now.
+    rtt_controller->getBoundIface(
+        [](const WifiStatus& status, const sp<IWifiIface>& /* iface */) {
+            ASSERT_EQ(WifiStatusCode::ERROR_WIFI_RTT_CONTROLLER_INVALID,
+                      status.code);
+        });
+}
+
 ////////// V1 Iface Combinations when AP creation is disabled //////////
 class WifiChipV1_AwareDisabledApIfaceCombinationTest : public WifiChipTest {
    public:
@@ -732,6 +801,7 @@
     ASSERT_TRUE(createIface(IfaceType::AP).empty());
 }
 
+////////// Hypothetical Iface Combination with multiple ifaces //////////
 class WifiChip_MultiIfaceTest : public WifiChipTest {
    public:
     void SetUp() override {
diff --git a/wifi/1.3/default/tests/wifi_iface_util_unit_tests.cpp b/wifi/1.3/default/tests/wifi_iface_util_unit_tests.cpp
index e5758fa..28d23ff 100644
--- a/wifi/1.3/default/tests/wifi_iface_util_unit_tests.cpp
+++ b/wifi/1.3/default/tests/wifi_iface_util_unit_tests.cpp
@@ -21,10 +21,15 @@
 #undef NAN
 #include "wifi_iface_util.h"
 
+#include "mock_interface_tool.h"
+
+using testing::NiceMock;
 using testing::Test;
 
 namespace {
 constexpr uint8_t kValidUnicastLocallyAssignedMacAddressMask = 0x02;
+constexpr uint8_t kMacAddress[] = {0x02, 0x12, 0x45, 0x56, 0xab, 0xcc};
+constexpr char kIfaceName[] = "test-wlan0";
 
 bool isValidUnicastLocallyAssignedMacAddress(
     const std::array<uint8_t, 6>& mac_address) {
@@ -38,19 +43,52 @@
 namespace wifi {
 namespace V1_3 {
 namespace implementation {
+namespace iface_util {
 class WifiIfaceUtilTest : public Test {
    protected:
-    iface_util::WifiIfaceUtil iface_util_;
+    std::shared_ptr<NiceMock<wifi_system::MockInterfaceTool>> iface_tool_{
+        new NiceMock<wifi_system::MockInterfaceTool>};
+    WifiIfaceUtil* iface_util_ = new WifiIfaceUtil(iface_tool_);
 };
 
 TEST_F(WifiIfaceUtilTest, GetOrCreateRandomMacAddress) {
-    auto mac_address = iface_util_.getOrCreateRandomMacAddress();
+    auto mac_address = iface_util_->getOrCreateRandomMacAddress();
     ASSERT_TRUE(isValidUnicastLocallyAssignedMacAddress(mac_address));
 
     // All further calls should return the same MAC address.
-    ASSERT_EQ(mac_address, iface_util_.getOrCreateRandomMacAddress());
-    ASSERT_EQ(mac_address, iface_util_.getOrCreateRandomMacAddress());
+    ASSERT_EQ(mac_address, iface_util_->getOrCreateRandomMacAddress());
+    ASSERT_EQ(mac_address, iface_util_->getOrCreateRandomMacAddress());
 }
+
+TEST_F(WifiIfaceUtilTest, IfaceEventHandlers_SetMacAddress) {
+    std::array<uint8_t, 6> mac_address = {};
+    std::copy(std::begin(kMacAddress), std::end(kMacAddress),
+              std::begin(mac_address));
+    EXPECT_CALL(*iface_tool_, SetMacAddress(testing::_, testing::_))
+        .WillRepeatedly(testing::Return(true));
+    EXPECT_CALL(*iface_tool_, SetUpState(testing::_, testing::_))
+        .WillRepeatedly(testing::Return(true));
+
+    // Register for iface state toggle events.
+    bool callback_invoked = false;
+    iface_util::IfaceEventHandlers event_handlers = {};
+    event_handlers.on_state_toggle_off_on =
+        [&callback_invoked](const std::string& /* iface_name */) {
+            callback_invoked = true;
+        };
+    iface_util_->registerIfaceEventHandlers(kIfaceName, event_handlers);
+    // Invoke setMacAddress and ensure that the cb is invoked.
+    ASSERT_TRUE(iface_util_->setMacAddress(kIfaceName, mac_address));
+    ASSERT_TRUE(callback_invoked);
+
+    // Unregister for iface state toggle events.
+    callback_invoked = false;
+    iface_util_->unregisterIfaceEventHandlers(kIfaceName);
+    // Invoke setMacAddress and ensure that the cb is not invoked.
+    ASSERT_TRUE(iface_util_->setMacAddress(kIfaceName, mac_address));
+    ASSERT_FALSE(callback_invoked);
+}
+}  // namespace iface_util
 }  // namespace implementation
 }  // namespace V1_3
 }  // namespace wifi
diff --git a/wifi/1.3/default/tests/wifi_nan_iface_unit_tests.cpp b/wifi/1.3/default/tests/wifi_nan_iface_unit_tests.cpp
new file mode 100644
index 0000000..eb6c610
--- /dev/null
+++ b/wifi/1.3/default/tests/wifi_nan_iface_unit_tests.cpp
@@ -0,0 +1,148 @@
+/*
+ * Copyright (C) 2019, The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include <android-base/logging.h>
+#include <android-base/macros.h>
+#include <cutils/properties.h>
+#include <gmock/gmock.h>
+
+#undef NAN  // This is weird, NAN is defined in bionic/libc/include/math.h:38
+#include "wifi_nan_iface.h"
+
+#include "mock_interface_tool.h"
+#include "mock_wifi_feature_flags.h"
+#include "mock_wifi_iface_util.h"
+#include "mock_wifi_legacy_hal.h"
+
+using testing::NiceMock;
+using testing::Return;
+using testing::Test;
+
+namespace {
+constexpr char kIfaceName[] = "mockWlan0";
+}  // namespace
+
+namespace android {
+namespace hardware {
+namespace wifi {
+namespace V1_3 {
+namespace implementation {
+
+bool CaptureIfaceEventHandlers(
+    const std::string& /* iface_name*/,
+    iface_util::IfaceEventHandlers in_iface_event_handlers,
+    iface_util::IfaceEventHandlers* out_iface_event_handlers) {
+    *out_iface_event_handlers = in_iface_event_handlers;
+    return true;
+}
+
+class MockNanIfaceEventCallback : public IWifiNanIfaceEventCallback {
+   public:
+    MockNanIfaceEventCallback() = default;
+
+    MOCK_METHOD3(notifyCapabilitiesResponse,
+                 Return<void>(uint16_t, const WifiNanStatus&,
+                              const NanCapabilities&));
+    MOCK_METHOD2(notifyEnableResponse,
+                 Return<void>(uint16_t, const WifiNanStatus&));
+    MOCK_METHOD2(notifyConfigResponse,
+                 Return<void>(uint16_t, const WifiNanStatus&));
+    MOCK_METHOD2(notifyDisableResponse,
+                 Return<void>(uint16_t, const WifiNanStatus&));
+    MOCK_METHOD3(notifyStartPublishResponse,
+                 Return<void>(uint16_t, const WifiNanStatus&, uint8_t));
+    MOCK_METHOD2(notifyStopPublishResponse,
+                 Return<void>(uint16_t, const WifiNanStatus&));
+    MOCK_METHOD3(notifyStartSubscribeResponse,
+                 Return<void>(uint16_t, const WifiNanStatus&, uint8_t));
+    MOCK_METHOD2(notifyStopSubscribeResponse,
+                 Return<void>(uint16_t, const WifiNanStatus&));
+    MOCK_METHOD2(notifyTransmitFollowupResponse,
+                 Return<void>(uint16_t, const WifiNanStatus&));
+    MOCK_METHOD2(notifyCreateDataInterfaceResponse,
+                 Return<void>(uint16_t, const WifiNanStatus&));
+    MOCK_METHOD2(notifyDeleteDataInterfaceResponse,
+                 Return<void>(uint16_t, const WifiNanStatus&));
+    MOCK_METHOD3(notifyInitiateDataPathResponse,
+                 Return<void>(uint16_t, const WifiNanStatus&, uint32_t));
+    MOCK_METHOD2(notifyRespondToDataPathIndicationResponse,
+                 Return<void>(uint16_t, const WifiNanStatus&));
+    MOCK_METHOD2(notifyTerminateDataPathResponse,
+                 Return<void>(uint16_t, const WifiNanStatus&));
+    MOCK_METHOD1(eventClusterEvent, Return<void>(const NanClusterEventInd&));
+    MOCK_METHOD1(eventDisabled, Return<void>(const WifiNanStatus&));
+    MOCK_METHOD2(eventPublishTerminated,
+                 Return<void>(uint8_t, const WifiNanStatus&));
+    MOCK_METHOD2(eventSubscribeTerminated,
+                 Return<void>(uint8_t, const WifiNanStatus&));
+    MOCK_METHOD1(eventMatch, Return<void>(const NanMatchInd&));
+    MOCK_METHOD2(eventMatchExpired, Return<void>(uint8_t, uint32_t));
+    MOCK_METHOD1(eventFollowupReceived,
+                 Return<void>(const NanFollowupReceivedInd&));
+    MOCK_METHOD2(eventTransmitFollowup,
+                 Return<void>(uint16_t, const WifiNanStatus&));
+    MOCK_METHOD1(eventDataPathRequest,
+                 Return<void>(const NanDataPathRequestInd&));
+    MOCK_METHOD1(eventDataPathConfirm,
+                 Return<void>(const NanDataPathConfirmInd&));
+    MOCK_METHOD1(eventDataPathTerminated, Return<void>(uint32_t));
+};
+
+class WifiNanIfaceTest : public Test {
+   protected:
+    std::shared_ptr<NiceMock<wifi_system::MockInterfaceTool>> iface_tool_{
+        new NiceMock<wifi_system::MockInterfaceTool>};
+    std::shared_ptr<NiceMock<legacy_hal::MockWifiLegacyHal>> legacy_hal_{
+        new NiceMock<legacy_hal::MockWifiLegacyHal>(iface_tool_)};
+    std::shared_ptr<NiceMock<iface_util::MockWifiIfaceUtil>> iface_util_{
+        new NiceMock<iface_util::MockWifiIfaceUtil>(iface_tool_)};
+};
+
+TEST_F(WifiNanIfaceTest, IfacEventHandlers_OnStateToggleOffOn) {
+    iface_util::IfaceEventHandlers captured_iface_event_handlers = {};
+    EXPECT_CALL(*legacy_hal_,
+                nanRegisterCallbackHandlers(testing::_, testing::_))
+        .WillOnce(testing::Return(legacy_hal::WIFI_SUCCESS));
+    EXPECT_CALL(*iface_util_,
+                registerIfaceEventHandlers(testing::_, testing::_))
+        .WillOnce(testing::Invoke(
+            bind(CaptureIfaceEventHandlers, std::placeholders::_1,
+                 std::placeholders::_2, &captured_iface_event_handlers)));
+    sp<WifiNanIface> nan_iface =
+        new WifiNanIface(kIfaceName, legacy_hal_, iface_util_);
+
+    // Register a mock nan event callback.
+    sp<NiceMock<MockNanIfaceEventCallback>> mock_event_callback{
+        new NiceMock<MockNanIfaceEventCallback>};
+    nan_iface->registerEventCallback(
+        mock_event_callback, [](const WifiStatus& status) {
+            ASSERT_EQ(WifiStatusCode::SUCCESS, status.code);
+        });
+    // Ensure that the eventDisabled() function in mock callback will be
+    // invoked.
+    WifiNanStatus expected_nan_status = {
+        NanStatusType::UNSUPPORTED_CONCURRENCY_NAN_DISABLED, ""};
+    EXPECT_CALL(*mock_event_callback, eventDisabled(expected_nan_status))
+        .Times(1);
+
+    // Trigger the iface state toggle callback.
+    captured_iface_event_handlers.on_state_toggle_off_on(kIfaceName);
+}
+}  // namespace implementation
+}  // namespace V1_3
+}  // namespace wifi
+}  // namespace hardware
+}  // namespace android
diff --git a/wifi/1.3/default/wifi.cpp b/wifi/1.3/default/wifi.cpp
index 1f64085..2f21819 100644
--- a/wifi/1.3/default/wifi.cpp
+++ b/wifi/1.3/default/wifi.cpp
@@ -34,11 +34,13 @@
 using hidl_return_util::validateAndCallWithLock;
 
 Wifi::Wifi(
+    const std::shared_ptr<wifi_system::InterfaceTool> iface_tool,
     const std::shared_ptr<legacy_hal::WifiLegacyHal> legacy_hal,
     const std::shared_ptr<mode_controller::WifiModeController> mode_controller,
     const std::shared_ptr<iface_util::WifiIfaceUtil> iface_util,
     const std::shared_ptr<feature_flags::WifiFeatureFlags> feature_flags)
-    : legacy_hal_(legacy_hal),
+    : iface_tool_(iface_tool),
+      legacy_hal_(legacy_hal),
       mode_controller_(mode_controller),
       iface_util_(iface_util),
       feature_flags_(feature_flags),
diff --git a/wifi/1.3/default/wifi.h b/wifi/1.3/default/wifi.h
index c4ab773..1c2a154 100644
--- a/wifi/1.3/default/wifi.h
+++ b/wifi/1.3/default/wifi.h
@@ -40,7 +40,8 @@
  */
 class Wifi : public V1_3::IWifi {
    public:
-    Wifi(const std::shared_ptr<legacy_hal::WifiLegacyHal> legacy_hal,
+    Wifi(const std::shared_ptr<wifi_system::InterfaceTool> iface_tool,
+         const std::shared_ptr<legacy_hal::WifiLegacyHal> legacy_hal,
          const std::shared_ptr<mode_controller::WifiModeController>
              mode_controller,
          const std::shared_ptr<iface_util::WifiIfaceUtil> iface_util,
@@ -77,6 +78,7 @@
 
     // Instance is created in this root level |IWifi| HIDL interface object
     // and shared with all the child HIDL interface objects.
+    std::shared_ptr<wifi_system::InterfaceTool> iface_tool_;
     std::shared_ptr<legacy_hal::WifiLegacyHal> legacy_hal_;
     std::shared_ptr<mode_controller::WifiModeController> mode_controller_;
     std::shared_ptr<iface_util::WifiIfaceUtil> iface_util_;
diff --git a/wifi/1.3/default/wifi_chip.cpp b/wifi/1.3/default/wifi_chip.cpp
index b768959..e9991dc 100644
--- a/wifi/1.3/default/wifi_chip.cpp
+++ b/wifi/1.3/default/wifi_chip.cpp
@@ -634,6 +634,27 @@
     rtt_controllers_.clear();
 }
 
+void WifiChip::invalidateAndRemoveDependencies(
+    const std::string& removed_iface_name) {
+    for (const auto& nan_iface : nan_ifaces_) {
+        if (nan_iface->getName() == removed_iface_name) {
+            invalidateAndClear(nan_ifaces_, nan_iface);
+            for (const auto& callback : event_cb_handler_.getCallbacks()) {
+                if (!callback
+                         ->onIfaceRemoved(IfaceType::NAN, removed_iface_name)
+                         .isOk()) {
+                    LOG(ERROR) << "Failed to invoke onIfaceRemoved callback";
+                }
+            }
+        }
+    }
+    for (const auto& rtt : rtt_controllers_) {
+        if (rtt->getIfaceName() == removed_iface_name) {
+            invalidateAndClear(rtt_controllers_, rtt);
+        }
+    }
+}
+
 std::pair<WifiStatus, ChipId> WifiChip::getIdInternal() {
     return {createWifiStatus(WifiStatusCode::SUCCESS), chip_id_};
 }
@@ -819,6 +840,11 @@
     if (!iface.get()) {
         return createWifiStatus(WifiStatusCode::ERROR_INVALID_ARGS);
     }
+    // Invalidate & remove any dependent objects first.
+    // Note: This is probably not required because we never create
+    // nan/rtt objects over AP iface. But, there is no harm to do it
+    // here and not make that assumption all over the place.
+    invalidateAndRemoveDependencies(ifname);
     invalidateAndClear(ap_ifaces_, iface);
     for (const auto& callback : event_cb_handler_.getCallbacks()) {
         if (!callback->onIfaceRemoved(IfaceType::AP, ifname).isOk()) {
@@ -835,7 +861,7 @@
     }
     // These are still assumed to be based on wlan0.
     std::string ifname = getFirstActiveWlanIfaceName();
-    sp<WifiNanIface> iface = new WifiNanIface(ifname, legacy_hal_);
+    sp<WifiNanIface> iface = new WifiNanIface(ifname, legacy_hal_, iface_util_);
     nan_ifaces_.push_back(iface);
     for (const auto& callback : event_cb_handler_.getCallbacks()) {
         if (!callback->onIfaceAdded(IfaceType::NAN, ifname).isOk()) {
@@ -960,6 +986,8 @@
     if (!iface.get()) {
         return createWifiStatus(WifiStatusCode::ERROR_INVALID_ARGS);
     }
+    // Invalidate & remove any dependent objects first.
+    invalidateAndRemoveDependencies(ifname);
     invalidateAndClear(sta_ifaces_, iface);
     for (const auto& callback : event_cb_handler_.getCallbacks()) {
         if (!callback->onIfaceRemoved(IfaceType::STA, ifname).isOk()) {
@@ -1435,6 +1463,13 @@
     return canCurrentModeSupportIfaceCombo(req_iface_combo);
 }
 
+bool WifiChip::isDualApAllowedInCurrentMode() {
+    // Check if we can support atleast 1 STA & 1 AP concurrently.
+    std::map<IfaceType, size_t> req_iface_combo;
+    req_iface_combo[IfaceType::AP] = 2;
+    return canCurrentModeSupportIfaceCombo(req_iface_combo);
+}
+
 std::string WifiChip::getFirstActiveWlanIfaceName() {
     if (sta_ifaces_.size() > 0) return sta_ifaces_[0]->getName();
     if (ap_ifaces_.size() > 0) return ap_ifaces_[0]->getName();
@@ -1460,10 +1495,12 @@
 }
 
 // AP iface names start with idx 1 for modes supporting
-// concurrent STA, else start with idx 0.
+// concurrent STA and not dual AP, else start with idx 0.
 std::string WifiChip::allocateApIfaceName() {
-    return allocateApOrStaIfaceName(
-        isStaApConcurrencyAllowedInCurrentMode() ? 1 : 0);
+    return allocateApOrStaIfaceName((isStaApConcurrencyAllowedInCurrentMode() &&
+                                     !isDualApAllowedInCurrentMode())
+                                        ? 1
+                                        : 0);
 }
 
 // STA iface names start with idx 0.
diff --git a/wifi/1.3/default/wifi_chip.h b/wifi/1.3/default/wifi_chip.h
index 3d12f4c..153ca6a 100644
--- a/wifi/1.3/default/wifi_chip.h
+++ b/wifi/1.3/default/wifi_chip.h
@@ -155,6 +155,9 @@
 
    private:
     void invalidateAndRemoveAllIfaces();
+    // When a STA iface is removed any dependent NAN-ifaces/RTT-controllers are
+    // invalidated & removed.
+    void invalidateAndRemoveDependencies(const std::string& removed_iface_name);
 
     // Corresponding worker functions for the HIDL methods.
     std::pair<WifiStatus, ChipId> getIdInternal();
@@ -237,6 +240,7 @@
     bool canCurrentModeSupportIfaceOfType(IfaceType requested_type);
     bool isValidModeId(ChipModeId mode_id);
     bool isStaApConcurrencyAllowedInCurrentMode();
+    bool isDualApAllowedInCurrentMode();
     std::string getFirstActiveWlanIfaceName();
     std::string allocateApOrStaIfaceName(uint32_t start_idx);
     std::string allocateApIfaceName();
diff --git a/wifi/1.3/default/wifi_iface_util.cpp b/wifi/1.3/default/wifi_iface_util.cpp
index 5d61271..34bc02d 100644
--- a/wifi/1.3/default/wifi_iface_util.cpp
+++ b/wifi/1.3/default/wifi_iface_util.cpp
@@ -39,27 +39,39 @@
 namespace implementation {
 namespace iface_util {
 
-WifiIfaceUtil::WifiIfaceUtil() : random_mac_address_(nullptr) {}
+WifiIfaceUtil::WifiIfaceUtil(
+    const std::weak_ptr<wifi_system::InterfaceTool> iface_tool)
+    : iface_tool_(iface_tool),
+      random_mac_address_(nullptr),
+      event_handlers_map_() {}
 
 std::array<uint8_t, 6> WifiIfaceUtil::getFactoryMacAddress(
     const std::string& iface_name) {
-    return iface_tool_.GetFactoryMacAddress(iface_name.c_str());
+    return iface_tool_.lock()->GetFactoryMacAddress(iface_name.c_str());
 }
 
 bool WifiIfaceUtil::setMacAddress(const std::string& iface_name,
                                   const std::array<uint8_t, 6>& mac) {
-    if (!iface_tool_.SetUpState(iface_name.c_str(), false)) {
+    if (!iface_tool_.lock()->SetUpState(iface_name.c_str(), false)) {
         LOG(ERROR) << "SetUpState(false) failed.";
         return false;
     }
-    if (!iface_tool_.SetMacAddress(iface_name.c_str(), mac)) {
+    if (!iface_tool_.lock()->SetMacAddress(iface_name.c_str(), mac)) {
         LOG(ERROR) << "SetMacAddress failed.";
         return false;
     }
-    if (!iface_tool_.SetUpState(iface_name.c_str(), true)) {
+    if (!iface_tool_.lock()->SetUpState(iface_name.c_str(), true)) {
         LOG(ERROR) << "SetUpState(true) failed.";
         return false;
     }
+    IfaceEventHandlers event_handlers = {};
+    const auto it = event_handlers_map_.find(iface_name);
+    if (it != event_handlers_map_.end()) {
+        event_handlers = it->second;
+    }
+    if (event_handlers.on_state_toggle_off_on != nullptr) {
+        event_handlers.on_state_toggle_off_on(iface_name);
+    }
     LOG(DEBUG) << "Successfully SetMacAddress.";
     return true;
 }
@@ -73,6 +85,16 @@
     return *random_mac_address_.get();
 }
 
+void WifiIfaceUtil::registerIfaceEventHandlers(const std::string& iface_name,
+                                               IfaceEventHandlers handlers) {
+    event_handlers_map_[iface_name] = handlers;
+}
+
+void WifiIfaceUtil::unregisterIfaceEventHandlers(
+    const std::string& iface_name) {
+    event_handlers_map_.erase(iface_name);
+}
+
 std::array<uint8_t, 6> WifiIfaceUtil::createRandomMacAddress() {
     std::array<uint8_t, 6> address = {};
     std::random_device rd;
diff --git a/wifi/1.3/default/wifi_iface_util.h b/wifi/1.3/default/wifi_iface_util.h
index b238234..98073e0 100644
--- a/wifi/1.3/default/wifi_iface_util.h
+++ b/wifi/1.3/default/wifi_iface_util.h
@@ -28,12 +28,19 @@
 namespace implementation {
 namespace iface_util {
 
+// Iface event handlers.
+struct IfaceEventHandlers {
+    // Callback to be invoked when the iface is set down & up for MAC address
+    // change.
+    std::function<void(const std::string& iface_name)> on_state_toggle_off_on;
+};
+
 /**
  * Util class for common iface operations.
  */
 class WifiIfaceUtil {
    public:
-    WifiIfaceUtil();
+    WifiIfaceUtil(const std::weak_ptr<wifi_system::InterfaceTool> iface_tool);
     virtual ~WifiIfaceUtil() = default;
 
     virtual std::array<uint8_t, 6> getFactoryMacAddress(
@@ -45,11 +52,17 @@
     // daemon. (So, changes on every reboot)
     virtual std::array<uint8_t, 6> getOrCreateRandomMacAddress();
 
+    // Register for any iface event callbacks for the provided interface.
+    virtual void registerIfaceEventHandlers(const std::string& iface_name,
+                                            IfaceEventHandlers handlers);
+    virtual void unregisterIfaceEventHandlers(const std::string& iface_name);
+
    private:
     std::array<uint8_t, 6> createRandomMacAddress();
 
-    wifi_system::InterfaceTool iface_tool_;
+    std::weak_ptr<wifi_system::InterfaceTool> iface_tool_;
     std::unique_ptr<std::array<uint8_t, 6>> random_mac_address_;
+    std::map<std::string, IfaceEventHandlers> event_handlers_map_;
 };
 
 }  // namespace iface_util
diff --git a/wifi/1.3/default/wifi_legacy_hal.cpp b/wifi/1.3/default/wifi_legacy_hal.cpp
index 7f9b635..485bd16 100644
--- a/wifi/1.3/default/wifi_legacy_hal.cpp
+++ b/wifi/1.3/default/wifi_legacy_hal.cpp
@@ -333,10 +333,12 @@
 }
 // End of the free-standing "C" style callbacks.
 
-WifiLegacyHal::WifiLegacyHal()
+WifiLegacyHal::WifiLegacyHal(
+    const std::weak_ptr<wifi_system::InterfaceTool> iface_tool)
     : global_handle_(nullptr),
       awaiting_event_loop_termination_(false),
-      is_started_(false) {}
+      is_started_(false),
+      iface_tool_(iface_tool) {}
 
 wifi_error WifiLegacyHal::initialize() {
     LOG(DEBUG) << "Initialize legacy HAL";
@@ -371,7 +373,7 @@
     property_set(kDriverPropName, "ok");
 
     LOG(DEBUG) << "Starting legacy HAL";
-    if (!iface_tool_.SetWifiUpState(true)) {
+    if (!iface_tool_.lock()->SetWifiUpState(true)) {
         LOG(ERROR) << "Failed to set WiFi interface up";
         return WIFI_ERROR_UNKNOWN;
     }
@@ -407,7 +409,7 @@
         // Invalidate all the internal pointers now that the HAL is
         // stopped.
         invalidate();
-        iface_tool_.SetWifiUpState(false);
+        iface_tool_.lock()->SetWifiUpState(false);
         on_stop_complete_user_callback();
         is_started_ = false;
     };
diff --git a/wifi/1.3/default/wifi_legacy_hal.h b/wifi/1.3/default/wifi_legacy_hal.h
index a3ed460..9cfa172 100644
--- a/wifi/1.3/default/wifi_legacy_hal.h
+++ b/wifi/1.3/default/wifi_legacy_hal.h
@@ -170,7 +170,7 @@
  */
 class WifiLegacyHal {
    public:
-    WifiLegacyHal();
+    WifiLegacyHal(const std::weak_ptr<wifi_system::InterfaceTool> iface_tool);
     virtual ~WifiLegacyHal() = default;
 
     // Initialize the legacy HAL function table.
@@ -391,7 +391,7 @@
     std::condition_variable_any stop_wait_cv_;
     // Flag to indicate if the legacy HAL has been started.
     bool is_started_;
-    wifi_system::InterfaceTool iface_tool_;
+    std::weak_ptr<wifi_system::InterfaceTool> iface_tool_;
 };
 
 }  // namespace legacy_hal
diff --git a/wifi/1.3/default/wifi_nan_iface.cpp b/wifi/1.3/default/wifi_nan_iface.cpp
index 4325f44..ff9f422 100644
--- a/wifi/1.3/default/wifi_nan_iface.cpp
+++ b/wifi/1.3/default/wifi_nan_iface.cpp
@@ -30,8 +30,12 @@
 
 WifiNanIface::WifiNanIface(
     const std::string& ifname,
-    const std::weak_ptr<legacy_hal::WifiLegacyHal> legacy_hal)
-    : ifname_(ifname), legacy_hal_(legacy_hal), is_valid_(true) {
+    const std::weak_ptr<legacy_hal::WifiLegacyHal> legacy_hal,
+    const std::weak_ptr<iface_util::WifiIfaceUtil> iface_util)
+    : ifname_(ifname),
+      legacy_hal_(legacy_hal),
+      iface_util_(iface_util),
+      is_valid_(true) {
     // Register all the callbacks here. these should be valid for the lifetime
     // of the object. Whenever the mode changes legacy HAL will remove
     // all of these callbacks.
@@ -498,6 +502,26 @@
         LOG(ERROR) << "Failed to register nan callbacks. Invalidating object";
         invalidate();
     }
+
+    // Register for iface state toggle events.
+    iface_util::IfaceEventHandlers event_handlers = {};
+    event_handlers.on_state_toggle_off_on =
+        [weak_ptr_this](const std::string& /* iface_name */) {
+            const auto shared_ptr_this = weak_ptr_this.promote();
+            if (!shared_ptr_this.get() || !shared_ptr_this->isValid()) {
+                LOG(ERROR) << "Callback invoked on an invalid object";
+                return;
+            }
+            // Tell framework that NAN has been disabled.
+            WifiNanStatus status = {
+                NanStatusType::UNSUPPORTED_CONCURRENCY_NAN_DISABLED, ""};
+            for (const auto& callback : shared_ptr_this->getEventCallbacks()) {
+                if (!callback->eventDisabled(status).isOk()) {
+                    LOG(ERROR) << "Failed to invoke the callback";
+                }
+            }
+        };
+    iface_util_.lock()->registerIfaceEventHandlers(ifname_, event_handlers);
 }
 
 void WifiNanIface::invalidate() {
@@ -505,7 +529,7 @@
     legacy_hal_.lock()->nanDisableRequest(ifname_, 0xFFFF);
     legacy_hal_.lock()->nanDataInterfaceDelete(ifname_, 0xFFFE, "aware_data0");
     legacy_hal_.lock()->nanDataInterfaceDelete(ifname_, 0xFFFD, "aware_data1");
-
+    iface_util_.lock()->unregisterIfaceEventHandlers(ifname_);
     legacy_hal_.reset();
     event_cb_handler_.invalidate();
     event_cb_handler_1_2_.invalidate();
diff --git a/wifi/1.3/default/wifi_nan_iface.h b/wifi/1.3/default/wifi_nan_iface.h
index f735d61..737be93 100644
--- a/wifi/1.3/default/wifi_nan_iface.h
+++ b/wifi/1.3/default/wifi_nan_iface.h
@@ -22,6 +22,7 @@
 #include <android/hardware/wifi/1.2/IWifiNanIface.h>
 
 #include "hidl_callback_util.h"
+#include "wifi_iface_util.h"
 #include "wifi_legacy_hal.h"
 
 namespace android {
@@ -37,7 +38,8 @@
 class WifiNanIface : public V1_2::IWifiNanIface {
    public:
     WifiNanIface(const std::string& ifname,
-                 const std::weak_ptr<legacy_hal::WifiLegacyHal> legacy_hal);
+                 const std::weak_ptr<legacy_hal::WifiLegacyHal> legacy_hal,
+                 const std::weak_ptr<iface_util::WifiIfaceUtil> iface_util);
     // Refer to |WifiChip::invalidate()|.
     void invalidate();
     bool isValid();
@@ -147,6 +149,7 @@
 
     std::string ifname_;
     std::weak_ptr<legacy_hal::WifiLegacyHal> legacy_hal_;
+    std::weak_ptr<iface_util::WifiIfaceUtil> iface_util_;
     bool is_valid_;
     hidl_callback_util::HidlCallbackHandler<V1_0::IWifiNanIfaceEventCallback>
         event_cb_handler_;
diff --git a/wifi/1.3/default/wifi_rtt_controller.cpp b/wifi/1.3/default/wifi_rtt_controller.cpp
index fa317e3..3dcbee6 100644
--- a/wifi/1.3/default/wifi_rtt_controller.cpp
+++ b/wifi/1.3/default/wifi_rtt_controller.cpp
@@ -49,6 +49,8 @@
     return event_callbacks_;
 }
 
+std::string WifiRttController::getIfaceName() { return ifname_; }
+
 Return<void> WifiRttController::getBoundIface(getBoundIface_cb hidl_status_cb) {
     return validateAndCall(
         this, WifiStatusCode::ERROR_WIFI_RTT_CONTROLLER_INVALID,
diff --git a/wifi/1.3/default/wifi_rtt_controller.h b/wifi/1.3/default/wifi_rtt_controller.h
index 9798b79..eedd22a 100644
--- a/wifi/1.3/default/wifi_rtt_controller.h
+++ b/wifi/1.3/default/wifi_rtt_controller.h
@@ -42,6 +42,7 @@
     void invalidate();
     bool isValid();
     std::vector<sp<IWifiRttControllerEventCallback>> getEventCallbacks();
+    std::string getIfaceName();
 
     // HIDL methods exposed.
     Return<void> getBoundIface(getBoundIface_cb hidl_status_cb) override;