Merge "wifi(tests): Unit tests for iface event cb's" into qt-dev
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/OWNERS b/automotive/OWNERS
index 4a94494..3cf4489 100644
--- a/automotive/OWNERS
+++ b/automotive/OWNERS
@@ -1,3 +1,4 @@
 randolphs@google.com
 pirozzoj@google.com
 twasilczyk@google.com
+pfg@google.com
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 258dbd9..7082566 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
@@ -105,6 +105,24 @@
     std::vector<VmsAssociatedLayer> associated_layers;
 };
 
+// An enum to represent the result of parsing START_SESSION message from the VMS service.
+enum VmsSessionStatus {
+    // New server session is received if the new client ID is -1 and the new server ID is not an
+    // invalid ID.
+    kNewServerSession,
+    // Ack to new client session is received if the new client ID is same as the old one and the new
+    // server ID is not an invalid ID.
+    kAckToNewClientSession,
+    // Error codes:
+    // Invalid message with either invalid format or unexpected data.
+    kInvalidMessage,
+    // Invalid server ID. New ID should always be greater than or equal to max_of(0, current server
+    // ID)
+    kInvalidServiceId,
+    // Invalid client ID. New ID should always be either -1 or the current client ID.
+    kInvalidClientId
+};
+
 // Creates an empty base VMS message with some pre-populated default fields.
 std::unique_ptr<VehiclePropValue> createBaseVmsMessage(size_t message_size);
 
@@ -146,11 +164,21 @@
 // Creates a VehiclePropValue containing a message of type VmsMessageType.DATA.
 // Returns a nullptr if the byte string in bytes is empty.
 //
-// For example, to build a VehiclePropMessage containing a proto, the caller
+// 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);
 
+// Creates a VehiclePropValue containing a message of type
+// VmsMessageType.PUBLISHER_ID_REQUEST with the given publisher information.
+// Returns a nullptr if the input is empty.
+std::unique_ptr<VehiclePropValue> createPublisherIdRequest(
+        const std::string& vms_provider_description);
+
+// Creates a VehiclePropValue message of type VmsMessageType.START_SESSION.
+std::unique_ptr<VehiclePropValue> createStartSessionMessage(const int service_id,
+                                                            const int client_id);
+
 // Returns true if the VehiclePropValue pointed to by value contains a valid Vms
 // message, i.e. the VehicleProperty, VehicleArea, and VmsMessageType are all
 // valid. Note: If the VmsMessageType enum is extended, this function will
@@ -169,12 +197,6 @@
 // function to ParseFromString.
 std::string parseData(const VehiclePropValue& value);
 
-// Creates a VehiclePropValue containing a message of type
-// VmsMessageType.PUBLISHER_ID_REQUEST with the given publisher information.
-// Returns a nullptr if the input is empty.
-std::unique_ptr<VehiclePropValue> createPublisherIdRequest(
-        const std::string& vms_provider_description);
-
 // Returns the publisher ID by parsing the VehiclePropValue containing the ID.
 // Returns null if the message is invalid.
 int32_t parsePublisherIdResponse(const VehiclePropValue& publisher_id_response);
@@ -204,6 +226,12 @@
 // has newly started or restarted.
 bool hasServiceNewlyStarted(const VehiclePropValue& availability_change);
 
+// Takes a start session message, current service ID, current client ID; and returns the type/status
+// of the message. It also populates the new service ID with the correct value.
+VmsSessionStatus parseStartSessionMessage(const VehiclePropValue& start_session,
+                                          const int service_id, const int client_id,
+                                          int* new_service_id);
+
 }  // namespace vms
 }  // namespace V2_0
 }  // namespace vehicle
diff --git a/automotive/vehicle/2.0/default/common/src/VmsUtils.cpp b/automotive/vehicle/2.0/default/common/src/VmsUtils.cpp
index 1863191..111f6ea 100644
--- a/automotive/vehicle/2.0/default/common/src/VmsUtils.cpp
+++ b/automotive/vehicle/2.0/default/common/src/VmsUtils.cpp
@@ -31,6 +31,7 @@
 static constexpr int kLayerNumberSize = 1;
 static constexpr int kLayerSize = 3;
 static constexpr int kLayerAndPublisherSize = 4;
+static constexpr int kSessionIdsSize = 2;
 static constexpr int kPublisherIdIndex =
         toInt(VmsPublisherInformationIntegerValuesIndex::PUBLISHER_ID);
 static constexpr int kSubscriptionStateSequenceNumberIndex =
@@ -41,9 +42,9 @@
 // TODO(aditin): We should extend the VmsMessageType enum to include a first and
 // last, which would prevent breakages in this API. However, for all of the
 // functions in this module, we only need to guarantee that the message type is
-// between SUBSCRIBE and PUBLISHER_ID_RESPONSE.
+// between SUBSCRIBE and START_SESSION.
 static constexpr int kFirstMessageType = toInt(VmsMessageType::SUBSCRIBE);
-static constexpr int kLastMessageType = toInt(VmsMessageType::PUBLISHER_ID_RESPONSE);
+static constexpr int kLastMessageType = toInt(VmsMessageType::START_SESSION);
 
 std::unique_ptr<VehiclePropValue> createBaseVmsMessage(size_t message_size) {
     auto result = createVehiclePropValue(VehiclePropertyType::INT32, message_size);
@@ -132,6 +133,28 @@
     return result;
 }
 
+std::unique_ptr<VehiclePropValue> createPublisherIdRequest(
+        const std::string& vms_provider_description) {
+    auto result = createBaseVmsMessage(kMessageTypeSize);
+    result->value.int32Values = hidl_vec<int32_t>{
+            toInt(VmsMessageType::PUBLISHER_ID_REQUEST),
+    };
+    result->value.bytes =
+            std::vector<uint8_t>(vms_provider_description.begin(), vms_provider_description.end());
+    return result;
+}
+
+std::unique_ptr<VehiclePropValue> createStartSessionMessage(const int service_id,
+                                                            const int client_id) {
+    auto result = createBaseVmsMessage(kMessageTypeSize + kSessionIdsSize);
+    result->value.int32Values = hidl_vec<int32_t>{
+            toInt(VmsMessageType::START_SESSION),
+            service_id,
+            client_id,
+    };
+    return result;
+}
+
 bool isValidVmsProperty(const VehiclePropValue& value) {
     return (value.prop == toInt(VehicleProperty::VEHICLE_MAP_SERVICE));
 }
@@ -159,17 +182,6 @@
     }
 }
 
-std::unique_ptr<VehiclePropValue> createPublisherIdRequest(
-        const std::string& vms_provider_description) {
-    auto result = createBaseVmsMessage(kMessageTypeSize);
-    result->value.int32Values = hidl_vec<int32_t>{
-            toInt(VmsMessageType::PUBLISHER_ID_REQUEST),
-    };
-    result->value.bytes =
-            std::vector<uint8_t>(vms_provider_description.begin(), vms_provider_description.end());
-    return result;
-}
-
 int32_t parsePublisherIdResponse(const VehiclePropValue& publisher_id_response) {
     if (isValidVmsMessage(publisher_id_response) &&
         parseMessageType(publisher_id_response) == VmsMessageType::PUBLISHER_ID_RESPONSE &&
@@ -256,6 +268,31 @@
             availability_change.value.int32Values[kAvailabilitySequenceNumberIndex] == 0);
 }
 
+VmsSessionStatus parseStartSessionMessage(const VehiclePropValue& start_session,
+                                          const int service_id, const int client_id,
+                                          int* new_service_id) {
+    if (isValidVmsMessage(start_session) &&
+        parseMessageType(start_session) == VmsMessageType::START_SESSION &&
+        start_session.value.int32Values.size() == kSessionIdsSize + 1) {
+        *new_service_id = start_session.value.int32Values[1];
+        const int new_client_id = start_session.value.int32Values[2];
+        if (*new_service_id < std::max(0, service_id)) {
+            *new_service_id = service_id;
+            return VmsSessionStatus::kInvalidServiceId;
+        }
+        if (new_client_id == -1) {
+            return VmsSessionStatus::kNewServerSession;
+        }
+        if (new_client_id == client_id) {
+            return VmsSessionStatus::kAckToNewClientSession;
+        }
+        *new_service_id = service_id;
+        return VmsSessionStatus::kInvalidClientId;
+    }
+    *new_service_id = service_id;
+    return VmsSessionStatus::kInvalidMessage;
+}
+
 }  // namespace vms
 }  // namespace V2_0
 }  // namespace vehicle
diff --git a/automotive/vehicle/2.0/default/impl/vhal_v2_0/DefaultConfig.h b/automotive/vehicle/2.0/default/impl/vhal_v2_0/DefaultConfig.h
index 08cdffa..39fe991 100644
--- a/automotive/vehicle/2.0/default/impl/vhal_v2_0/DefaultConfig.h
+++ b/automotive/vehicle/2.0/default/impl/vhal_v2_0/DefaultConfig.h
@@ -530,6 +530,7 @@
     {.config = {.prop = toInt(VehicleProperty::HVAC_TEMPERATURE_DISPLAY_UNITS),
                 .access = VehiclePropertyAccess::READ_WRITE,
                 .changeMode = VehiclePropertyChangeMode::ON_CHANGE,
+                .configArray = {(int)VehicleUnit::FAHRENHEIT, (int)VehicleUnit::CELSIUS},
                 .areaConfigs = {VehicleAreaConfig{.areaId = (0)}}},
      .initialValue = {.int32Values = {(int)VehicleUnit::FAHRENHEIT}}},
 
diff --git a/automotive/vehicle/2.0/default/tests/VmsUtils_test.cpp b/automotive/vehicle/2.0/default/tests/VmsUtils_test.cpp
index 5ea5bd4..2b3efc7 100644
--- a/automotive/vehicle/2.0/default/tests/VmsUtils_test.cpp
+++ b/automotive/vehicle/2.0/default/tests/VmsUtils_test.cpp
@@ -158,7 +158,7 @@
 TEST(VmsUtilsTest, invalidMessageType) {
     VmsLayer layer(1, 0, 2);
     auto message = createSubscribeMessage(layer);
-    message->value.int32Values[0] = 0;
+    message->value.int32Values[0] = -1;
 
     EXPECT_FALSE(isValidVmsMessage(*message));
 }
@@ -325,6 +325,98 @@
     EXPECT_FALSE(hasServiceNewlyStarted(*message));
 }
 
+TEST(VmsUtilsTest, startSessionRequest) {
+    auto message = createStartSessionMessage(123, 456);
+    ASSERT_NE(message, nullptr);
+    EXPECT_TRUE(isValidVmsMessage(*message));
+    EXPECT_EQ(message->prop, toInt(VehicleProperty::VEHICLE_MAP_SERVICE));
+    EXPECT_EQ(message->value.int32Values.size(), 0x3ul);
+    EXPECT_EQ(parseMessageType(*message), VmsMessageType::START_SESSION);
+    EXPECT_EQ(message->value.int32Values[1], 123);
+    EXPECT_EQ(message->value.int32Values[2], 456);
+}
+
+TEST(VmsUtilsTest, startSessionServiceNewlyStarted) {
+    auto message = createBaseVmsMessage(3);
+    int new_service_id;
+    message->value.int32Values = hidl_vec<int32_t>{toInt(VmsMessageType::START_SESSION), 123, -1};
+    EXPECT_EQ(parseStartSessionMessage(*message, 122, 456, &new_service_id),
+              VmsSessionStatus::kNewServerSession);
+    EXPECT_EQ(new_service_id, 123);
+}
+
+TEST(VmsUtilsTest, startSessionServiceNewlyStartedEdgeCase) {
+    auto message = createBaseVmsMessage(3);
+    int new_service_id;
+    message->value.int32Values = hidl_vec<int32_t>{toInt(VmsMessageType::START_SESSION), 0, -1};
+    EXPECT_EQ(parseStartSessionMessage(*message, -1, 0, &new_service_id),
+              VmsSessionStatus::kNewServerSession);
+    EXPECT_EQ(new_service_id, 0);
+}
+
+TEST(VmsUtilsTest, startSessionClientNewlyStarted) {
+    auto message = createBaseVmsMessage(3);
+    int new_service_id;
+    message->value.int32Values = hidl_vec<int32_t>{toInt(VmsMessageType::START_SESSION), 123, 456};
+    EXPECT_EQ(parseStartSessionMessage(*message, -1, 456, &new_service_id),
+              VmsSessionStatus::kAckToNewClientSession);
+    EXPECT_EQ(new_service_id, 123);
+}
+
+TEST(VmsUtilsTest, startSessionClientNewlyStartedWithSameServerId) {
+    auto message = createBaseVmsMessage(3);
+    int new_service_id;
+    message->value.int32Values = hidl_vec<int32_t>{toInt(VmsMessageType::START_SESSION), 123, 456};
+    EXPECT_EQ(parseStartSessionMessage(*message, 123, 456, &new_service_id),
+              VmsSessionStatus::kAckToNewClientSession);
+    EXPECT_EQ(new_service_id, 123);
+}
+
+TEST(VmsUtilsTest, startSessionClientNewlyStartedEdgeCase) {
+    auto message = createBaseVmsMessage(3);
+    int new_service_id;
+    message->value.int32Values = hidl_vec<int32_t>{toInt(VmsMessageType::START_SESSION), 0, 0};
+    EXPECT_EQ(parseStartSessionMessage(*message, 0, 0, &new_service_id),
+              VmsSessionStatus::kAckToNewClientSession);
+    EXPECT_EQ(new_service_id, 0);
+}
+
+TEST(VmsUtilsTest, startSessionOldServiceId) {
+    auto message = createBaseVmsMessage(3);
+    int new_service_id;
+    message->value.int32Values = hidl_vec<int32_t>{toInt(VmsMessageType::START_SESSION), 120, 456};
+    EXPECT_EQ(parseStartSessionMessage(*message, 123, 456, &new_service_id),
+              VmsSessionStatus::kInvalidServiceId);
+    EXPECT_EQ(new_service_id, 123);
+}
+
+TEST(VmsUtilsTest, startSessionInvalidServiceIdEdgeCase) {
+    auto message = createBaseVmsMessage(3);
+    int new_service_id;
+    message->value.int32Values = hidl_vec<int32_t>{toInt(VmsMessageType::START_SESSION), -1, 456};
+    EXPECT_EQ(parseStartSessionMessage(*message, -1, 456, &new_service_id),
+              VmsSessionStatus::kInvalidServiceId);
+    EXPECT_EQ(new_service_id, -1);
+}
+
+TEST(VmsUtilsTest, startSessionInvalidClientId) {
+    auto message = createBaseVmsMessage(3);
+    int new_service_id;
+    message->value.int32Values = hidl_vec<int32_t>{toInt(VmsMessageType::START_SESSION), 123, 457};
+    EXPECT_EQ(parseStartSessionMessage(*message, 123, 456, &new_service_id),
+              VmsSessionStatus::kInvalidClientId);
+    EXPECT_EQ(new_service_id, 123);
+}
+
+TEST(VmsUtilsTest, startSessionInvalidMessageFormat) {
+    auto message = createBaseVmsMessage(2);
+    int new_service_id;
+    message->value.int32Values = hidl_vec<int32_t>{toInt(VmsMessageType::START_SESSION), 123};
+    EXPECT_EQ(parseStartSessionMessage(*message, 123, 456, &new_service_id),
+              VmsSessionStatus::kInvalidMessage);
+    EXPECT_EQ(new_service_id, 123);
+}
+
 }  // namespace
 
 }  // namespace vms
diff --git a/automotive/vehicle/2.0/types.hal b/automotive/vehicle/2.0/types.hal
index b04d096..a535e64 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.
@@ -1120,9 +1126,9 @@
      *
      * Distance units are defined in VehicleUnit.
      * VehiclePropConfig.configArray is used to indicate the supported distance display units.
-     * For example: configArray[0] = 0x21 // METER
-     *              configArray[1] = 0x23 // KILOMETER
-     *              configArray[2] = 0x24 // MILE
+     * For example: configArray[0] = METER
+     *              configArray[1] = KILOMETER
+     *              configArray[2] = MILE
      * @change_mode VehiclePropertyChangeMode:ON_CHANGE
      * @access VehiclePropertyAccess:READ_WRITE
      * @data_enum VehicleUnit
@@ -1141,8 +1147,8 @@
      *
      * VehiclePropConfig.configArray is used to indicate the supported fuel volume display units.
      * Volume units are defined in VehicleUnit.
-     * For example: configArray[0] = 0x41 // LITER
-     *              configArray[1] = 0x42 // GALLON
+     * For example: configArray[0] = LITER
+     *              configArray[1] = GALLON
      * @change_mode VehiclePropertyChangeMode:ON_CHANGE
      * @access VehiclePropertyAccess:READ_WRITE
      * @data_enum VehicleUnit
@@ -1161,9 +1167,9 @@
      *
      * VehiclePropConfig.configArray is used to indicate the supported pressure display units.
      * Pressure units are defined in VehicleUnit.
-     * For example: configArray[0] = 0x70 // KILOPASCAL
-     *              configArray[1] = 0x71 // PSI
-     *              configArray[2] = 0x72 // BAR
+     * For example: configArray[0] = KILOPASCAL
+     *              configArray[1] = PSI
+     *              configArray[2] = BAR
      * @change_mode VehiclePropertyChangeMode:ON_CHANGE
      * @access VehiclePropertyAccess:READ_WRITE
      * @data_enum VehicleUnit
@@ -1182,9 +1188,9 @@
      *
      * VehiclePropConfig.configArray is used to indicate the supported electrical energy units.
      * Electrical energy units are defined in VehicleUnit.
-     * For example: configArray[0] = 0x60 // watt-hours
-     *              configArray[1] = 0x64 // ampere-hours
-     *              configArray[2] = 0x65 // kilowatt-hours
+     * For example: configArray[0] = WATT_HOUR
+     *              configArray[1] = AMPERE_HOURS
+     *              configArray[2] = KILOWATT_HOUR
      * @change_mode VehiclePropertyChangeMode:ON_CHANGE
      * @access VehiclePropertyAccess:READ_WRITE
      * @data_enum VehicleUnit
@@ -1212,6 +1218,25 @@
         | VehicleArea:GLOBAL),
 
     /**
+     * Speed units for display
+     *
+     * Indicates type of units the car is using to display speed to user. Eg. m/s, km/h, or mph.
+     *
+     * VehiclePropConfig.configArray is used to indicate the supported speed display units.
+     * Pressure units are defined in VehicleUnit.
+     * For example: configArray[0] = METER_PER_SEC
+     *              configArray[1] = MILES_PER_HOUR
+     *              configArray[2] = KILOMETERS_PER_HOUR
+     * @change_mode VehiclePropertyChangeMode:ON_CHANGE
+     * @access VehiclePropertyAccess:READ_WRITE
+     */
+    VEHICLE_SPEED_DISPLAY_UNITS = (
+        0x0605
+        | VehiclePropertyGroup:SYSTEM
+        | VehiclePropertyType:INT32
+        | VehicleArea:GLOBAL),
+
+    /**
      * Outside temperature
      *
      * @change_mode VehiclePropertyChangeMode:CONTINUOUS
@@ -2586,42 +2611,45 @@
  * Units used for int or float type with no attached enum types.
  */
 enum VehicleUnit : int32_t {
-    SHOULD_NOT_USE = 0x000,
+    SHOULD_NOT_USE      = 0x000,
 
-    METER_PER_SEC  = 0x01,
-    RPM            = 0x02,
-    HERTZ          = 0x03,
-    PERCENTILE     = 0x10,
-    MILLIMETER     = 0x20,
-    METER          = 0x21,
-    KILOMETER      = 0x23,
-    MILE           = 0x24,
-    CELSIUS        = 0x30,
-    FAHRENHEIT     = 0x31,
-    KELVIN         = 0x32,
-    MILLILITER     = 0x40,
-    LITER          = 0x41,
+    METER_PER_SEC       = 0x01,
+    RPM                 = 0x02,
+    HERTZ               = 0x03,
+    PERCENTILE          = 0x10,
+    MILLIMETER          = 0x20,
+    METER               = 0x21,
+    KILOMETER           = 0x23,
+    MILE                = 0x24,
+    CELSIUS             = 0x30,
+    FAHRENHEIT          = 0x31,
+    KELVIN              = 0x32,
+    MILLILITER          = 0x40,
+    LITER               = 0x41,
 
     /** deprecated. Use US_GALLON instead. */
-    GALLON         = 0x42,
-    US_GALLON      = 0x42,
-    IMPERIAL_GALLON= 0x43,
-    NANO_SECS      = 0x50,
-    SECS           = 0x53,
-    YEAR           = 0x59,
+    GALLON              = 0x42,
+    US_GALLON           = 0x42,
+    IMPERIAL_GALLON     = 0x43,
+    NANO_SECS           = 0x50,
+    SECS                = 0x53,
+    YEAR                = 0x59,
 
     // Electrical Units
-    WATT_HOUR      = 0x60,
-    MILLIAMPERE    = 0x61,
-    MILLIVOLT      = 0x62,
-    MILLIWATTS     = 0x63,
-    AMPERE_HOURS   = 0x64,
-    KILOWATT_HOUR  = 0x65,
+    WATT_HOUR           = 0x60,
+    MILLIAMPERE         = 0x61,
+    MILLIVOLT           = 0x62,
+    MILLIWATTS          = 0x63,
+    AMPERE_HOURS        = 0x64,
+    KILOWATT_HOUR       = 0x65,
 
-    KILOPASCAL     = 0x70,
-    PSI            = 0x71,
-    BAR            = 0x72,
-    DEGREES        = 0x80,
+    KILOPASCAL          = 0x70,
+    PSI                 = 0x71,
+    BAR                 = 0x72,
+    DEGREES             = 0x80,
+
+    MILES_PER_HOUR      = 0x90,
+    KILOMETERS_PER_HOUR = 0x91,
 };
 
 /**
@@ -2770,6 +2798,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;
 
@@ -3249,6 +3285,16 @@
  */
 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.
@@ -3364,7 +3410,7 @@
      */
     PUBLISHER_INFORMATION_RESPONSE = 16,
 
-    LAST_VMS_MESSAGE_TYPE = PUBLISHER_INFORMATION_RESPONSE,
+    LAST_VMS_MESSAGE_TYPE = START_SESSION,
 };
 
 /**
@@ -3378,6 +3424,30 @@
 };
 
 /*
+ * Handshake data sent as part of a VmsMessageType.START_SESSION message.
+ *
+ * A new session is initiated by sending a START_SESSION message with the
+ * sender's identifier populated and the receiver's identifier set to -1.
+ *
+ * Identifier values are independently generated, but must be non-negative, and
+ * increase monotonically between reboots.
+ *
+ * Upon receiving a START_SESSION with a mis-matching identifier, the receiver
+ * must clear any cached VMS offering or subscription state and acknowledge the
+ * new session by responding with a START_SESSION message that populates both
+ * identifier fields.
+ *
+ * Any VMS messages received between initiation and completion of the handshake
+ * must be discarded.
+ */
+enum VmsStartSessionMessageIntegerValuesIndex : VmsBaseMessageIntegerValuesIndex {
+    /* Identifier field for the Android system service. */
+    SERVICE_ID = 1,
+    /* Identifier field for the HAL client process. */
+    CLIENT_ID = 2,
+};
+
+/*
  * A VMS message with a layer is sent as part of a VmsMessageType.SUBSCRIBE or
  * VmsMessageType.UNSUBSCRIBE messages.
  *
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/ICameraDeviceCallback.hal b/camera/device/3.2/ICameraDeviceCallback.hal
index 69715de..dec3bd8 100644
--- a/camera/device/3.2/ICameraDeviceCallback.hal
+++ b/camera/device/3.2/ICameraDeviceCallback.hal
@@ -125,6 +125,21 @@
      * via a SHUTTER notify() call. It is highly recommended to dispatch this
      * call as early as possible.
      *
+     * The SHUTTER notify calls for requests with android.control.enableZsl
+     * set to TRUE and ANDROID_CONTROL_CAPTURE_INTENT == STILL_CAPTURE may be
+     * out-of-order compared to SHUTTER notify for other kinds of requests
+     * (including regular, reprocess, or zero-shutter-lag requests with
+     * different capture intents).
+     *
+     * As a result, the capture results of zero-shutter-lag requests with
+     * ANDROID_CONTROL_CAPTURE_INTENT == STILL_CAPTURE may be out-of-order
+     * compared to capture results for other kinds of requests.
+     *
+     * Different SHUTTER notify calls for zero-shutter-lag requests with
+     * ANDROID_CONTROL_CAPTURE_INTENT == STILL_CAPTURE must be in order between
+     * them, as is for other kinds of requests. SHUTTER notify calls for
+     * zero-shutter-lag requests with non STILL_CAPTURE intent must be in order
+     * with SHUTTER notify calls for regular requests.
      * ------------------------------------------------------------------------
      * Performance requirements:
      *
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.2/default/CameraDeviceSession.cpp b/camera/device/3.2/default/CameraDeviceSession.cpp
index f2d7a47..99cdccb 100644
--- a/camera/device/3.2/default/CameraDeviceSession.cpp
+++ b/camera/device/3.2/default/CameraDeviceSession.cpp
@@ -99,11 +99,20 @@
         return true;
     }
 
-    int32_t reqFMQSize = property_get_int32("ro.camera.req.fmq.size", /*default*/-1);
+    // "ro.camera" properties are no longer supported on vendor side.
+    //  Support a fall back for the fmq size override that uses "ro.vendor.camera"
+    //  properties.
+    int32_t reqFMQSize = property_get_int32("ro.vendor.camera.req.fmq.size", /*default*/-1);
     if (reqFMQSize < 0) {
-        reqFMQSize = CAMERA_REQUEST_METADATA_QUEUE_SIZE;
+        reqFMQSize = property_get_int32("ro.camera.req.fmq.size", /*default*/-1);
+        if (reqFMQSize < 0) {
+            reqFMQSize = CAMERA_REQUEST_METADATA_QUEUE_SIZE;
+        } else {
+            ALOGV("%s: request FMQ size overridden to %d", __FUNCTION__, reqFMQSize);
+        }
     } else {
-        ALOGV("%s: request FMQ size overridden to %d", __FUNCTION__, reqFMQSize);
+        ALOGV("%s: request FMQ size overridden to %d via fallback property", __FUNCTION__,
+                reqFMQSize);
     }
 
     mRequestMetadataQueue = std::make_unique<RequestMetadataQueue>(
@@ -114,12 +123,22 @@
         return true;
     }
 
-    int32_t resFMQSize = property_get_int32("ro.camera.res.fmq.size", /*default*/-1);
+    // "ro.camera" properties are no longer supported on vendor side.
+    //  Support a fall back for the fmq size override that uses "ro.vendor.camera"
+    //  properties.
+    int32_t resFMQSize = property_get_int32("ro.vendor.camera.res.fmq.size", /*default*/-1);
     if (resFMQSize < 0) {
-        resFMQSize = CAMERA_RESULT_METADATA_QUEUE_SIZE;
+        resFMQSize = property_get_int32("ro.camera.res.fmq.size", /*default*/-1);
+        if (resFMQSize < 0) {
+            resFMQSize = CAMERA_RESULT_METADATA_QUEUE_SIZE;
+        } else {
+            ALOGV("%s: result FMQ size overridden to %d", __FUNCTION__, resFMQSize);
+        }
     } else {
-        ALOGV("%s: result FMQ size overridden to %d", __FUNCTION__, resFMQSize);
+        ALOGV("%s: result FMQ size overridden to %d via fallback property", __FUNCTION__,
+                resFMQSize);
     }
+
     mResultMetadataQueue = std::make_shared<RequestMetadataQueue>(
             static_cast<size_t>(resFMQSize),
             false /* non blocking */);
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.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/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..200dd3f 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>
@@ -6104,36 +6106,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 1f32263..e6ac705 100644
--- a/current.txt
+++ b/current.txt
@@ -386,6 +386,7 @@
 
 # ABI preserving changes to HALs during Android Q
 2a55e224aa9bc62c0387cd85ad3c97e33f0c33a4e1489cbae86b2523e6f9df35 android.hardware.camera.device@3.2::ICameraDevice
+17e878cb11ea602c08af04a09182e6265498be16edf26605058383b9a7628261 android.hardware.camera.device@3.2::ICameraDeviceCallback
 8caf9104dc6885852c0b117d853dd93f6d4b61a0a365138295eb8bcd41b36423 android.hardware.camera.device@3.2::ICameraDeviceSession
 684702a60deef03a1e8093961dc0a18c555c857ad5a77ba7340b0635ae01eb70 android.hardware.camera.device@3.4::ICameraDeviceSession
 f8a19622cb0cc890913b1ef3e32b675ffb26089a09e02fef4056ebad324d2b5d android.hardware.camera.device@3.4::types
@@ -393,8 +394,10 @@
 23780340c686ee86986aa5a9755c2d8566224fed177bbb22a5ebf06be574b60c android.hardware.camera.metadata@3.3::types
 05d1ee760d81cdd2dc7a70ce0241af9fa830edae33b4be83d9bf5fffe05ddc6f android.hardware.camera.provider@2.4::ICameraProvider
 da33234403ff5d60f3473711917b9948e6484a4260b5247acdafb111193a9de2 android.hardware.configstore@1.0::ISurfaceFlingerConfigs
+ede69710c3a95c2cbe818e6c8bb72c7816823face5fc21c17731b26f41d94d65 android.hardware.gnss@1.0::IGnss
 21165b8e30c4b2d52980e4728f661420adc16e38bbe73476c06b2085be908f4c android.hardware.gnss@1.0::IGnssCallback
 d702fb01dc2a0733aa820b7eb65435ee3334f75632ef880bafd2fb8803a20a58 android.hardware.gnss@1.0::IGnssMeasurementCallback
+b5f1f4c1bd6de71a8e71d70f57cdab904ac024a12f3dee3e2173770a4583bcc2 android.hardware.gnss@1.1::IGnss
 7c7721c0f773fcf422b71a4f558545e9e36acc973e58ca51e5bd53905cf46bc0 android.hardware.graphics.bufferqueue@1.0::IGraphicBufferProducer
 d4fea995378bb4f421b4e24ccf68cad2734ab07fe4f874a126ba558b99df5766 android.hardware.graphics.composer@2.1::IComposerClient
 f7d7cb747dc01a9fdb2d39a80003b4d8df9be733d65f5842198802eb6209db69 android.hardware.graphics.mapper@2.0::IMapper
@@ -407,6 +410,7 @@
 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
 3d01e29e8129186f7567c4f9c8bee7480a0768e587b1be9b28adb0a6cbec6bf2 android.hardware.tv.cec@1.0::types
 1722ad002317b1fae1400de709e90f442d94ef22864e05f7a12af48c32e8edc8 android.hardware.usb@1.1::types
@@ -467,7 +471,7 @@
 7f460e795f5d1ed5e378935f98c6db4d39497de988aef1b4c2a4a07a6c400392 android.hardware.gnss@2.0::IAGnss
 2e5ad983734069e84a760004b32da0d09e4170c05380abe27e6eb80e4aa70d5a android.hardware.gnss@2.0::IAGnssCallback
 1f4ac068a88a72360280d94a7f6fd7c63813c1eea4891a0eb01394d3e7e775f2 android.hardware.gnss@2.0::IAGnssRil
-4deafcdcffa2d002119e7f58810b767a84666e76475aae68e757ec2845d9756d android.hardware.gnss@2.0::IGnss
+f5605f48c2fb9f231615dd932bf730ae9540f4f98b5b7ae2b269975f452f6d73 android.hardware.gnss@2.0::IGnss
 db6bdf6dfc5edf6c85d2944976db899227abb51079c893874353c322342c50b6 android.hardware.gnss@2.0::IGnssBatching
 1f89392f1ebb693d8fa6f50324b1635fc79fab246d31900e63998e1b0e17511c android.hardware.gnss@2.0::IGnssBatchingCallback
 64232037109a5e5f53ab0377e755ec494ae93fcb5279e6eea71dec2e7ac6fbfc android.hardware.gnss@2.0::IGnssCallback
@@ -523,6 +527,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
diff --git a/gnss/1.0/IGnss.hal b/gnss/1.0/IGnss.hal
index 602c615..d32bc63 100644
--- a/gnss/1.0/IGnss.hal
+++ b/gnss/1.0/IGnss.hal
@@ -75,8 +75,13 @@
     };
 
     /**
-     * Opens the interface and provides the callback routines
-     * to the implementation of this interface.
+     * Opens the interface and provides the callback routines to the implementation of this
+     * interface.
+     *
+     * The framework calls this method to instruct the GPS engine to prepare for serving requests
+     * from the framework. The GNSS HAL implementation must respond to all GNSS requests from the
+     * framework upon successful return from this method until cleanup() method is called to
+     * close this interface.
      *
      * @param callback Callback interface for IGnss.
      *
@@ -105,6 +110,18 @@
 
     /**
      * Closes the interface.
+     *
+     * The cleanup() method is called by the framework to tell the GNSS HAL implementation to
+     * not expect any GNSS requests in the immediate future - e.g. this may be called when
+     * location is disabled by a user setting or low battery conditions. The GNSS HAL
+     * implementation must immediately stop responding to any existing requests until the
+     * setCallback() method is called again and the requests are re-initiated by the framework.
+     *
+     * After this method is called, the GNSS HAL implementation may choose to modify GNSS hardware
+     * states to save power. It is expected that when setCallback() method is called again to
+     * reopen this interface, to serve requests, there may be some minor delays in GNSS response
+     * requests as hardware readiness states are restored, not to exceed those that occur on normal
+     * device boot up.
      */
     cleanup();
 
@@ -153,7 +170,7 @@
      * @param mode  Parameter must be one of MS_BASED or STANDALONE.
      * It is allowed by the platform (and it is recommended) to fallback to
      * MS_BASED if MS_ASSISTED is passed in, and MS_BASED is supported.
-     * @recurrence GNSS postion recurrence value, either periodic or single.
+     * @recurrence GNSS position recurrence value, either periodic or single.
      * @param minIntervalMs Represents the time between fixes in milliseconds.
      * @param preferredAccuracyMeters Represents the requested fix accuracy in meters.
      * @param preferredTimeMs Represents the requested time to first fix in milliseconds.
diff --git a/gnss/1.1/IGnss.hal b/gnss/1.1/IGnss.hal
index 672f742..3400807 100644
--- a/gnss/1.1/IGnss.hal
+++ b/gnss/1.1/IGnss.hal
@@ -29,6 +29,11 @@
      * Opens the interface and provides the callback routines to the implementation of this
      * interface.
      *
+     * The framework calls this method to instruct the GPS engine to prepare for serving requests
+     * from the framework. The GNSS HAL implementation must respond to all GNSS requests from the
+     * framework upon successful return from this method until cleanup() method is called to
+     * close this interface.
+     *
      * @param callback Callback interface for IGnss.
      *
      * @return success Returns true on success.
@@ -42,7 +47,7 @@
      * @param mode Parameter must be one of MS_BASED or STANDALONE. It is allowed by the platform
      *     (and it is recommended) to fallback to MS_BASED if MS_ASSISTED is passed in, and MS_BASED
      *     is supported.
-     * @param recurrence GNSS postion recurrence value, either periodic or single.
+     * @param recurrence GNSS position recurrence value, either periodic or single.
      * @param minIntervalMs Represents the time between fixes in milliseconds.
      * @param preferredAccuracyMeters Represents the requested fix accuracy in meters.
      * @param preferredTimeMs Represents the requested time to first fix in milliseconds.
diff --git a/gnss/2.0/IGnss.hal b/gnss/2.0/IGnss.hal
index f19f8d0..9935bf9 100644
--- a/gnss/2.0/IGnss.hal
+++ b/gnss/2.0/IGnss.hal
@@ -36,13 +36,18 @@
  * the interface @1.0::IGnssNi.hal and @1.0::IGnssNiCallback.hal are deprecated in this version
  * and are not supported by the framework. The GNSS HAL implementation of this interface
  * must return nullptr for the following @1.0::IGnss method.
- *      getExtensionGnssNi() generates (IGnssNi gnssNiIface);
+ *     getExtensionGnssNi() generates (IGnssNi gnssNiIface);
  */
 interface IGnss extends @1.1::IGnss {
     /**
      * Opens the interface and provides the callback routines to the implementation of this
      * interface.
      *
+     * The framework calls this method to instruct the GPS engine to prepare for serving requests
+     * from the framework. The GNSS HAL implementation must respond to all GNSS requests from the
+     * framework upon successful return from this method until cleanup() method is called to
+     * close this interface.
+     *
      * @param callback Callback interface for IGnss.
      *
      * @return success Returns true on success.
@@ -83,8 +88,9 @@
     /**
      * This method returns the IGnssMeasurement interface.
      *
-     * Exactly one of getExtensionGnssMeasurement_1_1() and getExtensionGnssMeasurement_2_0() must
-     * return a non-null handle, and the other method must return nullptr.
+     * Exactly one of getExtensionGnssMeasurement(), getExtensionGnssMeasurement_1_1(), and
+     * getExtensionGnssMeasurement_2_0() methods must return a non-null handle, and the other
+     * methods must return nullptr.
      *
      * @return gnssMeasurementIface Handle to the IGnssMeasurement interface.
      */
diff --git a/graphics/composer/2.3/default/android.hardware.graphics.composer@2.3-service.rc b/graphics/composer/2.3/default/android.hardware.graphics.composer@2.3-service.rc
index 08e32d8..81ce890 100644
--- a/graphics/composer/2.3/default/android.hardware.graphics.composer@2.3-service.rc
+++ b/graphics/composer/2.3/default/android.hardware.graphics.composer@2.3-service.rc
@@ -4,3 +4,4 @@
     group graphics drmrpc
     capabilities SYS_NICE
     onrestart restart surfaceflinger
+    writepid /dev/cpuset/system-background/tasks
diff --git a/neuralnetworks/1.2/vts/functional/CompilationCachingTests.cpp b/neuralnetworks/1.2/vts/functional/CompilationCachingTests.cpp
index bf91560..4411b90 100644
--- a/neuralnetworks/1.2/vts/functional/CompilationCachingTests.cpp
+++ b/neuralnetworks/1.2/vts/functional/CompilationCachingTests.cpp
@@ -45,9 +45,9 @@
 using ::android::nn::allocateSharedMemory;
 using ::test_helper::MixedTypedExample;
 
-namespace {
+namespace float32_model {
 
-// In frameworks/ml/nn/runtime/test/generated/, creates a hidl model of mobilenet.
+// In frameworks/ml/nn/runtime/test/generated/, creates a hidl model of float32 mobilenet.
 #include "examples/mobilenet_224_gender_basic_fixed.example.cpp"
 #include "vts_models/mobilenet_224_gender_basic_fixed.model.cpp"
 
@@ -55,6 +55,44 @@
 [[maybe_unused]] auto dummy_createTestModel = createTestModel_dynamic_output_shape;
 [[maybe_unused]] auto dummy_get_examples = get_examples_dynamic_output_shape;
 
+// MixedTypedExample is defined in frameworks/ml/nn/tools/test_generator/include/TestHarness.h.
+// This function assumes the operation is always ADD.
+std::vector<MixedTypedExample> getLargeModelExamples(uint32_t len) {
+    float outputValue = 1.0f + static_cast<float>(len);
+    return {{.operands = {
+                     // Input
+                     {.operandDimensions = {{0, {1}}}, .float32Operands = {{0, {1.0f}}}},
+                     // Output
+                     {.operandDimensions = {{0, {1}}}, .float32Operands = {{0, {outputValue}}}}}}};
+}
+
+}  // namespace float32_model
+
+namespace quant8_model {
+
+// In frameworks/ml/nn/runtime/test/generated/, creates a hidl model of quant8 mobilenet.
+#include "examples/mobilenet_quantized.example.cpp"
+#include "vts_models/mobilenet_quantized.model.cpp"
+
+// Prevent the compiler from complaining about an otherwise unused function.
+[[maybe_unused]] auto dummy_createTestModel = createTestModel_dynamic_output_shape;
+[[maybe_unused]] auto dummy_get_examples = get_examples_dynamic_output_shape;
+
+// MixedTypedExample is defined in frameworks/ml/nn/tools/test_generator/include/TestHarness.h.
+// This function assumes the operation is always ADD.
+std::vector<MixedTypedExample> getLargeModelExamples(uint32_t len) {
+    uint8_t outputValue = 1 + static_cast<uint8_t>(len);
+    return {{.operands = {// Input
+                          {.operandDimensions = {{0, {1}}}, .quant8AsymmOperands = {{0, {1}}}},
+                          // Output
+                          {.operandDimensions = {{0, {1}}},
+                           .quant8AsymmOperands = {{0, {outputValue}}}}}}};
+}
+
+}  // namespace quant8_model
+
+namespace {
+
 enum class AccessMode { READ_WRITE, READ_ONLY, WRITE_ONLY };
 
 // Creates cache handles based on provided file groups.
@@ -101,14 +139,18 @@
 //                ↑      ↑      ↑             ↑
 //               [1]    [1]    [1]           [1]
 //
-Model createLargeTestModel(OperationType op, uint32_t len) {
+// This function assumes the operation is either ADD or MUL.
+template <typename CppType, OperandType operandType>
+Model createLargeTestModelImpl(OperationType op, uint32_t len) {
+    EXPECT_TRUE(op == OperationType::ADD || op == OperationType::MUL);
+
     // Model operations and operands.
     std::vector<Operation> operations(len);
     std::vector<Operand> operands(len * 2 + 2);
 
     // The constant buffer pool. This contains the activation scalar, followed by the
     // per-operation constant operands.
-    std::vector<uint8_t> operandValues(sizeof(int32_t) + len * sizeof(float));
+    std::vector<uint8_t> operandValues(sizeof(int32_t) + len * sizeof(CppType));
 
     // The activation scalar, value = 0.
     operands[0] = {
@@ -122,7 +164,26 @@
     };
     memset(operandValues.data(), 0, sizeof(int32_t));
 
-    const float floatBufferValue = 1.0f;
+    // The buffer value of the constant second operand. The logical value is always 1.0f.
+    CppType bufferValue;
+    // The scale of the first and second operand.
+    float scale1, scale2;
+    if (operandType == OperandType::TENSOR_FLOAT32) {
+        bufferValue = 1.0f;
+        scale1 = 0.0f;
+        scale2 = 0.0f;
+    } else if (op == OperationType::ADD) {
+        bufferValue = 1;
+        scale1 = 1.0f;
+        scale2 = 1.0f;
+    } else {
+        // To satisfy the constraint on quant8 MUL: input0.scale * input1.scale < output.scale,
+        // set input1 to have scale = 0.5f and bufferValue = 2, i.e. 1.0f in floating point.
+        bufferValue = 2;
+        scale1 = 1.0f;
+        scale2 = 0.5f;
+    }
+
     for (uint32_t i = 0; i < len; i++) {
         const uint32_t firstInputIndex = i * 2 + 1;
         const uint32_t secondInputIndex = firstInputIndex + 1;
@@ -130,10 +191,10 @@
 
         // The first operation input.
         operands[firstInputIndex] = {
-                .type = OperandType::TENSOR_FLOAT32,
+                .type = operandType,
                 .dimensions = {1},
                 .numberOfConsumers = 1,
-                .scale = 0.0f,
+                .scale = scale1,
                 .zeroPoint = 0,
                 .lifetime = (i == 0 ? OperandLifeTime::MODEL_INPUT
                                     : OperandLifeTime::TEMPORARY_VARIABLE),
@@ -142,18 +203,18 @@
 
         // The second operation input, value = 1.
         operands[secondInputIndex] = {
-                .type = OperandType::TENSOR_FLOAT32,
+                .type = operandType,
                 .dimensions = {1},
                 .numberOfConsumers = 1,
-                .scale = 0.0f,
+                .scale = scale2,
                 .zeroPoint = 0,
                 .lifetime = OperandLifeTime::CONSTANT_COPY,
                 .location = {.poolIndex = 0,
-                             .offset = static_cast<uint32_t>(i * sizeof(float) + sizeof(int32_t)),
-                             .length = sizeof(float)},
+                             .offset = static_cast<uint32_t>(i * sizeof(CppType) + sizeof(int32_t)),
+                             .length = sizeof(CppType)},
         };
-        memcpy(operandValues.data() + sizeof(int32_t) + i * sizeof(float), &floatBufferValue,
-               sizeof(float));
+        memcpy(operandValues.data() + sizeof(int32_t) + i * sizeof(CppType), &bufferValue,
+               sizeof(CppType));
 
         // The operation. All operations share the same activation scalar.
         // The output operand is created as an input in the next iteration of the loop, in the case
@@ -168,10 +229,10 @@
 
     // The model output.
     operands.back() = {
-            .type = OperandType::TENSOR_FLOAT32,
+            .type = operandType,
             .dimensions = {1},
             .numberOfConsumers = 0,
-            .scale = 0.0f,
+            .scale = scale1,
             .zeroPoint = 0,
             .lifetime = OperandLifeTime::MODEL_OUTPUT,
             .location = {},
@@ -191,22 +252,13 @@
     };
 }
 
-// MixedTypedExample is defined in frameworks/ml/nn/tools/test_generator/include/TestHarness.h.
-// This function assumes the operation is always ADD.
-std::vector<MixedTypedExample> getLargeModelExamples(uint32_t len) {
-    float outputValue = 1.0f + static_cast<float>(len);
-    return {{.operands = {
-                     // Input
-                     {.operandDimensions = {{0, {1}}}, .float32Operands = {{0, {1.0f}}}},
-                     // Output
-                     {.operandDimensions = {{0, {1}}}, .float32Operands = {{0, {outputValue}}}}}}};
-};
-
 }  // namespace
 
 // Tag for the compilation caching tests.
-class CompilationCachingTest : public NeuralnetworksHidlTest {
+class CompilationCachingTestBase : public NeuralnetworksHidlTest {
   protected:
+    CompilationCachingTestBase(OperandType type) : kOperandType(type) {}
+
     void SetUp() override {
         NeuralnetworksHidlTest::SetUp();
         ASSERT_NE(device.get(), nullptr);
@@ -263,6 +315,40 @@
         NeuralnetworksHidlTest::TearDown();
     }
 
+    // Model and examples creators. According to kOperandType, the following methods will return
+    // either float32 model/examples or the quant8 variant.
+    Model createTestModel() {
+        if (kOperandType == OperandType::TENSOR_FLOAT32) {
+            return float32_model::createTestModel();
+        } else {
+            return quant8_model::createTestModel();
+        }
+    }
+
+    std::vector<MixedTypedExample> get_examples() {
+        if (kOperandType == OperandType::TENSOR_FLOAT32) {
+            return float32_model::get_examples();
+        } else {
+            return quant8_model::get_examples();
+        }
+    }
+
+    Model createLargeTestModel(OperationType op, uint32_t len) {
+        if (kOperandType == OperandType::TENSOR_FLOAT32) {
+            return createLargeTestModelImpl<float, OperandType::TENSOR_FLOAT32>(op, len);
+        } else {
+            return createLargeTestModelImpl<uint8_t, OperandType::TENSOR_QUANT8_ASYMM>(op, len);
+        }
+    }
+
+    std::vector<MixedTypedExample> getLargeModelExamples(uint32_t len) {
+        if (kOperandType == OperandType::TENSOR_FLOAT32) {
+            return float32_model::getLargeModelExamples(len);
+        } else {
+            return quant8_model::getLargeModelExamples(len);
+        }
+    }
+
     // See if the service can handle the model.
     bool isModelFullySupported(const V1_2::Model& model) {
         bool fullySupportsModel = false;
@@ -366,9 +452,20 @@
     uint32_t mNumModelCache;
     uint32_t mNumDataCache;
     uint32_t mIsCachingSupported;
+
+    // The primary data type of the testModel.
+    const OperandType kOperandType;
 };
 
-TEST_F(CompilationCachingTest, CacheSavingAndRetrieval) {
+// A parameterized fixture of CompilationCachingTestBase. Every test will run twice, with the first
+// pass running with float32 models and the second pass running with quant8 models.
+class CompilationCachingTest : public CompilationCachingTestBase,
+                               public ::testing::WithParamInterface<OperandType> {
+  protected:
+    CompilationCachingTest() : CompilationCachingTestBase(GetParam()) {}
+};
+
+TEST_P(CompilationCachingTest, CacheSavingAndRetrieval) {
     // Create test HIDL model and compile.
     const Model testModel = createTestModel();
     if (checkEarlyTermination(testModel)) return;
@@ -409,7 +506,7 @@
                                            /*testDynamicOutputShape=*/false);
 }
 
-TEST_F(CompilationCachingTest, CacheSavingAndRetrievalNonZeroOffset) {
+TEST_P(CompilationCachingTest, CacheSavingAndRetrievalNonZeroOffset) {
     // Create test HIDL model and compile.
     const Model testModel = createTestModel();
     if (checkEarlyTermination(testModel)) return;
@@ -472,7 +569,7 @@
                                            /*testDynamicOutputShape=*/false);
 }
 
-TEST_F(CompilationCachingTest, SaveToCacheInvalidNumCache) {
+TEST_P(CompilationCachingTest, SaveToCacheInvalidNumCache) {
     // Create test HIDL model and compile.
     const Model testModel = createTestModel();
     if (checkEarlyTermination(testModel)) return;
@@ -584,7 +681,7 @@
     }
 }
 
-TEST_F(CompilationCachingTest, PrepareModelFromCacheInvalidNumCache) {
+TEST_P(CompilationCachingTest, PrepareModelFromCacheInvalidNumCache) {
     // Create test HIDL model and compile.
     const Model testModel = createTestModel();
     if (checkEarlyTermination(testModel)) return;
@@ -664,7 +761,7 @@
     }
 }
 
-TEST_F(CompilationCachingTest, SaveToCacheInvalidNumFd) {
+TEST_P(CompilationCachingTest, SaveToCacheInvalidNumFd) {
     // Create test HIDL model and compile.
     const Model testModel = createTestModel();
     if (checkEarlyTermination(testModel)) return;
@@ -776,7 +873,7 @@
     }
 }
 
-TEST_F(CompilationCachingTest, PrepareModelFromCacheInvalidNumFd) {
+TEST_P(CompilationCachingTest, PrepareModelFromCacheInvalidNumFd) {
     // Create test HIDL model and compile.
     const Model testModel = createTestModel();
     if (checkEarlyTermination(testModel)) return;
@@ -856,7 +953,7 @@
     }
 }
 
-TEST_F(CompilationCachingTest, SaveToCacheInvalidAccessMode) {
+TEST_P(CompilationCachingTest, SaveToCacheInvalidAccessMode) {
     // Create test HIDL model and compile.
     const Model testModel = createTestModel();
     if (checkEarlyTermination(testModel)) return;
@@ -914,7 +1011,7 @@
     }
 }
 
-TEST_F(CompilationCachingTest, PrepareModelFromCacheInvalidAccessMode) {
+TEST_P(CompilationCachingTest, PrepareModelFromCacheInvalidAccessMode) {
     // Create test HIDL model and compile.
     const Model testModel = createTestModel();
     if (checkEarlyTermination(testModel)) return;
@@ -990,7 +1087,7 @@
 constexpr uint32_t kLargeModelSize = 100;
 constexpr uint32_t kNumIterationsTOCTOU = 100;
 
-TEST_F(CompilationCachingTest, SaveToCache_TOCTOU) {
+TEST_P(CompilationCachingTest, SaveToCache_TOCTOU) {
     if (!mIsCachingSupported) return;
 
     // Create test models and check if fully supported by the service.
@@ -1053,7 +1150,7 @@
     }
 }
 
-TEST_F(CompilationCachingTest, PrepareFromCache_TOCTOU) {
+TEST_P(CompilationCachingTest, PrepareFromCache_TOCTOU) {
     if (!mIsCachingSupported) return;
 
     // Create test models and check if fully supported by the service.
@@ -1116,7 +1213,7 @@
     }
 }
 
-TEST_F(CompilationCachingTest, ReplaceSecuritySensitiveCache) {
+TEST_P(CompilationCachingTest, ReplaceSecuritySensitiveCache) {
     if (!mIsCachingSupported) return;
 
     // Create test models and check if fully supported by the service.
@@ -1164,11 +1261,19 @@
     }
 }
 
-class CompilationCachingSecurityTest : public CompilationCachingTest,
-                                       public ::testing::WithParamInterface<uint32_t> {
+static const auto kOperandTypeChoices =
+        ::testing::Values(OperandType::TENSOR_FLOAT32, OperandType::TENSOR_QUANT8_ASYMM);
+
+INSTANTIATE_TEST_CASE_P(TestCompilationCaching, CompilationCachingTest, kOperandTypeChoices);
+
+class CompilationCachingSecurityTest
+    : public CompilationCachingTestBase,
+      public ::testing::WithParamInterface<std::tuple<OperandType, uint32_t>> {
   protected:
+    CompilationCachingSecurityTest() : CompilationCachingTestBase(std::get<0>(GetParam())) {}
+
     void SetUp() {
-        CompilationCachingTest::SetUp();
+        CompilationCachingTestBase::SetUp();
         generator.seed(kSeed);
     }
 
@@ -1254,7 +1359,7 @@
         }
     }
 
-    const uint32_t kSeed = GetParam();
+    const uint32_t kSeed = std::get<1>(GetParam());
     std::mt19937 generator;
 };
 
@@ -1302,7 +1407,7 @@
 }
 
 INSTANTIATE_TEST_CASE_P(TestCompilationCaching, CompilationCachingSecurityTest,
-                        ::testing::Range(0U, 10U));
+                        ::testing::Combine(kOperandTypeChoices, ::testing::Range(0U, 10U)));
 
 }  // namespace functional
 }  // namespace vts
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 730d969..63d3187 100644
--- a/radio/1.2/vts/functional/radio_hidl_hal_api.cpp
+++ b/radio/1.2/vts/functional/radio_hidl_hal_api.cpp
@@ -19,19 +19,25 @@
 
 #define ASSERT_OK(ret) ASSERT_TRUE(ret.isOk())
 
+namespace {
+const RadioAccessSpecifier GERAN_SPECIFIER_P900 = {.radioAccessNetwork = RadioAccessNetworks::GERAN,
+                                                   .geranBands = {GeranBands::BAND_P900},
+                                                   .channels = {1, 2}};
+const RadioAccessSpecifier GERAN_SPECIFIER_850 = {.radioAccessNetwork = RadioAccessNetworks::GERAN,
+                                                  .geranBands = {GeranBands::BAND_850},
+                                                  .channels = {128, 129}};
+}  // namespace
+
 /*
  * Test IRadio.startNetworkScan() for the response returned.
  */
 TEST_F(RadioHidlTest_v1_2, startNetworkScan) {
     serial = GetRandomSerialNumber();
 
-    RadioAccessSpecifier specifier = {
-        .radioAccessNetwork = RadioAccessNetworks::GERAN,
-        .geranBands = {GeranBands::BAND_450, GeranBands::BAND_480},
-        .channels = {1,2}};
-
     ::android::hardware::radio::V1_2::NetworkScanRequest request = {
-        .type = ScanType::ONE_SHOT, .interval = 60, .specifiers = {specifier}};
+            .type = ScanType::ONE_SHOT,
+            .interval = 60,
+            .specifiers = {::GERAN_SPECIFIER_P900, ::GERAN_SPECIFIER_850}};
 
     Return<void> res = radio_v1_2->startNetworkScan_1_2(serial, request);
     ASSERT_OK(res);
@@ -89,18 +95,13 @@
 TEST_F(RadioHidlTest_v1_2, startNetworkScan_InvalidInterval1) {
     serial = GetRandomSerialNumber();
 
-    RadioAccessSpecifier specifier = {
-        .radioAccessNetwork = RadioAccessNetworks::GERAN,
-        .geranBands = {GeranBands::BAND_450, GeranBands::BAND_480},
-        .channels = {1,2}};
-
     ::android::hardware::radio::V1_2::NetworkScanRequest request = {
-        .type = ScanType::ONE_SHOT,
-        .interval = 4,
-        .specifiers = {specifier},
-        .maxSearchTime = 60,
-        .incrementalResults = false,
-        .incrementalResultsPeriodicity = 1};
+            .type = ScanType::ONE_SHOT,
+            .interval = 4,
+            .specifiers = {::GERAN_SPECIFIER_P900, ::GERAN_SPECIFIER_850},
+            .maxSearchTime = 60,
+            .incrementalResults = false,
+            .incrementalResultsPeriodicity = 1};
 
     Return<void> res = radio_v1_2->startNetworkScan_1_2(serial, request);
     ASSERT_OK(res);
@@ -126,18 +127,13 @@
 TEST_F(RadioHidlTest_v1_2, startNetworkScan_InvalidInterval2) {
     serial = GetRandomSerialNumber();
 
-    RadioAccessSpecifier specifier = {
-        .radioAccessNetwork = RadioAccessNetworks::GERAN,
-        .geranBands = {GeranBands::BAND_450, GeranBands::BAND_480},
-        .channels = {1,2}};
-
     ::android::hardware::radio::V1_2::NetworkScanRequest request = {
-        .type = ScanType::ONE_SHOT,
-        .interval = 301,
-        .specifiers = {specifier},
-        .maxSearchTime = 60,
-        .incrementalResults = false,
-        .incrementalResultsPeriodicity = 1};
+            .type = ScanType::ONE_SHOT,
+            .interval = 301,
+            .specifiers = {::GERAN_SPECIFIER_P900, ::GERAN_SPECIFIER_850},
+            .maxSearchTime = 60,
+            .incrementalResults = false,
+            .incrementalResultsPeriodicity = 1};
 
     Return<void> res = radio_v1_2->startNetworkScan_1_2(serial, request);
     ASSERT_OK(res);
@@ -163,18 +159,13 @@
 TEST_F(RadioHidlTest_v1_2, startNetworkScan_InvalidMaxSearchTime1) {
     serial = GetRandomSerialNumber();
 
-    RadioAccessSpecifier specifier = {
-        .radioAccessNetwork = RadioAccessNetworks::GERAN,
-        .geranBands = {GeranBands::BAND_450, GeranBands::BAND_480},
-        .channels = {1,2}};
-
     ::android::hardware::radio::V1_2::NetworkScanRequest request = {
-        .type = ScanType::ONE_SHOT,
-        .interval = 60,
-        .specifiers = {specifier},
-        .maxSearchTime = 59,
-        .incrementalResults = false,
-        .incrementalResultsPeriodicity = 1};
+            .type = ScanType::ONE_SHOT,
+            .interval = 60,
+            .specifiers = {::GERAN_SPECIFIER_P900, ::GERAN_SPECIFIER_850},
+            .maxSearchTime = 59,
+            .incrementalResults = false,
+            .incrementalResultsPeriodicity = 1};
 
     Return<void> res = radio_v1_2->startNetworkScan_1_2(serial, request);
     ASSERT_OK(res);
@@ -200,18 +191,13 @@
 TEST_F(RadioHidlTest_v1_2, startNetworkScan_InvalidMaxSearchTime2) {
     serial = GetRandomSerialNumber();
 
-    RadioAccessSpecifier specifier = {
-        .radioAccessNetwork = RadioAccessNetworks::GERAN,
-        .geranBands = {GeranBands::BAND_450, GeranBands::BAND_480},
-        .channels = {1,2}};
-
     ::android::hardware::radio::V1_2::NetworkScanRequest request = {
-        .type = ScanType::ONE_SHOT,
-        .interval = 60,
-        .specifiers = {specifier},
-        .maxSearchTime = 3601,
-        .incrementalResults = false,
-        .incrementalResultsPeriodicity = 1};
+            .type = ScanType::ONE_SHOT,
+            .interval = 60,
+            .specifiers = {::GERAN_SPECIFIER_P900, ::GERAN_SPECIFIER_850},
+            .maxSearchTime = 3601,
+            .incrementalResults = false,
+            .incrementalResultsPeriodicity = 1};
 
     Return<void> res = radio_v1_2->startNetworkScan_1_2(serial, request);
     ASSERT_OK(res);
@@ -237,18 +223,13 @@
 TEST_F(RadioHidlTest_v1_2, startNetworkScan_InvalidPeriodicity1) {
     serial = GetRandomSerialNumber();
 
-    RadioAccessSpecifier specifier = {
-        .radioAccessNetwork = RadioAccessNetworks::GERAN,
-        .geranBands = {GeranBands::BAND_450, GeranBands::BAND_480},
-        .channels = {1,2}};
-
     ::android::hardware::radio::V1_2::NetworkScanRequest request = {
-        .type = ScanType::ONE_SHOT,
-        .interval = 60,
-        .specifiers = {specifier},
-        .maxSearchTime = 600,
-        .incrementalResults = false,
-        .incrementalResultsPeriodicity = 0};
+            .type = ScanType::ONE_SHOT,
+            .interval = 60,
+            .specifiers = {::GERAN_SPECIFIER_P900, ::GERAN_SPECIFIER_850},
+            .maxSearchTime = 600,
+            .incrementalResults = true,
+            .incrementalResultsPeriodicity = 0};
 
     Return<void> res = radio_v1_2->startNetworkScan_1_2(serial, request);
     ASSERT_OK(res);
@@ -274,18 +255,13 @@
 TEST_F(RadioHidlTest_v1_2, startNetworkScan_InvalidPeriodicity2) {
     serial = GetRandomSerialNumber();
 
-    RadioAccessSpecifier specifier = {
-        .radioAccessNetwork = RadioAccessNetworks::GERAN,
-        .geranBands = {GeranBands::BAND_450, GeranBands::BAND_480},
-        .channels = {1,2}};
-
     ::android::hardware::radio::V1_2::NetworkScanRequest request = {
-        .type = ScanType::ONE_SHOT,
-        .interval = 60,
-        .specifiers = {specifier},
-        .maxSearchTime = 600,
-        .incrementalResults = false,
-        .incrementalResultsPeriodicity = 11};
+            .type = ScanType::ONE_SHOT,
+            .interval = 60,
+            .specifiers = {::GERAN_SPECIFIER_P900, ::GERAN_SPECIFIER_850},
+            .maxSearchTime = 600,
+            .incrementalResults = true,
+            .incrementalResultsPeriodicity = 11};
 
     Return<void> res = radio_v1_2->startNetworkScan_1_2(serial, request);
     ASSERT_OK(res);
@@ -311,20 +287,15 @@
 TEST_F(RadioHidlTest_v1_2, startNetworkScan_GoodRequest1) {
     serial = GetRandomSerialNumber();
 
-    RadioAccessSpecifier specifier = {
-        .radioAccessNetwork = RadioAccessNetworks::GERAN,
-        .geranBands = {GeranBands::BAND_450, GeranBands::BAND_480},
-        .channels = {1,2}};
-
     ::android::hardware::radio::V1_2::NetworkScanRequest request = {
-        .type = ScanType::ONE_SHOT,
-        .interval = 60,
-        .specifiers = {specifier},
-        // Some vendor may not support max search time of 360s.
-        // This issue is tracked in b/112205669.
-        .maxSearchTime = 300,
-        .incrementalResults = false,
-        .incrementalResultsPeriodicity = 10};
+            .type = ScanType::ONE_SHOT,
+            .interval = 60,
+            .specifiers = {::GERAN_SPECIFIER_P900, ::GERAN_SPECIFIER_850},
+            // Some vendor may not support max search time of 360s.
+            // This issue is tracked in b/112205669.
+            .maxSearchTime = 300,
+            .incrementalResults = false,
+            .incrementalResultsPeriodicity = 10};
 
     Return<void> res = radio_v1_2->startNetworkScan_1_2(serial, request);
     ASSERT_OK(res);
@@ -350,21 +321,16 @@
 TEST_F(RadioHidlTest_v1_2, startNetworkScan_GoodRequest2) {
     serial = GetRandomSerialNumber();
 
-    RadioAccessSpecifier specifier = {
-        .radioAccessNetwork = RadioAccessNetworks::GERAN,
-        .geranBands = {GeranBands::BAND_450, GeranBands::BAND_480},
-        .channels = {1,2}};
-
     ::android::hardware::radio::V1_2::NetworkScanRequest request = {
-        .type = ScanType::ONE_SHOT,
-        .interval = 60,
-        .specifiers = {specifier},
-        // Some vendor may not support max search time of 360s.
-        // This issue is tracked in b/112205669.
-        .maxSearchTime = 300,
-        .incrementalResults = false,
-        .incrementalResultsPeriodicity = 10,
-        .mccMncs = {"310410"}};
+            .type = ScanType::ONE_SHOT,
+            .interval = 60,
+            .specifiers = {::GERAN_SPECIFIER_P900, ::GERAN_SPECIFIER_850},
+            // Some vendor may not support max search time of 360s.
+            // This issue is tracked in b/112205669.
+            .maxSearchTime = 300,
+            .incrementalResults = false,
+            .incrementalResultsPeriodicity = 10,
+            .mccMncs = {"310410"}};
 
     Return<void> res = radio_v1_2->startNetworkScan_1_2(serial, request);
     ASSERT_OK(res);
@@ -757,6 +723,7 @@
     // Check the mcc [0, 999] and mnc [0, 999].
     string hidl_mcc;
     string hidl_mnc;
+    bool checkMccMnc = true;
     int totalIdentitySizeExpected = 1;
     ::android::hardware::radio::V1_2::CellIdentity cellIdentities =
         radioRsp_v1_2->dataRegResp.cellIdentity;
@@ -765,6 +732,7 @@
     if (cellInfoType == CellInfoType::NONE) {
         // All the fields are 0
         totalIdentitySizeExpected = 0;
+        checkMccMnc = false;
     } else if (cellInfoType == CellInfoType::GSM) {
         EXPECT_EQ(1, cellIdentities.cellIdentityGsm.size());
         ::android::hardware::radio::V1_2::CellIdentityGsm cig = cellIdentities.cellIdentityGsm[0];
@@ -791,6 +759,7 @@
         // CellIndentityCdma has no mcc and mnc.
         EXPECT_EQ(CellInfoType::CDMA, cellInfoType);
         EXPECT_EQ(1, cellIdentities.cellIdentityCdma.size());
+        checkMccMnc = false;
     }
 
     // Check only one CellIdentity is size 1, and others must be 0.
@@ -799,10 +768,13 @@
                   cellIdentities.cellIdentityLte.size() + cellIdentities.cellIdentityWcdma.size() +
                   cellIdentities.cellIdentityTdscdma.size());
 
-    int mcc = stoi(hidl_mcc);
-    int mnc = stoi(hidl_mnc);
-    EXPECT_TRUE(mcc >= 0 && mcc <= 999);
-    EXPECT_TRUE(mnc >= 0 && mnc <= 999);
+    // 32 bit system might return invalid mcc and mnc hidl string "\xff\xff..."
+    if (checkMccMnc && hidl_mcc.size() < 4 && hidl_mnc.size() < 4) {
+        int mcc = stoi(hidl_mcc);
+        int mnc = stoi(hidl_mnc);
+        EXPECT_TRUE(mcc >= 0 && mcc <= 999);
+        EXPECT_TRUE(mnc >= 0 && mnc <= 999);
+    }
 }
 
 /*
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 030f489..813dd13 100644
--- a/radio/1.3/vts/functional/radio_hidl_hal_api.cpp
+++ b/radio/1.3/vts/functional/radio_hidl_hal_api.cpp
@@ -33,9 +33,9 @@
     EXPECT_EQ(serial, radioRsp_v1_3->rspInfo.serial);
     ALOGI("getModemStackStatus, rspInfo.error = %s\n",
           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}));
+    ASSERT_TRUE(CheckAnyOfErrors(radioRsp_v1_3->rspInfo.error,
+                                 {RadioError::NONE, RadioError::RADIO_NOT_AVAILABLE,
+                                  RadioError::MODEM_ERR, RadioError::INVALID_STATE}));
 
     // checking if getModemStackStatus returns true, as modem was enabled above
     if (RadioError::NONE == radioRsp_v1_3->rspInfo.error) {
@@ -50,9 +50,9 @@
         EXPECT_EQ(serial, radioRsp_v1_3->rspInfo.serial);
         ALOGI("getModemStackStatus, rspInfo.error = %s\n",
               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}));
+        ASSERT_TRUE(CheckAnyOfErrors(radioRsp_v1_3->rspInfo.error,
+                                     {RadioError::NONE, RadioError::RADIO_NOT_AVAILABLE,
+                                      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
+}