Merge "Correct TripleDes tests." into pi-dev
diff --git a/audio/core/all-versions/default/include/core/all-versions/default/Conversions.h b/audio/core/all-versions/default/include/core/all-versions/default/Conversions.h
index fa05350..b38eca3 100644
--- a/audio/core/all-versions/default/include/core/all-versions/default/Conversions.h
+++ b/audio/core/all-versions/default/include/core/all-versions/default/Conversions.h
@@ -30,6 +30,11 @@
 
 std::string deviceAddressToHal(const DeviceAddress& address);
 
+#ifdef AUDIO_HAL_VERSION_4_0
+bool halToMicrophoneCharacteristics(MicrophoneInfo* pDst,
+                                    const struct audio_microphone_characteristic_t& src);
+#endif
+
 }  // namespace implementation
 }  // namespace AUDIO_HAL_VERSION
 }  // namespace audio
diff --git a/audio/core/all-versions/default/include/core/all-versions/default/Conversions.impl.h b/audio/core/all-versions/default/include/core/all-versions/default/Conversions.impl.h
index 3f3f936..004a99e 100644
--- a/audio/core/all-versions/default/include/core/all-versions/default/Conversions.impl.h
+++ b/audio/core/all-versions/default/include/core/all-versions/default/Conversions.impl.h
@@ -24,6 +24,8 @@
 namespace AUDIO_HAL_VERSION {
 namespace implementation {
 
+using ::android::hardware::audio::common::AUDIO_HAL_VERSION::AudioDevice;
+
 std::string deviceAddressToHal(const DeviceAddress& address) {
     // HAL assumes that the address is NUL-terminated.
     char halAddress[AUDIO_DEVICE_MAX_ADDRESS_LEN];
@@ -54,6 +56,132 @@
     return halAddress;
 }
 
+#ifdef AUDIO_HAL_VERSION_4_0
+status_t deviceAddressFromHal(audio_devices_t device, const char* halAddress,
+                              DeviceAddress* address) {
+    if (address == nullptr) {
+        return BAD_VALUE;
+    }
+    address->device = AudioDevice(device);
+    if (halAddress == nullptr || strnlen(halAddress, AUDIO_DEVICE_MAX_ADDRESS_LEN) == 0) {
+        return OK;
+    }
+
+    const bool isInput = (device & AUDIO_DEVICE_BIT_IN) != 0;
+    if (isInput) device &= ~AUDIO_DEVICE_BIT_IN;
+    if ((!isInput && (device & AUDIO_DEVICE_OUT_ALL_A2DP) != 0) ||
+        (isInput && (device & AUDIO_DEVICE_IN_BLUETOOTH_A2DP) != 0)) {
+        int status =
+            sscanf(halAddress, "%hhX:%hhX:%hhX:%hhX:%hhX:%hhX", &address->address.mac[0],
+                   &address->address.mac[1], &address->address.mac[2], &address->address.mac[3],
+                   &address->address.mac[4], &address->address.mac[5]);
+        return status == 6 ? OK : BAD_VALUE;
+    } else if ((!isInput && (device & AUDIO_DEVICE_OUT_IP) != 0) ||
+               (isInput && (device & AUDIO_DEVICE_IN_IP) != 0)) {
+        int status =
+            sscanf(halAddress, "%hhu.%hhu.%hhu.%hhu", &address->address.ipv4[0],
+                   &address->address.ipv4[1], &address->address.ipv4[2], &address->address.ipv4[3]);
+        return status == 4 ? OK : BAD_VALUE;
+    } else if ((!isInput && (device & AUDIO_DEVICE_OUT_ALL_USB)) != 0 ||
+               (isInput && (device & AUDIO_DEVICE_IN_ALL_USB)) != 0) {
+        int status = sscanf(halAddress, "card=%d;device=%d", &address->address.alsa.card,
+                            &address->address.alsa.device);
+        return status == 2 ? OK : BAD_VALUE;
+    } else if ((!isInput && (device & AUDIO_DEVICE_OUT_BUS) != 0) ||
+               (isInput && (device & AUDIO_DEVICE_IN_BUS) != 0)) {
+        address->busAddress = halAddress;
+        return OK;
+    } else if ((!isInput && (device & AUDIO_DEVICE_OUT_REMOTE_SUBMIX)) != 0 ||
+               (isInput && (device & AUDIO_DEVICE_IN_REMOTE_SUBMIX) != 0)) {
+        address->rSubmixAddress = halAddress;
+        return OK;
+    }
+    address->busAddress = halAddress;
+    return OK;
+}
+
+AudioMicrophoneChannelMapping halToChannelMapping(audio_microphone_channel_mapping_t mapping) {
+    switch (mapping) {
+        case AUDIO_MICROPHONE_CHANNEL_MAPPING_UNUSED:
+            return AudioMicrophoneChannelMapping::UNUSED;
+        case AUDIO_MICROPHONE_CHANNEL_MAPPING_DIRECT:
+            return AudioMicrophoneChannelMapping::DIRECT;
+        case AUDIO_MICROPHONE_CHANNEL_MAPPING_PROCESSED:
+            return AudioMicrophoneChannelMapping::PROCESSED;
+    }
+}
+
+AudioMicrophoneLocation halToLocation(audio_microphone_location_t location) {
+    switch (location) {
+        default:
+        case AUDIO_MICROPHONE_LOCATION_UNKNOWN:
+            return AudioMicrophoneLocation::UNKNOWN;
+        case AUDIO_MICROPHONE_LOCATION_MAINBODY:
+            return AudioMicrophoneLocation::MAINBODY;
+        case AUDIO_MICROPHONE_LOCATION_MAINBODY_MOVABLE:
+            return AudioMicrophoneLocation::MAINBODY_MOVABLE;
+        case AUDIO_MICROPHONE_LOCATION_PERIPHERAL:
+            return AudioMicrophoneLocation::PERIPHERAL;
+    }
+}
+
+AudioMicrophoneDirectionality halToDirectionality(audio_microphone_directionality_t dir) {
+    switch (dir) {
+        default:
+        case AUDIO_MICROPHONE_DIRECTIONALITY_UNKNOWN:
+            return AudioMicrophoneDirectionality::UNKNOWN;
+        case AUDIO_MICROPHONE_DIRECTIONALITY_OMNI:
+            return AudioMicrophoneDirectionality::OMNI;
+        case AUDIO_MICROPHONE_DIRECTIONALITY_BI_DIRECTIONAL:
+            return AudioMicrophoneDirectionality::BI_DIRECTIONAL;
+        case AUDIO_MICROPHONE_DIRECTIONALITY_CARDIOID:
+            return AudioMicrophoneDirectionality::CARDIOID;
+        case AUDIO_MICROPHONE_DIRECTIONALITY_HYPER_CARDIOID:
+            return AudioMicrophoneDirectionality::HYPER_CARDIOID;
+        case AUDIO_MICROPHONE_DIRECTIONALITY_SUPER_CARDIOID:
+            return AudioMicrophoneDirectionality::SUPER_CARDIOID;
+    }
+}
+
+bool halToMicrophoneCharacteristics(MicrophoneInfo* pDst,
+                                    const struct audio_microphone_characteristic_t& src) {
+    bool status = false;
+    if (pDst != NULL) {
+        pDst->deviceId = src.device_id;
+
+        if (deviceAddressFromHal(src.device, src.address, &pDst->deviceAddress) != OK) {
+            return false;
+        }
+        pDst->channelMapping.resize(AUDIO_CHANNEL_COUNT_MAX);
+        for (size_t ch = 0; ch < pDst->channelMapping.size(); ch++) {
+            pDst->channelMapping[ch] = halToChannelMapping(src.channel_mapping[ch]);
+        }
+        pDst->location = halToLocation(src.location);
+        pDst->group = (AudioMicrophoneGroup)src.group;
+        pDst->indexInTheGroup = (uint32_t)src.index_in_the_group;
+        pDst->sensitivity = src.sensitivity;
+        pDst->maxSpl = src.max_spl;
+        pDst->minSpl = src.min_spl;
+        pDst->directionality = halToDirectionality(src.directionality);
+        pDst->frequencyResponse.resize(src.num_frequency_responses);
+        for (size_t k = 0; k < src.num_frequency_responses; k++) {
+            pDst->frequencyResponse[k].frequency = src.frequency_responses[0][k];
+            pDst->frequencyResponse[k].level = src.frequency_responses[1][k];
+        }
+        pDst->position.x = src.geometric_location.x;
+        pDst->position.y = src.geometric_location.y;
+        pDst->position.z = src.geometric_location.z;
+
+        pDst->orientation.x = src.orientation.x;
+        pDst->orientation.y = src.orientation.y;
+        pDst->orientation.z = src.orientation.z;
+
+        status = true;
+    }
+    return status;
+}
+#endif
+
 }  // namespace implementation
 }  // namespace AUDIO_HAL_VERSION
 }  // namespace audio
diff --git a/audio/core/all-versions/default/include/core/all-versions/default/Device.impl.h b/audio/core/all-versions/default/include/core/all-versions/default/Device.impl.h
index fb4b686..581e1dc 100644
--- a/audio/core/all-versions/default/include/core/all-versions/default/Device.impl.h
+++ b/audio/core/all-versions/default/include/core/all-versions/default/Device.impl.h
@@ -332,8 +332,20 @@
 
 #ifdef AUDIO_HAL_VERSION_4_0
 Return<void> Device::getMicrophones(getMicrophones_cb _hidl_cb) {
-    // TODO return device microphones
-    _hidl_cb(Result::NOT_SUPPORTED, {});
+    Result retval = Result::NOT_SUPPORTED;
+    size_t actual_mics = AUDIO_MICROPHONE_MAX_COUNT;
+    audio_microphone_characteristic_t mic_array[AUDIO_MICROPHONE_MAX_COUNT];
+
+    hidl_vec<MicrophoneInfo> microphones;
+    if (mDevice->get_microphones != NULL &&
+        mDevice->get_microphones(mDevice, &mic_array[0], &actual_mics) == 0) {
+        microphones.resize(actual_mics);
+        for (size_t i = 0; i < actual_mics; ++i) {
+            halToMicrophoneCharacteristics(&microphones[i], mic_array[i]);
+        }
+        retval = Result::OK;
+    }
+    _hidl_cb(retval, microphones);
     return Void();
 }
 
diff --git a/audio/core/all-versions/default/include/core/all-versions/default/StreamIn.impl.h b/audio/core/all-versions/default/include/core/all-versions/default/StreamIn.impl.h
index dcd3df1..8774be9 100644
--- a/audio/core/all-versions/default/include/core/all-versions/default/StreamIn.impl.h
+++ b/audio/core/all-versions/default/include/core/all-versions/default/StreamIn.impl.h
@@ -26,6 +26,8 @@
 
 using ::android::hardware::audio::AUDIO_HAL_VERSION::MessageQueueFlagBits;
 using ::android::hardware::audio::all_versions::implementation::isGainNormalized;
+#include "Conversions.h"
+#include "Util.h"
 
 namespace android {
 namespace hardware {
@@ -449,12 +451,39 @@
 }
 
 #ifdef AUDIO_HAL_VERSION_4_0
-Return<void> StreamIn::updateSinkMetadata(const SinkMetadata& /*sinkMetadata*/) {
-    return Void();  // TODO: propagate to legacy
+Return<void> StreamIn::updateSinkMetadata(const SinkMetadata& sinkMetadata) {
+    if (mStream->update_sink_metadata == nullptr) {
+        return Void();  // not supported by the HAL
+    }
+    std::vector<record_track_metadata> halTracks;
+    halTracks.reserve(sinkMetadata.tracks.size());
+    for (auto& metadata : sinkMetadata.tracks) {
+        halTracks.push_back(
+            {.source = static_cast<audio_source_t>(metadata.source), .gain = metadata.gain});
+    }
+    const sink_metadata_t halMetadata = {
+        .track_count = halTracks.size(), .tracks = halTracks.data(),
+    };
+    mStream->update_sink_metadata(mStream, &halMetadata);
+    return Void();
 }
 
 Return<void> StreamIn::getActiveMicrophones(getActiveMicrophones_cb _hidl_cb) {
-    _hidl_cb(Result::NOT_SUPPORTED, {});  // TODO: retrieve from legacy
+    Result retval = Result::NOT_SUPPORTED;
+    size_t actual_mics = AUDIO_MICROPHONE_MAX_COUNT;
+    audio_microphone_characteristic_t mic_array[AUDIO_MICROPHONE_MAX_COUNT];
+
+    hidl_vec<MicrophoneInfo> microphones;
+    if (mStream->get_active_microphones != NULL &&
+        mStream->get_active_microphones(mStream, &mic_array[0], &actual_mics) == 0) {
+        microphones.resize(actual_mics);
+        for (size_t i = 0; i < actual_mics; ++i) {
+            halToMicrophoneCharacteristics(&microphones[i], mic_array[i]);
+        }
+        retval = Result::OK;
+    }
+
+    _hidl_cb(retval, microphones);
     return Void();
 }
 #endif
diff --git a/audio/core/all-versions/default/include/core/all-versions/default/StreamOut.impl.h b/audio/core/all-versions/default/include/core/all-versions/default/StreamOut.impl.h
index 605b824..77098a8 100644
--- a/audio/core/all-versions/default/include/core/all-versions/default/StreamOut.impl.h
+++ b/audio/core/all-versions/default/include/core/all-versions/default/StreamOut.impl.h
@@ -547,8 +547,24 @@
 }
 
 #ifdef AUDIO_HAL_VERSION_4_0
-Return<void> StreamOut::updateSourceMetadata(const SourceMetadata& /*sourceMetadata*/) {
-    return Void();  // TODO: propagate to legacy
+Return<void> StreamOut::updateSourceMetadata(const SourceMetadata& sourceMetadata) {
+    if (mStream->update_source_metadata == nullptr) {
+        return Void();  // not supported by the HAL
+    }
+    std::vector<playback_track_metadata> halTracks;
+    halTracks.reserve(sourceMetadata.tracks.size());
+    for (auto& metadata : sourceMetadata.tracks) {
+        halTracks.push_back({
+            .usage = static_cast<audio_usage_t>(metadata.usage),
+            .content_type = static_cast<audio_content_type_t>(metadata.contentType),
+            .gain = metadata.gain,
+        });
+    }
+    const source_metadata_t halMetadata = {
+        .track_count = halTracks.size(), .tracks = halTracks.data(),
+    };
+    mStream->update_source_metadata(mStream, &halMetadata);
+    return Void();
 }
 Return<Result> StreamOut::selectPresentation(int32_t /*presentationId*/, int32_t /*programId*/) {
     return Result::NOT_SUPPORTED;  // TODO: propagate to legacy
diff --git a/audio/effect/4.0/xml/audio_effects_conf_V4_0.xsd b/audio/effect/4.0/xml/audio_effects_conf_V4_0.xsd
new file mode 120000
index 0000000..82d569a
--- /dev/null
+++ b/audio/effect/4.0/xml/audio_effects_conf_V4_0.xsd
@@ -0,0 +1 @@
+../../2.0/xml/audio_effects_conf_V2_0.xsd
\ No newline at end of file
diff --git a/automotive/vehicle/2.0/Android.bp b/automotive/vehicle/2.0/Android.bp
index 902a4e8..4b93008 100644
--- a/automotive/vehicle/2.0/Android.bp
+++ b/automotive/vehicle/2.0/Android.bp
@@ -26,14 +26,15 @@
         "Obd2IgnitionMonitorKind",
         "Obd2SecondaryAirStatus",
         "Obd2SparkIgnitionMonitors",
+        "PortLocationType",
         "StatusCode",
         "SubscribeFlags",
         "SubscribeOptions",
         "VehicleApPowerBootupReason",
-        "VehicleApPowerSetState",
-        "VehicleApPowerState",
         "VehicleApPowerStateConfigFlag",
-        "VehicleApPowerStateIndex",
+        "VehicleApPowerStateReq",
+        "VehicleApPowerStateReqIndex",
+        "VehicleApPowerStateReport",
         "VehicleApPowerStateShutdownParam",
         "VehicleArea",
         "VehicleAreaConfig",
@@ -41,13 +42,13 @@
         "VehicleAreaMirror",
         "VehicleAreaSeat",
         "VehicleAreaWindow",
-        "VehicleAreaZone",
         "VehicleDisplay",
-        "VehicleDrivingStatus",
         "VehicleGear",
         "VehicleHvacFanDirection",
         "VehicleHwKeyInputAction",
         "VehicleIgnitionState",
+        "VehicleLightState",
+        "VehicleLightSwitch",
         "VehicleOilLevel",
         "VehiclePropConfig",
         "VehiclePropValue",
@@ -55,10 +56,8 @@
         "VehiclePropertyAccess",
         "VehiclePropertyChangeMode",
         "VehiclePropertyGroup",
-        "VehiclePropertyOperation",
         "VehiclePropertyStatus",
         "VehiclePropertyType",
-        "VehicleRadioConstants",
         "VehicleTurnSignal",
         "VehicleUnit",
         "VmsAvailabilityStateIntegerValuesIndex",
diff --git a/automotive/vehicle/2.0/IVehicleCallback.hal b/automotive/vehicle/2.0/IVehicleCallback.hal
index 7060418..c4a756a 100644
--- a/automotive/vehicle/2.0/IVehicleCallback.hal
+++ b/automotive/vehicle/2.0/IVehicleCallback.hal
@@ -33,7 +33,7 @@
 
     /**
      * This method gets called if the client was subscribed to a property using
-     * SubscribeFlags::SET_CALL flag and IVehicle#set(...) method was called.
+     * SubscribeFlags::EVENTS_FROM_ANDROID flag and IVehicle#set(...) method was called.
      *
      * These events must be delivered to subscriber immediately without any
      * batching.
diff --git a/automotive/vehicle/2.0/default/common/include/vhal_v2_0/VehicleObjectPool.h b/automotive/vehicle/2.0/default/common/include/vhal_v2_0/VehicleObjectPool.h
index 359bb6d..946e74d 100644
--- a/automotive/vehicle/2.0/default/common/include/vhal_v2_0/VehicleObjectPool.h
+++ b/automotive/vehicle/2.0/default/common/include/vhal_v2_0/VehicleObjectPool.h
@@ -152,7 +152,7 @@
  *   VehiclePropValuePool pool;
  *   auto v = pool.obtain(VehiclePropertyType::INT32);
  *   v->propId = VehicleProperty::HVAC_FAN_SPEED;
- *   v->areaId = VehicleAreaZone::ROW_1_LEFT;
+ *   v->areaId = VehicleAreaSeat::ROW_1_LEFT;
  *   v->timestamp = elapsedRealtimeNano();
  *   v->value->int32Values[0] = 42;
  *
diff --git a/automotive/vehicle/2.0/default/common/include/vhal_v2_0/VehiclePropertyStore.h b/automotive/vehicle/2.0/default/common/include/vhal_v2_0/VehiclePropertyStore.h
index eda94b7..0a243fe 100644
--- a/automotive/vehicle/2.0/default/common/include/vhal_v2_0/VehiclePropertyStore.h
+++ b/automotive/vehicle/2.0/default/common/include/vhal_v2_0/VehiclePropertyStore.h
@@ -67,7 +67,7 @@
 
     /* Stores provided value. Returns true if value was written returns false if config for
      * example wasn't registered. */
-    bool writeValue(const VehiclePropValue& propValue);
+    bool writeValue(const VehiclePropValue& propValue, bool updateStatus);
 
     void removeValue(const VehiclePropValue& propValue);
     void removeValuesForProperty(int32_t propId);
diff --git a/automotive/vehicle/2.0/default/common/src/SubscriptionManager.cpp b/automotive/vehicle/2.0/default/common/src/SubscriptionManager.cpp
index a7d5f50..97aeca6 100644
--- a/automotive/vehicle/2.0/default/common/src/SubscriptionManager.cpp
+++ b/automotive/vehicle/2.0/default/common/src/SubscriptionManager.cpp
@@ -106,7 +106,7 @@
 
         addClientToPropMapLocked(opts.propId, client);
 
-        if (SubscribeFlags::HAL_EVENT & opts.flags) {
+        if (SubscribeFlags::EVENTS_FROM_CAR & opts.flags) {
             SubscribeOptions updated;
             if (updateHalEventSubscriptionLocked(opts, &updated)) {
                 outUpdatedSubscriptions->push_back(updated);
diff --git a/automotive/vehicle/2.0/default/common/src/VehicleHalManager.cpp b/automotive/vehicle/2.0/default/common/src/VehicleHalManager.cpp
index 1918421..b5de262 100644
--- a/automotive/vehicle/2.0/default/common/src/VehicleHalManager.cpp
+++ b/automotive/vehicle/2.0/default/common/src/VehicleHalManager.cpp
@@ -216,7 +216,7 @@
                                               int32_t property,
                                               int32_t areaId) {
     const auto& clients =
-        mSubscriptionManager.getSubscribedClients(property, SubscribeFlags::HAL_EVENT);
+        mSubscriptionManager.getSubscribedClients(property, SubscribeFlags::EVENTS_FROM_CAR);
 
     for (auto client : clients) {
         client->getCallback()->onPropertySetError(errorCode, property, areaId);
@@ -224,8 +224,8 @@
 }
 
 void VehicleHalManager::onBatchHalEvent(const std::vector<VehiclePropValuePtr>& values) {
-    const auto& clientValues = mSubscriptionManager.distributeValuesToClients(
-            values, SubscribeFlags::HAL_EVENT);
+    const auto& clientValues =
+        mSubscriptionManager.distributeValuesToClients(values, SubscribeFlags::EVENTS_FROM_CAR);
 
     for (const HalClientValues& cv : clientValues) {
         auto vecSize = cv.values.size();
@@ -250,8 +250,7 @@
 }
 
 bool VehicleHalManager::isSampleRateFixed(VehiclePropertyChangeMode mode) {
-    return (mode & VehiclePropertyChangeMode::ON_SET)
-           || (mode & VehiclePropertyChangeMode::ON_CHANGE);
+    return (mode & VehiclePropertyChangeMode::ON_CHANGE);
 }
 
 float VehicleHalManager::checkSampleRate(const VehiclePropConfig &config,
@@ -281,7 +280,7 @@
                                        SubscribeFlags flags) {
     bool isReadable = config.access & VehiclePropertyAccess::READ;
 
-    if (!isReadable && (SubscribeFlags::HAL_EVENT & flags)) {
+    if (!isReadable && (SubscribeFlags::EVENTS_FROM_CAR & flags)) {
         ALOGW("Cannot subscribe, property 0x%x is not readable", config.prop);
         return false;
     }
@@ -289,12 +288,6 @@
         ALOGW("Cannot subscribe, property 0x%x is static", config.prop);
         return false;
     }
-
-    //TODO: extend to support event notification for set from android
-    if (config.changeMode == VehiclePropertyChangeMode::POLL) {
-        ALOGW("Cannot subscribe, property 0x%x is poll only", config.prop);
-        return false;
-    }
     return true;
 }
 
@@ -317,7 +310,8 @@
 }
 
 void VehicleHalManager::handlePropertySetEvent(const VehiclePropValue& value) {
-    auto clients = mSubscriptionManager.getSubscribedClients(value.prop, SubscribeFlags::SET_CALL);
+    auto clients =
+        mSubscriptionManager.getSubscribedClients(value.prop, SubscribeFlags::EVENTS_FROM_ANDROID);
     for (auto client : clients) {
         client->getCallback()->onPropertySet(value);
     }
diff --git a/automotive/vehicle/2.0/default/common/src/VehiclePropertyStore.cpp b/automotive/vehicle/2.0/default/common/src/VehiclePropertyStore.cpp
index f2aa421..94ace45 100644
--- a/automotive/vehicle/2.0/default/common/src/VehiclePropertyStore.cpp
+++ b/automotive/vehicle/2.0/default/common/src/VehiclePropertyStore.cpp
@@ -41,7 +41,8 @@
     mConfigs.insert({ config.prop, RecordConfig { config, tokenFunc } });
 }
 
-bool VehiclePropertyStore::writeValue(const VehiclePropValue& propValue) {
+bool VehiclePropertyStore::writeValue(const VehiclePropValue& propValue,
+                                        bool updateStatus) {
     MuxGuard g(mLock);
     if (!mConfigs.count(propValue.prop)) return false;
 
@@ -52,7 +53,9 @@
     } else {
         valueToUpdate->timestamp = propValue.timestamp;
         valueToUpdate->value = propValue.value;
-        valueToUpdate->status = propValue.status;
+        if (updateStatus) {
+            valueToUpdate->status = propValue.status;
+        }
     }
     return true;
 }
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 e54de00..56813ce 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
@@ -30,7 +30,8 @@
 //
 // Some handy constants to avoid conversions from enum to int.
 constexpr int ABS_ACTIVE = (int)VehicleProperty::ABS_ACTIVE;
-constexpr int AP_POWER_STATE = (int)VehicleProperty::AP_POWER_STATE;
+constexpr int AP_POWER_STATE_REQ = (int)VehicleProperty::AP_POWER_STATE_REQ;
+constexpr int AP_POWER_STATE_REPORT = (int)VehicleProperty::AP_POWER_STATE_REPORT;
 constexpr int OBD2_LIVE_FRAME = (int)VehicleProperty::OBD2_LIVE_FRAME;
 constexpr int OBD2_FREEZE_FRAME = (int)VehicleProperty::OBD2_FREEZE_FRAME;
 constexpr int OBD2_FREEZE_FRAME_INFO = (int)VehicleProperty::OBD2_FREEZE_FRAME_INFO;
@@ -46,18 +47,35 @@
  *
  * It has the following format:
  *
- * int32Values[0] - command (1 - start fake data generation, 0 - stop)
+ * int32Values[0] - command (see FakeDataCommand below for possible values)
  * int32Values[1] - VehicleProperty to which command applies
- *
- * For start command, additional data should be provided:
- *   int64Values[0] - periodic interval in nanoseconds
- *   floatValues[0] - initial value
- *   floatValues[1] - dispersion defines min and max range relative to initial value
- *   floatValues[2] - increment, with every timer tick the value will be incremented by this amount
  */
 const int32_t kGenerateFakeDataControllingProperty =
     0x0666 | VehiclePropertyGroup::VENDOR | VehicleArea::GLOBAL | VehiclePropertyType::MIXED;
 
+enum class FakeDataCommand : int32_t {
+    /** Stops generating of fake data that was triggered by Start command */
+    Stop = 0,
+
+    /**
+     * Starts fake data generation.  Caller must provide additional data:
+     *     int64Values[0] - periodic interval in nanoseconds
+     *     floatValues[0] - initial value
+     *     floatValues[1] - dispersion defines min and max range relative to initial value
+     *     floatValues[2] - increment, with every timer tick the value will be incremented by this
+     * amount
+     */
+    Start = 1,
+
+    /**
+     * Injects key press event (HAL incorporates UP/DOWN acction and triggers 2 HAL events for every
+     * key-press). Caller must provide the following data: int32Values[2] - Android key code
+     *     int32Values[3] - target display (0 - for main display, 1 - for instrument cluster, see
+     * VehicleDisplay)
+     */
+    KeyPress = 2,
+};
+
 const int32_t kHvacPowerProperties[] = {
     toInt(VehicleProperty::HVAC_FAN_SPEED),
     toInt(VehicleProperty::HVAC_FAN_DIRECTION),
@@ -132,14 +150,6 @@
          },
      .initialValue = {.floatValues = {0.0f}}},
 
-    {.config =
-         {
-             .prop = toInt(VehicleProperty::ENGINE_ON),
-             .access = VehiclePropertyAccess::READ,
-             .changeMode = VehiclePropertyChangeMode::ON_CHANGE,
-         },
-     .initialValue = {.int32Values = {0}}},
-
     {
         .config =
             {
@@ -238,7 +248,7 @@
              .access = VehiclePropertyAccess::READ_WRITE,
              .changeMode = VehiclePropertyChangeMode::ON_CHANGE,
              .areaConfigs = {VehicleAreaConfig{
-                 .areaId = (VehicleAreaZone::ROW_1_LEFT | VehicleAreaZone::ROW_1_RIGHT)}},
+                 .areaId = (VehicleAreaSeat::ROW_1_LEFT | VehicleAreaSeat::ROW_1_RIGHT)}},
              // TODO(bryaneyler): Ideally, this is generated dynamically from
              // kHvacPowerProperties.
              .configString = "0x12400500,0x12400501"  // HVAC_FAN_SPEED,HVAC_FAN_DIRECTION
@@ -259,28 +269,28 @@
                 .access = VehiclePropertyAccess::READ_WRITE,
                 .changeMode = VehiclePropertyChangeMode::ON_CHANGE,
                 .areaConfigs = {VehicleAreaConfig{
-                    .areaId = (VehicleAreaZone::ROW_1_LEFT | VehicleAreaZone::ROW_1_RIGHT)}}},
+                    .areaId = (VehicleAreaSeat::ROW_1_LEFT | VehicleAreaSeat::ROW_1_RIGHT)}}},
      .initialValue = {.int32Values = {1}}},
 
     {.config = {.prop = toInt(VehicleProperty::HVAC_AC_ON),
                 .access = VehiclePropertyAccess::READ_WRITE,
                 .changeMode = VehiclePropertyChangeMode::ON_CHANGE,
                 .areaConfigs = {VehicleAreaConfig{
-                    .areaId = (VehicleAreaZone::ROW_1_LEFT | VehicleAreaZone::ROW_1_RIGHT)}}},
+                    .areaId = (VehicleAreaSeat::ROW_1_LEFT | VehicleAreaSeat::ROW_1_RIGHT)}}},
      .initialValue = {.int32Values = {1}}},
 
     {.config = {.prop = toInt(VehicleProperty::HVAC_AUTO_ON),
                 .access = VehiclePropertyAccess::READ_WRITE,
                 .changeMode = VehiclePropertyChangeMode::ON_CHANGE,
                 .areaConfigs = {VehicleAreaConfig{
-                    .areaId = (VehicleAreaZone::ROW_1_LEFT | VehicleAreaZone::ROW_1_RIGHT)}}},
+                    .areaId = (VehicleAreaSeat::ROW_1_LEFT | VehicleAreaSeat::ROW_1_RIGHT)}}},
      .initialValue = {.int32Values = {1}}},
 
     {.config = {.prop = toInt(VehicleProperty::HVAC_FAN_SPEED),
                 .access = VehiclePropertyAccess::READ_WRITE,
                 .changeMode = VehiclePropertyChangeMode::ON_CHANGE,
                 .areaConfigs = {VehicleAreaConfig{
-                    .areaId = (VehicleAreaZone::ROW_1_LEFT | VehicleAreaZone::ROW_1_RIGHT),
+                    .areaId = (VehicleAreaSeat::ROW_1_LEFT | VehicleAreaSeat::ROW_1_RIGHT),
                     .minInt32Value = 1,
                     .maxInt32Value = 7}}},
      .initialValue = {.int32Values = {3}}},
@@ -289,24 +299,24 @@
                 .access = VehiclePropertyAccess::READ_WRITE,
                 .changeMode = VehiclePropertyChangeMode::ON_CHANGE,
                 .areaConfigs = {VehicleAreaConfig{
-                    .areaId = (VehicleAreaZone::ROW_1_LEFT | VehicleAreaZone::ROW_1_RIGHT)}}},
+                    .areaId = (VehicleAreaSeat::ROW_1_LEFT | VehicleAreaSeat::ROW_1_RIGHT)}}},
      .initialValue = {.int32Values = {toInt(VehicleHvacFanDirection::FACE)}}},
 
     {.config = {.prop = toInt(VehicleProperty::HVAC_TEMPERATURE_SET),
                 .access = VehiclePropertyAccess::READ_WRITE,
                 .changeMode = VehiclePropertyChangeMode::ON_CHANGE,
                 .areaConfigs = {VehicleAreaConfig{
-                                    .areaId = toInt(VehicleAreaZone::ROW_1_LEFT),
+                                    .areaId = toInt(VehicleAreaSeat::ROW_1_LEFT),
                                     .minFloatValue = 16,
                                     .maxFloatValue = 32,
                                 },
                                 VehicleAreaConfig{
-                                    .areaId = toInt(VehicleAreaZone::ROW_1_RIGHT),
+                                    .areaId = toInt(VehicleAreaSeat::ROW_1_RIGHT),
                                     .minFloatValue = 16,
                                     .maxFloatValue = 32,
                                 }}},
-     .initialAreaValues = {{toInt(VehicleAreaZone::ROW_1_LEFT), {.floatValues = {16}}},
-                           {toInt(VehicleAreaZone::ROW_1_RIGHT), {.floatValues = {20}}}}},
+     .initialAreaValues = {{toInt(VehicleAreaSeat::ROW_1_LEFT), {.floatValues = {16}}},
+                           {toInt(VehicleAreaSeat::ROW_1_RIGHT), {.floatValues = {20}}}}},
 
     {.config =
          {
@@ -329,14 +339,6 @@
 
     {.config =
          {
-             .prop = toInt(VehicleProperty::DRIVING_STATUS),
-             .access = VehiclePropertyAccess::READ,
-             .changeMode = VehiclePropertyChangeMode::ON_CHANGE,
-         },
-     .initialValue = {.int32Values = {toInt(VehicleDrivingStatus::UNRESTRICTED)}}},
-
-    {.config =
-         {
              .prop = toInt(VehicleProperty::GEAR_SELECTION),
              .access = VehiclePropertyAccess::READ,
              .changeMode = VehiclePropertyChangeMode::ON_CHANGE,
@@ -415,11 +417,17 @@
             },
     },
 
-    {.config = {.prop = toInt(VehicleProperty::AP_POWER_STATE),
-                .access = VehiclePropertyAccess::READ_WRITE,
+    {.config = {.prop = toInt(VehicleProperty::AP_POWER_STATE_REQ),
+                .access = VehiclePropertyAccess::READ,
                 .changeMode = VehiclePropertyChangeMode::ON_CHANGE,
                 .configArray = {3}},
-     .initialValue = {.int32Values = {toInt(VehicleApPowerState::ON_FULL), 0}}},
+     .initialValue = {.int32Values = {toInt(VehicleApPowerStateReq::ON_FULL), 0}}},
+
+    {.config = {.prop = toInt(VehicleProperty::AP_POWER_STATE_REPORT),
+                .access = VehiclePropertyAccess::WRITE,
+                .changeMode = VehiclePropertyChangeMode::ON_CHANGE,
+                .configArray = {3}},
+     .initialValue = {.int32Values = {toInt(VehicleApPowerStateReport::BOOT_COMPLETE), 0}}},
 
     {.config = {.prop = toInt(VehicleProperty::DISPLAY_BRIGHTNESS),
                 .access = VehiclePropertyAccess::READ_WRITE,
diff --git a/automotive/vehicle/2.0/default/impl/vhal_v2_0/EmulatedVehicleHal.cpp b/automotive/vehicle/2.0/default/impl/vhal_v2_0/EmulatedVehicleHal.cpp
index dc34a50..2eb905d 100644
--- a/automotive/vehicle/2.0/default/impl/vhal_v2_0/EmulatedVehicleHal.cpp
+++ b/automotive/vehicle/2.0/default/impl/vhal_v2_0/EmulatedVehicleHal.cpp
@@ -85,11 +85,6 @@
     return sensorStore;
 }
 
-enum class FakeDataCommand : int32_t {
-    Stop = 0,
-    Start = 1,
-};
-
 EmulatedVehicleHal::EmulatedVehicleHal(VehiclePropertyStore* propStore)
     : mPropStore(propStore),
       mHvacPowerProps(std::begin(kHvacPowerProperties), std::end(kHvacPowerProperties)),
@@ -132,6 +127,8 @@
 }
 
 StatusCode EmulatedVehicleHal::set(const VehiclePropValue& propValue) {
+    static constexpr bool shouldUpdateStatus = false;
+
     if (propValue.prop == kGenerateFakeDataControllingProperty) {
         StatusCode status = handleGenerateFakeDataRequest(propValue);
         if (status != StatusCode::OK) {
@@ -141,7 +138,7 @@
         // TODO(75328113): this should be handled by property status
         auto hvacPowerOn = mPropStore->readValueOrNull(
             toInt(VehicleProperty::HVAC_POWER_ON),
-            (VehicleAreaZone::ROW_1_LEFT | VehicleAreaZone::ROW_1_RIGHT));
+            (VehicleAreaSeat::ROW_1_LEFT | VehicleAreaSeat::ROW_1_RIGHT));
 
         if (hvacPowerOn && hvacPowerOn->value.int32Values.size() == 1
                 && hvacPowerOn->value.int32Values[0] == 0) {
@@ -156,7 +153,7 @@
                 // Placeholder for future implementation of VMS property in the default hal. For
                 // now, just returns OK; otherwise, hal clients crash with property not supported.
                 return StatusCode::OK;
-            case AP_POWER_STATE:
+            case AP_POWER_STATE_REPORT:
                 // This property has different behavior between get/set.  When it is set, the value
                 //  goes to the vehicle but is NOT updated in the property store back to Android.
                 // Commented out for now, because it may mess up automated testing that use the
@@ -182,7 +179,7 @@
         return StatusCode::NOT_AVAILABLE;
     }
 
-    if (!mPropStore->writeValue(propValue)) {
+    if (!mPropStore->writeValue(propValue, shouldUpdateStatus)) {
         return StatusCode::INVALID_ARG;
     }
 
@@ -204,6 +201,8 @@
 
 // Parse supported properties list and generate vector of property values to hold current values.
 void EmulatedVehicleHal::onCreate() {
+    static constexpr bool shouldUpdateStatus = true;
+
     for (auto& it : kVehicleProperties) {
         VehiclePropConfig cfg = it.config;
         int32_t numAreas = cfg.areaConfigs.size();
@@ -245,7 +244,7 @@
             } else {
                 prop.value = it.initialValue;
             }
-            mPropStore->writeValue(prop);
+            mPropStore->writeValue(prop, shouldUpdateStatus);
         }
     }
     initObd2LiveFrame(*mPropStore->getConfigOrDie(OBD2_LIVE_FRAME));
@@ -305,6 +304,8 @@
 }
 
 bool EmulatedVehicleHal::setPropertyFromVehicle(const VehiclePropValue& propValue) {
+    static constexpr bool shouldUpdateStatus = true;
+
     if (propValue.prop == kGenerateFakeDataControllingProperty) {
         StatusCode status = handleGenerateFakeDataRequest(propValue);
         if (status != StatusCode::OK) {
@@ -312,7 +313,7 @@
         }
     }
 
-    if (mPropStore->writeValue(propValue)) {
+    if (mPropStore->writeValue(propValue, shouldUpdateStatus)) {
         doHalEvent(getValuePool()->obtain(propValue));
         return true;
     } else {
@@ -360,10 +361,20 @@
             break;
         }
         case FakeDataCommand::Stop: {
-            ALOGI("%s, FakeDataCommandStop", __func__);
+            ALOGI("%s, FakeDataCommand::Stop", __func__);
             mFakeValueGenerator.stopGeneratingHalEvents(propId);
             break;
         }
+        case FakeDataCommand::KeyPress: {
+            ALOGI("%s, FakeDataCommand::KeyPress", __func__);
+            int32_t keyCode = request.value.int32Values[2];
+            int32_t display = request.value.int32Values[3];
+            doHalEvent(
+                createHwInputKeyProp(VehicleHwKeyInputAction::ACTION_DOWN, keyCode, display));
+            doHalEvent(createHwInputKeyProp(VehicleHwKeyInputAction::ACTION_UP, keyCode, display));
+            break;
+        }
+
         default: {
             ALOGE("%s: unexpected command: %d", __func__, command);
             return StatusCode::INVALID_ARG;
@@ -372,7 +383,22 @@
     return StatusCode::OK;
 }
 
+VehicleHal::VehiclePropValuePtr EmulatedVehicleHal::createHwInputKeyProp(
+    VehicleHwKeyInputAction action, int32_t keyCode, int32_t targetDisplay) {
+    auto keyEvent = getValuePool()->obtain(VehiclePropertyType::INT32_VEC, 3);
+    keyEvent->prop = toInt(VehicleProperty::HW_KEY_INPUT);
+    keyEvent->areaId = 0;
+    keyEvent->timestamp = elapsedRealtimeNano();
+    keyEvent->status = VehiclePropertyStatus::AVAILABLE;
+    keyEvent->value.int32Values[0] = toInt(action);
+    keyEvent->value.int32Values[1] = keyCode;
+    keyEvent->value.int32Values[2] = targetDisplay;
+    return keyEvent;
+}
+
 void EmulatedVehicleHal::onFakeValueGenerated(int32_t propId, float value) {
+    static constexpr bool shouldUpdateStatus = false;
+
     VehiclePropValuePtr updatedPropValue {};
     switch (getPropType(propId)) {
         case VehiclePropertyType::FLOAT:
@@ -392,7 +418,7 @@
         updatedPropValue->areaId = 0;  // Add area support if necessary.
         updatedPropValue->timestamp = elapsedRealtimeNano();
         updatedPropValue->status = VehiclePropertyStatus::AVAILABLE;
-        mPropStore->writeValue(*updatedPropValue);
+        mPropStore->writeValue(*updatedPropValue, shouldUpdateStatus);
         auto changeMode = mPropStore->getConfigOrDie(propId)->changeMode;
         if (VehiclePropertyChangeMode::ON_CHANGE == changeMode) {
             doHalEvent(move(updatedPropValue));
@@ -421,16 +447,20 @@
 }
 
 void EmulatedVehicleHal::initObd2LiveFrame(const VehiclePropConfig& propConfig) {
+    static constexpr bool shouldUpdateStatus = true;
+
     auto liveObd2Frame = createVehiclePropValue(VehiclePropertyType::MIXED, 0);
     auto sensorStore = fillDefaultObd2Frame(static_cast<size_t>(propConfig.configArray[0]),
                                             static_cast<size_t>(propConfig.configArray[1]));
     sensorStore->fillPropValue("", liveObd2Frame.get());
     liveObd2Frame->prop = OBD2_LIVE_FRAME;
 
-    mPropStore->writeValue(*liveObd2Frame);
+    mPropStore->writeValue(*liveObd2Frame, shouldUpdateStatus);
 }
 
 void EmulatedVehicleHal::initObd2FreezeFrame(const VehiclePropConfig& propConfig) {
+    static constexpr bool shouldUpdateStatus = true;
+
     auto sensorStore = fillDefaultObd2Frame(static_cast<size_t>(propConfig.configArray[0]),
                                             static_cast<size_t>(propConfig.configArray[1]));
 
@@ -442,7 +472,7 @@
         sensorStore->fillPropValue(dtc, freezeFrame.get());
         freezeFrame->prop = OBD2_FREEZE_FRAME;
 
-        mPropStore->writeValue(*freezeFrame);
+        mPropStore->writeValue(*freezeFrame, shouldUpdateStatus);
     }
 }
 
diff --git a/automotive/vehicle/2.0/default/impl/vhal_v2_0/EmulatedVehicleHal.h b/automotive/vehicle/2.0/default/impl/vhal_v2_0/EmulatedVehicleHal.h
index 62fc126..d291dba 100644
--- a/automotive/vehicle/2.0/default/impl/vhal_v2_0/EmulatedVehicleHal.h
+++ b/automotive/vehicle/2.0/default/impl/vhal_v2_0/EmulatedVehicleHal.h
@@ -67,6 +67,8 @@
 
     StatusCode handleGenerateFakeDataRequest(const VehiclePropValue& request);
     void onFakeValueGenerated(int32_t propId, float value);
+    VehiclePropValuePtr createHwInputKeyProp(VehicleHwKeyInputAction action, int32_t keyCode,
+                                             int32_t targetDisplay);
 
     void onContinuousPropertyTimer(const std::vector<int32_t>& properties);
     bool isContinuousProperty(int32_t propId) const;
diff --git a/automotive/vehicle/2.0/default/tests/SubscriptionManager_test.cpp b/automotive/vehicle/2.0/default/tests/SubscriptionManager_test.cpp
index 4865e9e..ab2013d 100644
--- a/automotive/vehicle/2.0/default/tests/SubscriptionManager_test.cpp
+++ b/automotive/vehicle/2.0/default/tests/SubscriptionManager_test.cpp
@@ -51,19 +51,16 @@
     }
 
     hidl_vec<SubscribeOptions> subscrToProp1 = {
-        SubscribeOptions{.propId = PROP1, .flags = SubscribeFlags::HAL_EVENT},
+        SubscribeOptions{.propId = PROP1, .flags = SubscribeFlags::EVENTS_FROM_CAR},
     };
 
     hidl_vec<SubscribeOptions> subscrToProp2 = {
-        SubscribeOptions {
-            .propId = PROP2,
-            .flags = SubscribeFlags::HAL_EVENT
-        },
+        SubscribeOptions{.propId = PROP2, .flags = SubscribeFlags::EVENTS_FROM_CAR},
     };
 
     hidl_vec<SubscribeOptions> subscrToProp1and2 = {
-        SubscribeOptions{.propId = PROP1, .flags = SubscribeFlags::HAL_EVENT},
-        SubscribeOptions{.propId = PROP2, .flags = SubscribeFlags::HAL_EVENT},
+        SubscribeOptions{.propId = PROP1, .flags = SubscribeFlags::EVENTS_FROM_CAR},
+        SubscribeOptions{.propId = PROP2, .flags = SubscribeFlags::EVENTS_FROM_CAR},
     };
 
     static std::list<sp<IVehicleCallback>> extractCallbacks(
@@ -76,11 +73,11 @@
     }
 
     std::list<sp<HalClient>> clientsToProp1() {
-        return manager.getSubscribedClients(PROP1, SubscribeFlags::DEFAULT);
+        return manager.getSubscribedClients(PROP1, SubscribeFlags::EVENTS_FROM_CAR);
     }
 
     std::list<sp<HalClient>> clientsToProp2() {
-        return manager.getSubscribedClients(PROP2, SubscribeFlags::DEFAULT);
+        return manager.getSubscribedClients(PROP2, SubscribeFlags::EVENTS_FROM_CAR);
     }
 
     void onPropertyUnsubscribed(int propertyId) {
@@ -110,9 +107,7 @@
     ASSERT_EQ(StatusCode::OK,
               manager.addOrUpdateSubscription(2, cb2, subscrToProp1, &updatedOptions));
 
-    auto clients = manager.getSubscribedClients(
-            PROP1,
-            SubscribeFlags::HAL_EVENT);
+    auto clients = manager.getSubscribedClients(PROP1, SubscribeFlags::EVENTS_FROM_CAR);
 
     ASSERT_ALL_EXISTS({cb1, cb2}, extractCallbacks(clients));
 }
@@ -124,13 +119,11 @@
 
     // Wrong prop
     auto clients = manager.getSubscribedClients(toInt(VehicleProperty::AP_POWER_BOOTUP_REASON),
-                                                SubscribeFlags::HAL_EVENT);
+                                                SubscribeFlags::EVENTS_FROM_CAR);
     ASSERT_TRUE(clients.empty());
 
     // Wrong flag
-    clients = manager.getSubscribedClients(
-            PROP1,
-            SubscribeFlags::SET_CALL);
+    clients = manager.getSubscribedClients(PROP1, SubscribeFlags::EVENTS_FROM_ANDROID);
     ASSERT_TRUE(clients.empty());
 }
 
@@ -139,27 +132,22 @@
     ASSERT_EQ(StatusCode::OK, manager.addOrUpdateSubscription(1, cb1, subscrToProp1,
                                                               &updatedOptions));
 
-    auto clients = manager.getSubscribedClients(
-            PROP1,
-            SubscribeFlags::DEFAULT);
+    auto clients = manager.getSubscribedClients(PROP1, SubscribeFlags::EVENTS_FROM_CAR);
     ASSERT_EQ((size_t) 1, clients.size());
     ASSERT_EQ(cb1, clients.front()->getCallback());
 
     // Same property, but different zone, to make sure we didn't unsubscribe
     // from previous zone.
-    ASSERT_EQ(StatusCode::OK, manager.addOrUpdateSubscription(1, cb1, {
-        SubscribeOptions {
-                .propId = PROP1,
-                .flags = SubscribeFlags::DEFAULT
-            }
-        }, &updatedOptions));
+    ASSERT_EQ(
+        StatusCode::OK,
+        manager.addOrUpdateSubscription(
+            1, cb1, {SubscribeOptions{.propId = PROP1, .flags = SubscribeFlags::EVENTS_FROM_CAR}},
+            &updatedOptions));
 
-    clients = manager.getSubscribedClients(PROP1,
-                                           SubscribeFlags::DEFAULT);
+    clients = manager.getSubscribedClients(PROP1, SubscribeFlags::EVENTS_FROM_CAR);
     ASSERT_ALL_EXISTS({cb1}, extractCallbacks(clients));
 
-    clients = manager.getSubscribedClients(PROP1,
-                                           SubscribeFlags::DEFAULT);
+    clients = manager.getSubscribedClients(PROP1, SubscribeFlags::EVENTS_FROM_CAR);
     ASSERT_ALL_EXISTS({cb1}, extractCallbacks(clients));
 }
 
diff --git a/automotive/vehicle/2.0/default/tests/VehicleHalManager_test.cpp b/automotive/vehicle/2.0/default/tests/VehicleHalManager_test.cpp
index 5b195db..f64eab5 100644
--- a/automotive/vehicle/2.0/default/tests/VehicleHalManager_test.cpp
+++ b/automotive/vehicle/2.0/default/tests/VehicleHalManager_test.cpp
@@ -241,10 +241,7 @@
     sp<MockedVehicleCallback> cb = new MockedVehicleCallback();
 
     hidl_vec<SubscribeOptions> options = {
-        SubscribeOptions {
-            .propId = PROP,
-            .flags = SubscribeFlags::DEFAULT
-        },
+        SubscribeOptions{.propId = PROP, .flags = SubscribeFlags::EVENTS_FROM_CAR},
     };
 
     StatusCode res = manager->subscribe(cb, options);
@@ -259,11 +256,7 @@
     sp<MockedVehicleCallback> cb = new MockedVehicleCallback();
 
     hidl_vec<SubscribeOptions> options = {
-        SubscribeOptions {
-            .propId = PROP,
-            .flags = SubscribeFlags::DEFAULT
-        }
-    };
+        SubscribeOptions{.propId = PROP, .flags = SubscribeFlags::EVENTS_FROM_CAR}};
 
     StatusCode res = manager->subscribe(cb, options);
     ASSERT_EQ(StatusCode::OK, res);
@@ -301,18 +294,14 @@
     sp<MockedVehicleCallback> cb = new MockedVehicleCallback();
 
     hidl_vec<SubscribeOptions> options = {
-        SubscribeOptions {
-            .propId = PROP,
-            .flags = SubscribeFlags::HAL_EVENT
-        },
+        SubscribeOptions{.propId = PROP, .flags = SubscribeFlags::EVENTS_FROM_CAR},
     };
 
     StatusCode res = manager->subscribe(cb, options);
     // Unable to subscribe on Hal Events for write-only properties.
     ASSERT_EQ(StatusCode::INVALID_ARG, res);
 
-
-    options[0].flags = SubscribeFlags::SET_CALL;
+    options[0].flags = SubscribeFlags::EVENTS_FROM_ANDROID;
 
     res = manager->subscribe(cb, options);
     // OK to subscribe on SET method call for write-only properties.
@@ -396,8 +385,8 @@
     const auto PROP = toInt(VehicleProperty::HVAC_FAN_SPEED);
     const auto VAL1 = 1;
     const auto VAL2 = 2;
-    const auto AREA1 = toInt(VehicleAreaZone::ROW_1_LEFT);
-    const auto AREA2 = toInt(VehicleAreaZone::ROW_1_RIGHT);
+    const auto AREA1 = toInt(VehicleAreaSeat::ROW_1_LEFT);
+    const auto AREA2 = toInt(VehicleAreaSeat::ROW_1_RIGHT);
 
     {
         auto expectedValue1 = hal->getValuePool()->obtainInt32(VAL1);
diff --git a/automotive/vehicle/2.0/default/tests/VehicleHalTestUtils.h b/automotive/vehicle/2.0/default/tests/VehicleHalTestUtils.h
index 3cabcf2..108e32f 100644
--- a/automotive/vehicle/2.0/default/tests/VehicleHalTestUtils.h
+++ b/automotive/vehicle/2.0/default/tests/VehicleHalTestUtils.h
@@ -40,64 +40,38 @@
         .configString = "Some=config,options=if,you=have_any",
     },
 
-    {
-        .prop = toInt(VehicleProperty::HVAC_FAN_SPEED),
-        .access = VehiclePropertyAccess::READ_WRITE,
-        .changeMode = VehiclePropertyChangeMode::ON_CHANGE,
-        .areaConfigs = {
-            VehicleAreaConfig {
-                .areaId = toInt(VehicleAreaZone::ROW_1_LEFT),
-                .minInt32Value = 1,
-                .maxInt32Value = 7},
-            VehicleAreaConfig {
-                .areaId = toInt(VehicleAreaZone::ROW_1_RIGHT),
-                .minInt32Value = 1,
-                .maxInt32Value = 5,
-            }
-        }
-    },
+    {.prop = toInt(VehicleProperty::HVAC_FAN_SPEED),
+     .access = VehiclePropertyAccess::READ_WRITE,
+     .changeMode = VehiclePropertyChangeMode::ON_CHANGE,
+     .areaConfigs =
+         {VehicleAreaConfig{
+              .areaId = toInt(VehicleAreaSeat::ROW_1_LEFT), .minInt32Value = 1, .maxInt32Value = 7},
+          VehicleAreaConfig{
+              .areaId = toInt(VehicleAreaSeat::ROW_1_RIGHT), .minInt32Value = 1, .maxInt32Value = 5,
+          }}},
 
     // Write-only property
-    {
-        .prop = toInt(VehicleProperty::HVAC_SEAT_TEMPERATURE),
-        .access = VehiclePropertyAccess::WRITE,
-        .changeMode = VehiclePropertyChangeMode::ON_SET,
-        .areaConfigs = {
-            VehicleAreaConfig {
-                .areaId = toInt(VehicleAreaZone::ROW_1_LEFT),
-                .minInt32Value = 64,
-                .maxInt32Value = 80},
-            VehicleAreaConfig {
-                .areaId = toInt(VehicleAreaZone::ROW_1_RIGHT),
-                .minInt32Value = 64,
-                .maxInt32Value = 80,
-            }
-        }
-    },
+    {.prop = toInt(VehicleProperty::HVAC_SEAT_TEMPERATURE),
+     .access = VehiclePropertyAccess::WRITE,
+     .changeMode = VehiclePropertyChangeMode::ON_CHANGE,
+     .areaConfigs = {VehicleAreaConfig{.areaId = toInt(VehicleAreaSeat::ROW_1_LEFT),
+                                       .minInt32Value = 64,
+                                       .maxInt32Value = 80},
+                     VehicleAreaConfig{
+                         .areaId = toInt(VehicleAreaSeat::ROW_1_RIGHT),
+                         .minInt32Value = 64,
+                         .maxInt32Value = 80,
+                     }}},
 
-    {
-        .prop = toInt(VehicleProperty::INFO_FUEL_CAPACITY),
-        .access = VehiclePropertyAccess::READ,
-        .changeMode = VehiclePropertyChangeMode::ON_CHANGE,
-        .areaConfigs = {
-            VehicleAreaConfig {
-                .minFloatValue = 0,
-                .maxFloatValue = 1.0
-            }
-        }
-    },
+    {.prop = toInt(VehicleProperty::INFO_FUEL_CAPACITY),
+     .access = VehiclePropertyAccess::READ,
+     .changeMode = VehiclePropertyChangeMode::ON_CHANGE,
+     .areaConfigs = {VehicleAreaConfig{.minFloatValue = 0, .maxFloatValue = 1.0}}},
 
-    {
-        .prop = toInt(VehicleProperty::DISPLAY_BRIGHTNESS),
-        .access = VehiclePropertyAccess::READ_WRITE,
-        .changeMode = VehiclePropertyChangeMode::ON_CHANGE,
-        .areaConfigs = {
-            VehicleAreaConfig {
-                .minInt32Value = 0,
-                .maxInt32Value = 10
-            }
-        }
-    },
+    {.prop = toInt(VehicleProperty::DISPLAY_BRIGHTNESS),
+     .access = VehiclePropertyAccess::READ_WRITE,
+     .changeMode = VehiclePropertyChangeMode::ON_CHANGE,
+     .areaConfigs = {VehicleAreaConfig{.minInt32Value = 0, .maxInt32Value = 10}}},
 
     {
         .prop = toInt(VehicleProperty::MIRROR_FOLD),
@@ -107,12 +81,9 @@
     },
 
     // Complex data type.
-    {
-        .prop = kCustomComplexProperty,
-        .access = VehiclePropertyAccess::READ_WRITE,
-        .changeMode = VehiclePropertyChangeMode::ON_CHANGE
-    }
-};
+    {.prop = kCustomComplexProperty,
+     .access = VehiclePropertyAccess::READ_WRITE,
+     .changeMode = VehiclePropertyChangeMode::ON_CHANGE}};
 
 constexpr auto kTimeout = std::chrono::milliseconds(500);
 
diff --git a/automotive/vehicle/2.0/types.hal b/automotive/vehicle/2.0/types.hal
index 87daedc..15ba494 100644
--- a/automotive/vehicle/2.0/types.hal
+++ b/automotive/vehicle/2.0/types.hal
@@ -17,28 +17,28 @@
 package android.hardware.automotive.vehicle@2.0;
 
 /**
- * Enumerates supported data types for VehicleProperty.
+ * Enumerates supported data type for VehicleProperty.
  *
- * This is a bitwise flag that supposed to be used in VehicleProperty enum.
+ * Used to create property ID in VehicleProperty enum.
  */
 enum VehiclePropertyType : int32_t {
-    STRING         = 0x00100000,
-    BOOLEAN        = 0x00200000,
-    INT32          = 0x00400000,
-    INT32_VEC      = 0x00410000,
-    INT64          = 0x00500000,
-    INT64_VEC      = 0x00510000,
-    FLOAT          = 0x00600000,
-    FLOAT_VEC      = 0x00610000,
-    BYTES          = 0x00700000,
+    STRING          = 0x00100000,
+    BOOLEAN         = 0x00200000,
+    INT32           = 0x00400000,
+    INT32_VEC       = 0x00410000,
+    INT64           = 0x00500000,
+    INT64_VEC       = 0x00510000,
+    FLOAT           = 0x00600000,
+    FLOAT_VEC       = 0x00610000,
+    BYTES           = 0x00700000,
 
     /**
      * Any combination of scalar or vector types. The exact format must be
      * provided in the description of the property.
      */
-    MIXED          = 0x00e00000,
+    MIXED           = 0x00e00000,
 
-    MASK           = 0x00ff0000
+    MASK            = 0x00ff0000
 };
 
 /**
@@ -50,51 +50,60 @@
  * Other properties may not be associated with particular vehicle area,
  * these kind of properties must have VehicleArea:GLOBAL flag.
  *
- * This is a bitwise flag that supposed to be used in VehicleProperty enum.
+ * Used to create property ID in VehicleProperty enum.
  */
 enum VehicleArea : int32_t {
-      GLOBAL       = 0x01000000,
-      ZONE         = 0x02000000,
-      WINDOW       = 0x03000000,
-      MIRROR       = 0x04000000,
-      SEAT         = 0x05000000,
-      DOOR         = 0x06000000,
+    GLOBAL      = 0x01000000,
+    /** WINDOW maps to enum VehicleAreaWindow */
+    WINDOW      = 0x03000000,
+    /** MIRROR maps to enum VehicleAreaMirror */
+    MIRROR      = 0x04000000,
+    /** SEAT maps to enum VehicleAreaSeat */
+    SEAT        = 0x05000000,
+    /** DOOR maps to enum VehicleAreaDoor */
+    DOOR        = 0x06000000,
+    /** WHEEL maps to enum Wheel */
+    WHEEL       = 0x07000000,
 
-      MASK         = 0x0f000000,
+    MASK        = 0x0f000000,
 };
 
 /**
  * Enumerates property groups.
  *
- * This is a bitwise flag that supposed to be used in VehicleProperty enum.
+ * Used to create property ID in VehicleProperty enum.
  */
 enum VehiclePropertyGroup : int32_t {
     /**
-     * Properties declared in AOSP must have this flag.
+     * Properties declared in AOSP must use this flag.
      */
-    SYSTEM         = 0x10000000,
+    SYSTEM      = 0x10000000,
 
     /**
-     * Properties declared by vendors must have this flag.
+     * Properties declared by vendors must use this flag.
      */
-    VENDOR         = 0x20000000,
+    VENDOR      = 0x20000000,
 
-    MASK           = 0xf0000000,
+    MASK        = 0xf0000000,
 };
 
 /**
  * Declares all vehicle properties. VehicleProperty has a bitwise structure.
  * Each property must have:
- *   - an unique id from range 0x0100 - 0xffff
- *   - associated data type using VehiclePropertyType
- *   - property group (VehiclePropertyGroup)
- *   - vehicle area (VehicleArea)
+ *  - a unique id from range 0x0100 - 0xffff
+ *  - associated data type using VehiclePropertyType
+ *  - property group (VehiclePropertyGroup)
+ *  - vehicle area (VehicleArea)
  *
  * Vendors are allowed to extend this enum with their own properties. In this
  * case they must use VehiclePropertyGroup:VENDOR flag when property is
  * declared.
+ *
+ * When a property's status field is not set to AVAILABLE:
+ *  - IVehicle#set may return StatusCode::NOT_AVAILABLE.
+ *  - IVehicle#get is not guaranteed to work.
  */
-enum VehicleProperty: int32_t {
+enum VehicleProperty : int32_t {
 
     /** Undefined property. */
     INVALID = 0x00000000,
@@ -105,14 +114,14 @@
      * @change_mode VehiclePropertyChangeMode:STATIC
      * @access VehiclePropertyAccess:READ
      */
-    INFO_VIN= (
+    INFO_VIN = (
         0x0100
         | VehiclePropertyGroup:SYSTEM
         | VehiclePropertyType:STRING
         | VehicleArea:GLOBAL),
 
     /**
-     * Maker name of vehicle
+     * Manufacturer of vehicle
      *
      * @change_mode VehiclePropertyChangeMode:STATIC
      * @access VehiclePropertyAccess:READ
@@ -162,11 +171,11 @@
         | VehicleArea:GLOBAL),
 
     /**
-     * List of fuels the vehicle may use.  Uses enum FuelType
+     * List of fuels the vehicle may use
      *
      * @change_mode VehiclePropertyChangeMode:STATIC
      * @access VehiclePropertyAccess:READ
-     * @unit VehicleUnit:MILLILITERS
+     * @data_enum FuelType
      */
     INFO_FUEL_TYPE = (
         0x0105
@@ -189,9 +198,10 @@
         | VehicleArea:GLOBAL),
 
     /**
-     * List of connectors this EV may use.  Uses enum EvConnectorType
+     * List of connectors this EV may use
      *
      * @change_mode VehiclePropertyChangeMode:STATIC
+     * @data_enum EvConnectorType
      * @access VehiclePropertyAccess:READ
      */
     INFO_EV_CONNECTOR_TYPE = (
@@ -201,9 +211,49 @@
         | VehicleArea:GLOBAL),
 
     /**
+     * Fuel door location
+     *
+     * @change_mode VehiclePropertyChangeMode:STATIC
+     * @data_enum FuelDoorLocationType
+     * @access VehiclePropertyAccess:READ
+     */
+    INFO_FUEL_DOOR_LOCATION = (
+        0x0108
+        | VehiclePropertyGroup:SYSTEM
+        | VehiclePropertyType:INT32
+        | VehicleArea:GLOBAL),
+
+    /**
+     * EV port location
+     *
+     * @change_mode VehiclePropertyChangeMode:STATIC
+     * @access VehiclePropertyAccess:READ
+     * @data_enum PortLocationType
+     */
+    INFO_EV_PORT_LOCATION = (
+        0x0109
+        | VehiclePropertyGroup:SYSTEM
+        | VehiclePropertyType:INT32
+        | VehicleArea:GLOBAL),
+
+    /**
+     * Driver's seat location
+     *
+     * @change_mode VehiclePropertyChangeMode:STATIC
+     * @data_enum VehicleAreaSeat
+     * @access VehiclePropertyAccess:READ
+     */
+    INFO_DRIVER_SEAT = (
+        0x010A
+        | VehiclePropertyGroup:SYSTEM
+        | VehiclePropertyType:INT32
+        | VehicleArea:SEAT),
+
+
+    /**
      * Current odometer value of the vehicle
      *
-     * @change_mode VehiclePropertyChangeMode:ON_CHANGE | VehiclePropertyChangeMode:CONTINUOUS
+     * @change_mode VehiclePropertyChangeMode:CONTINUOUS
      * @access VehiclePropertyAccess:READ
      * @unit VehicleUnit:KILOMETER
      */
@@ -216,7 +266,7 @@
     /**
      * Speed of the vehicle
      *
-     * @change_mode VehiclePropertyChangeMode:ON_CHANGE|VehiclePropertyChangeMode:CONTINUOUS
+     * @change_mode VehiclePropertyChangeMode:CONTINUOUS
      * @access VehiclePropertyAccess:READ
      * @unit VehicleUnit:METER_PER_SEC
      */
@@ -227,22 +277,9 @@
         | VehicleArea:GLOBAL),
 
     /**
-     * Engine on
-     *
-     * @change_mode VehiclePropertyChangeMode:STATIC
-     * @access VehiclePropertyAccess:READ
-     */
-    ENGINE_ON = (
-        0x0300
-        | VehiclePropertyGroup:SYSTEM
-        | VehiclePropertyType:BOOLEAN
-        | VehicleArea:GLOBAL),
-
-
-    /**
      * Temperature of engine coolant
      *
-     * @change_mode VehiclePropertyChangeMode:ON_CHANGE|VehiclePropertyChangeMode:CONTINUOUS
+     * @change_mode VehiclePropertyChangeMode:CONTINUOUS
      * @access VehiclePropertyAccess:READ
      * @unit VehicleUnit:CELSIUS
      */
@@ -268,7 +305,7 @@
     /**
      * Temperature of engine oil
      *
-     * @change_mode VehiclePropertyChangeMode:ON_CHANGE|VehiclePropertyChangeMode:CONTINUOUS
+     * @change_mode VehiclePropertyChangeMode:CONTINUOUS
      * @access VehiclePropertyAccess:READ
      * @unit VehicleUnit:CELSIUS
      */
@@ -281,7 +318,7 @@
     /**
      * Engine rpm
      *
-     * @change_mode VehiclePropertyChangeMode:ON_CHANGE|VehiclePropertyChangeMode:CONTINUOUS
+     * @change_mode VehiclePropertyChangeMode:CONTINUOUS
      * @access VehiclePropertyAccess:READ
      * @unit VehicleUnit:RPM
      */
@@ -310,7 +347,7 @@
      *  int64Values[3] = rear right ticks
      *  int64Values[4] = rear left ticks
      *
-     * configArray is used to indicate the micrometers-per-wheel-tick value as well as
+     * configArray is used to indicate the micrometers-per-wheel-tick value and
      * which wheels are supported.  configArray is set as follows:
      *
      *  configArray[0], bits [0:3] = supported wheels.  Uses enum Wheel.
@@ -327,10 +364,10 @@
      * @access VehiclePropertyAccess:READ
      */
     WHEEL_TICK = (
-      0x0306
-      | VehiclePropertyGroup:SYSTEM
-      | VehiclePropertyType:MIXED
-      | VehicleArea:GLOBAL),
+        0x0306
+        | VehiclePropertyGroup:SYSTEM
+        | VehiclePropertyType:INT64_VEC
+        | VehicleArea:GLOBAL),
 
 
     /**
@@ -338,7 +375,7 @@
      *
      * Value may not exceed INFO_FUEL_CAPACITY
      *
-     * @change_mode VehiclePropertyChangeMode:STATIC
+     * @change_mode VehiclePropertyChangeMode:CONTINUOUS
      * @access VehiclePropertyAccess:READ
      * @unit VehicleUnit:MILLILITER
      */
@@ -351,8 +388,8 @@
     /**
      * Fuel door open
      *
-     * @change_mode VehiclePropertyChangeMode:STATIC
-     * @access VehiclePropertyAccess:READ
+     * @change_mode VehiclePropertyChangeMode:ON_CHANGE
+     * @access VehiclePropertyAccess:READ_WRITE
      */
     FUEL_DOOR_OPEN = (
         0x0308
@@ -365,7 +402,7 @@
      *
      * Value may not exceed INFO_EV_BATTERY_CAPACITY
      *
-     * @change_mode VehiclePropertyChangeMode:STATIC
+     * @change_mode VehiclePropertyChangeMode:CONTINUOUS
      * @access VehiclePropertyAccess:READ
      * @unit VehicleUnit:WH
      */
@@ -378,8 +415,8 @@
     /**
      * EV charge port open
      *
-     * @change_mode VehiclePropertyChangeMode:STATIC
-     * @access VehiclePropertyAccess:READ
+     * @change_mode VehiclePropertyChangeMode:ON_CHANGE
+     * @access VehiclePropertyAccess:READ_WRITE
      */
     EV_CHARGE_PORT_OPEN = (
         0x030A
@@ -390,7 +427,7 @@
     /**
      * EV charge port connected
      *
-     * @change_mode VehiclePropertyChangeMode:STATIC
+     * @change_mode VehiclePropertyChangeMode:ON_CHANGE
      * @access VehiclePropertyAccess:READ
      */
     EV_CHARGE_PORT_CONNECTED = (
@@ -405,7 +442,7 @@
      * Positive value indicates battery is being charged.
      * Negative value indicates battery being discharged.
      *
-     * @change_mode VehiclePropertyChangeMode:STATIC
+     * @change_mode VehiclePropertyChangeMode:CONTINUOUS
      * @access VehiclePropertyAccess:READ
      * @unit VehicleUnit:MW
      */
@@ -416,8 +453,42 @@
         | VehicleArea:GLOBAL),
 
     /**
+     * Range remaining
+     *
+     * Meters remaining of fuel and charge.  Range remaining shall account for
+     * all energy sources in a vehicle.  For example, a hybrid car's range will
+     * be the sum of the ranges based on fuel and battery.
+     *
+     * @change_mode VehiclePropertyChangeMode:CONTINUOUS
+     * @access VehiclePropertyAccess:READ_WRITE
+     * @unit VehicleUnit:METER
+     */
+    RANGE_REMAINING = (
+        0x0308
+        | VehiclePropertyGroup:SYSTEM
+        | VehiclePropertyType:FLOAT
+        | VehicleArea:GLOBAL),
+
+    /**
+     * Tire pressure
+     *
+     * The min/max range is used to indicate the recommended tire pressure.
+     *
+     * @change_mode VehiclePropertyChangeMode:CONTINUOUS
+     * @access VehiclePropertyAccess:READ
+     * @unit VehicleUnit:KILOPASCAL
+     */
+    TIRE_PRESSURE = (
+        0x0309
+        | VehiclePropertyGroup:SYSTEM
+        | VehiclePropertyType:MIXED
+        | VehicleArea:WHEEL),
+
+    /**
      * Currently selected gear
      *
+     * This is the gear selected by the user.
+     *
      * @change_mode VehiclePropertyChangeMode:ON_CHANGE
      * @access VehiclePropertyAccess:READ
      * @data_enum VehicleGear
@@ -467,21 +538,12 @@
         | VehicleArea:GLOBAL),
 
     /**
-     * Driving status policy.
-     *
-     * @change_mode VehiclePropertyChangeMode:ON_CHANGE
-     * @access VehiclePropertyAccess:READ
-     * @data_enum VehicleDrivingStatus
-     */
-    DRIVING_STATUS = (
-        0x0404
-        | VehiclePropertyGroup:SYSTEM
-        | VehiclePropertyType:INT32
-        | VehicleArea:GLOBAL),
-
-    /**
      * Warning for fuel low level.
      *
+     * This property corresponds to the low fuel warning on the dashboard.
+     * Once FUEL_LEVEL_LOW is set, it should not be cleared until more fuel is
+     * added to the vehicle.
+     *
      * @change_mode VehiclePropertyChangeMode:ON_CHANGE
      * @access VehiclePropertyAccess:READ
      */
@@ -492,7 +554,9 @@
         | VehicleArea:GLOBAL),
 
     /**
-     * Night mode or not.
+     * Night mode
+     *
+     * True indicates that night mode is currently enabled.
      *
      * @change_mode VehiclePropertyChangeMode:ON_CHANGE
      * @access VehiclePropertyAccess:READ
@@ -506,8 +570,6 @@
     /**
      * State of the vehicles turn signals
      *
-     * Values from VehicleTurnSignal
-     *
      * @change_mode VehiclePropertyChangeMode:ON_CHANGE
      * @access VehiclePropertyAccess:READ
      * @data_enum VehicleTurnSignal
@@ -527,12 +589,16 @@
      */
     IGNITION_STATE = (
         0x0409
-            | VehiclePropertyGroup:SYSTEM
-            | VehiclePropertyType:INT32
-            | VehicleArea:GLOBAL),
+        | VehiclePropertyGroup:SYSTEM
+        | VehiclePropertyType:INT32
+        | VehicleArea:GLOBAL),
 
     /**
-     * ABS is active.  Set to true whenever ABS is activated.  Reset to false when ABS is off.
+     * ABS is active
+     *
+     * Set to true when ABS is active.  Reset to false when ABS is off.  This
+     * property may be intermittently set (pulsing) based on the real-time
+     * state of the ABS system.
      *
      * @change_mode VehiclePropertyChangeMode:ON_CHANGE
      * @access VehiclePropertyAccess:READ
@@ -544,7 +610,11 @@
         | VehicleArea:GLOBAL),
 
     /**
-     * Traction Control is active.
+     * Traction Control is active
+     *
+     * Set to true when traction control (TC) is active.  Reset to false when
+     * TC is off.  This property may be intermittently set (pulsing) based on
+     * the real-time state of the TC system.
      *
      * @change_mode VehiclePropertyChangeMode:ON_CHANGE
      * @access VehiclePropertyAccess:READ
@@ -558,10 +628,6 @@
     /**
      * Fan speed setting
      *
-     * IVehicle#set may return StatusCode::NOT_AVAILABLE and IVehicle#get is not
-     * guaranteed to work if HVAC unit is off.  See HVAC_POWER_ON property for
-     * details.
-     *
      * @change_mode VehiclePropertyChangeMode:ON_CHANGE
      * @access VehiclePropertyAccess:READ_WRITE
      */
@@ -569,15 +635,11 @@
         0x0500
         | VehiclePropertyGroup:SYSTEM
         | VehiclePropertyType:INT32
-        | VehicleArea:ZONE),
+        | VehicleArea:SEAT),
 
     /**
      * Fan direction setting
      *
-     * IVehicle#set may return StatusCode::NOT_AVAILABLE and IVehicle#get is not
-     * guaranteed to work if HVAC unit is off.  See HVAC_POWER_ON property for
-     * details.
-     *
      * @change_mode VehiclePropertyChangeMode:ON_CHANGE
      * @access VehiclePropertyAccess:READ_WRITE
      * @data_enum VehicleHvacFanDirection
@@ -586,15 +648,11 @@
         0x0501
         | VehiclePropertyGroup:SYSTEM
         | VehiclePropertyType:INT32
-        | VehicleArea:ZONE),
+        | VehicleArea:SEAT),
 
     /**
      * HVAC current temperature.
      *
-     * IVehicle#set may return StatusCode::NOT_AVAILABLE and IVehicle#get is not
-     * guaranteed to work if HVAC unit is off.  See HVAC_POWER_ON property for
-     * details.
-     *
      * @change_mode VehiclePropertyChangeMode:ON_CHANGE
      * @access VehiclePropertyAccess:READ_WRITE
      */
@@ -602,15 +660,11 @@
         0x0502
         | VehiclePropertyGroup:SYSTEM
         | VehiclePropertyType:FLOAT
-        | VehicleArea:ZONE),
+        | VehicleArea:SEAT),
 
     /**
      * HVAC, target temperature set.
      *
-     * IVehicle#set may return StatusCode::NOT_AVAILABLE and IVehicle#get is not
-     * guaranteed to work if HVAC unit is off.  See HVAC_POWER_ON property for
-     * details.
-     *
      * @change_mode VehiclePropertyChangeMode:ON_CHANGE
      * @access VehiclePropertyAccess:READ_WRITE
      */
@@ -618,14 +672,10 @@
         0x0503
         | VehiclePropertyGroup:SYSTEM
         | VehiclePropertyType:FLOAT
-        | VehicleArea:ZONE),
+        | VehicleArea:SEAT),
 
     /**
-     * On/off defrost
-     *
-     * IVehicle#set may return StatusCode::NOT_AVAILABLE and IVehicle#get is not
-     * guaranteed to work if HVAC unit is off.  See HVAC_POWER_ON property for
-     * details.
+     * On/off defrost for designated window
      *
      * @change_mode VehiclePropertyChangeMode:ON_CHANGE
      * @access VehiclePropertyAccess:READ_WRITE
@@ -637,28 +687,25 @@
         | VehicleArea:WINDOW),
 
     /**
-     * On/off AC
-     *
-     * IVehicle#set may return StatusCode::NOT_AVAILABLE and IVehicle#get is not
-     * guaranteed to work if HVAC unit is off.  See HVAC_POWER_ON property for
-     * details.
+     * On/off AC for designated areaId
      *
      * @change_mode VehiclePropertyChangeMode:ON_CHANGE
      * @access VehiclePropertyAccess:READ_WRITE
-     * @config_flags Supported zones
+     * @config_flags Supported areaIds
      */
     HVAC_AC_ON = (
         0x0505
         | VehiclePropertyGroup:SYSTEM
         | VehiclePropertyType:BOOLEAN
-        | VehicleArea:ZONE),
+        | VehicleArea:SEAT),
 
     /**
      * On/off max AC
      *
-     * IVehicle#set may return StatusCode::NOT_AVAILABLE and IVehicle#get is not
-     * guaranteed to work if HVAC unit is off.  See HVAC_POWER_ON property for
-     * details.
+     * When MAX AC is on, the ECU may adjust the vent position, fan speed,
+     * temperature, etc as necessary to cool the vehicle as quickly as possible.
+     * Any parameters modified as a side effect of turning on/off the MAX AC
+     * parameter shall generate onPropertyEvent() callbacks to the VHAL.
      *
      * @change_mode VehiclePropertyChangeMode:ON_CHANGE
      * @access VehiclePropertyAccess:READ_WRITE
@@ -667,14 +714,16 @@
         0x0506
         | VehiclePropertyGroup:SYSTEM
         | VehiclePropertyType:BOOLEAN
-        | VehicleArea:ZONE),
+        | VehicleArea:SEAT),
 
     /**
      * On/off max defrost
      *
-     * IVehicle#set may return StatusCode::NOT_AVAILABLE and IVehicle#get is not
-     * guaranteed to work if HVAC unit is off.  See HVAC_POWER_ON property for
-     * details.
+     * When MAX DEFROST is on, the ECU may adjust the vent position, fan speed,
+     * temperature, etc as necessary to defrost the windows as quickly as
+     * possible.  Any parameters modified as a side effect of turning on/off
+     * the MAX DEFROST parameter shall generate onPropertyEvent() callbacks to
+     * the VHAL.
      *
      * @change_mode VehiclePropertyChangeMode:ON_CHANGE
      * @access VehiclePropertyAccess:READ_WRITE
@@ -683,14 +732,15 @@
         0x0507
         | VehiclePropertyGroup:SYSTEM
         | VehiclePropertyType:BOOLEAN
-        | VehicleArea:ZONE),
+        | VehicleArea:SEAT),
 
     /**
-     * On/off re-circulation
+     * Recirculation on/off
      *
-     * IVehicle#set may return StatusCode::NOT_AVAILABLE and IVehicle#get is not
-     * guaranteed to work if HVAC unit is off.  See HVAC_POWER_ON property for
-     * details.
+     * Controls the supply of exterior air to the cabin.  Recirc “on” means the
+     * majority of the airflow into the cabin is originating in the cabin.
+     * Recirc “off” means the majority of the airflow into the cabin is coming
+     * from outside the car.
      *
      * @change_mode VehiclePropertyChangeMode:ON_CHANGE
      * @access VehiclePropertyAccess:READ_WRITE
@@ -699,14 +749,25 @@
         0x0508
         | VehiclePropertyGroup:SYSTEM
         | VehiclePropertyType:BOOLEAN
-        | VehicleArea:ZONE),
+        | VehicleArea:SEAT),
 
     /**
-     * On/off dual. This must be defined per each row.
+     * Enable temperature coupling between zones.
      *
-     * IVehicle#set may return StatusCode::NOT_AVAILABLE and IVehicle#get is not
-     * guaranteed to work if HVAC unit is off.  See HVAC_POWER_ON property for
-     * details.
+     * The areaId for this property must include the zones that are coupled
+     * together.  Typically, the front two zones (ROW_1_LEFT and ROW_1_RIGHT)
+     * are coupled together when this property is enabled.  Thus, the areaId
+     * shall be (ROW_1_LEFT | ROW_1_RIGHT).  When the property is enabled, the
+     * ECU may synchronize the temperature for the affected zones.  Any
+     * parameters modified as a side effect of turning on/off the DUAL_ON
+     * parameter shall generate onPropertyEvent() callbacks to the VHAL.  In
+     * addition, if setting a temperature (i.e. driver's temp) changes another
+     * temperature (i.e. front passenger's temp), then the appropriate
+     * onPropertyEvent() callbacks must be generated.  If a user changes a
+     * temperature that breaks the coupling (e.g. setting the passenger
+     * temperature independently) then the VHAL must send the appropriate
+     * onPropertyEvent() callbacks (i.e. HVAC_DUAL_ON = false,
+     * HVAC_TEMPERATURE_SET[zone] = xxx, etc).
      *
      * @change_mode VehiclePropertyChangeMode:ON_CHANGE
      * @access VehiclePropertyAccess:READ_WRITE
@@ -715,15 +776,11 @@
         0x0509
         | VehiclePropertyGroup:SYSTEM
         | VehiclePropertyType:BOOLEAN
-        | VehicleArea:ZONE),
+        | VehicleArea:SEAT),
 
     /**
      * On/off automatic mode
      *
-     * IVehicle#set may return StatusCode::NOT_AVAILABLE and IVehicle#get is not
-     * guaranteed to work if HVAC unit is off.  See HVAC_POWER_ON property for
-     * details.
-     *
      * @change_mode VehiclePropertyChangeMode:ON_CHANGE
      * @access VehiclePropertyAccess:READ_WRITE
      */
@@ -731,7 +788,7 @@
         0x050A
         | VehiclePropertyGroup:SYSTEM
         | VehiclePropertyType:BOOLEAN
-        | VehicleArea:ZONE),
+        | VehicleArea:SEAT),
 
     /**
      * Seat temperature
@@ -744,10 +801,6 @@
      * min/max range defines the allowable range and number of steps in each
      * direction.
      *
-     * IVehicle#set may return StatusCode::NOT_AVAILABLE and IVehicle#get is not
-     * guaranteed to work if HVAC unit is off.  See HVAC_POWER_ON property for
-     * details.
-     *
      * @change_mode VehiclePropertyChangeMode:ON_CHANGE
      * @access VehiclePropertyAccess:READ_WRITE
      */
@@ -760,12 +813,9 @@
     /**
      * Side Mirror Heat
      *
-     * Increase values denote higher heating levels for side mirrors.
-     * 0 indicates heating is turned off.
-     *
-     * IVehicle#set may return StatusCode::NOT_AVAILABLE and IVehicle#get is not
-     * guaranteed to work if HVAC unit is off.  See HVAC_POWER_ON property for
-     * details.
+     * Increasing values denote higher heating levels for side mirrors.
+     * The Max value in the config data represents the highest heating level.
+     * The Min value in the config data MUST be zero and indicates no heating.
      *
      * @change_mode VehiclePropertyChangeMode:ON_CHANGE
      * @access VehiclePropertyAccess:READ_WRITE
@@ -777,51 +827,42 @@
         | VehicleArea:MIRROR),
 
     /**
-     * Steering Wheel Temperature
+     * Steering Wheel Heating/Cooling
      *
-     * Sets the temperature for the steering wheel
+     * Sets the amount of heating/cooling for the steering wheel
+     * config data Min and Max MUST be set appropriately.
      * Positive value indicates heating.
      * Negative value indicates cooling.
      * 0 indicates temperature control is off.
      *
-     * IVehicle#set may return StatusCode::NOT_AVAILABLE and IVehicle#get is not
-     * guaranteed to work if HVAC unit is off.  See HVAC_POWER_ON property for
-     * details.
-     *
      * @change_mode VehiclePropertyChangeMode:ON_CHANGE
      * @access VehiclePropertyAccess:READ_WRITE
      */
-    HVAC_STEERING_WHEEL_TEMP = (
+    HVAC_STEERING_WHEEL_HEAT = (
         0x050D
         | VehiclePropertyGroup:SYSTEM
         | VehiclePropertyType:INT32
         | VehicleArea:GLOBAL),
 
     /**
-     * Temperature units
+     * Temperature units for display
      *
      * Indicates whether the temperature is in Celsius, Fahrenheit, or a
-     * different unit from VehicleUnit enum.
-     * This parameter affects all HVAC temperatures in the system.
-     *
-     * IVehicle#get is not guaranteed to work if HVAC unit is off.  See
-     * HVAC_POWER_ON property for details.
+     * different unit from VehicleUnit enum.  This parameter MAY be used for
+     * displaying any HVAC temperature in the system.
      *
      * @change_mode VehiclePropertyChangeMode:ON_CHANGE
-     * @access VehiclePropertyAccess:READ
+     * @access VehiclePropertyAccess:READ_WRITE
      */
-    HVAC_TEMPERATURE_UNITS = (
+    HVAC_TEMPERATURE_DISPLAY_UNITS = (
         0x050E
         | VehiclePropertyGroup:SYSTEM
         | VehiclePropertyType:INT32
-        | VehicleArea:ZONE),
+        | VehicleArea:GLOBAL),
 
     /**
      * Actual fan speed
      *
-     * IVehicle#get is not guaranteed to work if HVAC unit is off.  See
-     * HVAC_POWER_ON property for details.
-     *
      * @change_mode VehiclePropertyChangeMode:ON_CHANGE
      * @access VehiclePropertyAccess:READ
      */
@@ -829,37 +870,38 @@
         0x050F
         | VehiclePropertyGroup:SYSTEM
         | VehiclePropertyType:INT32
-        | VehicleArea:ZONE),
+        | VehicleArea:SEAT),
 
     /**
-     * Represents power state for HVAC. Some HVAC properties must require
-     * matching power to be turned on to get out of OFF state. For non-zoned
-     * HVAC properties, VEHICLE_ALL_ZONE corresponds to global power state.
+     * Represents global power state for HVAC.  Setting this property to false
+     * MAY mark some properties that control individual HVAC features/subsystems
+     * to UNAVAILABLE state. Setting this property to true MAY mark some
+     * properties that control individual HVAC features/subsystems to AVAILABLE
+     * state (unless any/all of them are UNAVAILABLE on their own individual
+     * merits).  The list of properties affected by HVAC_POWER_ON must be set
+     * in the VehiclePropConfig.configArray.
      *
      * @change_mode VehiclePropertyChangeMode:ON_CHANGE
      * @access VehiclePropertyAccess:READ_WRITE
-     * @config_string list of HVAC properties whose power is controlled by this
-     *                property. Format is hexa-decimal number (0x...) separated
-     *                by comma like "0x500,0x503". All zones defined in these
-     *                affected properties must be available in the property.
      */
     HVAC_POWER_ON = (
         0x0510
         | VehiclePropertyGroup:SYSTEM
         | VehiclePropertyType:BOOLEAN
-        | VehicleArea:ZONE),
+        | VehicleArea:SEAT),
 
     /**
      * Fan Positions Available
      *
-     * This is a bit mask of fan positions available for the zone.  Each available fan direction is
-     * denoted by a separate entry in the vector.  A fan direction may have multiple bits from
-     * vehicle_hvac_fan_direction set.  For instance, a typical car may have the following setting:
-     *   - [0] = FAN_DIRECTION_FACE (0x1)
-     *   - [1] = FAN_DIRECTION_FLOOR (0x2)
-     *   - [2] = FAN_DIRECTION_FACE | FAN_DIRECTION_FLOOR (0x3)
-     *   - [3] = FAN_DIRECTION_DEFROST (0x4)
-     *   - [4] = FAN_DIRECTION_FLOOR | FAN_DIRECTION_DEFROST (0x6)
+     * This is a bit mask of fan positions available for the zone.  Each
+     * available fan direction is denoted by a separate entry in the vector.  A
+     * fan direction may have multiple bits from vehicle_hvac_fan_direction set.
+     * For instance, a typical car may have the following fan positions:
+     *   - FAN_DIRECTION_FACE (0x1)
+     *   - FAN_DIRECTION_FLOOR (0x2)
+     *   - FAN_DIRECTION_FACE | FAN_DIRECTION_FLOOR (0x3)
+     *   - FAN_DIRECTION_DEFROST (0x4)
+     *   - FAN_DIRECTION_FLOOR | FAN_DIRECTION_DEFROST (0x6)
      *
      * @change_mode VehiclePropertyChangeMode:STATIC
      * @access VehiclePropertyAccess:READ
@@ -868,13 +910,14 @@
         0x0511
         | VehiclePropertyGroup:SYSTEM
         | VehiclePropertyType:INT32_VEC
-        | VehicleArea:ZONE),
+        | VehicleArea:SEAT),
 
     /**
-     * Automatic re-circulation on/off
+     * Automatic recirculation on/off
      *
-     * IVehicle#set and IVehicle#get must return StatusCode::NOT_AVAILABLE when HVAC unit is off.
-     * See HVAC_POWER_ON property for details.
+     * When automatic recirculation is ON, the HVAC system may automatically
+     * switch to recirculation mode if the vehicle detects poor incoming air
+     * quality.
      *
      * @change_mode VehiclePropertyChangeMode:ON_CHANGE
      * @access VehiclePropertyAccess:READ_WRITE
@@ -883,12 +926,32 @@
         0x0512
         | VehiclePropertyGroup:SYSTEM
         | VehiclePropertyType:BOOLEAN
-        | VehicleArea:ZONE),
+        | VehicleArea:SEAT),
+
+    /**
+     * Seat ventilation
+     *
+     * 0 indicates off.
+     * Positive values indicates ventilation level.
+     *
+     * Used by HVAC apps and Assistant to enable, change, or read state of seat
+     * ventilation.  This is different than seating cooling. It can be on at the
+     * same time as cooling, or not.
+     *
+     * @change_mode VehiclePropertyChangeMode:ON_CHANGE
+     * @access VehiclePropertyAccess:READ_WRITE
+     */
+    HVAC_SEAT_VENTILATION = (
+        0x0513
+        | VehiclePropertyGroup:SYSTEM
+        | VehiclePropertyType:INT32
+        | VehicleArea:SEAT),
+
 
     /**
      * Outside temperature
      *
-     * @change_mode VehiclePropertyChangeMode:ON_CHANGE|VehiclePropertyChangeMode:CONTINUOUS
+     * @change_mode VehiclePropertyChangeMode:CONTINUOUS
      * @access VehiclePropertyAccess:READ
      * @unit VehicleUnit:CELSIUS
      */
@@ -901,7 +964,7 @@
     /**
      * Cabin temperature
      *
-     * @change_mode VehiclePropertyChangeMode:ON_CHANGE|VehiclePropertyChangeMode:CONTINUOUS
+     * @change_mode VehiclePropertyChangeMode:CONTINUOUS
      * @access VehiclePropertyAccess:READ
      * @unit VehicleUnit:CELSIUS
      */
@@ -909,31 +972,7 @@
         0x0704
         | VehiclePropertyGroup:SYSTEM
         | VehiclePropertyType:FLOAT
-        | VehicleArea:GLOBAL),
-
-    /**
-     * Radio presets stored on the Car radio module. The data type used is int32
-     * array with the following fields:
-     * <ul>
-     *    <li> int32Values[0]: Preset number </li>
-     *    <li> int32Values[1]: Band type (see #RADIO_BAND_FM in
-     *    system/core/include/system/radio.h).
-     *    <li> int32Values[2]: Channel number </li>
-     *    <li> int32Values[3]: Sub channel number </li>
-     * </ul>
-     *
-     * NOTE: When getting a current preset config ONLY set preset number (i.e.
-     * int32Values[0]). For setting a preset other fields are required.
-     *
-     * @change_mode VehiclePropertyChangeMode:ON_CHANGE
-     * @access VehiclePropertyAccess:READ_WRITE
-     * @config_flags Number of presets supported
-     */
-    RADIO_PRESET = (
-        0x0801
-        | VehiclePropertyGroup:SYSTEM
-        | VehiclePropertyType:INT32_VEC
-        | VehicleArea:GLOBAL),
+        | VehicleArea:SEAT),
 
     /**
      * Property to control power state of application processor
@@ -944,40 +983,36 @@
      * For configuration information, VehiclePropConfig.configFlags can
      * have bit flag combining values in VehicleApPowerStateConfigFlag.
      *
-     * Value format for IVehicle#get / IVehicle#subscribe:
-     *   int32Values[0] : vehicle_ap_power_state_type
+     *   int32Values[0] : VehicleApPowerStateReq enum value
      *   int32Values[1] : additional parameter relevant for each state,
      *                    0 if not used.
-     * Value format for IVehicle#set:
-     *   int32Values[0] : vehicle_ap_power_state_set_type
-     *   int32Values[1] : additional parameter relevant for each request. should be 0 if not used.
      *
-     * @change_mode VEHICLE_PROP_CHANGE_MODE_ON_CHANGE
-     * @access VEHICLE_PROP_ACCESS_READ_WRITE
+     * @change_mode VehiclePropertyChangeMode:ON_CHANGE
+     * @access VEHICLE_PROP_ACCESS_READ
      */
-    AP_POWER_STATE = (
+    AP_POWER_STATE_REQ = (
         0x0A00
         | VehiclePropertyGroup:SYSTEM
         | VehiclePropertyType:INT32_VEC
         | VehicleArea:GLOBAL),
 
     /**
-     * Property to represent brightness of the display. Some cars have single
-     * control for the brightness of all displays and this property is to share
-     * change in that control.
+     * Property to report power state of application processor
      *
-     * If this is writable, android side can set this value when user changes
-     * display brightness from Settings. If this is read only, user may still
-     * change display brightness from Settings, but that will not be reflected
-     * to other displays.
+     * It is assumed that AP's power state is controller by separate power
+     * controller.
+     *
+     *   int32Values[0] : VehicleApPowerStateReport enum value
+     *   int32Values[1] : Time in ms to wake up, if necessary.  Otherwise 0.
+
      *
      * @change_mode VehiclePropertyChangeMode:ON_CHANGE
-     * @access VehiclePropertyAccess:READ_WRITE
+     * @access VEHICLE_PROP_ACCESS_WRITE
      */
-    DISPLAY_BRIGHTNESS = (
+    AP_POWER_STATE_REPORT = (
         0x0A01
         | VehiclePropertyGroup:SYSTEM
-        | VehiclePropertyType:INT32
+        | VehiclePropertyType:INT32_VEC
         | VehicleArea:GLOBAL),
 
     /**
@@ -999,6 +1034,25 @@
         | VehicleArea:GLOBAL),
 
     /**
+     * Property to represent brightness of the display. Some cars have single
+     * control for the brightness of all displays and this property is to share
+     * change in that control.
+     *
+     * If this is writable, android side can set this value when user changes
+     * display brightness from Settings. If this is read only, user may still
+     * change display brightness from Settings, but that must not be reflected
+     * to other displays.
+     *
+     * @change_mode VehiclePropertyChangeMode:ON_CHANGE
+     * @access VehiclePropertyAccess:READ_WRITE
+     */
+    DISPLAY_BRIGHTNESS = (
+        0x0A03
+        | VehiclePropertyGroup:SYSTEM
+        | VehiclePropertyType:INT32
+        | VehicleArea:GLOBAL),
+
+    /**
      * Property to feed H/W input events to android
      *
      * int32Values[0] : action defined by VehicleHwKeyInputAction
@@ -1006,6 +1060,7 @@
      * int32Values[2] : target display defined in VehicleDisplay. Events not
      *                  tied to specific display must be sent to
      *                  VehicleDisplay#MAIN.
+     *
      * @change_mode VehiclePropertyChangeMode:ON_CHANGE
      * @access VehiclePropertyAccess:READ
      * @config_flags
@@ -1016,36 +1071,23 @@
         | VehiclePropertyType:INT32_VEC
         | VehicleArea:GLOBAL),
 
-    /**
-     * Current date and time, encoded as Unix time.
-     * This value denotes the number of seconds that have elapsed since
-     * 1/1/1970.
+    /***************************************************************************
+     * Most Car Cabin properties have both a POSition and MOVE parameter.  These
+     * are used to control the various movements for seats, doors, and windows
+     * in a vehicle.
      *
-     * @change_mode VehiclePropertyChangeMode:ON_SET
-     * @access VehiclePropertyAccess:READ_WRITE
-     * @unit VehicleUnit:SECS
-     */
-    UNIX_TIME = (
-        0x0A30
-        | VehiclePropertyGroup:SYSTEM
-        | VehiclePropertyType:INT64
-        | VehicleArea:GLOBAL),
-
-    /**
-     * Current time only.
-     * Some vehicles may not keep track of date.  This property only affects
-     * the current time, in seconds during the day.  Thus, the max value for
-     * this parameter is 86,400 (24 * 60 * 60)
+     * A POS parameter allows the user to set the absolution position.  For
+     * instance, for a door, 0 indicates fully closed and max value indicates
+     * fully open.  Thus, a value halfway between min and max must indicate
+     * the door is halfway open.
      *
-     * @change_mode VehiclePropertyChangeMode:ON_SET
-     * @access VehiclePropertyAccess:READ_WRITE
-     * @unit VehicleUnit:SECS
-     */
-    CURRENT_TIME_IN_SECONDS = (
-        0x0A31
-        | VehiclePropertyGroup:SYSTEM
-        | VehiclePropertyType:INT32
-        | VehicleArea:GLOBAL),
+     * A MOVE parameter moves the device in a particular direction.  The sign
+     * indicates direction, and the magnitude indicates speed (if multiple
+     * speeds are available).  For a door, a move of -1 will close the door, and
+     * a move of +1 will open it.  Once a door reaches the limit of open/close,
+     * the door should automatically stop moving.  The user must NOT need to
+     * send a MOVE(0) command to stop the door at the end of its range.
+     **************************************************************************/
 
     /**
      * Door position
@@ -1200,7 +1242,7 @@
      *
      * This setting allows the user to save the current seat position settings
      * into the selected preset slot.  The maxValue for each seat position
-     * shall match the maxValue for SEAT_MEMORY_SELECT.
+     * must match the maxValue for SEAT_MEMORY_SELECT.
      *
      * @change_mode VehiclePropertyChangeMode:ON_CHANGE
      * @access VehiclePropertyAccess:WRITE
@@ -1590,6 +1632,14 @@
      * Max = window up / closed
      * Min = window down / open
      *
+     * For a window that may open out of plane (i.e. vent mode of sunroof) this
+     * parameter will work with negative values as follows:
+     *  Max = sunroof completely open
+     *  0 = sunroof closed.
+     *  Min = sunroof vent completely open
+     *
+     *  Note that in this mode, 0 indicates the window is closed.
+     *
      * @change_mode VehiclePropertyChangeMode:ON_CHANGE
      * @access VehiclePropertyAccess:READ_WRITE
      */
@@ -1607,6 +1657,21 @@
      * Magnitude denotes relative speed.  I.e. +2 is faster than +1 in raising
      * the window.
      *
+     * For a window that may open out of plane (i.e. vent mode of sunroof) this
+     * parameter will work as follows:
+     *
+     *  If sunroof is open:
+     *    Max = open the sunroof further, automatically stop when fully open.
+     *    Min = close the sunroof, automatically stop when sunroof is closed.
+     *
+     * If vent is open:
+     *  Max = close the vent, automatically stop when vent is closed.
+     *  Min = open the vent further, automatically stop when vent is fully open.
+     *
+     * If window is in the closed position:
+     *  Max = open the sunroof, automatically stop when sunroof is fully open.
+     *  Min = open the vent, automatically stop when vent is fully open.
+     *
      * @change_mode VehiclePropertyChangeMode:ON_CHANGE
      * @access VehiclePropertyAccess:READ_WRITE
      */
@@ -1617,40 +1682,6 @@
         | VehicleArea:WINDOW),
 
     /**
-     * Window Vent Position
-     *
-     * This feature is used to control the vent feature on a sunroof.
-     *
-     * Max = vent open
-     * Min = vent closed
-     *
-     * @change_mode VehiclePropertyChangeMode:ON_CHANGE
-     * @access VehiclePropertyAccess:READ_WRITE
-     */
-    WINDOW_VENT_POS = (
-        0x0BC2
-        | VehiclePropertyGroup:SYSTEM
-        | VehiclePropertyType:INT32
-        | VehicleArea:WINDOW),
-
-    /**
-     * Window Vent Move
-     *
-     * This feature is used to control the vent feature on a sunroof.
-     *
-     * Max = vent open
-     * Min = vent closed
-     *
-     * @change_mode VehiclePropertyChangeMode:ON_CHANGE
-     * @access VehiclePropertyAccess:READ_WRITE
-     */
-    WINDOW_VENT_MOVE = (
-        0x0BC3
-        | VehiclePropertyGroup:SYSTEM
-        | VehiclePropertyType:INT32
-        | VehicleArea:WINDOW),
-
-    /**
      * Window Lock
      *
      * True indicates windows are locked and can't be moved.
@@ -1729,10 +1760,10 @@
      * @access VehiclePropertyAccess:READ
      */
     OBD2_LIVE_FRAME = (
-      0x0D00
-      | VehiclePropertyGroup:SYSTEM
-      | VehiclePropertyType:MIXED
-      | VehicleArea:GLOBAL),
+        0x0D00
+        | VehiclePropertyGroup:SYSTEM
+        | VehiclePropertyType:MIXED
+        | VehicleArea:GLOBAL),
 
     /**
      * OBD2 Freeze Frame Sensor Data
@@ -1759,10 +1790,10 @@
      * @access VehiclePropertyAccess:READ
      */
     OBD2_FREEZE_FRAME = (
-      0x0D01
-      | VehiclePropertyGroup:SYSTEM
-      | VehiclePropertyType:MIXED
-      | VehicleArea:GLOBAL),
+        0x0D01
+        | VehiclePropertyGroup:SYSTEM
+        | VehiclePropertyType:MIXED
+        | VehicleArea:GLOBAL),
 
     /**
      * OBD2 Freeze Frame Information
@@ -1780,10 +1811,10 @@
      * @access VehiclePropertyAccess:READ
      */
     OBD2_FREEZE_FRAME_INFO = (
-      0x0D02
-      | VehiclePropertyGroup:SYSTEM
-      | VehiclePropertyType:MIXED
-      | VehicleArea:GLOBAL),
+        0x0D02
+        | VehiclePropertyGroup:SYSTEM
+        | VehiclePropertyType:MIXED
+        | VehicleArea:GLOBAL),
 
     /**
      * OBD2 Freeze Frame Clear
@@ -1806,10 +1837,164 @@
      * @access VehiclePropertyAccess:WRITE
      */
     OBD2_FREEZE_FRAME_CLEAR = (
-      0x0D03
-      | VehiclePropertyGroup:SYSTEM
-      | VehiclePropertyType:MIXED
-      | VehicleArea:GLOBAL),
+        0x0D03
+        | VehiclePropertyGroup:SYSTEM
+        | VehiclePropertyType:MIXED
+        | VehicleArea:GLOBAL),
+
+    /**
+     * Headlights State
+     *
+     * Return the current state of headlights.
+     *
+     * @change_mode VehiclePropertyChangeMode:ON_CHANGE
+     * @access VehiclePropertyAccess:READ
+     * @data_enum VehicleLightState
+     */
+    HEADLIGHTS_STATE = (
+        0x0E00
+        | VehiclePropertyGroup:SYSTEM
+        | VehiclePropertyType:INT32
+        | VehicleArea:GLOBAL),
+
+    /**
+     * High beam lights state
+     *
+     * Return the current state of high beam lights.
+     *
+     * @change_mode VehiclePropertyChangeMode:ON_CHANGE
+     * @access VehiclePropertyAccess:READ
+     * @data_enum VehicleLightState
+     */
+    HIGH_BEAM_LIGHTS_STATE = (
+        0x0E01
+        | VehiclePropertyGroup:SYSTEM
+        | VehiclePropertyType:INT32
+        | VehicleArea:GLOBAL),
+
+    /**
+     * Fog light state
+     *
+     * Return the current state of fog lights.
+     *
+     * @change_mode VehiclePropertyChangeMode:ON_CHANGE
+     * @access VehiclePropertyAccess:READ
+     * @data_enum VehicleLightState
+     */
+    FOG_LIGHTS_STATE = (
+        0x0E02
+        | VehiclePropertyGroup:SYSTEM
+        | VehiclePropertyType:INT32
+        | VehicleArea:GLOBAL),
+
+    /**
+     * Hazard light status
+     *
+     * Return the current status of hazard lights.
+     *
+     * @change_mode VehiclePropertyChangeMode:ON_CHANGE
+     * @access VehiclePropertyAccess:READ
+     * @data_enum VehicleLightState
+     */
+    HAZARD_LIGHTS_STATE = (
+        0x0E03
+        | VehiclePropertyGroup:SYSTEM
+        | VehiclePropertyType:INT32
+        | VehicleArea:GLOBAL),
+
+    /**
+     * Headlight switch
+     *
+     * The setting that the user wants.
+     *
+     * @change_mode VehiclePropertyChangeMode:ON_CHANGE
+     * @access VehiclePropertyAccess:READ_WRITE
+     * @data_enum VehicleLightSwitch
+     */
+    HEADLIGHTS_SWITCH = (
+        0x0E10
+        | VehiclePropertyGroup:SYSTEM
+        | VehiclePropertyType:INT32
+        | VehicleArea:GLOBAL),
+
+    /**
+     * High beam light switch
+     *
+     * The setting that the user wants.
+     *
+     * @change_mode VehiclePropertyChangeMode:ON_CHANGE
+     * @access VehiclePropertyAccess:READ_WRITE
+     * @data_enum VehicleLightSwitch
+     */
+    HIGH_BEAM_LIGHTS_SWITCH = (
+        0x0E11
+        | VehiclePropertyGroup:SYSTEM
+        | VehiclePropertyType:INT32
+        | VehicleArea:GLOBAL),
+
+    /**
+     * Fog light switch
+     *
+     * The setting that the user wants.
+     *
+     * @change_mode VehiclePropertyChangeMode:ON_CHANGE
+     * @access VehiclePropertyAccess:READ_WRITE
+     * @data_enum VehicleLightSwitch
+     */
+    FOG_LIGHTS_SWITCH = (
+        0x0E12
+        | VehiclePropertyGroup:SYSTEM
+        | VehiclePropertyType:INT32
+        | VehicleArea:GLOBAL),
+
+    /**
+     * Hazard light switch
+     *
+     * The setting that the user wants.
+     *
+     * @change_mode VehiclePropertyChangeMode:ON_CHANGE
+     * @access VehiclePropertyAccess:READ_WRITE
+     * @data_enum VehicleLightSwitch
+     */
+    HAZARD_LIGHTS_SWITCH = (
+        0x0E13
+        | VehiclePropertyGroup:SYSTEM
+        | VehiclePropertyType:INT32
+        | VehicleArea:GLOBAL),
+};
+
+/**
+ * Used by lights state properties to enumerate the current state of the lights.
+ *
+ * Most XXX_LIGHTS_STATE properties will only report ON and OFF states.  Only
+ * the HEADLIGHTS_STATE property will report DAYTIME_RUNNING.
+ */
+enum  VehicleLightState : int32_t {
+
+    OFF = 0,
+    ON = 1,
+    DAYTIME_RUNNING = 2
+};
+
+/**
+ * Used by lights switch properties to enumerate user selected switch setting.
+ *
+ * XXX_LIGHTS_SWITCH properties report the switch settings that the user
+ * selects.  The switch setting may be decoupled from the state reported if the
+ * user selects AUTOMATIC.
+ */
+enum VehicleLightSwitch : int32_t {
+    OFF = 0,
+    ON = 1,
+    /**
+     * Daytime running lights mode.  Most cars automatically use DRL but some
+     * cars allow the user to activate them manually.
+     */
+    DAYTIME_RUNNING = 2,
+    /**
+     * Allows the vehicle ECU to set the lights automatically
+     */
+    AUTOMATIC = 0x100,
 };
 
 /**
@@ -1841,6 +2026,24 @@
 };
 
 /**
+ * Used by INFO_FUEL_DOOR_LOCATION/INFO_CHARGE_PORT_LOCATION to enumerate fuel door or
+ * ev port location.
+ */
+enum PortLocationType : int32_t {
+    /**
+     * Default type if the vehicle does not know or report the Fuel door
+     * and ev port location.
+     */
+    UNKNOWN = 0,
+    FRONT_LEFT = 1,
+    FRONT_RIGHT = 2,
+    REAR_RIGHT = 3,
+    REAR_LEFT = 4,
+    FRONT = 5,
+    REAR = 6,
+};
+
+/**
  * Used by INFO_FUEL_TYPE to enumerate the type of fuels this vehicle uses.
  * Consistent with projection protocol.
  */
@@ -1899,14 +2102,6 @@
     ERROR = 4,
 };
 
-/**
- * Constants relevant to radio.
- */
-enum VehicleRadioConstants : int32_t {
-    /** Minimum value for the radio preset */
-    VEHICLE_RADIO_PRESET_MIN_VALUE = 1,
-};
-
 enum VehicleApPowerStateConfigFlag : int32_t /* NOTE: type is guessed */ {
     /**
      * AP can enter deep sleep state. If not set, AP will always shutdown from
@@ -1921,7 +2116,7 @@
     CONFIG_SUPPORT_TIMER_POWER_ON_FLAG = 0x2,
 };
 
-enum VehicleApPowerState : int32_t /* NOTE: type is guessed */ {
+enum VehicleApPowerStateReq : int32_t {
     /** vehicle HAL will never publish this state to AP */
     OFF = 0,
 
@@ -1946,6 +2141,16 @@
     SHUTDOWN_PREPARE = 4,
 };
 
+/**
+ * Index in int32Values for VehicleProperty#AP_POWER_STATE_REQ property.
+ */
+enum VehicleApPowerStateReqIndex : int32_t {
+    STATE = 0,
+    ADDITIONAL = 1,
+};
+
+
+
 enum VehicleApPowerStateShutdownParam : int32_t {
     /** AP must shutdown immediately. Postponing is not allowed. */
     SHUTDOWN_IMMEDIATELY = 1,
@@ -1957,7 +2162,7 @@
     SHUTDOWN_ONLY = 3,
 };
 
-enum VehicleApPowerSetState : int32_t /* NOTE: type is guessed */ {
+enum VehicleApPowerStateReport : int32_t {
     /**
      * AP has finished boot up, and can start shutdown if requested by power
      * controller.
@@ -2022,14 +2227,6 @@
 };
 
 /**
- * Index in int32Values for VehicleProperty#AP_POWER_STATE property.
- */
-enum VehicleApPowerStateIndex : int32_t {
-    STATE = 0,
-    ADDITIONAL = 1,
-};
-
-/**
  * Enum to represent bootup reason.
  */
 enum VehicleApPowerBootupReason : int32_t {
@@ -2063,7 +2260,7 @@
 };
 
 enum VehicleDisplay : int32_t {
-    /** center console */
+    /** The primary Android display (for example, center console) */
     MAIN = 0,
 
     INSTRUMENT_CLUSTER = 1,
@@ -2089,6 +2286,7 @@
     NANO_SECS      = 0x50,
     SECS           = 0x53,
     YEAR           = 0x59,
+    KILOPASCAL     = 0x70,
 
     // Electrical Units
     WATT_HOUR      = 0x60,
@@ -2097,46 +2295,33 @@
     MILLIWATTS     = 0x63,
 };
 
-  /**
-   * This describes how value of property can change.
-   */
+/**
+ * This describes how value of property can change.
+ */
 enum VehiclePropertyChangeMode : int32_t {
-  /**
-   * Property of this type must never be changed. Subscription is not supported
-   * for these properties.
-   */
-  STATIC = 0x00,
+    /**
+     * Property of this type must never be changed. Subscription is not supported
+     * for these properties.
+     */
+    STATIC = 0x00,
 
-  /**
-   * Property of this type must be reported when there is a change.
-   * IVehicle#get call must return the current value.
-   * Set operation for this property is assumed to be asynchronous. When the
-   * property is read (using IVehicle#get) after IVehicle#set, it may still
-   * return old value until underlying H/W backing this property has actually
-   * changed the state. Once state is changed, the property must dispatch
-   * changed value as event.
-   */
-  ON_CHANGE = 0x01,
+    /**
+     * Properties of this type must report when there is a change.
+     * IVehicle#get call must return the current value.
+     * Set operation for this property is assumed to be asynchronous. When the
+     * property is read (using IVehicle#get) after IVehicle#set, it may still
+     * return old value until underlying H/W backing this property has actually
+     * changed the state. Once state is changed, the property must dispatch
+     * changed value as event.
+     */
+    ON_CHANGE = 0x01,
 
-  /**
-   * Property of this type change continuously and requires fixed rate of
-   * sampling to retrieve the data.
-   */
-  CONTINUOUS = 0x02,
-
-  /**
-   * Property of this type may be polled to get the current value.
-   */
-  POLL = 0x03,
-
-  /**
-   * This is for property where change event must be sent only when the
-   * value is set from external component. Normal value change must not trigger
-   * event. For example, clock property can send change event only when it is
-   * set, outside android, for case like user setting time or time getting
-   * update. There is no need to send it per every value change.
-   */
-  ON_SET = 0x04,
+    /**
+     * Properties of this type change continuously and require a fixed rate of
+     * sampling to retrieve the data.  Implementers may choose to send extra
+     * notifications on significant value changes.
+     */
+    CONTINUOUS = 0x02,
 };
 
 /**
@@ -2160,8 +2345,15 @@
     /** Property is available and behaving normally */
     AVAILABLE   = 0x00,
     /**
-     * Property is not available, for read and/or write.  This is a transient state, as the
-     *  property is expected to be available at a later time.
+     * A property in this state is not available for reading and writing.  This
+     * is a transient state that depends on the availability of the underlying
+     * implementation (e.g. hardware or driver). It MUST NOT be used to
+     * represent features that this vehicle is always incapable of.  A get() of
+     * a property in this state MAY return an undefined value, but MUST
+     * correctly describe its status as UNAVAILABLE A set() of a property in
+     * this state MAY return NOT_AVAILABLE. The HAL implementation MUST ignore
+     * the value of the status field when writing a property value coming from
+     * Android.
      */
     UNAVAILABLE = 0x01,
     /** There is an error with this property. */
@@ -2169,28 +2361,13 @@
 };
 
 /**
- * Car states.
- *
- * The driving states determine what features of the UI will be accessible.
- */
-enum VehicleDrivingStatus : int32_t {
-    UNRESTRICTED = 0x00,
-    NO_VIDEO = 0x01,
-    NO_KEYBOARD_INPUT = 0x02,
-    NO_VOICE_INPUT = 0x04,
-    NO_CONFIG = 0x08,
-    LIMIT_MESSAGE_LEN = 0x10,
-};
-
-/**
  * Various gears which can be selected by user and chosen in system.
  */
-enum VehicleGear: int32_t {
+enum VehicleGear : int32_t {
     GEAR_NEUTRAL = 0x0001,
     GEAR_REVERSE = 0x0002,
     GEAR_PARK = 0x0004,
     GEAR_DRIVE = 0x0008,
-    GEAR_LOW = 0x0010,
     GEAR_1 = 0x0010,
     GEAR_2 = 0x0020,
     GEAR_3 = 0x0040,
@@ -2203,27 +2380,6 @@
 };
 
 /**
- * Various zones in the car.
- *
- * Zones are used for Air Conditioning purposes and divide the car into physical
- * area zones.
- */
-enum VehicleAreaZone : int32_t {
-  ROW_1_LEFT = 0x00000001,
-  ROW_1_CENTER = 0x00000002,
-  ROW_1_RIGHT = 0x00000004,
-  ROW_2_LEFT = 0x00000010,
-  ROW_2_CENTER = 0x00000020,
-  ROW_2_RIGHT = 0x00000040,
-  ROW_3_LEFT = 0x00000100,
-  ROW_3_CENTER = 0x00000200,
-  ROW_3_RIGHT = 0x00000400,
-  ROW_4_LEFT = 0x00001000,
-  ROW_4_CENTER = 0x00002000,
-  ROW_4_RIGHT = 0x00004000,
-};
-
-/**
  * Various Seats in the car.
  */
 enum VehicleAreaSeat : int32_t {
@@ -2242,15 +2398,18 @@
  * Various windshields/windows in the car.
  */
 enum VehicleAreaWindow : int32_t {
-    FRONT_WINDSHIELD = 0x0001,
-    REAR_WINDSHIELD = 0x0002,
-    ROOF_TOP = 0x0004,
-    ROW_1_LEFT = 0x0010,
-    ROW_1_RIGHT = 0x0020,
-    ROW_2_LEFT = 0x0100,
-    ROW_2_RIGHT = 0x0200,
-    ROW_3_LEFT = 0x1000,
-    ROW_3_RIGHT = 0x2000,
+    FRONT_WINDSHIELD  = 0x00000001,
+    REAR_WINDSHIELD   = 0x00000002,
+    ROW_1_LEFT        = 0x00000010,
+    ROW_1_RIGHT       = 0x00000040,
+    ROW_2_LEFT        = 0x00000100,
+    ROW_2_RIGHT       = 0x00000400,
+    ROW_3_LEFT        = 0x00001000,
+    ROW_3_RIGHT       = 0x00004000,
+
+    ROOF_TOP_1        = 0x00010000,
+    ROOF_TOP_2        = 0x00020000,
+
 };
 
 enum VehicleAreaDoor : int32_t {
@@ -2274,7 +2433,6 @@
     NONE = 0x00,
     RIGHT = 0x01,
     LEFT = 0x02,
-    EMERGENCY = 0x04,
 };
 
 struct VehicleAreaConfig {
@@ -2348,9 +2506,6 @@
  * events.
  */
 struct VehiclePropValue {
-    /** Property identifier */
-    int32_t prop;
-
     /** Time is elapsed nanoseconds since boot */
     int64_t timestamp;
 
@@ -2360,6 +2515,9 @@
      */
     int32_t areaId;
 
+    /** Property identifier */
+    int32_t prop;
+
     /** Status of the property */
     VehiclePropertyStatus status;
 
@@ -2399,11 +2557,11 @@
     /** Steering wheel is locked */
     LOCK = 1,
 
-     /**
-      * Steering wheel is not locked, engine and all accessories are OFF. If
-      * car can be in LOCK and OFF state at the same time than HAL must report
-      * LOCK state.
-      */
+    /**
+     * Steering wheel is not locked, engine and all accessories are OFF. If
+     * car can be in LOCK and OFF state at the same time than HAL must report
+     * LOCK state.
+     */
     OFF,
 
     /**
@@ -2422,33 +2580,6 @@
     START
 };
 
-
-/**
- * Represent the operation where the current error has happened.
- */
-enum VehiclePropertyOperation : int32_t {
-    /**
-     * Generic error to this property which is not tied to any operation.
-     */
-    GENERIC = 0,
-
-    /**
-     * Error happened while handling property set.
-     */
-    SET = 1,
-
-    /**
-     * Error happened while handling property get.
-     */
-    GET = 2,
-
-    /**
-     * Error happened while handling property subscription.
-     */
-    SUBSCRIBE = 3,
-};
-
-
 enum SubscribeFlags : int32_t {
     UNDEFINED = 0x0,
 
@@ -2456,15 +2587,13 @@
      * Subscribe to event that was originated in vehicle HAL
      * (most likely this event came from the vehicle itself).
      */
-    HAL_EVENT = 0x1,
+    EVENTS_FROM_CAR = 0x1,
 
     /**
      * Use this flag to subscribe on events when IVehicle#set(...) was called by
      * vehicle HAL's client (e.g. Car Service).
      */
-    SET_CALL = 0x2,
-
-    DEFAULT = HAL_EVENT,
+    EVENTS_FROM_ANDROID = 0x2,
 };
 
 /**
@@ -2485,7 +2614,7 @@
      */
     float sampleRate;
 
-    /** Flags that indicate what kind of events listen to. */
+    /** Flags that indicate to which event sources to listen. */
     SubscribeFlags flags;
 };
 
@@ -2775,11 +2904,11 @@
     ACCELERATOR_PEDAL_POSITION_E = 54, /* PID 0x4A */
     ACCELERATOR_PEDAL_POSITION_F = 55, /* PID 0x4B */
     COMMANDED_THROTTLE_ACTUATOR = 56, /* PID 0x4C */
-    ETHANOL_FUEL_PERCENTAGE = 57,/* PID 0x52 */
+    ETHANOL_FUEL_PERCENTAGE = 57, /* PID 0x52 */
     ABSOLUTE_EVAPORATION_SYSTEM_VAPOR_PRESSURE = 58, /* PID 0x53 */
     SHORT_TERM_SECONDARY_OXYGEN_SENSOR_TRIM_BANK1 = 59, /* PID 0x55 */
     SHORT_TERM_SECONDARY_OXYGEN_SENSOR_TRIM_BANK2 = 60, /* PID 0x57 */
-    SHORT_TERM_SECONDARY_OXYGEN_SENSOR_TRIM_BANK3 = 61,/* PID 0x55 */
+    SHORT_TERM_SECONDARY_OXYGEN_SENSOR_TRIM_BANK3 = 61, /* PID 0x55 */
     SHORT_TERM_SECONDARY_OXYGEN_SENSOR_TRIM_BANK4 = 62, /* PID 0x57 */
     LONG_TERM_SECONDARY_OXYGEN_SENSOR_TRIM_BANK1 = 63, /* PID 0x56 */
     LONG_TERM_SECONDARY_OXYGEN_SENSOR_TRIM_BANK2 = 64, /* PID 0x58 */
@@ -3005,7 +3134,7 @@
  * - Layer version
  * - Number of publisher IDs (N)
  * - N x publisher ID
-*/
+ */
 enum VmsAvailabilityStateIntegerValuesIndex : VmsBaseMessageIntegerValuesIndex {
     SEQUENCE_NUMBER = 1,
     NUMBER_OF_ASSOCIATED_LAYERS = 2,
diff --git a/bluetooth/1.0/default/android.hardware.bluetooth@1.0-service.rc b/bluetooth/1.0/default/android.hardware.bluetooth@1.0-service.rc
index 5a01ecc..a634441 100644
--- a/bluetooth/1.0/default/android.hardware.bluetooth@1.0-service.rc
+++ b/bluetooth/1.0/default/android.hardware.bluetooth@1.0-service.rc
@@ -1,6 +1,6 @@
 service vendor.bluetooth-1-0 /vendor/bin/hw/android.hardware.bluetooth@1.0-service
     class hal
-    capabilities NET_ADMIN SYS_NICE
+    capabilities BLOCK_SUSPEND NET_ADMIN SYS_NICE
     user bluetooth
     group bluetooth
     writepid /dev/stune/foreground/tasks
diff --git a/broadcastradio/1.1/default/Tuner.cpp b/broadcastradio/1.1/default/Tuner.cpp
index ae01879..4b49b59 100644
--- a/broadcastradio/1.1/default/Tuner.cpp
+++ b/broadcastradio/1.1/default/Tuner.cpp
@@ -86,6 +86,7 @@
 
     mIsAmfmConfigSet = true;
     mCallback->configChange(Result::OK, mAmfmConfig);
+    if (mCallback1_1 != nullptr) mCallback1_1->programListChanged();
 }
 
 bool Tuner::autoConfigureLocked(uint64_t frequency) {
diff --git a/broadcastradio/2.0/ITunerCallback.hal b/broadcastradio/2.0/ITunerCallback.hal
index ede8350..b20a0b2 100644
--- a/broadcastradio/2.0/ITunerCallback.hal
+++ b/broadcastradio/2.0/ITunerCallback.hal
@@ -17,12 +17,14 @@
 
 interface ITunerCallback {
     /**
-     * Method called by the HAL when a tuning operation fails
+     * Method called by the HAL when a tuning operation fails asynchronously
      * following a step(), scan() or tune() command.
      *
-     * @param result OK if tune succeeded;
-     *               TIMEOUT in case of time out.
-     * @param selector A ProgramSelector structure passed from tune(),
+     * This callback is only called when the step(), scan() or tune() command
+     * returned OK at first.
+     *
+     * @param result TIMEOUT in case of time out.
+     * @param selector A ProgramSelector structure passed from tune() call;
      *                 empty for step() and scan().
      */
     oneway onTuneFailed(Result result, ProgramSelector selector);
diff --git a/broadcastradio/2.0/types.hal b/broadcastradio/2.0/types.hal
index a9b9600..1ce61df 100644
--- a/broadcastradio/2.0/types.hal
+++ b/broadcastradio/2.0/types.hal
@@ -351,10 +351,16 @@
      * related content (i.e. DAB soft-links). This field is a list of pointers
      * to other programs on the program list.
      *
-     * Please note, that these identifiers does not have to exist on the program
+     * This is not a list of programs that carry the same content (i.e.
+     * DAB hard-links, RDS AF). Switching to programs from this list usually
+     * require user action.
+     *
+     * Please note, that these identifiers do not have to exist on the program
      * list - i.e. DAB tuner may provide information on FM RDS alternatives
      * despite not supporting FM RDS. If the system has multiple tuners, another
      * one may have it on its list.
+     *
+     * This field is optional (can be empty).
      */
     vec<ProgramIdentifier> relatedContent;
 
diff --git a/camera/device/3.4/default/CameraDeviceSession.cpp b/camera/device/3.4/default/CameraDeviceSession.cpp
index ad7f6f5..550d65a 100644
--- a/camera/device/3.4/default/CameraDeviceSession.cpp
+++ b/camera/device/3.4/default/CameraDeviceSession.cpp
@@ -51,6 +51,32 @@
             }
         }
     }
+
+    camera_metadata_entry_t capabilities =
+            mDeviceInfo.find(ANDROID_REQUEST_AVAILABLE_CAPABILITIES);
+    bool isLogicalMultiCamera = false;
+    for (size_t i = 0; i < capabilities.count; i++) {
+        if (capabilities.data.u8[i] ==
+                ANDROID_REQUEST_AVAILABLE_CAPABILITIES_LOGICAL_MULTI_CAMERA) {
+            isLogicalMultiCamera = true;
+            break;
+        }
+    }
+    if (isLogicalMultiCamera) {
+        camera_metadata_entry entry =
+                mDeviceInfo.find(ANDROID_LOGICAL_MULTI_CAMERA_PHYSICAL_IDS);
+        const uint8_t* ids = entry.data.u8;
+        size_t start = 0;
+        for (size_t i = 0; i < entry.count; ++i) {
+            if (ids[i] == '\0') {
+                if (start != i) {
+                    const char* physicalId = reinterpret_cast<const char*>(ids+start);
+                    mPhysicalCameraIds.emplace(physicalId);
+                }
+                start = i + 1;
+            }
+        }
+    }
 }
 
 CameraDeviceSession::~CameraDeviceSession() {
@@ -456,9 +482,19 @@
         return;
     }
 
+    if (hal_result->num_physcam_metadata > d->mPhysicalCameraIds.size()) {
+        ALOGE("%s: Fatal: Invalid num_physcam_metadata %u", __FUNCTION__,
+                hal_result->num_physcam_metadata);
+        return;
+    }
     result.physicalCameraMetadata.resize(hal_result->num_physcam_metadata);
     for (uint32_t i = 0; i < hal_result->num_physcam_metadata; i++) {
         std::string physicalId = hal_result->physcam_ids[i];
+        if (d->mPhysicalCameraIds.find(physicalId) == d->mPhysicalCameraIds.end()) {
+            ALOGE("%s: Fatal: Invalid physcam_ids[%u]: %s", __FUNCTION__,
+                  i, hal_result->physcam_ids[i]);
+            return;
+        }
         V3_2::CameraMetadata physicalMetadata;
         V3_2::implementation::convertToHidl(hal_result->physcam_metadata[i], &physicalMetadata);
         PhysicalCameraMetadata physicalCameraMetadata = {
diff --git a/camera/device/3.4/default/ExternalCameraDeviceSession.cpp b/camera/device/3.4/default/ExternalCameraDeviceSession.cpp
index 7015bcb..bb11d7c 100644
--- a/camera/device/3.4/default/ExternalCameraDeviceSession.cpp
+++ b/camera/device/3.4/default/ExternalCameraDeviceSession.cpp
@@ -51,10 +51,12 @@
                              // webcam showing temporarily ioctl failures.
 constexpr int IOCTL_RETRY_SLEEP_US = 33000; // 33ms * MAX_RETRY = 5 seconds
 
+// Constants for tryLock during dumpstate
+static constexpr int kDumpLockRetries = 50;
+static constexpr int kDumpLockSleep = 60000;
+
 bool tryLock(Mutex& mutex)
 {
-    static const int kDumpLockRetries = 50;
-    static const int kDumpLockSleep = 60000;
     bool locked = false;
     for (int i = 0; i < kDumpLockRetries; ++i) {
         if (mutex.tryLock() == NO_ERROR) {
@@ -66,6 +68,19 @@
     return locked;
 }
 
+bool tryLock(std::mutex& mutex)
+{
+    bool locked = false;
+    for (int i = 0; i < kDumpLockRetries; ++i) {
+        if (mutex.try_lock()) {
+            locked = true;
+            break;
+        }
+        usleep(kDumpLockSleep);
+    }
+    return locked;
+}
+
 } // Anonymous namespace
 
 // Static instances
@@ -163,7 +178,6 @@
     bool streaming = false;
     size_t v4L2BufferCount = 0;
     SupportedV4L2Format streamingFmt;
-    std::unordered_set<uint32_t>  inflightFrames;
     {
         bool sessionLocked = tryLock(mLock);
         if (!sessionLocked) {
@@ -172,12 +186,25 @@
         streaming = mV4l2Streaming;
         streamingFmt = mV4l2StreamingFmt;
         v4L2BufferCount = mV4L2BufferCount;
-        inflightFrames = mInflightFrames;
+
         if (sessionLocked) {
             mLock.unlock();
         }
     }
 
+    std::unordered_set<uint32_t>  inflightFrames;
+    {
+        bool iffLocked = tryLock(mInflightFramesLock);
+        if (!iffLocked) {
+            dprintf(fd,
+                    "!! ExternalCameraDeviceSession mInflightFramesLock may be deadlocked !!\n");
+        }
+        inflightFrames = mInflightFrames;
+        if (iffLocked) {
+            mInflightFramesLock.unlock();
+        }
+    }
+
     dprintf(fd, "External camera %s V4L2 FD %d, cropping type %s, %s\n",
             mCameraId.c_str(), mV4l2Fd.get(),
             (mCroppingType == VERTICAL) ? "vertical" : "horizontal",
@@ -457,6 +484,7 @@
 }
 
 int ExternalCameraDeviceSession::waitForV4L2BufferReturnLocked(std::unique_lock<std::mutex>& lk) {
+    ATRACE_CALL();
     std::chrono::seconds timeout = std::chrono::seconds(kBufferWaitTimeoutSec);
     mLock.unlock();
     auto st = mV4L2BufferReturned.wait_for(lk, timeout);
@@ -612,7 +640,10 @@
         halBuf.acquireFence = allFences[i];
         halBuf.fenceTimeout = false;
     }
-    mInflightFrames.insert(halReq->frameNumber);
+    {
+        std::lock_guard<std::mutex> lk(mInflightFramesLock);
+        mInflightFrames.insert(halReq->frameNumber);
+    }
     // Send request to OutputThread for the rest of processing
     mOutputThread->submitRequest(halReq);
     mFirstRequest = false;
@@ -670,7 +701,7 @@
 
     // update inflight records
     {
-        Mutex::Autolock _l(mLock);
+        std::lock_guard<std::mutex> lk(mInflightFramesLock);
         mInflightFrames.erase(req->frameNumber);
     }
 
@@ -724,7 +755,7 @@
 
     // update inflight records
     {
-        Mutex::Autolock _l(mLock);
+        std::lock_guard<std::mutex> lk(mInflightFramesLock);
         mInflightFrames.erase(req->frameNumber);
     }
 
@@ -2149,6 +2180,13 @@
     }
     uint32_t bufferSize = fmt.fmt.pix.sizeimage;
     ALOGI("%s: V4L2 buffer size is %d", __FUNCTION__, bufferSize);
+    uint32_t expectedMaxBufferSize = kMaxBytesPerPixel * fmt.fmt.pix.width * fmt.fmt.pix.height;
+    if ((bufferSize == 0) || (bufferSize > expectedMaxBufferSize)) {
+        ALOGE("%s: V4L2 buffer size: %u looks invalid. Expected maximum size: %u", __FUNCTION__,
+                bufferSize, expectedMaxBufferSize);
+        return -EINVAL;
+    }
+    mMaxV4L2BufferSize = bufferSize;
 
     const double kDefaultFps = 30.0;
     double fps = 1000.0;
@@ -2278,6 +2316,7 @@
         }
     }
 
+    ATRACE_BEGIN("VIDIOC_DQBUF");
     v4l2_buffer buffer{};
     buffer.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
     buffer.memory = V4L2_MEMORY_MMAP;
@@ -2285,6 +2324,7 @@
         ALOGE("%s: DQBUF fails: %s", __FUNCTION__, strerror(errno));
         return ret;
     }
+    ATRACE_END();
 
     if (buffer.index >= mV4L2BufferCount) {
         ALOGE("%s: Invalid buffer id: %d", __FUNCTION__, buffer.index);
@@ -2296,6 +2336,12 @@
         // TODO: try to dequeue again
     }
 
+    if (buffer.bytesused > mMaxV4L2BufferSize) {
+        ALOGE("%s: v4l2 buffer bytes used: %u maximum %u", __FUNCTION__, buffer.bytesused,
+                mMaxV4L2BufferSize);
+        return ret;
+    }
+
     if (buffer.flags & V4L2_BUF_FLAG_TIMESTAMP_MONOTONIC) {
         // Ideally we should also check for V4L2_BUF_FLAG_TSTAMP_SRC_SOE, but
         // even V4L2_BUF_FLAG_TSTAMP_SRC_EOF is better than capture a timestamp now
@@ -2316,21 +2362,18 @@
 
 void ExternalCameraDeviceSession::enqueueV4l2Frame(const sp<V4L2Frame>& frame) {
     ATRACE_CALL();
-    {
-        // Release mLock before acquiring mV4l2BufferLock to avoid potential
-        // deadlock
-        Mutex::Autolock _l(mLock);
-        frame->unmap();
-        v4l2_buffer buffer{};
-        buffer.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
-        buffer.memory = V4L2_MEMORY_MMAP;
-        buffer.index = frame->mBufferIndex;
-        if (TEMP_FAILURE_RETRY(ioctl(mV4l2Fd.get(), VIDIOC_QBUF, &buffer)) < 0) {
-            ALOGE("%s: QBUF index %d fails: %s", __FUNCTION__,
-                    frame->mBufferIndex, strerror(errno));
-            return;
-        }
+    frame->unmap();
+    ATRACE_BEGIN("VIDIOC_QBUF");
+    v4l2_buffer buffer{};
+    buffer.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
+    buffer.memory = V4L2_MEMORY_MMAP;
+    buffer.index = frame->mBufferIndex;
+    if (TEMP_FAILURE_RETRY(ioctl(mV4l2Fd.get(), VIDIOC_QBUF, &buffer)) < 0) {
+        ALOGE("%s: QBUF index %d fails: %s", __FUNCTION__,
+                frame->mBufferIndex, strerror(errno));
+        return;
     }
+    ATRACE_END();
 
     {
         std::lock_guard<std::mutex> lk(mV4l2BufferLock);
@@ -2383,13 +2426,17 @@
         return status;
     }
 
-    Mutex::Autolock _l(mLock);
-    if (!mInflightFrames.empty()) {
-        ALOGE("%s: trying to configureStreams while there are still %zu inflight frames!",
-                __FUNCTION__, mInflightFrames.size());
-        return Status::INTERNAL_ERROR;
+
+    {
+        std::lock_guard<std::mutex> lk(mInflightFramesLock);
+        if (!mInflightFrames.empty()) {
+            ALOGE("%s: trying to configureStreams while there are still %zu inflight frames!",
+                    __FUNCTION__, mInflightFrames.size());
+            return Status::INTERNAL_ERROR;
+        }
     }
 
+    Mutex::Autolock _l(mLock);
     // Add new streams
     for (const auto& stream : config.streams) {
         if (mStreamMap.count(stream.id) == 0) {
@@ -2689,14 +2736,17 @@
     const uint8_t ae_lock = ANDROID_CONTROL_AE_LOCK_OFF;
     UPDATE(md, ANDROID_CONTROL_AE_LOCK, &ae_lock, 1);
 
-    bool afTrigger = mAfTrigger;
-    if (md.exists(ANDROID_CONTROL_AF_TRIGGER)) {
-        Mutex::Autolock _l(mLock);
-        camera_metadata_entry entry = md.find(ANDROID_CONTROL_AF_TRIGGER);
-        if (entry.data.u8[0] == ANDROID_CONTROL_AF_TRIGGER_START) {
-            mAfTrigger = afTrigger = true;
-        } else if (entry.data.u8[0] == ANDROID_CONTROL_AF_TRIGGER_CANCEL) {
-            mAfTrigger = afTrigger = false;
+    bool afTrigger = false;
+    {
+        std::lock_guard<std::mutex> lk(mAfTriggerLock);
+        afTrigger = mAfTrigger;
+        if (md.exists(ANDROID_CONTROL_AF_TRIGGER)) {
+            camera_metadata_entry entry = md.find(ANDROID_CONTROL_AF_TRIGGER);
+            if (entry.data.u8[0] == ANDROID_CONTROL_AF_TRIGGER_START) {
+                mAfTrigger = afTrigger = true;
+            } else if (entry.data.u8[0] == ANDROID_CONTROL_AF_TRIGGER_CANCEL) {
+                mAfTrigger = afTrigger = false;
+            }
         }
     }
 
diff --git a/camera/device/3.4/default/include/device_v3_4_impl/CameraDeviceSession.h b/camera/device/3.4/default/include/device_v3_4_impl/CameraDeviceSession.h
index 6e90ed4..5d6a112 100644
--- a/camera/device/3.4/default/include/device_v3_4_impl/CameraDeviceSession.h
+++ b/camera/device/3.4/default/include/device_v3_4_impl/CameraDeviceSession.h
@@ -27,6 +27,7 @@
 #include <hidl/Status.h>
 #include <deque>
 #include <map>
+#include <unordered_set>
 #include <unordered_map>
 #include "CameraMetadata.h"
 #include "HandleImporter.h"
@@ -110,6 +111,10 @@
 
     // Whether this camera device session is created with version 3.4 callback.
     bool mHasCallback_3_4;
+
+    // Physical camera ids for the logical multi-camera. Empty if this
+    // is not a logical multi-camera.
+    std::unordered_set<std::string> mPhysicalCameraIds;
 private:
 
     struct TrampolineSessionInterface_3_4 : public ICameraDeviceSession {
diff --git a/camera/device/3.4/default/include/ext_device_v3_4_impl/ExternalCameraDeviceSession.h b/camera/device/3.4/default/include/ext_device_v3_4_impl/ExternalCameraDeviceSession.h
index 5315097..14e5c9a 100644
--- a/camera/device/3.4/default/include/ext_device_v3_4_impl/ExternalCameraDeviceSession.h
+++ b/camera/device/3.4/default/include/ext_device_v3_4_impl/ExternalCameraDeviceSession.h
@@ -108,6 +108,7 @@
 
     static const int kMaxProcessedStream = 2;
     static const int kMaxStallStream = 1;
+    static const uint32_t kMaxBytesPerPixel = 2;
 
 protected:
 
@@ -299,6 +300,9 @@
     const std::vector<SupportedV4L2Format> mSupportedFormats;
     const CroppingType mCroppingType;
     const std::string& mCameraId;
+
+    // Not protected by mLock, this is almost a const.
+    // Setup in constructor, reset in close() after OutputThread is joined
     unique_fd mV4l2Fd;
 
     // device is closed either
@@ -319,12 +323,15 @@
     std::mutex mV4l2BufferLock; // protect the buffer count and condition below
     std::condition_variable mV4L2BufferReturned;
     size_t mNumDequeuedV4l2Buffers = 0;
+    uint32_t mMaxV4L2BufferSize = 0;
 
     // Not protected by mLock (but might be used when mLock is locked)
     sp<OutputThread> mOutputThread;
 
     // Stream ID -> Camera3Stream cache
     std::unordered_map<int, Stream> mStreamMap;
+
+    std::mutex mInflightFramesLock; // protect mInflightFrames
     std::unordered_set<uint32_t>  mInflightFrames;
 
     // buffers currently circulating between HAL and camera service
@@ -336,6 +343,7 @@
     // Stream ID -> circulating buffers map
     std::map<int, CirculatingBuffers> mCirculatingBuffers;
 
+    std::mutex mAfTriggerLock; // protect mAfTrigger
     bool mAfTrigger = false;
 
     static HandleImporter sHandleImporter;
diff --git a/camera/metadata/3.3/types.hal b/camera/metadata/3.3/types.hal
index 0535be1..04edfe9 100644
--- a/camera/metadata/3.3/types.hal
+++ b/camera/metadata/3.3/types.hal
@@ -230,6 +230,7 @@
         @3.2::CameraMetadataEnumAndroidRequestAvailableCapabilities {
     ANDROID_REQUEST_AVAILABLE_CAPABILITIES_MOTION_TRACKING,
     ANDROID_REQUEST_AVAILABLE_CAPABILITIES_LOGICAL_MULTI_CAMERA,
+    ANDROID_REQUEST_AVAILABLE_CAPABILITIES_MONOCHROME,
 };
 
 /** android.statistics.oisDataMode enumeration values
diff --git a/compatibility_matrices/Android.mk b/compatibility_matrices/Android.mk
index 71253da..948b4fe 100644
--- a/compatibility_matrices/Android.mk
+++ b/compatibility_matrices/Android.mk
@@ -21,6 +21,8 @@
 # Clear potential input variables to BUILD_FRAMEWORK_COMPATIBILITY_MATRIX
 LOCAL_ADD_VBMETA_VERSION :=
 LOCAL_ASSEMBLE_VINTF_ENV_VARS :=
+LOCAL_ASSEMBLE_VINTF_ENV_VARS_OVERRIDE :=
+LOCAL_ASSEMBLE_VINTF_ERROR_MESSAGE :=
 LOCAL_ASSEMBLE_VINTF_FLAGS :=
 LOCAL_KERNEL_VERSIONS :=
 LOCAL_GEN_FILE_DEPENDENCIES :=
@@ -29,18 +31,21 @@
 
 
 include $(CLEAR_VARS)
+LOCAL_MODULE := framework_compatibility_matrix.legacy.xml
 LOCAL_MODULE_STEM := compatibility_matrix.legacy.xml
 LOCAL_SRC_FILES := $(LOCAL_MODULE_STEM)
 LOCAL_KERNEL_VERSIONS := 3.18.0 4.4.0 4.9.0
 include $(BUILD_FRAMEWORK_COMPATIBILITY_MATRIX)
 
 include $(CLEAR_VARS)
+LOCAL_MODULE := framework_compatibility_matrix.1.xml
 LOCAL_MODULE_STEM := compatibility_matrix.1.xml
 LOCAL_SRC_FILES := $(LOCAL_MODULE_STEM)
 LOCAL_KERNEL_VERSIONS := 3.18.0 4.4.0 4.9.0
 include $(BUILD_FRAMEWORK_COMPATIBILITY_MATRIX)
 
 include $(CLEAR_VARS)
+LOCAL_MODULE := framework_compatibility_matrix.2.xml
 LOCAL_MODULE_STEM := compatibility_matrix.2.xml
 LOCAL_SRC_FILES := $(LOCAL_MODULE_STEM)
 LOCAL_KERNEL_VERSIONS := 3.18.0 4.4.0 4.9.0
@@ -49,7 +54,8 @@
 # TODO(b/72409164): STOPSHIP: update kernel version requirements
 
 include $(CLEAR_VARS)
-LOCAL_MODULE_STEM := compatibility_matrix.current.xml
+LOCAL_MODULE := framework_compatibility_matrix.3.xml
+LOCAL_MODULE_STEM := compatibility_matrix.3.xml
 LOCAL_SRC_FILES := $(LOCAL_MODULE_STEM)
 LOCAL_KERNEL_VERSIONS := 4.4.0 4.9.0
 include $(BUILD_FRAMEWORK_COMPATIBILITY_MATRIX)
@@ -57,14 +63,47 @@
 # Framework Compatibility Matrix (common to all FCM versions)
 
 include $(CLEAR_VARS)
-LOCAL_MODULE_STEM := compatibility_matrix.empty.xml
-LOCAL_SRC_FILES := $(LOCAL_MODULE_STEM)
+LOCAL_MODULE := framework_compatibility_matrix.device.xml
+LOCAL_MODULE_STEM := compatibility_matrix.device.xml
+# define LOCAL_MODULE_CLASS for local-generated-sources-dir.
+LOCAL_MODULE_CLASS := ETC
+
+ifndef DEVICE_FRAMEWORK_COMPATIBILITY_MATRIX_FILE
+LOCAL_SRC_FILES := compatibility_matrix.empty.xml
+else
+
+# DEVICE_FRAMEWORK_COMPATIBILITY_MATRIX_FILE specify an absolute path
+LOCAL_GENERATED_SOURCES := $(DEVICE_FRAMEWORK_COMPATIBILITY_MATRIX_FILE)
+
+# Enforce that DEVICE_FRAMEWORK_COMPATIBILITY_MATRIX_FILE does not specify required HALs
+# by checking it against an empty manifest. But the empty manifest needs to contain
+# BOARD_SEPOLICY_VERS to be compatible with DEVICE_FRAMEWORK_COMPATIBILITY_MATRIX_FILE.
+my_manifest_src_file := $(LOCAL_PATH)/manifest.empty.xml
+my_gen_check_manifest := $(local-generated-sources-dir)/manifest.check.xml
+$(my_gen_check_manifest): PRIVATE_SRC_FILE := $(my_manifest_src_file)
+$(my_gen_check_manifest): $(my_manifest_src_file) $(HOST_OUT_EXECUTABLES)/assemble_vintf
+	BOARD_SEPOLICY_VERS=$(BOARD_SEPOLICY_VERS) \
+	VINTF_IGNORE_TARGET_FCM_VERSION=true \
+		$(HOST_OUT_EXECUTABLES)/assemble_vintf -i $(PRIVATE_SRC_FILE) -o $@
+
+LOCAL_GEN_FILE_DEPENDENCIES += $(my_gen_check_manifest)
+LOCAL_ASSEMBLE_VINTF_FLAGS += -c "$(my_gen_check_manifest)"
+
+my_gen_check_manifest :=
+my_manifest_src_file :=
+
+endif # DEVICE_FRAMEWORK_COMPATIBILITY_MATRIX_FILE
+
 LOCAL_ADD_VBMETA_VERSION := true
 LOCAL_ASSEMBLE_VINTF_ENV_VARS := \
     POLICYVERS \
     PLATFORM_SEPOLICY_VERSION \
     PLATFORM_SEPOLICY_COMPAT_VERSIONS
 
+LOCAL_ASSEMBLE_VINTF_ENV_VARS_OVERRIDE := PRODUCT_ENFORCE_VINTF_MANIFEST=true
+LOCAL_ASSEMBLE_VINTF_ERROR_MESSAGE := \
+    "Error: DEVICE_FRAMEWORK_COMPATIBILITY_MATRIX cannot contain required HALs."
+
 include $(BUILD_FRAMEWORK_COMPATIBILITY_MATRIX)
 
 # Framework Compatibility Matrix
@@ -77,8 +116,8 @@
     framework_compatibility_matrix.legacy.xml \
     framework_compatibility_matrix.1.xml \
     framework_compatibility_matrix.2.xml \
-    framework_compatibility_matrix.current.xml \
-    framework_compatibility_matrix.empty.xml
+    framework_compatibility_matrix.3.xml \
+    framework_compatibility_matrix.device.xml
 LOCAL_GENERATED_SOURCES := $(call module-installed-files,$(LOCAL_REQUIRED_MODULES))
 
 ifdef BUILT_VENDOR_MANIFEST
@@ -88,6 +127,14 @@
 
 LOCAL_ASSEMBLE_VINTF_ENV_VARS := PRODUCT_ENFORCE_VINTF_MANIFEST
 
+# TODO(b/65028233): Enforce no "unused HALs" for devices that does not define
+# DEVICE_FRAMEWORK_COMPATIBILITY_MATRIX_FILE as well
+ifeq (true,$(strip $(PRODUCT_ENFORCE_VINTF_MANIFEST)))
+ifdef DEVICE_FRAMEWORK_COMPATIBILITY_MATRIX_FILE
+LOCAL_ASSEMBLE_VINTF_ENV_VARS_OVERRIDE := VINTF_ENFORCE_NO_UNUSED_HALS=true
+endif
+endif
+
 include $(BUILD_FRAMEWORK_COMPATIBILITY_MATRIX)
 BUILT_SYSTEM_COMPATIBILITY_MATRIX := $(LOCAL_BUILT_MODULE)
 
diff --git a/compatibility_matrices/compatibility_matrix.current.xml b/compatibility_matrices/compatibility_matrix.3.xml
similarity index 87%
rename from compatibility_matrices/compatibility_matrix.current.xml
rename to compatibility_matrices/compatibility_matrix.3.xml
index 370ffdd..6aa5fc5 100644
--- a/compatibility_matrices/compatibility_matrix.current.xml
+++ b/compatibility_matrices/compatibility_matrix.3.xml
@@ -24,6 +24,14 @@
         </interface>
     </hal>
     <hal format="hidl" optional="true">
+        <name>android.hardware.automotive.audiocontrol</name>
+        <version>1.0</version>
+        <interface>
+            <name>IAudioControl</name>
+            <instance>default</instance>
+        </interface>
+    </hal>
+    <hal format="hidl" optional="true">
         <name>android.hardware.automotive.evs</name>
         <version>1.0</version>
         <interface>
@@ -56,6 +64,14 @@
         </interface>
     </hal>
     <hal format="hidl" optional="true">
+        <name>android.hardware.bluetooth.a2dp</name>
+        <version>1.0</version>
+        <interface>
+            <name>IBluetoothAudioOffload</name>
+            <instance>default</instance>
+        </interface>
+    </hal>
+    <hal format="hidl" optional="true">
         <name>android.hardware.boot</name>
         <version>1.0</version>
         <interface>
@@ -76,7 +92,7 @@
         <version>2.4</version>
         <interface>
             <name>ICameraProvider</name>
-            <instance>legacy/0</instance>
+            <regex-instance>[^/]+/[0-9]+</regex-instance>
         </interface>
     </hal>
     <hal format="hidl" optional="true">
@@ -96,6 +112,14 @@
         </interface>
     </hal>
     <hal format="hidl" optional="true">
+        <name>android.hardware.confirmationui</name>
+        <version>1.0</version>
+        <interface>
+            <name>IConfirmationUI</name>
+            <instance>default</instance>
+        </interface>
+    </hal>
+    <hal format="hidl" optional="true">
         <name>android.hardware.contexthub</name>
         <version>1.0</version>
         <interface>
@@ -103,16 +127,28 @@
             <instance>default</instance>
         </interface>
     </hal>
-    <hal format="hidl" optional="false">
+    <hal format="hidl" optional="true">
         <name>android.hardware.drm</name>
         <version>1.0</version>
         <interface>
             <name>ICryptoFactory</name>
-            <instance>default</instance>
+            <regex-instance>.*</regex-instance>
         </interface>
         <interface>
             <name>IDrmFactory</name>
-            <instance>default</instance>
+            <regex-instance>.*</regex-instance>
+        </interface>
+    </hal>
+    <hal format="hidl" optional="false">
+        <name>android.hardware.drm</name>
+        <version>1.1</version>
+        <interface>
+            <name>ICryptoFactory</name>
+            <regex-instance>.*</regex-instance>
+        </interface>
+        <interface>
+            <name>IDrmFactory</name>
+            <regex-instance>.*</regex-instance>
         </interface>
     </hal>
     <hal format="hidl" optional="true">
@@ -133,7 +169,7 @@
     </hal>
     <hal format="hidl" optional="true">
         <name>android.hardware.gnss</name>
-        <version>1.0</version>
+        <version>1.0-1</version>
         <interface>
             <name>IGnss</name>
             <instance>default</instance>
@@ -225,13 +261,12 @@
         <version>1.0</version>
         <interface>
             <name>IDevice</name>
-            <!-- TODO(b/73738616): This should be * (match any) -->
-            <instance>hvx</instance>
+            <regex-instance>.*</regex-instance>
         </interface>
     </hal>
     <hal format="hidl" optional="true">
         <name>android.hardware.nfc</name>
-        <version>1.0</version>
+        <version>1.0-1</version>
         <interface>
             <name>INfc</name>
             <instance>default</instance>
@@ -255,10 +290,12 @@
     </hal>
     <hal format="hidl" optional="true">
         <name>android.hardware.radio</name>
-        <version>1.0-1</version>
+        <version>1.0-2</version>
         <interface>
             <name>IRadio</name>
             <instance>slot1</instance>
+            <instance>slot2</instance>
+            <instance>slot3</instance>
         </interface>
         <interface>
             <name>ISap</name>
@@ -266,6 +303,14 @@
         </interface>
     </hal>
     <hal format="hidl" optional="true">
+        <name>android.hardware.radio.config</name>
+        <version>1.0</version>
+        <interface>
+            <name>IRadioConfig</name>
+            <instance>default</instance>
+        </interface>
+    </hal>
+    <hal format="hidl" optional="true">
         <name>android.hardware.renderscript</name>
         <version>1.0</version>
         <interface>
@@ -278,7 +323,8 @@
         <version>1.0</version>
         <interface>
             <name>ISecureElement</name>
-            <instance>eSE1</instance>
+            <regex-instance>eSE[1-9][0-9]*</regex-instance>
+            <regex-instance>SIM[1-9][0-9]*</regex-instance>
         </interface>
     </hal>
     <hal format="hidl" optional="true">
diff --git a/compatibility_matrices/compatibility_matrix.mk b/compatibility_matrices/compatibility_matrix.mk
index 96815b8..6dc2b4f 100644
--- a/compatibility_matrices/compatibility_matrix.mk
+++ b/compatibility_matrices/compatibility_matrix.mk
@@ -25,12 +25,38 @@
 
 # $(warning $(call remove-minor-revision,3.18.0))
 
-ifndef LOCAL_MODULE_STEM
-$(error LOCAL_MODULE_STEM must be defined.)
+##### Input Variables:
+# LOCAL_MODULE: required. Module name for the build system.
+# LOCAL_MODULE_CLASS: optional. Default is ETC.
+# LOCAL_MODULE_PATH: optional. Path of output file. Default is $(TARGET_OUT)/etc/vintf.
+# LOCAL_MODULE_STEM: optional. Name of output file. Default is $(LOCAL_MODULE).
+# LOCAL_SRC_FILES: required. Local source files provided to assemble_vintf
+#       (command line argument -i).
+# LOCAL_GENERATED_SOURCES: optional. Global source files provided to assemble_vintf
+#       (command line argument -i).
+#
+# LOCAL_ADD_VBMETA_VERSION: Use AVBTOOL to add avb version to the output matrix
+#       (corresponds to <avb><vbmeta-version> tag)
+# LOCAL_ASSEMBLE_VINTF_ENV_VARS: Add a list of environment variable names from global variables in
+#       the build system that is lazily evaluated (e.g. PRODUCT_ENFORCE_VINTF_MANIFEST).
+# LOCAL_ASSEMBLE_VINTF_ENV_VARS_OVERRIDE: Add a list of environment variables that is local to
+#       assemble_vintf invocation. Format is "VINTF_ENFORCE_NO_UNUSED_HALS=true".
+# LOCAL_ASSEMBLE_VINTF_FLAGS: Add additional command line arguments to assemble_vintf invocation.
+# LOCAL_KERNEL_VERSIONS: Parse kernel configurations and add to the output matrix
+#       (corresponds to <kernel> tags.)
+# LOCAL_GEN_FILE_DEPENDENCIES: A list of additional dependencies for the generated file.
+
+ifndef LOCAL_MODULE
+$(error LOCAL_MODULE must be defined.)
 endif
 
-LOCAL_MODULE := framework_$(LOCAL_MODULE_STEM)
+ifndef LOCAL_MODULE_STEM
+LOCAL_MODULE_STEM := $(LOCAL_MODULE)
+endif
+
+ifndef LOCAL_MODULE_CLASS
 LOCAL_MODULE_CLASS := ETC
+endif
 
 ifndef LOCAL_MODULE_PATH
 LOCAL_MODULE_PATH := $(TARGET_OUT)/etc/vintf
@@ -76,13 +102,23 @@
 	$(addprefix $(LOCAL_PATH)/,$(LOCAL_SRC_FILES)) \
 	$(LOCAL_GENERATED_SOURCES)
 
+$(GEN): PRIVATE_ADDITIONAL_ENV_VARS := $(LOCAL_ASSEMBLE_VINTF_ENV_VARS_OVERRIDE)
+
+ifneq (,$(strip $(LOCAL_ASSEMBLE_VINTF_ERROR_MESSAGE)))
+$(GEN): PRIVATE_COMMAND_TAIL := || (echo $(strip $(LOCAL_ASSEMBLE_VINTF_ERROR_MESSAGE)) && false)
+endif
+
 $(GEN): PRIVATE_SRC_FILES := $(my_matrix_src_files)
 $(GEN): $(my_matrix_src_files) $(HOST_OUT_EXECUTABLES)/assemble_vintf
+	$(foreach varname,$(PRIVATE_ENV_VARS),\
+		$(if $(findstring $(varname),$(PRIVATE_ADDITIONAL_ENV_VARS)),\
+			$(error $(varname) should not be overridden by LOCAL_ASSEMBLE_VINTF_ENV_VARS_OVERRIDE.)))
 	$(foreach varname,$(PRIVATE_ENV_VARS),$(varname)="$($(varname))") \
+		$(PRIVATE_ADDITIONAL_ENV_VARS) \
 		$(HOST_OUT_EXECUTABLES)/assemble_vintf \
 		-i $(call normalize-path-list,$(PRIVATE_SRC_FILES)) \
 		-o $@ \
-		$(PRIVATE_FLAGS)
+		$(PRIVATE_FLAGS) $(PRIVATE_COMMAND_TAIL)
 
 LOCAL_PREBUILT_MODULE_FILE := $(GEN)
 LOCAL_SRC_FILES :=
@@ -90,6 +126,8 @@
 
 LOCAL_ADD_VBMETA_VERSION :=
 LOCAL_ASSEMBLE_VINTF_ENV_VARS :=
+LOCAL_ASSEMBLE_VINTF_ENV_VARS_OVERRIDE :=
+LOCAL_ASSEMBLE_VINTF_ERROR_MESSAGE :=
 LOCAL_ASSEMBLE_VINTF_FLAGS :=
 LOCAL_KERNEL_VERSIONS :=
 LOCAL_GEN_FILE_DEPENDENCIES :=
diff --git a/compatibility_matrices/manifest.empty.xml b/compatibility_matrices/manifest.empty.xml
new file mode 100644
index 0000000..e50e0e5
--- /dev/null
+++ b/compatibility_matrices/manifest.empty.xml
@@ -0,0 +1 @@
+<manifest version="1.0" type="device" />
diff --git a/current.txt b/current.txt
index 69ad1ed..5aa6259 100644
--- a/current.txt
+++ b/current.txt
@@ -250,12 +250,15 @@
 c8bc853546dd55584611def2a9fa1d99f657e3366c976d2f60fe6b8aa6d2cb87 android.hardware.thermal@1.1::IThermalCallback
 
 # ABI preserving changes to HALs during Android P
+eaeb3e4f3237430a7fdc206bffdf844713f5682990b2d49ea24392e15b5d343f android.hardware.broadcastradio@2.0::ITunerCallback
+2804120c1f8522ad15feb7695fe5eece527d399b406c671ea99618194118c316 android.hardware.broadcastradio@2.0::types
 cf72ff5a52bfa4d08e9e1000cf3ab5952a2d280c7f13cdad5ab7905c08050766 android.hardware.camera.metadata@3.2::types
 3902efc42097cba55f0655aa389e052ea70164e99ced1a6d1ef53dafc13f7650 android.hardware.camera.provider@2.4::ICameraProvider
 6fa9804a17a8bb7923a56bd10493a5483c20007e4c9026fd04287bee7c945a8c android.hardware.gnss@1.0::IGnssCallback
 fb92e2b40f8e9d494e8fd3b4ac18499a3216342e7cff160714c3bbf3660b6e79 android.hardware.gnss@1.0::IGnssConfiguration
 251594ea9b27447bfa005ebd806e58fb0ae4aad84a69938129c9800ec0c64eda android.hardware.gnss@1.0::IGnssMeasurementCallback
 4e7169919d24fbe5573e5bcd683d0bd7abf553a4e6c34c41f9dfc1e12050db07 android.hardware.gnss@1.0::IGnssNavigationMessageCallback
+08ae9fc24f21f809e9b8501dfbc803662fcd6a8d8e1fb71d9dd7c0c4c6f5d556 android.hardware.neuralnetworks@1.0::types
 d4840db8efabdf1e4b344fc981cd36e5fe81a39aff6e199f6d06c1c8da413efd android.hardware.radio@1.0::types
 b280c4704dfcc548a9bf127b59b7c3578f460c50cce70a06b66fe0df8b27cff0 android.hardware.wifi@1.0::types
 
@@ -293,8 +296,8 @@
 14ef8e993a4a7c899b19bb5e39b5b0cafd28312ea2b127e35b3be8f08e23fe8e android.hardware.automotive.evs@1.0::IEvsEnumerator
 3b17c1fdfc389e0abe626c37054954b07201127d890c2bc05d47613ec1f4de4f android.hardware.automotive.evs@1.0::types
 b3caf524c46a47d67e6453a34419e1881942d059e146cda740502670e9a752c3 android.hardware.automotive.vehicle@2.0::IVehicle
-80fb4156fa91ce86e49bd2cabe215078f6b69591d416a09e914532eae6712052 android.hardware.automotive.vehicle@2.0::IVehicleCallback
-4ff0dcfb938a5df283eef47de33b4e1284fab73f584cfc0c94e97317bdb7bf26 android.hardware.automotive.vehicle@2.0::types
+7ce8728b27600e840cacf0a832f6942819fe535f9d3797ae052d5eef5065921c android.hardware.automotive.vehicle@2.0::IVehicleCallback
+848fb32d5ca79dd527d966e67c0af5874b6d7b361246b491e315cf7dea7888ab android.hardware.automotive.vehicle@2.0::types
 32cc50cc2a7658ec613c0c2dd2accbf6a05113b749852879e818b8b7b438db19 android.hardware.bluetooth.a2dp@1.0::IBluetoothAudioHost
 ff4be64d7992f8bec97dff37f35450e79b3430c61f85f54322ce45bef229dc3b android.hardware.bluetooth.a2dp@1.0::IBluetoothAudioOffload
 27f22d2e873e6201f9620cf4d8e2facb25bd0dd30a2b911e441b4600d560fa62 android.hardware.bluetooth.a2dp@1.0::types
@@ -307,7 +310,7 @@
 4fb0725c36ed4f77a42b42e3f18d8b5f7919cb62b90098b23143a555aa7dd96d android.hardware.camera.device@3.4::ICameraDeviceCallback
 812fa66aa10ba0cba27cfddc2fd7f0ee27a8ab65a1f15aa79fdad97d403e6a14 android.hardware.camera.device@3.4::ICameraDeviceSession
 cc288f1f78d1e643eb3d3dbc16e1401d44033d8e6856761f5156814a29986ec7 android.hardware.camera.device@3.4::types
-71ee1f46dac4df417d2950e4de760e4145038ae363fc11aeea487350bf603897 android.hardware.camera.metadata@3.3::types
+f9278c8beb9d42d96e26d73ecabe1dff1d7e2fb301ab7f737d93e5ffae8d3312 android.hardware.camera.metadata@3.3::types
 1a46aeae45b7a0e47f79b7207300532986f9d9cd7060779afc7a529f54d712ab android.hardware.confirmationui@1.0::IConfirmationResultCallback
 6d8347ff3cd7de471065ac3e8e68385073630cdeebe9f8fa58cb91cf44436c95 android.hardware.confirmationui@1.0::IConfirmationUI
 a3ff916784dce87a56c757ab5c86433f0cdf562280999a5f978a6e8a0f3f19e7 android.hardware.confirmationui@1.0::types
@@ -315,20 +318,20 @@
 7877ff8e4c1e48b825e6e5e66d050288e5656ed535c61cc7830a92ed4a9e1990 android.hardware.drm@1.1::IDrmFactory
 fef2f0ebde7704548fb203df46673ceb342272fc4fa9d0af25a980d2584a36e7 android.hardware.drm@1.1::IDrmPlugin
 5047a346ecce239404b9020959f60dd467318e9c17b290a6386bc3894df62c3c android.hardware.drm@1.1::types
-be794f5df97f134d6dcabb866b250d1305100e7ae07fb253b7841df890b931bb android.hardware.gnss@1.1::IGnss
+a830336ac8627d6432cfafb1b884343ad9f885dee0a5323e380e6d3c519156b8 android.hardware.gnss@1.1::IGnss
 8ad55bc35bb3a83e65c018bdfde7ae5ebc749ff2bf6b79412ded0bc6c89b97d8 android.hardware.gnss@1.1::IGnssCallback
 3c5183d7506010be57e0f748e3640fc2ded1ba955784b6256ba427f4c399591c android.hardware.gnss@1.1::IGnssConfiguration
-b054af24fbb70d54cde1fb5cba126809e7c4e863e8f9115dc492321dfbcbc993 android.hardware.gnss@1.1::IGnssMeasurement
+1a07d1383e847c3deb696ec7a2c9e33b9683772945660448a010b18063da67a4 android.hardware.gnss@1.1::IGnssMeasurement
 83e7a10ff3702147bd7ffa04567b20d407a3b16bbb7705644af44d919afe9103 android.hardware.gnss@1.1::IGnssMeasurementCallback
-82da7e7624f72ff1927f48738913e20bee3a513adfe5dc7c4f888176e20376e6 android.hardware.graphics.common@1.1::types
+0b96e0254e2168cfecb30c1ed5fb42681652cc00faa68c6e07568fafe64d1d50 android.hardware.graphics.common@1.1::types
 d9b40a5b09962a5a0780b10fe33a4e607e69e2e088fc83de88a584115b7cb1c0 android.hardware.graphics.composer@2.2::IComposer
-d6ce042995239712bc1d0970fa9d512c15c0b1ac9bcb048bd8b69f617b45c25e android.hardware.graphics.composer@2.2::IComposerClient
+c3cd2a3e245ffefae859c9a3d31382a9421be95cfa6bc1231571eb3533049b54 android.hardware.graphics.composer@2.2::IComposerClient
 dd83be076b6b3f10ed62ab34d8c8b95f2415961fb785200eb842e7bfb2b0ee92 android.hardware.graphics.mapper@2.1::IMapper
 675682dd3007805c985eaaec91612abc88f4c25b3431fb84070b7584a1a741fb android.hardware.health@2.0::IHealth
 434c4c32c00b0e54bb05e40c79503208b40f786a318029a2a4f66e34f10f2a76 android.hardware.health@2.0::IHealthInfoCallback
 c9e498f1ade5e26f00d290b4763a9671ec6720f915e7d592844b62e8cb1f9b5c android.hardware.health@2.0::types
 a6cf986593c6ad15fe2ae3a1995d2cae233500bc32c055912a42723bdc076868 android.hardware.keymaster@4.0::IKeymasterDevice
-3ce01f7a38013f15d2ffc9c66a81eb85061ab6585fb1e659fe6da36bdcbfa9cf android.hardware.keymaster@4.0::types
+e15ebdf1e0a326ff5b8a59668d4d8cd3852bd88388eae91de13f5f7e1af50ed1 android.hardware.keymaster@4.0::types
 6d5c646a83538f0f9d8438c259932509f4353410c6c76e56db0d6ca98b69c3bb android.hardware.media.bufferpool@1.0::IAccessor
 b8c7ed58aa8740361e63d0ce9e7c94227572a629f356958840b34809d2393a7c android.hardware.media.bufferpool@1.0::IClientManager
 4a2c0dc82780e6c90731725a103feab8ab6ecf85a64e049b9cbd2b2c61620fe1 android.hardware.media.bufferpool@1.0::IConnection
@@ -337,14 +340,14 @@
 e808a6f61cd7b47887c599d8843e67a2dcbf4ec5aadd5d22fdce93020070ef1b android.hardware.neuralnetworks@1.1::types
 8d3d86da0bfa4bf070970d8303c659f67f35d670c287d45a3f542e4fedadd578 android.hardware.nfc@1.1::INfc
 e85f566698d2a2c28100e264fcf2c691a066756ddf8dd341d009ff50cfe10614 android.hardware.nfc@1.1::INfcClientCallback
-2b8f6165b3d350485eb89eb6e931cf876688cde9155f7b31a8d8fe7abdfe5b95 android.hardware.nfc@1.1::types
+5e278fcaa3287d397d8eebe1c22aaa28150f5caae1cf9381cd6dc32cb37899c5 android.hardware.nfc@1.1::types
 163e115e833fc1d77cdd4a8cf0c833bb8b8d74fe35c880fe693101d17774926f android.hardware.power@1.2::IPower
 7899b9305587b2d5cd74a3cc87e9090f58bf4ae74256ce3ee36e7ec011822840 android.hardware.power@1.2::types
 ab132c990a62f0aca35871c092c22fb9c85d478e22124ef6a4d0a2302da76a9f android.hardware.radio@1.2::IRadio
 cda752aeabaabc20486a82ac57a3dd107785c006094a349bc5e224e8aa22a17c android.hardware.radio@1.2::IRadioIndication
-c38b7e1f808565a535ff19fd4c1b512b22dfa0b58ec91dce03f72a8f1eaf6957 android.hardware.radio@1.2::IRadioResponse
+da8c6ae991c6a4b284cc6e445332e064e28ee8a09482ed5afff9d159ec6694b7 android.hardware.radio@1.2::IRadioResponse
 b65332996eb39ba63300a1011404141fa59ce5c252bc17afae637be6eeca5f55 android.hardware.radio@1.2::ISap
-508ace7d4023b865b8b77c3ca3c86cc9525ef3803dc9c6b461b7c1f91b0fec00 android.hardware.radio@1.2::types
+a9361522cc97ef66209d39ba324095b2f08344054bb4d3481e803eee0480623a android.hardware.radio@1.2::types
 87385469cf4409f0f33b01508e7a477cf71f2a11e466dd7e3ab5971a1baaa72b android.hardware.radio.config@1.0::IRadioConfig
 228b2ee3c8c276c9f0afad2dc313ca3d6bbd9e482ddf313c7204c60ad9b636ab android.hardware.radio.config@1.0::IRadioConfigIndication
 a2e9b7aa09f79426f765838174e04b6f9a3e6c8b76b923fc1705632207bad44b android.hardware.radio.config@1.0::IRadioConfigResponse
@@ -364,9 +367,11 @@
 167af870fdb87e1cbbaa0fa62ef35e1031caad20dd1ba695983dedb1e9993486 android.hardware.wifi@1.2::IWifiChipEventCallback
 8c7ef32fc78d5ec6e6956de3784cc2c6f42614b5272d2e461f6d60534ba38ec2 android.hardware.wifi@1.2::IWifiNanIface
 1e6074efad9da333803fb7c1acdb719d51c30b2e1e92087b0420341631c30b60 android.hardware.wifi@1.2::IWifiNanIfaceEventCallback
-a9d733eb0d555f2a6cb79a212810e81b56ecba0e31a8ffe0916de086a29e4f88 android.hardware.wifi@1.2::IWifiStaIface
+f5682dbf19f712bef9cc3faa5fe3dc670b6ffbcb62a147a1d86b9d43574cd83f android.hardware.wifi@1.2::IWifiStaIface
 6db2e7d274be2dca9bf3087afd1f774a68c99d2b4dc7eeaf41690e5cebcbef7a android.hardware.wifi@1.2::types
 ee08280de21cb41e3ec26d6ed636c701b7f70516e71fb22f4fe60a13e603f406 android.hardware.wifi.hostapd@1.0::IHostapd
 b2479cd7a417a1cf4f3a22db4e4579e21bac38fdcaf381e2bf10176d05397e01 android.hardware.wifi.hostapd@1.0::types
 e362203b941f18bd4cba29a62adfa02453ed00d6be5b72cdb6c4d7e0bf394a40 android.hardware.wifi.supplicant@1.1::ISupplicant
+21757d0e5dd4b7e4bd981a4a20531bca3c32271ad9777b17b74eb5a1ea508384 android.hardware.wifi.supplicant@1.1::ISupplicantStaIface
+cd4330c3196bda1d642a32abfe23a7d64ebfbda721940643af6867af3b3f0aa9 android.hardware.wifi.supplicant@1.1::ISupplicantStaIfaceCallback
 10ff2fae516346b86121368ce5790d5accdfcb73983246b813f3d488b66db45a android.hardware.wifi.supplicant@1.1::ISupplicantStaNetwork
diff --git a/drm/1.1/vts/functional/drm_hal_clearkey_test.cpp b/drm/1.1/vts/functional/drm_hal_clearkey_test.cpp
index 061f2cd..1246616 100644
--- a/drm/1.1/vts/functional/drm_hal_clearkey_test.cpp
+++ b/drm/1.1/vts/functional/drm_hal_clearkey_test.cpp
@@ -43,7 +43,6 @@
 using ::android::hardware::drm::V1_0::ICryptoPlugin;
 using ::android::hardware::drm::V1_0::KeyedVector;
 using ::android::hardware::drm::V1_0::KeyValue;
-using ::android::hardware::drm::V1_0::KeyRequestType;
 using ::android::hardware::drm::V1_0::KeyType;
 using ::android::hardware::drm::V1_0::Mode;
 using ::android::hardware::drm::V1_0::Pattern;
@@ -60,6 +59,8 @@
 using ::android::hardware::drm::V1_1::ICryptoFactory;
 using ::android::hardware::drm::V1_1::IDrmFactory;
 using ::android::hardware::drm::V1_1::IDrmPlugin;
+using ::android::hardware::drm::V1_1::KeyRequestType;
+using ::android::hardware::drm::V1_1::SecureStopRelease;
 using ::android::hardware::drm::V1_1::SecurityLevel;
 using ::android::hardware::drm::V1_1::SecurityLevel;
 
@@ -167,7 +168,6 @@
     SessionId openSession(SecurityLevel level);
     void closeSession(const SessionId& sessionId);
     hidl_vec<uint8_t> loadKeys(const SessionId& sessionId, const KeyType& type);
-    sp<IMemory> getDecryptMemory(size_t size, size_t index);
 
   private:
     sp<IDrmPlugin> createDrmPlugin(sp<IDrmFactory> drmFactory) {
@@ -308,6 +308,125 @@
 }
 
 /**
+ * Helper method to load keys for subsequent decrypt tests.
+ * These tests use predetermined key request/response to
+ * avoid requiring a round trip to a license server.
+ */
+hidl_vec<uint8_t> DrmHalClearkeyTest::loadKeys(
+    const SessionId& sessionId, const KeyType& type = KeyType::STREAMING) {
+    hidl_vec<uint8_t> initData = {
+        // BMFF box header (4 bytes size + 'pssh')
+        0x00, 0x00, 0x00, 0x34, 0x70, 0x73, 0x73, 0x68,
+        // full box header (version = 1 flags = 0)
+        0x01, 0x00, 0x00, 0x00,
+        // system id
+        0x10, 0x77, 0xef, 0xec, 0xc0, 0xb2, 0x4d, 0x02, 0xac, 0xe3, 0x3c,
+        0x1e, 0x52, 0xe2, 0xfb, 0x4b,
+        // number of key ids
+        0x00, 0x00, 0x00, 0x01,
+        // key id
+        0x60, 0x06, 0x1e, 0x01, 0x7e, 0x47, 0x7e, 0x87, 0x7e, 0x57, 0xd0,
+        0x0d, 0x1e, 0xd0, 0x0d, 0x1e,
+        // size of data, must be zero
+        0x00, 0x00, 0x00, 0x00};
+
+    hidl_vec<uint8_t> expectedKeyRequest = {
+        0x7b, 0x22, 0x6b, 0x69, 0x64, 0x73, 0x22, 0x3a, 0x5b, 0x22, 0x59, 0x41, 0x59, 0x65,
+        0x41, 0x58, 0x35, 0x48, 0x66, 0x6f, 0x64, 0x2d, 0x56, 0x39, 0x41, 0x4e, 0x48, 0x74,
+        0x41, 0x4e, 0x48, 0x67, 0x22, 0x5d, 0x2c, 0x22, 0x74, 0x79, 0x70, 0x65, 0x22, 0x3a,
+        0x22, 0x74, 0x65, 0x6d, 0x70, 0x6f, 0x72, 0x61, 0x72, 0x79, 0x22, 0x7d};
+
+    hidl_vec<uint8_t> knownKeyResponse = {
+        0x7b, 0x22, 0x6b, 0x65, 0x79, 0x73, 0x22, 0x3a, 0x5b, 0x7b, 0x22, 0x6b, 0x74, 0x79, 0x22,
+        0x3a, 0x22, 0x6f, 0x63, 0x74, 0x22, 0x2c, 0x22, 0x6b, 0x69, 0x64, 0x22, 0x3a, 0x22, 0x59,
+        0x41, 0x59, 0x65, 0x41, 0x58, 0x35, 0x48, 0x66, 0x6f, 0x64, 0x2d, 0x56, 0x39, 0x41, 0x4e,
+        0x48, 0x74, 0x41, 0x4e, 0x48, 0x67, 0x22, 0x2c, 0x22, 0x6b, 0x22, 0x3a, 0x22, 0x47, 0x6f,
+        0x6f, 0x67, 0x6c, 0x65, 0x54, 0x65, 0x73, 0x74, 0x4b, 0x65, 0x79, 0x42, 0x61, 0x73, 0x65,
+        0x36, 0x34, 0x67, 0x67, 0x67, 0x22, 0x7d, 0x5d, 0x7d, 0x0a};
+
+    hidl_string mimeType = "video/mp4";
+    KeyedVector optionalParameters;
+    auto res = drmPlugin->getKeyRequest_1_1(
+        sessionId, initData, mimeType, type, optionalParameters,
+        [&](Status status, const hidl_vec<uint8_t>& request,
+            KeyRequestType requestType, const hidl_string&) {
+            EXPECT_EQ(Status::OK, status);
+            EXPECT_EQ(KeyRequestType::INITIAL, requestType);
+            EXPECT_EQ(request, expectedKeyRequest);
+        });
+    EXPECT_OK(res);
+
+    hidl_vec<uint8_t> keySetId;
+    res = drmPlugin->provideKeyResponse(
+        sessionId, knownKeyResponse,
+        [&](Status status, const hidl_vec<uint8_t>& myKeySetId) {
+            EXPECT_EQ(Status::OK, status);
+            EXPECT_EQ(0u, myKeySetId.size());
+            keySetId = myKeySetId;
+        });
+    EXPECT_OK(res);
+    return keySetId;
+}
+
+/**
+ * Test openSession negative case: security level higher than supported
+ */
+TEST_F(DrmHalClearkeyTest, OpenSessionBadLevel) {
+    auto res = drmPlugin->openSession_1_1(SecurityLevel::HW_SECURE_ALL,
+            [&](Status status, const SessionId& /* id */) {
+                EXPECT_EQ(Status::ERROR_DRM_CANNOT_HANDLE, status);
+            });
+    EXPECT_OK(res);
+}
+
+/**
+ * Test getKeyRequest_1_1 via loadKeys
+ */
+TEST_F(DrmHalClearkeyTest, GetKeyRequest) {
+    auto sessionId = openSession();
+    loadKeys(sessionId);
+    closeSession(sessionId);
+}
+
+/**
+ * A get key request should fail if no sessionId is provided
+ */
+TEST_F(DrmHalClearkeyTest, GetKeyRequestNoSession) {
+    SessionId invalidSessionId;
+    hidl_vec<uint8_t> initData;
+    hidl_string mimeType = "video/mp4";
+    KeyedVector optionalParameters;
+    auto res = drmPlugin->getKeyRequest_1_1(
+            invalidSessionId, initData, mimeType, KeyType::STREAMING,
+            optionalParameters,
+            [&](Status status, const hidl_vec<uint8_t>&, KeyRequestType,
+                const hidl_string&) { EXPECT_EQ(Status::BAD_VALUE, status); });
+    EXPECT_OK(res);
+}
+
+/**
+ * The clearkey plugin doesn't support offline key requests.
+ * Test that the plugin returns the expected error code in
+ * this case.
+ */
+TEST_F(DrmHalClearkeyTest, GetKeyRequestOfflineKeyTypeNotSupported) {
+    auto sessionId = openSession();
+    hidl_vec<uint8_t> initData;
+    hidl_string mimeType = "video/mp4";
+    KeyedVector optionalParameters;
+
+    auto res = drmPlugin->getKeyRequest_1_1(
+            sessionId, initData, mimeType, KeyType::OFFLINE, optionalParameters,
+            [&](Status status, const hidl_vec<uint8_t>&, KeyRequestType,
+                const hidl_string&) {
+                // Clearkey plugin doesn't support offline key type
+                EXPECT_EQ(Status::ERROR_DRM_CANNOT_HANDLE, status);
+            });
+    EXPECT_OK(res);
+    closeSession(sessionId);
+}
+
+/**
  * Test that the plugin returns valid connected and max HDCP levels
  */
 TEST_F(DrmHalClearkeyTest, GetHdcpLevels) {
@@ -322,6 +441,11 @@
 }
 
 /**
+ * Since getHdcpLevels only queries information there are no
+ * negative cases.
+ */
+
+/**
  * Test that the plugin returns default open and max session counts
  */
 TEST_F(DrmHalClearkeyTest, GetDefaultSessionCounts) {
@@ -373,6 +497,11 @@
 }
 
 /**
+ * Since getNumberOfSessions only queries information there are no
+ * negative cases.
+ */
+
+/**
  * Test that the plugin returns the same security level
  * by default as when it is requested explicitly
  */
@@ -428,7 +557,7 @@
 /**
  * Test metrics are set appropriately for open and close operations.
  */
-TEST_F(DrmHalClearkeyTest, GetMetricsSuccess) {
+TEST_F(DrmHalClearkeyTest, GetMetricsOpenClose) {
     SessionId sessionId = openSession();
     // The first close should be successful.
     closeSession(sessionId);
@@ -449,8 +578,292 @@
                                                     (int64_t)Status::ERROR_DRM_SESSION_NOT_OPENED,
                                                     "count", (int64_t)1));
     });
+    EXPECT_OK(res);
 }
 
+/**
+ * Since getMetrics only queries information there are no
+ * negative cases.
+ */
+
+/**
+ * Test that there are no secure stop ids after clearing them
+ */
+TEST_F(DrmHalClearkeyTest, GetSecureStopIdsCleared) {
+    auto stat = drmPlugin->removeAllSecureStops();
+    EXPECT_OK(stat);
+
+    bool ok = drmPlugin->getSecureStopIds(
+            [&](Status status, const hidl_vec<SecureStopId>& ids) {
+                EXPECT_EQ(Status::OK, status);
+                EXPECT_EQ(0u, ids.size());
+            }).isOk();
+    EXPECT_TRUE(ok);
+}
+
+/**
+ * Test that there are secure stop ids after loading keys once
+ */
+TEST_F(DrmHalClearkeyTest, GetSecureStopIdsOnce) {
+    auto stat = drmPlugin->removeAllSecureStops();
+    EXPECT_OK(stat);
+
+    auto sessionId = openSession();
+    loadKeys(sessionId);
+    closeSession(sessionId);
+
+    auto res = drmPlugin->getSecureStopIds(
+            [&](Status status, const hidl_vec<SecureStopId>& ids) {
+                EXPECT_EQ(Status::OK, status);
+                EXPECT_EQ(1u, ids.size());
+            });
+    EXPECT_OK(res);
+
+    stat = drmPlugin->removeAllSecureStops();
+    EXPECT_OK(stat);
+
+    res = drmPlugin->getSecureStopIds(
+            [&](Status status, const hidl_vec<SecureStopId>& ids) {
+                EXPECT_EQ(Status::OK, status);
+                EXPECT_EQ(0u, ids.size());
+            });
+    EXPECT_OK(res);
+}
+
+/**
+ * Since getSecureStopIds only queries information there are no
+ * negative cases.
+ */
+
+/**
+ * Test that the clearkey plugin reports no secure stops when
+ * there are none.
+ */
+TEST_F(DrmHalClearkeyTest, GetNoSecureStops) {
+    auto stat = drmPlugin->removeAllSecureStops();
+    EXPECT_OK(stat);
+
+    auto res = drmPlugin->getSecureStops(
+            [&](Status status, const hidl_vec<SecureStop>& stops) {
+                EXPECT_EQ(Status::OK, status);
+                EXPECT_EQ(0u, stops.size());
+            });
+    EXPECT_OK(res);
+}
+
+/**
+ * Test get/remove of one secure stop
+ */
+TEST_F(DrmHalClearkeyTest, GetOneSecureStopAndRemoveIt) {
+    auto stat = drmPlugin->removeAllSecureStops();
+    EXPECT_OK(stat);
+
+    auto sessionId = openSession();
+    loadKeys(sessionId);
+    closeSession(sessionId);
+
+    auto res = drmPlugin->getSecureStops(
+            [&](Status status, const hidl_vec<SecureStop>& stops) {
+                EXPECT_EQ(Status::OK, status);
+                EXPECT_EQ(1u, stops.size());
+            });
+    EXPECT_OK(res);
+
+    stat = drmPlugin->removeAllSecureStops();
+    EXPECT_OK(stat);
+
+    res = drmPlugin->getSecureStops(
+            [&](Status status, const hidl_vec<SecureStop>& stops) {
+                EXPECT_EQ(Status::OK, status);
+                EXPECT_EQ(0u, stops.size());
+            });
+    EXPECT_OK(res);
+}
+
+/**
+ * Since getSecureStops only queries information there are no
+ * negative cases.
+ */
+
+/**
+ * Test that there are no secure stops after clearing them
+ */
+TEST_F(DrmHalClearkeyTest, GetSecureStopsCleared) {
+    auto stat = drmPlugin->removeAllSecureStops();
+    EXPECT_OK(stat);
+
+    auto res = drmPlugin->getSecureStops(
+            [&](Status status, const hidl_vec<SecureStop>& stops) {
+                EXPECT_EQ(Status::OK, status);
+                EXPECT_EQ(0u, stops.size());
+            });
+    EXPECT_OK(res);
+}
+
+/**
+ * Test that there are secure stops after loading keys once
+ */
+TEST_F(DrmHalClearkeyTest, GetSecureStopsOnce) {
+    auto stat = drmPlugin->removeAllSecureStops();
+    EXPECT_OK(stat);
+
+    auto sessionId = openSession();
+    loadKeys(sessionId);
+    closeSession(sessionId);
+
+    auto res = drmPlugin->getSecureStops(
+            [&](Status status, const hidl_vec<SecureStop>& stops) {
+                EXPECT_EQ(Status::OK, status);
+                EXPECT_EQ(1u, stops.size());
+            });
+    EXPECT_OK(res);
+
+    stat = drmPlugin->removeAllSecureStops();
+    EXPECT_OK(stat);
+
+    res = drmPlugin->getSecureStops(
+            [&](Status status, const hidl_vec<SecureStop>& stops) {
+                EXPECT_EQ(Status::OK, status);
+                EXPECT_EQ(0u, stops.size());
+            });
+    EXPECT_OK(res);
+}
+
+/**
+ * Since getSecureStops only queries information there are no
+ * negative cases.
+ */
+
+/**
+ * Test that releasing a secure stop with empty
+ * release message fails with the documented error
+ */
+TEST_F(DrmHalClearkeyTest, ReleaseEmptySecureStop) {
+    SecureStopRelease emptyRelease = {.opaqueData = hidl_vec<uint8_t>()};
+    Status status = drmPlugin->releaseSecureStops(emptyRelease);
+    EXPECT_EQ(Status::BAD_VALUE, status);
+}
+
+/**
+ * Helper function to create a secure release message for
+ * a secure stop. The clearkey secure stop release format
+ * is just a count followed by the secure stop opaque data.
+ */
+SecureStopRelease makeSecureRelease(const SecureStop &stop) {
+    std::vector<uint8_t> stopData = stop.opaqueData;
+    std::vector<uint8_t> buffer;
+    std::string count = "0001";
+
+    auto it = buffer.insert(buffer.begin(), count.begin(), count.end());
+    buffer.insert(it + count.size(), stopData.begin(), stopData.end());
+    SecureStopRelease release = { .opaqueData = hidl_vec<uint8_t>(buffer) };
+    return release;
+}
+
+/**
+ * Test that releasing one secure stop works
+ */
+TEST_F(DrmHalClearkeyTest, ReleaseOneSecureStop) {
+
+    auto stat = drmPlugin->removeAllSecureStops();
+    EXPECT_OK(stat);
+
+    auto sessionId = openSession();
+    loadKeys(sessionId);
+    closeSession(sessionId);
+
+    SecureStopRelease release;
+    auto res = drmPlugin->getSecureStops(
+            [&](Status status, const hidl_vec<SecureStop>& stops) {
+                EXPECT_EQ(Status::OK, status);
+                EXPECT_EQ(1u, stops.size());
+                release = makeSecureRelease(stops[0]);
+            });
+    EXPECT_OK(res);
+
+    stat = drmPlugin->releaseSecureStops(release);
+    EXPECT_OK(stat);
+
+    res = drmPlugin->getSecureStops(
+            [&](Status status, const hidl_vec<SecureStop>& stops) {
+                EXPECT_EQ(Status::OK, status);
+                EXPECT_EQ(0u, stops.size());
+            });
+    EXPECT_OK(res);
+}
+
+
+/**
+ * Test that removing a secure stop with an empty ID returns
+ * documented error
+ */
+TEST_F(DrmHalClearkeyTest, RemoveEmptySecureStopId) {
+    hidl_vec<uint8_t> emptyId;
+    auto stat = drmPlugin->removeSecureStop(emptyId);
+    EXPECT_OK(stat);
+    EXPECT_EQ(Status::BAD_VALUE, stat);
+}
+
+/**
+ * Test that removing a secure stop after it has already
+ * been removed fails with the documented error code.
+ */
+TEST_F(DrmHalClearkeyTest, RemoveRemovedSecureStopId) {
+    auto stat = drmPlugin->removeAllSecureStops();
+    EXPECT_OK(stat);
+
+    auto sessionId = openSession();
+    loadKeys(sessionId);
+    closeSession(sessionId);
+    SecureStopId ssid;
+
+    auto res = drmPlugin->getSecureStopIds(
+            [&](Status status, const hidl_vec<SecureStopId>& ids) {
+                EXPECT_EQ(Status::OK, status);
+                EXPECT_EQ(1u, ids.size());
+                ssid = ids[0];
+            });
+    EXPECT_OK(res);
+
+    stat = drmPlugin->removeAllSecureStops();
+    EXPECT_OK(stat);
+
+    Status status = drmPlugin->removeSecureStop(ssid);
+    EXPECT_EQ(Status::BAD_VALUE, status);
+}
+
+/**
+ * Test that removing a secure stop by id works
+ */
+TEST_F(DrmHalClearkeyTest, RemoveSecureStopById) {
+    auto stat = drmPlugin->removeAllSecureStops();
+    EXPECT_OK(stat);
+
+    auto sessionId = openSession();
+    loadKeys(sessionId);
+    closeSession(sessionId);
+    SecureStopId ssid;
+
+    auto res = drmPlugin->getSecureStopIds(
+            [&](Status status, const hidl_vec<SecureStopId>& ids) {
+                EXPECT_EQ(Status::OK, status);
+                EXPECT_EQ(1u, ids.size());
+                ssid = ids[0];
+            });
+    EXPECT_OK(res);
+
+    stat = drmPlugin->removeSecureStop(ssid);
+    EXPECT_OK(stat);
+
+    res = drmPlugin->getSecureStopIds(
+            [&](Status status, const hidl_vec<SecureStopId>& ids) {
+                EXPECT_EQ(Status::OK, status);
+                EXPECT_EQ(0u, ids.size());
+            });
+    EXPECT_OK(res);
+}
+
+
 int main(int argc, char** argv) {
     ::testing::AddGlobalTestEnvironment(DrmHidlEnvironment::Instance());
     ::testing::InitGoogleTest(&argc, argv);
diff --git a/gnss/1.1/IGnss.hal b/gnss/1.1/IGnss.hal
index 096f251..672f742 100644
--- a/gnss/1.1/IGnss.hal
+++ b/gnss/1.1/IGnss.hal
@@ -46,15 +46,17 @@
      * @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.
-     * @param lowPowerMode When true, HAL must make strong tradeoffs to substantially restrict power
-     *     use. Specifically, in the case of a several second long minIntervalMs, the GNSS chipset
-     *     must not, on average, run power hungry operations like RF and signal searches for more
-     *     than one second per interval, and must make exactly one call to gnssSvStatusCb(), and
-     *     either zero or one call to GnssLocationCb() at each interval. When false, HAL must
-     *     operate in the nominal mode (similar to V1.0 where this flag wasn't present) and is
-     *     expected to make power and performance tradoffs such as duty-cycling when signal
-     *     conditions are good and more active searches to reacquire GNSS signals when no signals
-     *     are present.
+     * @param lowPowerMode When true, and IGnss.hal is the only client to the GNSS hardware, the
+     *     GNSS hardware must make strong tradeoffs to substantially restrict power use.
+     *     Specifically, in the case of a several second long minIntervalMs, the GNSS hardware must
+     *     not, on average, run power hungry operations like RF and signal searches for more than
+     *     one second per interval, and must make exactly one call to gnssSvStatusCb(), and either
+     *     zero or one call to GnssLocationCb() at each interval. When false, HAL must operate in
+     *     the nominal mode (similar to V1.0 where this flag wasn't present) and is expected to make
+     *     power and performance tradoffs such as duty-cycling when signal conditions are good and
+     *     more active searches to reacquire GNSS signals when no signals are present.
+     *     When there are additional clients using the GNSS hardware other than IGnss.hal, the GNSS
+     *     hardware may operate in a higher power mode, on behalf of those clients.
      *
      * @return success Returns true if successful.
      */
diff --git a/gnss/1.1/IGnssMeasurement.hal b/gnss/1.1/IGnssMeasurement.hal
index cd83ae3..6ed8e53 100644
--- a/gnss/1.1/IGnssMeasurement.hal
+++ b/gnss/1.1/IGnssMeasurement.hal
@@ -33,10 +33,11 @@
      * @param callback Handle to GnssMeasurement callback interface.
      * @param enableFullTracking If true, GNSS chipset must switch off duty cycling. In such mode
      *     no clock discontinuities are expected and, when supported, carrier phase should be
-     *     continuous in good signal conditions. All constellations and frequency bands that the
-     *     chipset supports must be reported in this mode. The GNSS chipset is allowed to consume
-     *     more power in this mode. If false, API must behave as in HAL V1_0, optimizing power via
-     *     duty cycling, constellations and frequency limits, etc.
+     *     continuous in good signal conditions. All non-blacklisted, healthy constellations,
+     *     satellites and frequency bands that the chipset supports must be reported in this mode.
+     *     The GNSS chipset is allowed to consume more power in this mode. If false, API must behave
+     *     as in HAL V1_0, optimizing power via duty cycling, constellations and frequency limits,
+     *     etc.
      *
      * @return initRet Returns SUCCESS if successful. Returns ERROR_ALREADY_INIT if a callback has
      *     already been registered without a corresponding call to 'close'. Returns ERROR_GENERIC
diff --git a/graphics/common/1.1/Android.bp b/graphics/common/1.1/Android.bp
index c319d80..8bc68f5 100644
--- a/graphics/common/1.1/Android.bp
+++ b/graphics/common/1.1/Android.bp
@@ -15,8 +15,10 @@
     ],
     types: [
         "BufferUsage",
+        "ColorMode",
         "Dataspace",
         "PixelFormat",
+        "RenderIntent",
     ],
     gen_java: true,
     gen_java_constants: true,
diff --git a/graphics/common/1.1/types.hal b/graphics/common/1.1/types.hal
index b917d5e..5dca482 100644
--- a/graphics/common/1.1/types.hal
+++ b/graphics/common/1.1/types.hal
@@ -16,9 +16,10 @@
 
 package android.hardware.graphics.common@1.1;
 
-import @1.0::PixelFormat;
 import @1.0::BufferUsage;
+import @1.0::ColorMode;
 import @1.0::Dataspace;
+import @1.0::PixelFormat;
 
 /**
  * Pixel formats for graphics buffers.
@@ -129,15 +130,165 @@
 @export(name="android_dataspace_v1_1_t", value_prefix="HAL_DATASPACE_",
         export_parent="false")
 enum Dataspace : @1.0::Dataspace {
+    /*
+     * @1.0::Dataspace defines six legacy dataspaces
+     *
+     *   SRGB_LINEAR = 0x200, // deprecated, use V0_SRGB_LINEAR
+     *   SRGB = 0x201, // deprecated, use V0_SRGB
+     *   JFIF = 0x101, // deprecated, use V0_JFIF
+     *   BT601_625 = 0x102, // deprecated, use V0_BT601_625
+     *   BT601_525 = 0x103, // deprecated, use V0_BT601_525
+     *   BT709 = 0x104, // deprecated, use V0_BT709
+     *
+     * The difference between the legacy dataspaces and their modern
+     * counterparts is that, with legacy dataspaces, the pixel values may have
+     * been desaturated by the content creator in an unspecified way.
+     *
+     * When colorimetric mapping is required, the legacy dataspaces must be
+     * treated as their modern counterparts (e.g., SRGB must be treated as
+     * V0_SRGB) and no re-saturation is allowed. When non-colorimetric mapping
+     * is allowed, the pixel values can be interpreted freely by
+     * implementations for the purpose of re-saturation, and the re-saturated
+     * pixel values are in the respective modern dataspaces.
+     *
+     * This is also true when UNKNOWN is treated as a legacy dataspace.
+     */
+
     /**
      * ITU-R Recommendation 2020 (BT.2020)
      *
      * Ultra High-definition television
      *
-     * Use limited range, SMPTE 2084 (PQ) transfer and BT2020 standard
-     * limited range is the preferred / normative definition for BT.2020
+     * Use limited range, BT.709 transfer and BT2020 standard
      */
     BT2020_ITU = STANDARD_BT2020 | TRANSFER_SMPTE_170M | RANGE_LIMITED,
 
+    /**
+     * ITU-R Recommendation 2100 (BT.2100)
+     *
+     * High dynamic range television
+     *
+     * Use limited/full range, PQ/HLG transfer, and BT2020 standard
+     * limited range is the preferred / normative definition for BT.2100
+     */
     BT2020_ITU_PQ = STANDARD_BT2020 | TRANSFER_ST2084 | RANGE_LIMITED,
+    BT2020_ITU_HLG = STANDARD_BT2020 | TRANSFER_HLG | RANGE_LIMITED,
+    BT2020_HLG = STANDARD_BT2020 | TRANSFER_HLG | RANGE_FULL,
+};
+
+@export(name="android_color_mode_v1_1_t", value_prefix="HAL_COLOR_MODE_",
+        export_parent="false")
+enum ColorMode : @1.0::ColorMode {
+    /**
+     * BT2020 corresponds with display settings that implement the ITU-R
+     * Recommendation BT.2020 / Rec. 2020 for UHDTV.
+     *
+     * Primaries:
+     *                  x       y
+     *  green           0.170   0.797
+     *  blue            0.131   0.046
+     *  red             0.708   0.292
+     *  white (D65)     0.3127  0.3290
+     *
+     * Inverse Gamma Correction (IGC): V represents normalized (with [0 to 1]
+     * range) value of R, G, or B.
+     *
+     *  if Vnonlinear < b * 4.5
+     *    Vlinear = Vnonlinear / 4.5
+     *  else
+     *    Vlinear = ((Vnonlinear + (a - 1)) / a) ^ (1/0.45)
+     *
+     * Gamma Correction (GC):
+     *
+     *  if Vlinear < b
+     *    Vnonlinear = 4.5 * Vlinear
+     *  else
+     *    Vnonlinear = a * Vlinear ^ 0.45 - (a - 1)
+     *
+     * where
+     *
+     *   a = 1.09929682680944, b = 0.018053968510807
+     *
+     * For practical purposes, these a/b values can be used instead
+     *
+     *   a = 1.099, b = 0.018 for 10-bit display systems
+     *   a = 1.0993, b = 0.0181 for 12-bit display systems
+     */
+    BT2020 = 10,
+
+    /**
+     * BT2100_PQ and BT2100_HLG correspond with display settings that
+     * implement the ITU-R Recommendation BT.2100 / Rec. 2100 for HDR TV.
+     *
+     * Primaries:
+     *                  x       y
+     *  green           0.170   0.797
+     *  blue            0.131   0.046
+     *  red             0.708   0.292
+     *  white (D65)     0.3127  0.3290
+     *
+     * For BT2100_PQ, the transfer function is Perceptual Quantizer (PQ). For
+     * BT2100_HLG, the transfer function is Hybrid Log-Gamma (HLG).
+     */
+    BT2100_PQ = 11,
+    BT2100_HLG = 12,
+};
+
+/**
+ * RenderIntent defines the mapping from color mode colors to display colors.
+ *
+ * A render intent must not change how it maps colors when the color mode
+ * changes. That is to say that when a render intent maps color C to color C',
+ * the fact that color C can have different pixel values in different color
+ * modes should not affect the mapping.
+ *
+ * RenderIntent overrides the render intents defined for individual color
+ * modes. It is ignored when the color mode is ColorMode::NATIVE, because
+ * ColorMode::NATIVE colors are already display colors.
+ */
+@export(name="android_render_intent_v1_1_t", value_prefix="HAL_RENDER_INTENT_",
+        export_parent="false")
+enum RenderIntent : int32_t {
+    /**
+     * Colors in the display gamut are unchanged. Colors out of the display
+     * gamut are hard-clipped.
+     *
+     * This implies that the display must have been calibrated unless
+     * ColorMode::NATIVE is the only supported color mode.
+     */
+    COLORIMETRIC = 0,
+
+    /**
+     * Enhance colors that are in the display gamut. Colors out of the display
+     * gamut are hard-clipped.
+     *
+     * The enhancement typically picks the biggest standard color space (e.g.
+     * DCI-P3) that is narrower than the display gamut and stretches it to the
+     * display gamut. The stretching is recommended to preserve skin tones.
+     */
+    ENHANCE = 1,
+
+    /**
+     * Tone map high-dynamic-range colors to the display's dynamic range. The
+     * dynamic range of the colors are communicated separately. After tone
+     * mapping, the mapping to the display gamut is as defined in
+     * COLORIMETRIC.
+     */
+    TONE_MAP_COLORIMETRIC = 2,
+
+    /**
+     * Tone map high-dynamic-range colors to the display's dynamic range. The
+     * dynamic range of the colors are communicated separately. After tone
+     * mapping, the mapping to the display gamut is as defined in ENHANCE.
+     *
+     * The tone mapping step and the enhancing step must match
+     * TONE_MAP_COLORIMETRIC and ENHANCE respectively when they are also
+     * supported.
+     */
+    TONE_MAP_ENHANCE = 3,
+
+    /*
+     * Vendors are recommended to use 0x100 - 0x1FF for their own values, and
+     * that must be done with subtypes defined by vendor extensions.
+     */
 };
diff --git a/graphics/composer/2.1/utils/command-buffer/include/composer-command-buffer/2.1/ComposerCommandBuffer.h b/graphics/composer/2.1/utils/command-buffer/include/composer-command-buffer/2.1/ComposerCommandBuffer.h
index df529ec..2742207 100644
--- a/graphics/composer/2.1/utils/command-buffer/include/composer-command-buffer/2.1/ComposerCommandBuffer.h
+++ b/graphics/composer/2.1/utils/command-buffer/include/composer-command-buffer/2.1/ComposerCommandBuffer.h
@@ -247,21 +247,8 @@
 
     void setClientTarget(uint32_t slot, const native_handle_t* target, int acquireFence,
                          Dataspace dataspace, const std::vector<IComposerClient::Rect>& damage) {
-        bool doWrite = (damage.size() <= (kMaxLength - 4) / 4);
-        size_t length = 4 + ((doWrite) ? damage.size() * 4 : 0);
-
-        beginCommand(IComposerClient::Command::SET_CLIENT_TARGET, length);
-        write(slot);
-        writeHandle(target, true);
-        writeFence(acquireFence);
-        writeSigned(static_cast<int32_t>(dataspace));
-        // When there are too many rectangles in the damage region and doWrite
-        // is false, we write no rectangle at all which means the entire
-        // client target is damaged.
-        if (doWrite) {
-            writeRegion(damage);
-        }
-        endCommand();
+        setClientTargetInternal(slot, target, acquireFence, static_cast<int32_t>(dataspace),
+                                damage);
     }
 
     static constexpr uint16_t kSetOutputBufferLength = 3;
@@ -354,9 +341,7 @@
 
     static constexpr uint16_t kSetLayerDataspaceLength = 1;
     void setLayerDataspace(Dataspace dataspace) {
-        beginCommand(IComposerClient::Command::SET_LAYER_DATASPACE, kSetLayerDataspaceLength);
-        writeSigned(static_cast<int32_t>(dataspace));
-        endCommand();
+        setLayerDataspaceInternal(static_cast<int32_t>(dataspace));
     }
 
     static constexpr uint16_t kSetLayerDisplayFrameLength = 4;
@@ -418,6 +403,32 @@
     }
 
    protected:
+    void setClientTargetInternal(uint32_t slot, const native_handle_t* target, int acquireFence,
+                                 int32_t dataspace,
+                                 const std::vector<IComposerClient::Rect>& damage) {
+        bool doWrite = (damage.size() <= (kMaxLength - 4) / 4);
+        size_t length = 4 + ((doWrite) ? damage.size() * 4 : 0);
+
+        beginCommand(IComposerClient::Command::SET_CLIENT_TARGET, length);
+        write(slot);
+        writeHandle(target, true);
+        writeFence(acquireFence);
+        writeSigned(dataspace);
+        // When there are too many rectangles in the damage region and doWrite
+        // is false, we write no rectangle at all which means the entire
+        // client target is damaged.
+        if (doWrite) {
+            writeRegion(damage);
+        }
+        endCommand();
+    }
+
+    void setLayerDataspaceInternal(int32_t dataspace) {
+        beginCommand(IComposerClient::Command::SET_LAYER_DATASPACE, kSetLayerDataspaceLength);
+        writeSigned(dataspace);
+        endCommand();
+    }
+
     void beginCommand(IComposerClient::Command command, uint16_t length) {
         if (mCommandEnd) {
             LOG_FATAL("endCommand was not called before command 0x%x", command);
diff --git a/graphics/composer/2.1/utils/vts/include/composer-vts/2.1/ComposerVts.h b/graphics/composer/2.1/utils/vts/include/composer-vts/2.1/ComposerVts.h
index 0d883e4..8d5493e 100644
--- a/graphics/composer/2.1/utils/vts/include/composer-vts/2.1/ComposerVts.h
+++ b/graphics/composer/2.1/utils/vts/include/composer-vts/2.1/ComposerVts.h
@@ -104,9 +104,7 @@
 
     void execute(TestCommandReader* reader, CommandWriterBase* writer);
 
-   private:
-    sp<IComposerClient> mClient;
-
+   protected:
     // Keep track of all virtual displays and layers.  When a test fails with
     // ASSERT_*, the destructor will clean up the resources for the test.
     struct DisplayResource {
@@ -116,6 +114,9 @@
         std::unordered_set<Layer> layers;
     };
     std::unordered_map<Display, DisplayResource> mDisplayResources;
+
+   private:
+    sp<IComposerClient> mClient;
 };
 
 }  // namespace vts
diff --git a/graphics/composer/2.2/Android.bp b/graphics/composer/2.2/Android.bp
index 633a208..fe71e9e 100644
--- a/graphics/composer/2.2/Android.bp
+++ b/graphics/composer/2.2/Android.bp
@@ -12,6 +12,7 @@
     ],
     interfaces: [
         "android.hardware.graphics.common@1.0",
+        "android.hardware.graphics.common@1.1",
         "android.hardware.graphics.composer@2.1",
         "android.hidl.base@1.0",
     ],
diff --git a/graphics/composer/2.2/IComposerClient.hal b/graphics/composer/2.2/IComposerClient.hal
index dcd9c8d..b7ba6a6 100644
--- a/graphics/composer/2.2/IComposerClient.hal
+++ b/graphics/composer/2.2/IComposerClient.hal
@@ -16,11 +16,14 @@
 
 package android.hardware.graphics.composer@2.2;
 
-import android.hardware.graphics.common@1.0::PixelFormat;
-import android.hardware.graphics.common@1.0::Dataspace;
+import android.hardware.graphics.common@1.1::ColorMode;
+import android.hardware.graphics.common@1.1::Dataspace;
+import android.hardware.graphics.common@1.1::PixelFormat;
+import android.hardware.graphics.common@1.1::RenderIntent;
 import @2.1::IComposerClient;
 import @2.1::Display;
 import @2.1::Error;
+import @2.1::IComposerClient;
 
 interface IComposerClient extends @2.1::IComposerClient {
 
@@ -90,16 +93,20 @@
 
     enum Command : @2.1::IComposerClient.Command {
         /**
-         * setPerFrameMetadata(Display display, vec<PerFrameMetadata> data)
+         * SET_LAYER_PER_FRAME_METADATA has this pseudo prototype
+         *
+         *   setLayerPerFrameMetadata(Display display, Layer layer,
+         *                            vec<PerFrameMetadata> data);
+         *
          * Sets the PerFrameMetadata for the display. This metadata must be used
          * by the implementation to better tone map content to that display.
          *
          * This is a method that may be called every frame. Thus it's
          * implemented using buffered transport.
-         * SET_PER_FRAME_METADATA is the command used by the buffered transport
+         * SET_LAYER_PER_FRAME_METADATA is the command used by the buffered transport
          * mechanism.
          */
-        SET_PER_FRAME_METADATA = 0x207 << @2.1::IComposerClient.Command:OPCODE_SHIFT,
+        SET_LAYER_PER_FRAME_METADATA = 0x303 << @2.1::IComposerClient.Command:OPCODE_SHIFT,
 
         /**
          * SET_LAYER_COLOR has this pseudo prototype
@@ -242,6 +249,65 @@
     setReadbackBuffer(Display display, handle buffer, handle releaseFence) generates (Error error);
 
     /**
+     * createVirtualDisplay_2_2
+     * Creates a new virtual display with the given width and height. The
+     * format passed into this function is the default format requested by the
+     * consumer of the virtual display output buffers.
+     *
+     * The display must be assumed to be on from the time the first frame is
+     * presented until the display is destroyed.
+     *
+     * @param width is the width in pixels.
+     * @param height is the height in pixels.
+     * @param formatHint is the default output buffer format selected by
+     *        the consumer.
+     * @param outputBufferSlotCount is the number of output buffer slots to be
+     *        reserved.
+     * @return error is NONE upon success. Otherwise,
+     *         UNSUPPORTED when the width or height is too large for the
+     *                     device to be able to create a virtual display.
+     *         NO_RESOURCES when the device is unable to create a new virtual
+     *                      display at this time.
+     * @return display is the newly-created virtual display.
+     * @return format is the format of the buffer the device will produce.
+     */
+    @callflow(next="*")
+    createVirtualDisplay_2_2(uint32_t width,
+                             uint32_t height,
+                             PixelFormat formatHint,
+                             uint32_t outputBufferSlotCount)
+                  generates (Error error,
+                             Display display,
+                             PixelFormat format);
+
+    /**
+     * getClientTargetSupport_2_2
+     * Returns whether a client target with the given properties can be
+     * handled by the device.
+     *
+     * This function must return true for a client target with width and
+     * height equal to the active display configuration dimensions,
+     * PixelFormat::RGBA_8888, and Dataspace::UNKNOWN. It is not required to
+     * return true for any other configuration.
+     *
+     * @param display is the display to query.
+     * @param width is the client target width in pixels.
+     * @param height is the client target height in pixels.
+     * @param format is the client target format.
+     * @param dataspace is the client target dataspace, as described in
+     *        setLayerDataspace.
+     * @return error is NONE upon success. Otherwise,
+     *         BAD_DISPLAY when an invalid display handle was passed in.
+     *         UNSUPPORTED when the given configuration is not supported.
+     */
+    @callflow(next="*")
+    getClientTargetSupport_2_2(Display display,
+                               uint32_t width,
+                               uint32_t height,
+                               PixelFormat format,
+                               Dataspace dataspace)
+                    generates (Error error);
+    /**
      * setPowerMode_2_2
      * Sets the power mode of the given display. The transition must be
      * complete when this function returns. It is valid to call this function
@@ -260,4 +326,118 @@
      */
     setPowerMode_2_2(Display display, PowerMode mode) generates (Error error);
 
+    /**
+     * Returns the color modes supported on this display.
+     *
+     * All devices must support at least ColorMode::NATIVE.
+     *
+     * @param display is the display to query.
+     * @return error is NONE upon success. Otherwise,
+     *         BAD_DISPLAY when an invalid display handle was passed in.
+     * @return modes is an array of color modes.
+     */
+    getColorModes_2_2(Display display)
+           generates (Error error,
+                      vec<ColorMode> modes);
+
+    /**
+     * Returns the render intents supported by the specified display and color
+     * mode.
+     *
+     * RenderIntent::COLORIMETRIC is always supported.
+     *
+     * @param display is the display to query.
+     * @param mode is the color mode to query.
+     * @return error is NONE upon success. Otherwise,
+     *         BAD_DISPLAY when an invalid display handle was passed in.
+     *         BAD_PARAMETER when an invalid color mode was passed in.
+     * @return intents is an array of render intents.
+     */
+    getRenderIntents(Display display, ColorMode mode)
+          generates (Error error,
+                     vec<RenderIntent> intents);
+
+    /**
+     * Sets the color mode and render intent of the given display.
+     *
+     * The color mode and render intent change must take effect on next
+     * presentDisplay.
+     *
+     * All devices must support at least ColorMode::NATIVE and
+     * RenderIntent::COLORIMETRIC, and displays are assumed to be in this mode
+     * upon hotplug.
+     *
+     * @param display is the display to which the color mode is set.
+     * @param mode is the color mode to set to.
+     * @param intent is the render intent to set to.
+     * @return error is NONE upon success. Otherwise,
+     *         BAD_DISPLAY when an invalid display handle was passed in.
+     *         BAD_PARAMETER when mode or intent is invalid
+     *         UNSUPPORTED when mode or intent is not supported on this
+     *                     display.
+     */
+    setColorMode_2_2(Display display, ColorMode mode, RenderIntent intent)
+          generates (Error error);
+
+    /*
+     * By default, layer dataspaces are mapped to the current color mode
+     * colorimetrically with a few exceptions.
+     *
+     * When the layer dataspace is a legacy sRGB dataspace
+     * (Dataspace::SRGB_LINEAR, Dataspace::SRGB, or Dataspace::UNKNOWN when
+     * treated as such) and the display render intent is
+     * RenderIntent::ENHANCE, the pixel values can go through an
+     * implementation-defined saturation transform before being mapped to the
+     * current color mode colorimetrically.
+     *
+     * Colors that are out of the gamut of the current color mode are
+     * hard-clipped.
+     */
+
+    /**
+     * Returns the saturation matrix of the specified legacy dataspace.
+     *
+     * The saturation matrix can be used to approximate the legacy dataspace
+     * saturation transform. It is to be applied on linear pixel values like
+     * this:
+     *
+     *   (in GLSL)
+     *   linearSrgb = clamp(saturationMatrix * linearSrgb, 0.0, 1.0);
+     *
+     * @param dataspace must be Dataspace::SRGB_LINEAR.
+     * @return error is NONE upon success. Otherwise,
+     *         BAD_PARAMETER when an invalid dataspace was passed in.
+     * @return matrix is the 4x4 column-major matrix used to approximate the
+     *         legacy dataspace saturation operation. The last row must be
+     *         [0.0, 0.0, 0.0, 1.0].
+     */
+    getDataspaceSaturationMatrix(Dataspace dataspace)
+                      generates (Error error,
+                                 float[4][4] matrix);
+
+    /**
+     * Executes commands from the input command message queue. Return values
+     * generated by the input commands are written to the output command
+     * message queue in the form of value commands.
+     *
+     * @param inLength is the length of input commands.
+     * @param inHandles is an array of handles referenced by the input
+     *        commands.
+     * @return error is NONE upon success. Otherwise,
+     *         BAD_PARAMETER when inLength is not equal to the length of
+     *                       commands in the input command message queue.
+     *         NO_RESOURCES when the output command message queue was not
+     *                      properly drained.
+     * @param outQueueChanged indicates whether the output command message
+     *        queue has changed.
+     * @param outLength is the length of output commands.
+     * @param outHandles is an array of handles referenced by the output
+     *        commands.
+     */
+    executeCommands_2_2(uint32_t inLength,
+                        vec<handle> inHandles)
+             generates (Error error,
+                        bool outQueueChanged,
+                        uint32_t outLength,
+                        vec<handle> outHandles);
 };
diff --git a/graphics/composer/2.2/default/Android.bp b/graphics/composer/2.2/default/Android.bp
deleted file mode 100644
index 906479e..0000000
--- a/graphics/composer/2.2/default/Android.bp
+++ /dev/null
@@ -1,31 +0,0 @@
-cc_binary {
-    name: "android.hardware.graphics.composer@2.2-service",
-    defaults: ["hidl_defaults"],
-    vendor: true,
-    relative_install_path: "hw",
-    srcs: ["service.cpp"],
-    init_rc: ["android.hardware.graphics.composer@2.2-service.rc"],
-    header_libs: [
-        "android.hardware.graphics.composer@2.2-passthrough",
-    ],
-    shared_libs: [
-        "android.hardware.graphics.composer@2.1",
-        "android.hardware.graphics.composer@2.2",
-        "android.hardware.graphics.mapper@2.0",
-        "libbase",
-        "libbinder",
-        "libcutils",
-        "libfmq",
-        "libhardware",
-        "libhidlbase",
-        "libhidltransport",
-        "libhwc2on1adapter",
-        "libhwc2onfbadapter",
-        "liblog",
-        "libsync",
-        "libutils",
-    ],
-    cflags: [
-        "-DLOG_TAG=\"ComposerHal\""
-    ],
-}
diff --git a/graphics/composer/2.2/default/Android.mk b/graphics/composer/2.2/default/Android.mk
new file mode 100644
index 0000000..2f80f0c
--- /dev/null
+++ b/graphics/composer/2.2/default/Android.mk
@@ -0,0 +1,32 @@
+LOCAL_PATH := $(call my-dir)
+
+include $(CLEAR_VARS)
+LOCAL_MODULE := android.hardware.graphics.composer@2.2-service
+LOCAL_VENDOR_MODULE := true
+LOCAL_MODULE_RELATIVE_PATH := hw
+LOCAL_CFLAGS := -Wall -Werror -DLOG_TAG=\"ComposerHal\"
+LOCAL_SRC_FILES := service.cpp
+LOCAL_INIT_RC := android.hardware.graphics.composer@2.2-service.rc
+LOCAL_HEADER_LIBRARIES := android.hardware.graphics.composer@2.2-passthrough
+LOCAL_SHARED_LIBRARIES := \
+        android.hardware.graphics.composer@2.1 \
+        android.hardware.graphics.composer@2.2 \
+        android.hardware.graphics.mapper@2.0 \
+        libbase \
+        libbinder \
+        libcutils \
+        libfmq \
+        libhardware \
+        libhidlbase \
+        libhidltransport \
+        libhwc2on1adapter \
+        libhwc2onfbadapter \
+        liblog \
+        libsync \
+        libutils
+
+ifdef TARGET_USES_DISPLAY_RENDER_INTENTS
+LOCAL_CFLAGS += -DUSES_DISPLAY_RENDER_INTENTS
+endif
+
+include $(BUILD_EXECUTABLE)
diff --git a/graphics/composer/2.2/utils/command-buffer/include/composer-command-buffer/2.2/ComposerCommandBuffer.h b/graphics/composer/2.2/utils/command-buffer/include/composer-command-buffer/2.2/ComposerCommandBuffer.h
index c803d3c..138d700 100644
--- a/graphics/composer/2.2/utils/command-buffer/include/composer-command-buffer/2.2/ComposerCommandBuffer.h
+++ b/graphics/composer/2.2/utils/command-buffer/include/composer-command-buffer/2.2/ComposerCommandBuffer.h
@@ -47,8 +47,8 @@
 
 using android::hardware::MessageQueue;
 using android::hardware::graphics::common::V1_0::ColorTransform;
-using android::hardware::graphics::common::V1_0::Dataspace;
 using android::hardware::graphics::common::V1_0::Transform;
+using android::hardware::graphics::common::V1_1::Dataspace;
 using android::hardware::graphics::composer::V2_1::Config;
 using android::hardware::graphics::composer::V2_1::Display;
 using android::hardware::graphics::composer::V2_1::Error;
@@ -64,6 +64,16 @@
    public:
     CommandWriterBase(uint32_t initialMaxSize) : V2_1::CommandWriterBase(initialMaxSize) {}
 
+    void setClientTarget(uint32_t slot, const native_handle_t* target, int acquireFence,
+                         Dataspace dataspace, const std::vector<IComposerClient::Rect>& damage) {
+        setClientTargetInternal(slot, target, acquireFence, static_cast<int32_t>(dataspace),
+                                damage);
+    }
+
+    void setLayerDataspace(Dataspace dataspace) {
+        setLayerDataspaceInternal(static_cast<int32_t>(dataspace));
+    }
+
     static constexpr uint16_t kSetLayerFloatColorLength = 4;
     void setLayerFloatColor(IComposerClient::FloatColor color) {
         beginCommand_2_2(IComposerClient::Command::SET_LAYER_FLOAT_COLOR,
@@ -72,8 +82,9 @@
         endCommand();
     }
 
-    void setPerFrameMetadata(const hidl_vec<IComposerClient::PerFrameMetadata>& metadataVec) {
-        beginCommand_2_2(IComposerClient::Command::SET_PER_FRAME_METADATA, metadataVec.size() * 2);
+    void setLayerPerFrameMetadata(const hidl_vec<IComposerClient::PerFrameMetadata>& metadataVec) {
+        beginCommand_2_2(IComposerClient::Command::SET_LAYER_PER_FRAME_METADATA,
+                         metadataVec.size() * 2);
         for (const auto& metadata : metadataVec) {
             writeSigned(static_cast<int32_t>(metadata.key));
             writeFloat(metadata.value);
diff --git a/graphics/composer/2.2/utils/hal/include/composer-hal/2.2/ComposerClient.h b/graphics/composer/2.2/utils/hal/include/composer-hal/2.2/ComposerClient.h
index d550f83..a6871fb 100644
--- a/graphics/composer/2.2/utils/hal/include/composer-hal/2.2/ComposerClient.h
+++ b/graphics/composer/2.2/utils/hal/include/composer-hal/2.2/ComposerClient.h
@@ -99,10 +99,87 @@
         return mHal->setReadbackBuffer(display, readbackBuffer, std::move(fenceFd));
     }
 
+    Return<void> createVirtualDisplay_2_2(
+        uint32_t width, uint32_t height, PixelFormat formatHint, uint32_t outputBufferSlotCount,
+        IComposerClient::createVirtualDisplay_2_2_cb hidl_cb) override {
+        Display display = 0;
+        Error err = mHal->createVirtualDisplay_2_2(width, height, &formatHint, &display);
+        if (err == Error::NONE) {
+            mResources->addVirtualDisplay(display, outputBufferSlotCount);
+        }
+
+        hidl_cb(err, display, formatHint);
+        return Void();
+    }
+
+    Return<Error> getClientTargetSupport_2_2(Display display, uint32_t width, uint32_t height,
+                                             PixelFormat format, Dataspace dataspace) override {
+        Error err = mHal->getClientTargetSupport_2_2(display, width, height, format, dataspace);
+        return err;
+    }
+
     Return<Error> setPowerMode_2_2(Display display, IComposerClient::PowerMode mode) override {
         return mHal->setPowerMode_2_2(display, mode);
     }
 
+    Return<void> getColorModes_2_2(Display display,
+                                   IComposerClient::getColorModes_2_2_cb hidl_cb) override {
+        hidl_vec<ColorMode> modes;
+        Error err = mHal->getColorModes_2_2(display, &modes);
+        hidl_cb(err, modes);
+        return Void();
+    }
+
+    Return<void> getRenderIntents(Display display, ColorMode mode,
+                                  IComposerClient::getRenderIntents_cb hidl_cb) override {
+#ifdef USES_DISPLAY_RENDER_INTENTS
+        std::vector<RenderIntent> intents;
+        Error err = mHal->getRenderIntents(display, mode, &intents);
+        hidl_cb(err, intents);
+#else
+        (void)display;
+        (void)mode;
+        hidl_cb(Error::NONE, hidl_vec<RenderIntent>({RenderIntent::COLORIMETRIC}));
+#endif
+        return Void();
+    }
+
+    Return<Error> setColorMode_2_2(Display display, ColorMode mode, RenderIntent intent) override {
+#ifndef USES_DISPLAY_RENDER_INTENTS
+        if (intent != RenderIntent::COLORIMETRIC) {
+            return Error::BAD_PARAMETER;
+        }
+#endif
+        return mHal->setColorMode_2_2(display, mode, intent);
+    }
+
+    Return<void> getDataspaceSaturationMatrix(
+        Dataspace dataspace, IComposerClient::getDataspaceSaturationMatrix_cb hidl_cb) override {
+        if (dataspace != Dataspace::SRGB_LINEAR) {
+            hidl_cb(Error::BAD_PARAMETER, std::array<float, 16>{0.0f}.data());
+            return Void();
+        }
+
+        hidl_cb(Error::NONE, mHal->getDataspaceSaturationMatrix(dataspace).data());
+        return Void();
+    }
+
+    Return<void> executeCommands_2_2(uint32_t inLength, const hidl_vec<hidl_handle>& inHandles,
+                                     IComposerClient::executeCommands_2_2_cb hidl_cb) override {
+        std::lock_guard<std::mutex> lock(mCommandEngineMutex);
+        bool outChanged = false;
+        uint32_t outLength = 0;
+        hidl_vec<hidl_handle> outHandles;
+        Error error =
+            mCommandEngine->execute(inLength, inHandles, &outChanged, &outLength, &outHandles);
+
+        hidl_cb(error, outChanged, outLength, outHandles);
+
+        mCommandEngine->reset();
+
+        return Void();
+    }
+
    protected:
     std::unique_ptr<V2_1::hal::ComposerResources> createResources() override {
         return ComposerResources::create();
@@ -146,6 +223,8 @@
 
    private:
     using BaseType2_1 = V2_1::hal::detail::ComposerClientImpl<Interface, Hal>;
+    using BaseType2_1::mCommandEngine;
+    using BaseType2_1::mCommandEngineMutex;
     using BaseType2_1::mHal;
     using BaseType2_1::mResources;
 };
diff --git a/graphics/composer/2.2/utils/hal/include/composer-hal/2.2/ComposerCommandEngine.h b/graphics/composer/2.2/utils/hal/include/composer-hal/2.2/ComposerCommandEngine.h
index adcac46..97e3a9e 100644
--- a/graphics/composer/2.2/utils/hal/include/composer-hal/2.2/ComposerCommandEngine.h
+++ b/graphics/composer/2.2/utils/hal/include/composer-hal/2.2/ComposerCommandEngine.h
@@ -40,8 +40,8 @@
    protected:
     bool executeCommand(V2_1::IComposerClient::Command command, uint16_t length) override {
         switch (static_cast<IComposerClient::Command>(command)) {
-            case IComposerClient::Command::SET_PER_FRAME_METADATA:
-                return executeSetPerFrameMetadata(length);
+            case IComposerClient::Command::SET_LAYER_PER_FRAME_METADATA:
+                return executeSetLayerPerFrameMetadata(length);
             case IComposerClient::Command::SET_LAYER_FLOAT_COLOR:
                 return executeSetLayerFloatColor(length);
             default:
@@ -49,7 +49,7 @@
         }
     }
 
-    bool executeSetPerFrameMetadata(uint16_t length) {
+    bool executeSetLayerPerFrameMetadata(uint16_t length) {
         // (key, value) pairs
         if (length % 2 != 0) {
             return false;
@@ -63,7 +63,7 @@
             length -= 2;
         }
 
-        auto err = mHal->setPerFrameMetadata(mCurrentDisplay, metadata);
+        auto err = mHal->setLayerPerFrameMetadata(mCurrentDisplay, mCurrentLayer, metadata);
         if (err != Error::NONE) {
             mWriter.setError(getCommandLoc(), err);
         }
diff --git a/graphics/composer/2.2/utils/hal/include/composer-hal/2.2/ComposerHal.h b/graphics/composer/2.2/utils/hal/include/composer-hal/2.2/ComposerHal.h
index 30b3643..335dc24 100644
--- a/graphics/composer/2.2/utils/hal/include/composer-hal/2.2/ComposerHal.h
+++ b/graphics/composer/2.2/utils/hal/include/composer-hal/2.2/ComposerHal.h
@@ -28,34 +28,68 @@
 namespace V2_2 {
 namespace hal {
 
-using common::V1_0::Dataspace;
-using common::V1_0::PixelFormat;
+using common::V1_1::ColorMode;
+using common::V1_1::Dataspace;
+using common::V1_1::PixelFormat;
+using common::V1_1::RenderIntent;
 using V2_1::Display;
 using V2_1::Error;
 using V2_1::Layer;
 
 class ComposerHal : public V2_1::hal::ComposerHal {
    public:
+    Error createVirtualDisplay(uint32_t width, uint32_t height, common::V1_0::PixelFormat* format,
+                               Display* outDisplay) override {
+        return createVirtualDisplay_2_2(width, height, reinterpret_cast<PixelFormat*>(format),
+                                        outDisplay);
+    }
+    Error getClientTargetSupport(Display display, uint32_t width, uint32_t height,
+                                 common::V1_0::PixelFormat format,
+                                 common::V1_0::Dataspace dataspace) override {
+        return getClientTargetSupport_2_2(display, width, height, static_cast<PixelFormat>(format),
+                                          static_cast<Dataspace>(dataspace));
+    }
     // superceded by setPowerMode_2_2
     Error setPowerMode(Display display, V2_1::IComposerClient::PowerMode mode) override {
         return setPowerMode_2_2(display, static_cast<IComposerClient::PowerMode>(mode));
     }
 
+    // superceded by getColorModes_2_2
+    Error getColorModes(Display display, hidl_vec<common::V1_0::ColorMode>* outModes) override {
+        return getColorModes_2_2(display, reinterpret_cast<hidl_vec<ColorMode>*>(outModes));
+    }
+
+    // superceded by setColorMode_2_2
+    Error setColorMode(Display display, common::V1_0::ColorMode mode) override {
+        return setColorMode_2_2(display, static_cast<ColorMode>(mode), RenderIntent::COLORIMETRIC);
+    }
+
     virtual Error getPerFrameMetadataKeys(
         Display display, std::vector<IComposerClient::PerFrameMetadataKey>* outKeys) = 0;
-    virtual Error setPerFrameMetadata(
-        Display display, const std::vector<IComposerClient::PerFrameMetadata>& metadata) = 0;
+    virtual Error setLayerPerFrameMetadata(
+        Display display, Layer layer,
+        const std::vector<IComposerClient::PerFrameMetadata>& metadata) = 0;
 
     virtual Error getReadbackBufferAttributes(Display display, PixelFormat* outFormat,
                                               Dataspace* outDataspace) = 0;
     virtual Error setReadbackBuffer(Display display, const native_handle_t* bufferHandle,
                                     base::unique_fd fenceFd) = 0;
     virtual Error getReadbackBufferFence(Display display, base::unique_fd* outFenceFd) = 0;
-
+    virtual Error createVirtualDisplay_2_2(uint32_t width, uint32_t height, PixelFormat* format,
+                                           Display* outDisplay) = 0;
+    virtual Error getClientTargetSupport_2_2(Display display, uint32_t width, uint32_t height,
+                                             PixelFormat format, Dataspace dataspace) = 0;
     virtual Error setPowerMode_2_2(Display display, IComposerClient::PowerMode mode) = 0;
 
     virtual Error setLayerFloatColor(Display display, Layer layer,
                                      IComposerClient::FloatColor color) = 0;
+
+    virtual Error getColorModes_2_2(Display display, hidl_vec<ColorMode>* outModes) = 0;
+    virtual Error getRenderIntents(Display display, ColorMode mode,
+                                   std::vector<RenderIntent>* outIntents) = 0;
+    virtual Error setColorMode_2_2(Display display, ColorMode mode, RenderIntent intent) = 0;
+
+    virtual std::array<float, 16> getDataspaceSaturationMatrix(Dataspace dataspace) = 0;
 };
 
 }  // namespace hal
diff --git a/graphics/composer/2.2/utils/passthrough/include/composer-passthrough/2.2/HwcHal.h b/graphics/composer/2.2/utils/passthrough/include/composer-passthrough/2.2/HwcHal.h
index b251351..93da0a5 100644
--- a/graphics/composer/2.2/utils/passthrough/include/composer-passthrough/2.2/HwcHal.h
+++ b/graphics/composer/2.2/utils/passthrough/include/composer-passthrough/2.2/HwcHal.h
@@ -34,8 +34,10 @@
 
 namespace detail {
 
-using common::V1_0::Dataspace;
-using common::V1_0::PixelFormat;
+using common::V1_1::ColorMode;
+using common::V1_1::Dataspace;
+using common::V1_1::PixelFormat;
+using common::V1_1::RenderIntent;
 using V2_1::Display;
 using V2_1::Error;
 using V2_1::Layer;
@@ -72,9 +74,10 @@
         return Error::NONE;
     }
 
-    Error setPerFrameMetadata(
-        Display display, const std::vector<IComposerClient::PerFrameMetadata>& metadata) override {
-        if (!mDispatch.setPerFrameMetadata) {
+    Error setLayerPerFrameMetadata(
+        Display display, Layer layer,
+        const std::vector<IComposerClient::PerFrameMetadata>& metadata) override {
+        if (!mDispatch.setLayerPerFrameMetadata) {
             return Error::UNSUPPORTED;
         }
 
@@ -87,8 +90,8 @@
             values.push_back(m.value);
         }
 
-        int32_t error = mDispatch.setPerFrameMetadata(mDevice, display, metadata.size(),
-                                                      keys.data(), values.data());
+        int32_t error = mDispatch.setLayerPerFrameMetadata(mDevice, display, layer, metadata.size(),
+                                                           keys.data(), values.data());
         return static_cast<Error>(error);
     }
 
@@ -131,6 +134,19 @@
         return static_cast<Error>(error);
     }
 
+    Error createVirtualDisplay_2_2(uint32_t width, uint32_t height, PixelFormat* format,
+                                   Display* outDisplay) override {
+        return createVirtualDisplay(
+            width, height, reinterpret_cast<common::V1_0::PixelFormat*>(format), outDisplay);
+    }
+
+    Error getClientTargetSupport_2_2(Display display, uint32_t width, uint32_t height,
+                                     PixelFormat format, Dataspace dataspace) override {
+        return getClientTargetSupport(display, width, height,
+                                      static_cast<common::V1_0::PixelFormat>(format),
+                                      static_cast<common::V1_0::Dataspace>(dataspace));
+    }
+
     Error setPowerMode_2_2(Display display, IComposerClient::PowerMode mode) override {
         if (mode == IComposerClient::PowerMode::ON_SUSPEND) {
             return Error::UNSUPPORTED;
@@ -149,6 +165,69 @@
         return static_cast<Error>(error);
     }
 
+    Error getColorModes_2_2(Display display, hidl_vec<ColorMode>* outModes) override {
+        return getColorModes(display,
+                             reinterpret_cast<hidl_vec<common::V1_0::ColorMode>*>(outModes));
+    }
+
+    Error getRenderIntents(Display display, ColorMode mode,
+                           std::vector<RenderIntent>* outIntents) override {
+        if (!mDispatch.getRenderIntents) {
+            *outIntents = std::vector<RenderIntent>({RenderIntent::COLORIMETRIC});
+            return Error::NONE;
+        }
+
+        uint32_t count = 0;
+        int32_t error =
+            mDispatch.getRenderIntents(mDevice, display, int32_t(mode), &count, nullptr);
+        if (error != HWC2_ERROR_NONE) {
+            return static_cast<Error>(error);
+        }
+
+        std::vector<RenderIntent> intents(count);
+        error = mDispatch.getRenderIntents(
+            mDevice, display, int32_t(mode), &count,
+            reinterpret_cast<std::underlying_type<RenderIntent>::type*>(intents.data()));
+        if (error != HWC2_ERROR_NONE) {
+            return static_cast<Error>(error);
+        }
+        intents.resize(count);
+
+        *outIntents = std::move(intents);
+        return Error::NONE;
+    }
+
+    Error setColorMode_2_2(Display display, ColorMode mode, RenderIntent intent) override {
+        if (!mDispatch.setColorModeWithRenderIntent) {
+            if (intent != RenderIntent::COLORIMETRIC) {
+                return Error::UNSUPPORTED;
+            }
+            return setColorMode(display, static_cast<common::V1_0::ColorMode>(mode));
+        }
+
+        int32_t err = mDispatch.setColorModeWithRenderIntent(
+            mDevice, display, static_cast<int32_t>(mode), static_cast<int32_t>(intent));
+        return static_cast<Error>(err);
+    }
+
+    std::array<float, 16> getDataspaceSaturationMatrix(Dataspace dataspace) override {
+        std::array<float, 16> matrix;
+
+        int32_t error = HWC2_ERROR_UNSUPPORTED;
+        if (mDispatch.getDataspaceSaturationMatrix) {
+            error = mDispatch.getDataspaceSaturationMatrix(mDevice, static_cast<int32_t>(dataspace),
+                                                           matrix.data());
+        }
+        if (error != HWC2_ERROR_NONE) {
+            return std::array<float, 16>{
+                1.0f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f, 0.0f, 0.0f,
+                0.0f, 0.0f, 1.0f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f,
+            };
+        }
+
+        return matrix;
+    }
+
    protected:
     template <typename T>
     bool initOptionalDispatch(hwc2_function_descriptor_t desc, T* outPfn) {
@@ -168,7 +247,8 @@
 
         initOptionalDispatch(HWC2_FUNCTION_SET_LAYER_FLOAT_COLOR, &mDispatch.setLayerFloatColor);
 
-        initOptionalDispatch(HWC2_FUNCTION_SET_PER_FRAME_METADATA, &mDispatch.setPerFrameMetadata);
+        initOptionalDispatch(HWC2_FUNCTION_SET_LAYER_PER_FRAME_METADATA,
+                             &mDispatch.setLayerPerFrameMetadata);
         initOptionalDispatch(HWC2_FUNCTION_GET_PER_FRAME_METADATA_KEYS,
                              &mDispatch.getPerFrameMetadataKeys);
 
@@ -178,21 +258,34 @@
         initOptionalDispatch(HWC2_FUNCTION_GET_READBACK_BUFFER_FENCE,
                              &mDispatch.getReadbackBufferFence);
 
+        initOptionalDispatch(HWC2_FUNCTION_GET_RENDER_INTENTS, &mDispatch.getRenderIntents);
+        initOptionalDispatch(HWC2_FUNCTION_SET_COLOR_MODE_WITH_RENDER_INTENT,
+                             &mDispatch.setColorModeWithRenderIntent);
+        initOptionalDispatch(HWC2_FUNCTION_GET_DATASPACE_SATURATION_MATRIX,
+                             &mDispatch.getDataspaceSaturationMatrix);
+
         return true;
     }
 
     struct {
         HWC2_PFN_SET_LAYER_FLOAT_COLOR setLayerFloatColor;
-        HWC2_PFN_SET_PER_FRAME_METADATA setPerFrameMetadata;
+        HWC2_PFN_SET_LAYER_PER_FRAME_METADATA setLayerPerFrameMetadata;
         HWC2_PFN_GET_PER_FRAME_METADATA_KEYS getPerFrameMetadataKeys;
         HWC2_PFN_SET_READBACK_BUFFER setReadbackBuffer;
         HWC2_PFN_GET_READBACK_BUFFER_ATTRIBUTES getReadbackBufferAttributes;
         HWC2_PFN_GET_READBACK_BUFFER_FENCE getReadbackBufferFence;
+        HWC2_PFN_GET_RENDER_INTENTS getRenderIntents;
+        HWC2_PFN_SET_COLOR_MODE_WITH_RENDER_INTENT setColorModeWithRenderIntent;
+        HWC2_PFN_GET_DATASPACE_SATURATION_MATRIX getDataspaceSaturationMatrix;
     } mDispatch = {};
 
    private:
     using BaseType2_1 = V2_1::passthrough::detail::HwcHalImpl<Hal>;
+    using BaseType2_1::getColorModes;
     using BaseType2_1::mDevice;
+    using BaseType2_1::setColorMode;
+    using BaseType2_1::createVirtualDisplay;
+    using BaseType2_1::getClientTargetSupport;
     using BaseType2_1::setPowerMode;
 };
 
diff --git a/graphics/composer/2.2/utils/vts/Android.bp b/graphics/composer/2.2/utils/vts/Android.bp
index 641fdcb..c6b524d 100644
--- a/graphics/composer/2.2/utils/vts/Android.bp
+++ b/graphics/composer/2.2/utils/vts/Android.bp
@@ -26,10 +26,17 @@
         "android.hardware.graphics.composer@2.1-vts",
         "android.hardware.graphics.composer@2.2",
     ],
+    export_static_lib_headers: [
+        "android.hardware.graphics.composer@2.1-vts",
+    ],
     header_libs: [
         "android.hardware.graphics.composer@2.1-command-buffer",
         "android.hardware.graphics.composer@2.2-command-buffer",
     ],
+    export_header_lib_headers: [
+        "android.hardware.graphics.composer@2.1-command-buffer",
+        "android.hardware.graphics.composer@2.2-command-buffer",
+    ],
     cflags: [
         "-O0",
         "-g",
diff --git a/graphics/composer/2.2/utils/vts/ComposerVts.cpp b/graphics/composer/2.2/utils/vts/ComposerVts.cpp
index b536f67..357c772 100644
--- a/graphics/composer/2.2/utils/vts/ComposerVts.cpp
+++ b/graphics/composer/2.2/utils/vts/ComposerVts.cpp
@@ -87,6 +87,33 @@
                                   });
 }
 
+Display ComposerClient_v2_2::createVirtualDisplay_2_2(uint32_t width, uint32_t height,
+                                                      PixelFormat formatHint,
+                                                      uint32_t outputBufferSlotCount,
+                                                      PixelFormat* outFormat) {
+    Display display = 0;
+    mClient_v2_2->createVirtualDisplay_2_2(
+        width, height, formatHint, outputBufferSlotCount,
+        [&](const auto& tmpError, const auto& tmpDisplay, const auto& tmpFormat) {
+            ASSERT_EQ(Error::NONE, tmpError) << "failed to create virtual display";
+            display = tmpDisplay;
+            *outFormat = tmpFormat;
+
+            ASSERT_TRUE(mDisplayResources.insert({display, DisplayResource(true)}).second)
+                << "duplicated virtual display id " << display;
+        });
+
+    return display;
+}
+
+bool ComposerClient_v2_2::getClientTargetSupport_2_2(Display display, uint32_t width,
+                                                     uint32_t height, PixelFormat format,
+                                                     Dataspace dataspace) {
+    Error error =
+        mClient_v2_2->getClientTargetSupport_2_2(display, width, height, format, dataspace);
+    return error == Error::NONE;
+}
+
 void ComposerClient_v2_2::setPowerMode_2_2(Display display, V2_2::IComposerClient::PowerMode mode) {
     Error error = mClient_v2_2->setPowerMode_2_2(display, mode);
     ASSERT_TRUE(error == Error::NONE || error == Error::UNSUPPORTED) << "failed to set power mode";
@@ -119,6 +146,41 @@
     *outFence = 0;
 }
 
+std::vector<ColorMode> ComposerClient_v2_2::getColorModes(Display display) {
+    std::vector<ColorMode> modes;
+    mClient_v2_2->getColorModes_2_2(display, [&](const auto& tmpError, const auto& tmpModes) {
+        ASSERT_EQ(Error::NONE, tmpError) << "failed to get color modes";
+        modes = tmpModes;
+    });
+    return modes;
+}
+
+std::vector<RenderIntent> ComposerClient_v2_2::getRenderIntents(Display display, ColorMode mode) {
+    std::vector<RenderIntent> intents;
+    mClient_v2_2->getRenderIntents(
+        display, mode, [&](const auto& tmpError, const auto& tmpIntents) {
+            ASSERT_EQ(Error::NONE, tmpError) << "failed to get render intents";
+            intents = tmpIntents;
+        });
+    return intents;
+}
+
+void ComposerClient_v2_2::setColorMode(Display display, ColorMode mode, RenderIntent intent) {
+    Error error = mClient_v2_2->setColorMode_2_2(display, mode, intent);
+    ASSERT_TRUE(error == Error::NONE || error == Error::UNSUPPORTED) << "failed to set color mode";
+}
+
+std::array<float, 16> ComposerClient_v2_2::getDataspaceSaturationMatrix(Dataspace dataspace) {
+    std::array<float, 16> matrix;
+    mClient_v2_2->getDataspaceSaturationMatrix(
+        dataspace, [&](const auto& tmpError, const auto& tmpMatrix) {
+            ASSERT_EQ(Error::NONE, tmpError) << "failed to get datasapce saturation matrix";
+            std::copy_n(tmpMatrix.data(), matrix.size(), matrix.begin());
+        });
+
+    return matrix;
+}
+
 }  // namespace vts
 }  // namespace V2_2
 }  // namespace composer
diff --git a/graphics/composer/2.2/utils/vts/include/composer-vts/2.2/ComposerVts.h b/graphics/composer/2.2/utils/vts/include/composer-vts/2.2/ComposerVts.h
index eced69f..62ab83f 100644
--- a/graphics/composer/2.2/utils/vts/include/composer-vts/2.2/ComposerVts.h
+++ b/graphics/composer/2.2/utils/vts/include/composer-vts/2.2/ComposerVts.h
@@ -36,10 +36,11 @@
 namespace V2_2 {
 namespace vts {
 
-using android::hardware::graphics::common::V1_0::ColorMode;
-using android::hardware::graphics::common::V1_0::Dataspace;
 using android::hardware::graphics::common::V1_0::Hdr;
-using android::hardware::graphics::common::V1_0::PixelFormat;
+using android::hardware::graphics::common::V1_1::ColorMode;
+using android::hardware::graphics::common::V1_1::Dataspace;
+using android::hardware::graphics::common::V1_1::PixelFormat;
+using android::hardware::graphics::common::V1_1::RenderIntent;
 using android::hardware::graphics::composer::V2_2::IComposer;
 using android::hardware::graphics::composer::V2_2::IComposerClient;
 
@@ -66,12 +67,22 @@
 
     std::vector<IComposerClient::PerFrameMetadataKey> getPerFrameMetadataKeys(Display display);
 
+    Display createVirtualDisplay_2_2(uint32_t width, uint32_t height, PixelFormat formatHint,
+                                     uint32_t outputBufferSlotCount, PixelFormat* outFormat);
+    bool getClientTargetSupport_2_2(Display display, uint32_t width, uint32_t height,
+                                    PixelFormat format, Dataspace dataspace);
     void setPowerMode_2_2(Display display, V2_2::IComposerClient::PowerMode mode);
     void setReadbackBuffer(Display display, const native_handle_t* buffer, int32_t releaseFence);
     void getReadbackBufferAttributes(Display display, PixelFormat* outPixelFormat,
                                      Dataspace* outDataspace);
     void getReadbackBufferFence(Display display, int32_t* outFence);
 
+    std::vector<ColorMode> getColorModes(Display display);
+    std::vector<RenderIntent> getRenderIntents(Display display, ColorMode mode);
+    void setColorMode(Display display, ColorMode mode, RenderIntent intent);
+
+    std::array<float, 16> getDataspaceSaturationMatrix(Dataspace dataspace);
+
    private:
     sp<V2_2::IComposerClient> mClient_v2_2;
 };
diff --git a/graphics/composer/2.2/vts/functional/Android.bp b/graphics/composer/2.2/vts/functional/Android.bp
index 7747900..669fbae 100644
--- a/graphics/composer/2.2/vts/functional/Android.bp
+++ b/graphics/composer/2.2/vts/functional/Android.bp
@@ -27,6 +27,7 @@
     ],
     static_libs: [
         "android.hardware.graphics.allocator@2.0",
+        "android.hardware.graphics.common@1.1",
         "android.hardware.graphics.composer@2.1",
         "android.hardware.graphics.composer@2.1-vts",
         "android.hardware.graphics.composer@2.2",
@@ -34,6 +35,7 @@
         "android.hardware.graphics.mapper@2.0",
         "android.hardware.graphics.mapper@2.0-vts",
         "android.hardware.graphics.mapper@2.1",
+        "android.hardware.graphics.mapper@2.1-vts",
     ],
     header_libs: [
         "android.hardware.graphics.composer@2.1-command-buffer",
diff --git a/graphics/composer/2.2/vts/functional/VtsHalGraphicsComposerV2_2TargetTest.cpp b/graphics/composer/2.2/vts/functional/VtsHalGraphicsComposerV2_2TargetTest.cpp
index c494329..4e41333 100644
--- a/graphics/composer/2.2/vts/functional/VtsHalGraphicsComposerV2_2TargetTest.cpp
+++ b/graphics/composer/2.2/vts/functional/VtsHalGraphicsComposerV2_2TargetTest.cpp
@@ -22,7 +22,7 @@
 #include <composer-vts/2.1/GraphicsComposerCallback.h>
 #include <composer-vts/2.1/TestCommandReader.h>
 #include <composer-vts/2.2/ComposerVts.h>
-#include <mapper-vts/2.0/MapperVts.h>
+#include <mapper-vts/2.1/MapperVts.h>
 
 namespace android {
 namespace hardware {
@@ -33,14 +33,15 @@
 namespace {
 
 using android::hardware::graphics::common::V1_0::BufferUsage;
-using android::hardware::graphics::common::V1_0::ColorMode;
 using android::hardware::graphics::common::V1_0::ColorTransform;
-using android::hardware::graphics::common::V1_0::Dataspace;
-using android::hardware::graphics::common::V1_0::PixelFormat;
 using android::hardware::graphics::common::V1_0::Transform;
+using android::hardware::graphics::common::V1_1::ColorMode;
+using android::hardware::graphics::common::V1_1::Dataspace;
+using android::hardware::graphics::common::V1_1::PixelFormat;
+using android::hardware::graphics::common::V1_1::RenderIntent;
 using android::hardware::graphics::composer::V2_2::IComposerClient;
-using android::hardware::graphics::mapper::V2_0::IMapper;
-using android::hardware::graphics::mapper::V2_0::vts::Gralloc;
+using android::hardware::graphics::mapper::V2_1::IMapper;
+using android::hardware::graphics::mapper::V2_1::vts::Gralloc;
 using GrallocError = android::hardware::graphics::mapper::V2_0::Error;
 
 // Test environment for graphics.composer
@@ -146,9 +147,9 @@
 };
 
 /**
- * Test IComposerClient::Command::SET_PER_FRAME_METADATA.
+ * Test IComposerClient::Command::SET_LAYER_PER_FRAME_METADATA.
  */
-TEST_F(GraphicsComposerHidlCommandTest, SET_PER_FRAME_METADATA) {
+TEST_F(GraphicsComposerHidlCommandTest, SET_LAYER_PER_FRAME_METADATA) {
     Layer layer;
     ASSERT_NO_FATAL_FAILURE(layer =
                                 mComposerClient->createLayer(mPrimaryDisplay, kBufferSlotCount));
@@ -182,7 +183,7 @@
     hidlMetadata.push_back({IComposerClient::PerFrameMetadataKey::MAX_CONTENT_LIGHT_LEVEL, 78.0});
     hidlMetadata.push_back(
         {IComposerClient::PerFrameMetadataKey::MAX_FRAME_AVERAGE_LIGHT_LEVEL, 62.0});
-    mWriter->setPerFrameMetadata(hidlMetadata);
+    mWriter->setLayerPerFrameMetadata(hidlMetadata);
     execute();
 }
 
@@ -192,6 +193,55 @@
 TEST_F(GraphicsComposerHidlTest, GetPerFrameMetadataKeys) {
     mComposerClient->getPerFrameMetadataKeys(mPrimaryDisplay);
 }
+
+/**
+ * Test IComposerClient::createVirtualDisplay_2_2 and
+ * IComposerClient::destroyVirtualDisplay.
+ *
+ * Test that virtual displays can be created and has the correct display type.
+ */
+TEST_F(GraphicsComposerHidlTest, CreateVirtualDisplay_2_2) {
+    if (mComposerClient->getMaxVirtualDisplayCount() == 0) {
+        GTEST_SUCCEED() << "no virtual display support";
+        return;
+    }
+
+    Display display;
+    PixelFormat format;
+    ASSERT_NO_FATAL_FAILURE(
+        display = mComposerClient->createVirtualDisplay_2_2(
+            64, 64, PixelFormat::IMPLEMENTATION_DEFINED, kBufferSlotCount, &format));
+
+    // test display type
+    IComposerClient::DisplayType type = mComposerClient->getDisplayType(display);
+    EXPECT_EQ(IComposerClient::DisplayType::VIRTUAL, type);
+
+    mComposerClient->destroyVirtualDisplay(display);
+}
+
+/**
+ * Test IComposerClient::getClientTargetSupport_2_2.
+ *
+ * Test that IComposerClient::getClientTargetSupport returns true for the
+ * required client targets.
+ */
+TEST_F(GraphicsComposerHidlTest, GetClientTargetSupport_2_2) {
+    std::vector<Config> configs = mComposerClient->getDisplayConfigs(mPrimaryDisplay);
+    for (auto config : configs) {
+        int32_t width = mComposerClient->getDisplayAttribute(mPrimaryDisplay, config,
+                                                             IComposerClient::Attribute::WIDTH);
+        int32_t height = mComposerClient->getDisplayAttribute(mPrimaryDisplay, config,
+                                                              IComposerClient::Attribute::HEIGHT);
+        ASSERT_LT(0, width);
+        ASSERT_LT(0, height);
+
+        mComposerClient->setActiveConfig(mPrimaryDisplay, config);
+
+        ASSERT_TRUE(mComposerClient->getClientTargetSupport_2_2(
+            mPrimaryDisplay, width, height, PixelFormat::RGBA_8888, Dataspace::UNKNOWN));
+    }
+}
+
 /**
  * Test IComposerClient::setPowerMode_2_2.
  */
@@ -235,6 +285,56 @@
     mWriter->setLayerFloatColor(IComposerClient::FloatColor{0.0, 0.0, 0.0, 0.0});
 }
 
+/**
+ * Test IComposerClient::getDataspaceSaturationMatrix.
+ */
+TEST_F(GraphicsComposerHidlTest, getDataspaceSaturationMatrix) {
+    auto matrix = mComposerClient->getDataspaceSaturationMatrix(Dataspace::SRGB_LINEAR);
+    // the last row is known
+    ASSERT_EQ(0.0f, matrix[12]);
+    ASSERT_EQ(0.0f, matrix[13]);
+    ASSERT_EQ(0.0f, matrix[14]);
+    ASSERT_EQ(1.0f, matrix[15]);
+}
+
+/**
+ * Test IComposerClient::getColorMode_2_2.
+ */
+TEST_F(GraphicsComposerHidlTest, GetColorMode_2_2) {
+    std::vector<ColorMode> modes = mComposerClient->getColorModes(mPrimaryDisplay);
+
+    auto nativeMode = std::find(modes.cbegin(), modes.cend(), ColorMode::NATIVE);
+    EXPECT_NE(modes.cend(), nativeMode);
+}
+
+/**
+ * Test IComposerClient::getRenderIntent.
+ */
+TEST_F(GraphicsComposerHidlTest, GetRenderIntent) {
+    std::vector<ColorMode> modes = mComposerClient->getColorModes(mPrimaryDisplay);
+    for (auto mode : modes) {
+        std::vector<RenderIntent> intents =
+            mComposerClient->getRenderIntents(mPrimaryDisplay, mode);
+        auto colorimetricIntent =
+            std::find(intents.cbegin(), intents.cend(), RenderIntent::COLORIMETRIC);
+        EXPECT_NE(intents.cend(), colorimetricIntent);
+    }
+}
+
+/**
+ * Test IComposerClient::setColorMode_2_2.
+ */
+TEST_F(GraphicsComposerHidlTest, SetColorMode_2_2) {
+    std::vector<ColorMode> modes = mComposerClient->getColorModes(mPrimaryDisplay);
+    for (auto mode : modes) {
+        std::vector<RenderIntent> intents =
+            mComposerClient->getRenderIntents(mPrimaryDisplay, mode);
+        for (auto intent : intents) {
+            mComposerClient->setColorMode(mPrimaryDisplay, mode, intent);
+        }
+    }
+}
+
 }  // namespace
 }  // namespace vts
 }  // namespace V2_2
diff --git a/graphics/mapper/2.1/utils/vts/MapperVts.cpp b/graphics/mapper/2.1/utils/vts/MapperVts.cpp
index 0aaa926..078068e 100644
--- a/graphics/mapper/2.1/utils/vts/MapperVts.cpp
+++ b/graphics/mapper/2.1/utils/vts/MapperVts.cpp
@@ -43,6 +43,13 @@
                       offsetof(IMapper::BufferDescriptorInfo, usage),
               "");
 
+Gralloc::Gralloc() : V2_0::vts::Gralloc() {
+    if (::testing::Test::HasFatalFailure()) {
+        return;
+    }
+    init();
+}
+
 Gralloc::Gralloc(const std::string& allocatorServiceName, const std::string& mapperServiceName)
     : V2_0::vts::Gralloc(allocatorServiceName, mapperServiceName) {
     if (::testing::Test::HasFatalFailure()) {
diff --git a/graphics/mapper/2.1/utils/vts/include/mapper-vts/2.1/MapperVts.h b/graphics/mapper/2.1/utils/vts/include/mapper-vts/2.1/MapperVts.h
index b7fa751..423d4b3 100644
--- a/graphics/mapper/2.1/utils/vts/include/mapper-vts/2.1/MapperVts.h
+++ b/graphics/mapper/2.1/utils/vts/include/mapper-vts/2.1/MapperVts.h
@@ -32,6 +32,7 @@
 // A wrapper to IAllocator and IMapper.
 class Gralloc : public V2_0::vts::Gralloc {
    public:
+    Gralloc();
     Gralloc(const std::string& allocatorServiceName, const std::string& mapperServiceName);
 
     sp<IMapper> getMapper() const;
diff --git a/keymaster/3.0/vts/functional/keymaster_hidl_hal_test.cpp b/keymaster/3.0/vts/functional/keymaster_hidl_hal_test.cpp
index 3a181a9..fbe5237 100644
--- a/keymaster/3.0/vts/functional/keymaster_hidl_hal_test.cpp
+++ b/keymaster/3.0/vts/functional/keymaster_hidl_hal_test.cpp
@@ -2918,6 +2918,28 @@
 }
 
 /*
+ * EncryptionOperationsTest.AesEcbWithUserId
+ *
+ * Verifies that AES ECB mode works when Tag::USER_ID is specified.
+ */
+TEST_F(EncryptionOperationsTest, AesEcbWithUserId) {
+    string key = {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0};
+    ASSERT_EQ(ErrorCode::OK, ImportKey(AuthorizationSetBuilder()
+                                           .Authorization(TAG_NO_AUTH_REQUIRED)
+                                           .Authorization(TAG_USER_ID, 0)
+                                           .AesEncryptionKey(key.size() * 8)
+                                           .EcbMode()
+                                           .Padding(PaddingMode::PKCS7),
+                                       KeyFormat::RAW, key));
+
+    string message = "Hello World!";
+    auto params = AuthorizationSetBuilder().BlockMode(BlockMode::ECB).Padding(PaddingMode::PKCS7);
+    string ciphertext = EncryptMessage(message, params);
+    string plaintext = DecryptMessage(ciphertext, params);
+    EXPECT_EQ(message, plaintext);
+}
+
+/*
  * EncryptionOperationsTest.AesEcbRoundTripSuccess
  *
  * Verifies that AES encryption fails in the correct way when an unauthorized mode is specified.
diff --git a/keymaster/4.0/support/Keymaster.cpp b/keymaster/4.0/support/Keymaster.cpp
index bf52c47..fac0017 100644
--- a/keymaster/4.0/support/Keymaster.cpp
+++ b/keymaster/4.0/support/Keymaster.cpp
@@ -40,7 +40,7 @@
     serviceManager->listByInterface(descriptor, [&](const hidl_vec<hidl_string>& names) {
         for (auto& name : names) {
             if (name == "default") foundDefault = true;
-            auto device = Wrapper::WrappedIKeymasterDevice::getService();
+            auto device = Wrapper::WrappedIKeymasterDevice::getService(name);
             CHECK(device) << "Failed to get service for " << descriptor << " with interface name "
                           << name;
             result.push_back(std::unique_ptr<Keymaster>(new Wrapper(device, name)));
diff --git a/keymaster/4.0/support/include/keymasterV4_0/keymaster_tags.h b/keymaster/4.0/support/include/keymasterV4_0/keymaster_tags.h
index 9d6501b..ce213bc 100644
--- a/keymaster/4.0/support/include/keymasterV4_0/keymaster_tags.h
+++ b/keymaster/4.0/support/include/keymasterV4_0/keymaster_tags.h
@@ -142,24 +142,28 @@
 DECLARE_TYPED_TAG(RSA_PUBLIC_EXPONENT);
 DECLARE_TYPED_TAG(TRUSTED_CONFIRMATION_REQUIRED);
 DECLARE_TYPED_TAG(UNIQUE_ID);
+DECLARE_TYPED_TAG(UNLOCKED_DEVICE_REQUIRED);
 DECLARE_TYPED_TAG(USAGE_EXPIRE_DATETIME);
 DECLARE_TYPED_TAG(USER_AUTH_TYPE);
+DECLARE_TYPED_TAG(USER_ID);
 DECLARE_TYPED_TAG(USER_SECURE_ID);
 
 template <typename... Elems>
 struct MetaList {};
 
-using all_tags_t = MetaList<
-    TAG_INVALID_t, TAG_KEY_SIZE_t, TAG_MAC_LENGTH_t, TAG_CALLER_NONCE_t, TAG_MIN_MAC_LENGTH_t,
-    TAG_RSA_PUBLIC_EXPONENT_t, TAG_INCLUDE_UNIQUE_ID_t, TAG_ACTIVE_DATETIME_t,
-    TAG_ORIGINATION_EXPIRE_DATETIME_t, TAG_USAGE_EXPIRE_DATETIME_t, TAG_MIN_SECONDS_BETWEEN_OPS_t,
-    TAG_MAX_USES_PER_BOOT_t, TAG_USER_SECURE_ID_t, TAG_NO_AUTH_REQUIRED_t, TAG_AUTH_TIMEOUT_t,
-    TAG_ALLOW_WHILE_ON_BODY_t, TAG_APPLICATION_ID_t, TAG_APPLICATION_DATA_t,
-    TAG_CREATION_DATETIME_t, TAG_ROLLBACK_RESISTANCE_t, TAG_ROOT_OF_TRUST_t, TAG_ASSOCIATED_DATA_t,
-    TAG_NONCE_t, TAG_BOOTLOADER_ONLY_t, TAG_OS_VERSION_t, TAG_OS_PATCHLEVEL_t, TAG_UNIQUE_ID_t,
-    TAG_ATTESTATION_CHALLENGE_t, TAG_ATTESTATION_APPLICATION_ID_t, TAG_RESET_SINCE_ID_ROTATION_t,
-    TAG_PURPOSE_t, TAG_ALGORITHM_t, TAG_BLOCK_MODE_t, TAG_DIGEST_t, TAG_PADDING_t,
-    TAG_BLOB_USAGE_REQUIREMENTS_t, TAG_ORIGIN_t, TAG_USER_AUTH_TYPE_t, TAG_EC_CURVE_t>;
+using all_tags_t =
+    MetaList<TAG_INVALID_t, TAG_KEY_SIZE_t, TAG_MAC_LENGTH_t, TAG_CALLER_NONCE_t,
+             TAG_MIN_MAC_LENGTH_t, TAG_RSA_PUBLIC_EXPONENT_t, TAG_INCLUDE_UNIQUE_ID_t,
+             TAG_ACTIVE_DATETIME_t, TAG_ORIGINATION_EXPIRE_DATETIME_t, TAG_USAGE_EXPIRE_DATETIME_t,
+             TAG_MIN_SECONDS_BETWEEN_OPS_t, TAG_MAX_USES_PER_BOOT_t, TAG_USER_ID_t,
+             TAG_USER_SECURE_ID_t, TAG_NO_AUTH_REQUIRED_t, TAG_AUTH_TIMEOUT_t,
+             TAG_ALLOW_WHILE_ON_BODY_t, TAG_UNLOCKED_DEVICE_REQUIRED_t, TAG_APPLICATION_ID_t,
+             TAG_APPLICATION_DATA_t, TAG_CREATION_DATETIME_t, TAG_ROLLBACK_RESISTANCE_t,
+             TAG_ROOT_OF_TRUST_t, TAG_ASSOCIATED_DATA_t, TAG_NONCE_t, TAG_BOOTLOADER_ONLY_t,
+             TAG_OS_VERSION_t, TAG_OS_PATCHLEVEL_t, TAG_UNIQUE_ID_t, TAG_ATTESTATION_CHALLENGE_t,
+             TAG_ATTESTATION_APPLICATION_ID_t, TAG_RESET_SINCE_ID_ROTATION_t, TAG_PURPOSE_t,
+             TAG_ALGORITHM_t, TAG_BLOCK_MODE_t, TAG_DIGEST_t, TAG_PADDING_t,
+             TAG_BLOB_USAGE_REQUIREMENTS_t, TAG_ORIGIN_t, TAG_USER_AUTH_TYPE_t, TAG_EC_CURVE_t>;
 
 template <typename TypedTagType>
 struct TypedTag2ValueType;
@@ -343,6 +347,7 @@
         case Tag::BOOTLOADER_ONLY:
         case Tag::NO_AUTH_REQUIRED:
         case Tag::ALLOW_WHILE_ON_BODY:
+        case Tag::UNLOCKED_DEVICE_REQUIRED:
         case Tag::ROLLBACK_RESISTANCE:
         case Tag::RESET_SINCE_ID_ROTATION:
         case Tag::TRUSTED_CONFIRMATION_REQUIRED:
@@ -357,6 +362,7 @@
         case Tag::OS_VERSION:
         case Tag::OS_PATCHLEVEL:
         case Tag::MAC_LENGTH:
+        case Tag::USER_ID:
         case Tag::AUTH_TIMEOUT:
         case Tag::VENDOR_PATCHLEVEL:
         case Tag::BOOT_PATCHLEVEL:
diff --git a/keymaster/4.0/types.hal b/keymaster/4.0/types.hal
index 91ec9bf..47fd1ed 100644
--- a/keymaster/4.0/types.hal
+++ b/keymaster/4.0/types.hal
@@ -118,7 +118,8 @@
                                                        * boot. */
 
     /* User authentication */
-    // 500-501 reserved
+    // 500 reserved
+    USER_ID = TagType:UINT | 501,             /* Android ID of authorized user or authenticator(s), */
     USER_SECURE_ID = TagType:ULONG_REP | 502, /* Secure ID of authorized user or authenticator(s).
                                                * Disallowed if NO_AUTH_REQUIRED is present. */
     NO_AUTH_REQUIRED = TagType:BOOL | 503,    /* If key is usable without authentication. */
@@ -191,6 +192,9 @@
      * match the data described in the token, keymaster must return NO_USER_CONFIRMATION. */
     TRUSTED_CONFIRMATION_REQUIRED = TagType:BOOL | 508,
 
+    UNLOCKED_DEVICE_REQUIRED = TagType:BOOL | 509, /* Require the device screen to be unlocked if
+                                                    * the key is used. */
+
     /* Application access control */
     APPLICATION_ID = TagType:BYTES | 601, /* Byte string identifying the authorized application. */
 
@@ -471,6 +475,7 @@
     PROOF_OF_PRESENCE_REQUIRED = -69,
     CONCURRENT_PROOF_OF_PRESENCE_REQUESTED = -70,
     NO_USER_CONFIRMATION = -71,
+    DEVICE_LOCKED = -72,
 
     UNIMPLEMENTED = -100,
     VERSION_MISMATCH = -101,
diff --git a/neuralnetworks/1.0/types.hal b/neuralnetworks/1.0/types.hal
index 8779723..c97a00b 100644
--- a/neuralnetworks/1.0/types.hal
+++ b/neuralnetworks/1.0/types.hal
@@ -84,6 +84,7 @@
      *     output.dimension = {5, 4, 3, 2}
      *
      * Supported tensor types: {@link OperandType::TENSOR_FLOAT32}
+     *                         {@link OperandType::TENSOR_QUANT8_ASYMM}
      * Supported tensor rank: up to 4
      *
      * Inputs:
@@ -645,6 +646,7 @@
      * input operands. It starts with the trailing dimensions, and works its way forward.
      *
      * Supported tensor types: {@link OperandType::TENSOR_FLOAT32}
+     *                         {@link OperandType::TENSOR_QUANT8_ASYMM}
      * Supported tensor rank: up to 4
      *
      * Inputs:
diff --git a/neuralnetworks/1.0/vts/functional/Android.bp b/neuralnetworks/1.0/vts/functional/Android.bp
index 54dd14a..e28113b 100644
--- a/neuralnetworks/1.0/vts/functional/Android.bp
+++ b/neuralnetworks/1.0/vts/functional/Android.bp
@@ -18,7 +18,6 @@
     name: "VtsHalNeuralnetworksTest_utils",
     srcs: [
         "Callbacks.cpp",
-        "Models.cpp",
         "GeneratedTestHarness.cpp",
     ],
     defaults: ["VtsHalTargetTestDefaults"],
@@ -41,14 +40,17 @@
 cc_test {
     name: "VtsHalNeuralnetworksV1_0TargetTest",
     srcs: [
-        "VtsHalNeuralnetworksV1_0.cpp",
-        "VtsHalNeuralnetworksV1_0BasicTest.cpp",
-        "VtsHalNeuralnetworksV1_0GeneratedTest.cpp",
+        "BasicTests.cpp",
+        "GeneratedTests.cpp",
+        "ValidateModel.cpp",
+        "ValidateRequest.cpp",
+        "ValidationTests.cpp",
+        "VtsHalNeuralnetworks.cpp",
     ],
     defaults: ["VtsHalTargetTestDefaults"],
     static_libs: [
-        "android.hardware.neuralnetworks@1.0",
         "android.hardware.neuralnetworks@1.1",
+        "android.hardware.neuralnetworks@1.0",
         "android.hidl.allocator@1.0",
         "android.hidl.memory@1.0",
         "libhidlmemory",
diff --git a/neuralnetworks/1.0/vts/functional/BasicTests.cpp b/neuralnetworks/1.0/vts/functional/BasicTests.cpp
new file mode 100644
index 0000000..945c406
--- /dev/null
+++ b/neuralnetworks/1.0/vts/functional/BasicTests.cpp
@@ -0,0 +1,56 @@
+/*
+ * Copyright (C) 2018 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#define LOG_TAG "neuralnetworks_hidl_hal_test"
+
+#include "VtsHalNeuralnetworks.h"
+
+namespace android {
+namespace hardware {
+namespace neuralnetworks {
+namespace V1_0 {
+namespace vts {
+namespace functional {
+
+// create device test
+TEST_F(NeuralnetworksHidlTest, CreateDevice) {}
+
+// status test
+TEST_F(NeuralnetworksHidlTest, StatusTest) {
+    Return<DeviceStatus> status = device->getStatus();
+    ASSERT_TRUE(status.isOk());
+    EXPECT_EQ(DeviceStatus::AVAILABLE, static_cast<DeviceStatus>(status));
+}
+
+// initialization
+TEST_F(NeuralnetworksHidlTest, GetCapabilitiesTest) {
+    Return<void> ret =
+        device->getCapabilities([](ErrorStatus status, const Capabilities& capabilities) {
+            EXPECT_EQ(ErrorStatus::NONE, status);
+            EXPECT_LT(0.0f, capabilities.float32Performance.execTime);
+            EXPECT_LT(0.0f, capabilities.float32Performance.powerUsage);
+            EXPECT_LT(0.0f, capabilities.quantized8Performance.execTime);
+            EXPECT_LT(0.0f, capabilities.quantized8Performance.powerUsage);
+        });
+    EXPECT_TRUE(ret.isOk());
+}
+
+}  // namespace functional
+}  // namespace vts
+}  // namespace V1_0
+}  // namespace neuralnetworks
+}  // namespace hardware
+}  // namespace android
diff --git a/neuralnetworks/1.0/vts/functional/Callbacks.h b/neuralnetworks/1.0/vts/functional/Callbacks.h
index 0e2ffb3..2ac6130 100644
--- a/neuralnetworks/1.0/vts/functional/Callbacks.h
+++ b/neuralnetworks/1.0/vts/functional/Callbacks.h
@@ -17,14 +17,6 @@
 namespace V1_0 {
 namespace implementation {
 
-using ::android::hardware::hidl_array;
-using ::android::hardware::hidl_memory;
-using ::android::hardware::hidl_string;
-using ::android::hardware::hidl_vec;
-using ::android::hardware::Return;
-using ::android::hardware::Void;
-using ::android::sp;
-
 /**
  * The CallbackBase class is used internally by the NeuralNetworks runtime to
  * synchronize between different threads. An asynchronous task is launched
diff --git a/neuralnetworks/1.0/vts/functional/GeneratedTestHarness.cpp b/neuralnetworks/1.0/vts/functional/GeneratedTestHarness.cpp
index 8646a4c..4f9d528 100644
--- a/neuralnetworks/1.0/vts/functional/GeneratedTestHarness.cpp
+++ b/neuralnetworks/1.0/vts/functional/GeneratedTestHarness.cpp
@@ -179,7 +179,7 @@
     }
 }
 
-void Execute(sp<V1_0::IDevice>& device, std::function<V1_0::Model(void)> create_model,
+void Execute(const sp<V1_0::IDevice>& device, std::function<V1_0::Model(void)> create_model,
              std::function<bool(int)> is_ignored,
              const std::vector<MixedTypedExampleType>& examples) {
     V1_0::Model model = create_model();
@@ -223,7 +223,7 @@
     EvaluatePreparedModel(preparedModel, is_ignored, examples);
 }
 
-void Execute(sp<V1_1::IDevice>& device, std::function<V1_1::Model(void)> create_model,
+void Execute(const sp<V1_1::IDevice>& device, std::function<V1_1::Model(void)> create_model,
              std::function<bool(int)> is_ignored,
              const std::vector<MixedTypedExampleType>& examples) {
     V1_1::Model model = create_model();
diff --git a/neuralnetworks/1.0/vts/functional/VtsHalNeuralnetworksV1_0GeneratedTest.cpp b/neuralnetworks/1.0/vts/functional/GeneratedTests.cpp
similarity index 61%
rename from neuralnetworks/1.0/vts/functional/VtsHalNeuralnetworksV1_0GeneratedTest.cpp
rename to neuralnetworks/1.0/vts/functional/GeneratedTests.cpp
index b99aef7..2107333 100644
--- a/neuralnetworks/1.0/vts/functional/VtsHalNeuralnetworksV1_0GeneratedTest.cpp
+++ b/neuralnetworks/1.0/vts/functional/GeneratedTests.cpp
@@ -16,47 +16,33 @@
 
 #define LOG_TAG "neuralnetworks_hidl_hal_test"
 
-#include "VtsHalNeuralnetworksV1_0.h"
+#include "VtsHalNeuralnetworks.h"
 
 #include "Callbacks.h"
 #include "TestHarness.h"
+#include "Utils.h"
 
 #include <android-base/logging.h>
 #include <android/hidl/memory/1.0/IMemory.h>
 #include <hidlmemory/mapping.h>
 
-using ::android::hardware::neuralnetworks::V1_0::IDevice;
-using ::android::hardware::neuralnetworks::V1_0::IPreparedModel;
-using ::android::hardware::neuralnetworks::V1_0::Capabilities;
-using ::android::hardware::neuralnetworks::V1_0::DeviceStatus;
-using ::android::hardware::neuralnetworks::V1_0::FusedActivationFunc;
-using ::android::hardware::neuralnetworks::V1_0::Model;
-using ::android::hardware::neuralnetworks::V1_0::OperationType;
-using ::android::hardware::neuralnetworks::V1_0::PerformanceInfo;
-using ::android::hardware::Return;
-using ::android::hardware::Void;
-using ::android::hardware::hidl_memory;
-using ::android::hardware::hidl_string;
-using ::android::hardware::hidl_vec;
-using ::android::hidl::allocator::V1_0::IAllocator;
-using ::android::hidl::memory::V1_0::IMemory;
-using ::android::sp;
-
 namespace android {
 namespace hardware {
 namespace neuralnetworks {
 
 namespace generated_tests {
 using ::generated_tests::MixedTypedExampleType;
-extern void Execute(sp<IDevice>&, std::function<Model(void)>, std::function<bool(int)>,
-                    const std::vector<MixedTypedExampleType>&);
+extern void Execute(const sp<V1_0::IDevice>&, std::function<V1_0::Model(void)>,
+                    std::function<bool(int)>, const std::vector<MixedTypedExampleType>&);
 }  // namespace generated_tests
 
 namespace V1_0 {
 namespace vts {
 namespace functional {
+
 using ::android::hardware::neuralnetworks::V1_0::implementation::ExecutionCallback;
 using ::android::hardware::neuralnetworks::V1_0::implementation::PreparedModelCallback;
+using ::android::nn::allocateSharedMemory;
 
 // Mixed-typed examples
 typedef generated_tests::MixedTypedExampleType MixedTypedExample;
diff --git a/neuralnetworks/1.0/vts/functional/Models.cpp b/neuralnetworks/1.0/vts/functional/Models.cpp
deleted file mode 100644
index 180286a..0000000
--- a/neuralnetworks/1.0/vts/functional/Models.cpp
+++ /dev/null
@@ -1,202 +0,0 @@
-/*
- * Copyright (C) 2017 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-#define LOG_TAG "neuralnetworks_hidl_hal_test"
-
-#include "Models.h"
-#include "Utils.h"
-
-#include <android-base/logging.h>
-#include <android/hidl/allocator/1.0/IAllocator.h>
-#include <android/hidl/memory/1.0/IMemory.h>
-#include <hidlmemory/mapping.h>
-#include <vector>
-
-using ::android::sp;
-
-namespace android {
-namespace hardware {
-namespace neuralnetworks {
-
-// create a valid model
-V1_1::Model createValidTestModel_1_1() {
-    const std::vector<float> operand2Data = {5.0f, 6.0f, 7.0f, 8.0f};
-    const uint32_t size = operand2Data.size() * sizeof(float);
-
-    const uint32_t operand1 = 0;
-    const uint32_t operand2 = 1;
-    const uint32_t operand3 = 2;
-    const uint32_t operand4 = 3;
-
-    const std::vector<Operand> operands = {
-        {
-            .type = OperandType::TENSOR_FLOAT32,
-            .dimensions = {1, 2, 2, 1},
-            .numberOfConsumers = 1,
-            .scale = 0.0f,
-            .zeroPoint = 0,
-            .lifetime = OperandLifeTime::MODEL_INPUT,
-            .location = {.poolIndex = 0, .offset = 0, .length = 0},
-        },
-        {
-            .type = OperandType::TENSOR_FLOAT32,
-            .dimensions = {1, 2, 2, 1},
-            .numberOfConsumers = 1,
-            .scale = 0.0f,
-            .zeroPoint = 0,
-            .lifetime = OperandLifeTime::CONSTANT_COPY,
-            .location = {.poolIndex = 0, .offset = 0, .length = size},
-        },
-        {
-            .type = OperandType::INT32,
-            .dimensions = {},
-            .numberOfConsumers = 1,
-            .scale = 0.0f,
-            .zeroPoint = 0,
-            .lifetime = OperandLifeTime::CONSTANT_COPY,
-            .location = {.poolIndex = 0, .offset = size, .length = sizeof(int32_t)},
-        },
-        {
-            .type = OperandType::TENSOR_FLOAT32,
-            .dimensions = {1, 2, 2, 1},
-            .numberOfConsumers = 0,
-            .scale = 0.0f,
-            .zeroPoint = 0,
-            .lifetime = OperandLifeTime::MODEL_OUTPUT,
-            .location = {.poolIndex = 0, .offset = 0, .length = 0},
-        },
-    };
-
-    const std::vector<Operation> operations = {{
-        .type = OperationType::ADD, .inputs = {operand1, operand2, operand3}, .outputs = {operand4},
-    }};
-
-    const std::vector<uint32_t> inputIndexes = {operand1};
-    const std::vector<uint32_t> outputIndexes = {operand4};
-    std::vector<uint8_t> operandValues(
-        reinterpret_cast<const uint8_t*>(operand2Data.data()),
-        reinterpret_cast<const uint8_t*>(operand2Data.data()) + size);
-    int32_t activation[1] = {static_cast<int32_t>(FusedActivationFunc::NONE)};
-    operandValues.insert(operandValues.end(), reinterpret_cast<const uint8_t*>(&activation[0]),
-                         reinterpret_cast<const uint8_t*>(&activation[1]));
-
-    const std::vector<hidl_memory> pools = {};
-
-    return {
-        .operands = operands,
-        .operations = operations,
-        .inputIndexes = inputIndexes,
-        .outputIndexes = outputIndexes,
-        .operandValues = operandValues,
-        .pools = pools,
-    };
-}
-
-// create first invalid model
-V1_1::Model createInvalidTestModel1_1_1() {
-    Model model = createValidTestModel_1_1();
-    model.operations[0].type = static_cast<OperationType>(0xDEADBEEF); /* INVALID */
-    return model;
-}
-
-// create second invalid model
-V1_1::Model createInvalidTestModel2_1_1() {
-    Model model = createValidTestModel_1_1();
-    const uint32_t operand1 = 0;
-    const uint32_t operand5 = 4;  // INVALID OPERAND
-    model.inputIndexes = std::vector<uint32_t>({operand1, operand5 /* INVALID OPERAND */});
-    return model;
-}
-
-V1_0::Model createValidTestModel_1_0() {
-    V1_1::Model model = createValidTestModel_1_1();
-    return nn::convertToV1_0(model);
-}
-
-V1_0::Model createInvalidTestModel1_1_0() {
-    V1_1::Model model = createInvalidTestModel1_1_1();
-    return nn::convertToV1_0(model);
-}
-
-V1_0::Model createInvalidTestModel2_1_0() {
-    V1_1::Model model = createInvalidTestModel2_1_1();
-    return nn::convertToV1_0(model);
-}
-
-// create a valid request
-Request createValidTestRequest() {
-    std::vector<float> inputData = {1.0f, 2.0f, 3.0f, 4.0f};
-    std::vector<float> outputData = {-1.0f, -1.0f, -1.0f, -1.0f};
-    const uint32_t INPUT = 0;
-    const uint32_t OUTPUT = 1;
-
-    // prepare inputs
-    uint32_t inputSize = static_cast<uint32_t>(inputData.size() * sizeof(float));
-    uint32_t outputSize = static_cast<uint32_t>(outputData.size() * sizeof(float));
-    std::vector<RequestArgument> inputs = {{
-        .location = {.poolIndex = INPUT, .offset = 0, .length = inputSize}, .dimensions = {},
-    }};
-    std::vector<RequestArgument> outputs = {{
-        .location = {.poolIndex = OUTPUT, .offset = 0, .length = outputSize}, .dimensions = {},
-    }};
-    std::vector<hidl_memory> pools = {nn::allocateSharedMemory(inputSize),
-                                      nn::allocateSharedMemory(outputSize)};
-    if (pools[INPUT].size() == 0 || pools[OUTPUT].size() == 0) {
-        return {};
-    }
-
-    // load data
-    sp<IMemory> inputMemory = mapMemory(pools[INPUT]);
-    sp<IMemory> outputMemory = mapMemory(pools[OUTPUT]);
-    if (inputMemory.get() == nullptr || outputMemory.get() == nullptr) {
-        return {};
-    }
-    float* inputPtr = reinterpret_cast<float*>(static_cast<void*>(inputMemory->getPointer()));
-    float* outputPtr = reinterpret_cast<float*>(static_cast<void*>(outputMemory->getPointer()));
-    if (inputPtr == nullptr || outputPtr == nullptr) {
-        return {};
-    }
-    inputMemory->update();
-    outputMemory->update();
-    std::copy(inputData.begin(), inputData.end(), inputPtr);
-    std::copy(outputData.begin(), outputData.end(), outputPtr);
-    inputMemory->commit();
-    outputMemory->commit();
-
-    return {.inputs = inputs, .outputs = outputs, .pools = pools};
-}
-
-// create first invalid request
-Request createInvalidTestRequest1() {
-    Request request = createValidTestRequest();
-    const uint32_t INVALID = 2;
-    std::vector<float> inputData = {1.0f, 2.0f, 3.0f, 4.0f};
-    uint32_t inputSize = static_cast<uint32_t>(inputData.size() * sizeof(float));
-    request.inputs[0].location = {
-        .poolIndex = INVALID /* INVALID */, .offset = 0, .length = inputSize};
-    return request;
-}
-
-// create second invalid request
-Request createInvalidTestRequest2() {
-    Request request = createValidTestRequest();
-    request.inputs[0].dimensions = std::vector<uint32_t>({1, 2, 3, 4, 5, 6, 7, 8} /* INVALID */);
-    return request;
-}
-
-}  // namespace neuralnetworks
-}  // namespace hardware
-}  // namespace android
diff --git a/neuralnetworks/1.0/vts/functional/Models.h b/neuralnetworks/1.0/vts/functional/Models.h
index 9398235..a1fbe92 100644
--- a/neuralnetworks/1.0/vts/functional/Models.h
+++ b/neuralnetworks/1.0/vts/functional/Models.h
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2017 The Android Open Source Project
+ * Copyright (C) 2018 The Android Open Source Project
  *
  * Licensed under the Apache License, Version 2.0 (the "License");
  * you may not use this file except in compliance with the License.
@@ -14,29 +14,187 @@
  * limitations under the License.
  */
 
+#ifndef VTS_HAL_NEURALNETWORKS_V1_0_VTS_FUNCTIONAL_MODELS_H
+#define VTS_HAL_NEURALNETWORKS_V1_0_VTS_FUNCTIONAL_MODELS_H
+
 #define LOG_TAG "neuralnetworks_hidl_hal_test"
 
-#include <android/hardware/neuralnetworks/1.1/types.h>
+#include "TestHarness.h"
+
+#include <android/hardware/neuralnetworks/1.0/types.h>
 
 namespace android {
 namespace hardware {
 namespace neuralnetworks {
+namespace V1_0 {
+namespace vts {
+namespace functional {
 
-// create V1_1 model
-V1_1::Model createValidTestModel_1_1();
-V1_1::Model createInvalidTestModel1_1_1();
-V1_1::Model createInvalidTestModel2_1_1();
+using MixedTypedExample = generated_tests::MixedTypedExampleType;
 
-// create V1_0 model
-V1_0::Model createValidTestModel_1_0();
-V1_0::Model createInvalidTestModel1_1_0();
-V1_0::Model createInvalidTestModel2_1_0();
+#define FOR_EACH_TEST_MODEL(FN)                          \
+    FN(add_broadcast_quant8)                             \
+    FN(add)                                              \
+    FN(add_quant8)                                       \
+    FN(avg_pool_float_1)                                 \
+    FN(avg_pool_float_2)                                 \
+    FN(avg_pool_float_3)                                 \
+    FN(avg_pool_float_4)                                 \
+    FN(avg_pool_float_5)                                 \
+    FN(avg_pool_quant8_1)                                \
+    FN(avg_pool_quant8_2)                                \
+    FN(avg_pool_quant8_3)                                \
+    FN(avg_pool_quant8_4)                                \
+    FN(avg_pool_quant8_5)                                \
+    FN(concat_float_1)                                   \
+    FN(concat_float_2)                                   \
+    FN(concat_float_3)                                   \
+    FN(concat_quant8_1)                                  \
+    FN(concat_quant8_2)                                  \
+    FN(concat_quant8_3)                                  \
+    FN(conv_1_h3_w2_SAME)                                \
+    FN(conv_1_h3_w2_VALID)                               \
+    FN(conv_3_h3_w2_SAME)                                \
+    FN(conv_3_h3_w2_VALID)                               \
+    FN(conv_float_2)                                     \
+    FN(conv_float_channels)                              \
+    FN(conv_float_channels_weights_as_inputs)            \
+    FN(conv_float_large)                                 \
+    FN(conv_float_large_weights_as_inputs)               \
+    FN(conv_float)                                       \
+    FN(conv_float_weights_as_inputs)                     \
+    FN(conv_quant8_2)                                    \
+    FN(conv_quant8_channels)                             \
+    FN(conv_quant8_channels_weights_as_inputs)           \
+    FN(conv_quant8_large)                                \
+    FN(conv_quant8_large_weights_as_inputs)              \
+    FN(conv_quant8)                                      \
+    FN(conv_quant8_overflow)                             \
+    FN(conv_quant8_overflow_weights_as_inputs)           \
+    FN(conv_quant8_weights_as_inputs)                    \
+    FN(depth_to_space_float_1)                           \
+    FN(depth_to_space_float_2)                           \
+    FN(depth_to_space_float_3)                           \
+    FN(depth_to_space_quant8_1)                          \
+    FN(depth_to_space_quant8_2)                          \
+    FN(depthwise_conv2d_float_2)                         \
+    FN(depthwise_conv2d_float_large_2)                   \
+    FN(depthwise_conv2d_float_large_2_weights_as_inputs) \
+    FN(depthwise_conv2d_float_large)                     \
+    FN(depthwise_conv2d_float_large_weights_as_inputs)   \
+    FN(depthwise_conv2d_float)                           \
+    FN(depthwise_conv2d_float_weights_as_inputs)         \
+    FN(depthwise_conv2d_quant8_2)                        \
+    FN(depthwise_conv2d_quant8_large)                    \
+    FN(depthwise_conv2d_quant8_large_weights_as_inputs)  \
+    FN(depthwise_conv2d_quant8)                          \
+    FN(depthwise_conv2d_quant8_weights_as_inputs)        \
+    FN(depthwise_conv)                                   \
+    FN(dequantize)                                       \
+    FN(embedding_lookup)                                 \
+    FN(floor)                                            \
+    FN(fully_connected_float_2)                          \
+    FN(fully_connected_float_large)                      \
+    FN(fully_connected_float_large_weights_as_inputs)    \
+    FN(fully_connected_float)                            \
+    FN(fully_connected_float_weights_as_inputs)          \
+    FN(fully_connected_quant8_2)                         \
+    FN(fully_connected_quant8_large)                     \
+    FN(fully_connected_quant8_large_weights_as_inputs)   \
+    FN(fully_connected_quant8)                           \
+    FN(fully_connected_quant8_weights_as_inputs)         \
+    FN(hashtable_lookup_float)                           \
+    FN(hashtable_lookup_quant8)                          \
+    FN(l2_normalization_2)                               \
+    FN(l2_normalization_large)                           \
+    FN(l2_normalization)                                 \
+    FN(l2_pool_float_2)                                  \
+    FN(l2_pool_float_large)                              \
+    FN(l2_pool_float)                                    \
+    FN(local_response_norm_float_1)                      \
+    FN(local_response_norm_float_2)                      \
+    FN(local_response_norm_float_3)                      \
+    FN(local_response_norm_float_4)                      \
+    FN(logistic_float_1)                                 \
+    FN(logistic_float_2)                                 \
+    FN(logistic_quant8_1)                                \
+    FN(logistic_quant8_2)                                \
+    FN(lsh_projection_2)                                 \
+    FN(lsh_projection)                                   \
+    FN(lsh_projection_weights_as_inputs)                 \
+    FN(lstm2)                                            \
+    FN(lstm2_state2)                                     \
+    FN(lstm2_state)                                      \
+    FN(lstm3)                                            \
+    FN(lstm3_state2)                                     \
+    FN(lstm3_state3)                                     \
+    FN(lstm3_state)                                      \
+    FN(lstm)                                             \
+    FN(lstm_state2)                                      \
+    FN(lstm_state)                                       \
+    FN(max_pool_float_1)                                 \
+    FN(max_pool_float_2)                                 \
+    FN(max_pool_float_3)                                 \
+    FN(max_pool_float_4)                                 \
+    FN(max_pool_quant8_1)                                \
+    FN(max_pool_quant8_2)                                \
+    FN(max_pool_quant8_3)                                \
+    FN(max_pool_quant8_4)                                \
+    FN(mobilenet_224_gender_basic_fixed)                 \
+    FN(mobilenet_quantized)                              \
+    FN(mul_broadcast_quant8)                             \
+    FN(mul)                                              \
+    FN(mul_quant8)                                       \
+    FN(mul_relu)                                         \
+    FN(relu1_float_1)                                    \
+    FN(relu1_float_2)                                    \
+    FN(relu1_quant8_1)                                   \
+    FN(relu1_quant8_2)                                   \
+    FN(relu6_float_1)                                    \
+    FN(relu6_float_2)                                    \
+    FN(relu6_quant8_1)                                   \
+    FN(relu6_quant8_2)                                   \
+    FN(relu_float_1)                                     \
+    FN(relu_float_2)                                     \
+    FN(relu_quant8_1)                                    \
+    FN(relu_quant8_2)                                    \
+    FN(reshape)                                          \
+    FN(reshape_quant8)                                   \
+    FN(reshape_quant8_weights_as_inputs)                 \
+    FN(reshape_weights_as_inputs)                        \
+    FN(resize_bilinear_2)                                \
+    FN(resize_bilinear)                                  \
+    FN(rnn)                                              \
+    FN(rnn_state)                                        \
+    FN(softmax_float_1)                                  \
+    FN(softmax_float_2)                                  \
+    FN(softmax_quant8_1)                                 \
+    FN(softmax_quant8_2)                                 \
+    FN(space_to_depth_float_1)                           \
+    FN(space_to_depth_float_2)                           \
+    FN(space_to_depth_float_3)                           \
+    FN(space_to_depth_quant8_1)                          \
+    FN(space_to_depth_quant8_2)                          \
+    FN(svdf2)                                            \
+    FN(svdf)                                             \
+    FN(svdf_state)                                       \
+    FN(tanh)
 
-// create the request
-V1_0::Request createValidTestRequest();
-V1_0::Request createInvalidTestRequest1();
-V1_0::Request createInvalidTestRequest2();
+#define FORWARD_DECLARE_GENERATED_OBJECTS(function) \
+    namespace function {                            \
+    extern std::vector<MixedTypedExample> examples; \
+    Model createTestModel();                        \
+    }
 
+FOR_EACH_TEST_MODEL(FORWARD_DECLARE_GENERATED_OBJECTS)
+
+#undef FORWARD_DECLARE_GENERATED_OBJECTS
+
+}  // namespace functional
+}  // namespace vts
+}  // namespace V1_0
 }  // namespace neuralnetworks
 }  // namespace hardware
 }  // namespace android
+
+#endif  // VTS_HAL_NEURALNETWORKS_V1_0_VTS_FUNCTIONAL_MODELS_H
diff --git a/neuralnetworks/1.0/vts/functional/ValidateModel.cpp b/neuralnetworks/1.0/vts/functional/ValidateModel.cpp
new file mode 100644
index 0000000..4f0697e
--- /dev/null
+++ b/neuralnetworks/1.0/vts/functional/ValidateModel.cpp
@@ -0,0 +1,506 @@
+/*
+ * Copyright (C) 2018 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#define LOG_TAG "neuralnetworks_hidl_hal_test"
+
+#include "VtsHalNeuralnetworks.h"
+
+#include "Callbacks.h"
+
+namespace android {
+namespace hardware {
+namespace neuralnetworks {
+namespace V1_0 {
+namespace vts {
+namespace functional {
+
+using ::android::hardware::neuralnetworks::V1_0::implementation::ExecutionCallback;
+using ::android::hardware::neuralnetworks::V1_0::implementation::PreparedModelCallback;
+
+///////////////////////// UTILITY FUNCTIONS /////////////////////////
+
+static void validateGetSupportedOperations(const sp<IDevice>& device, const std::string& message,
+                                           const V1_0::Model& model) {
+    SCOPED_TRACE(message + " [getSupportedOperations]");
+
+    Return<void> ret =
+        device->getSupportedOperations(model, [&](ErrorStatus status, const hidl_vec<bool>&) {
+            EXPECT_EQ(ErrorStatus::INVALID_ARGUMENT, status);
+        });
+    EXPECT_TRUE(ret.isOk());
+}
+
+static void validatePrepareModel(const sp<IDevice>& device, const std::string& message,
+                                 const V1_0::Model& model) {
+    SCOPED_TRACE(message + " [prepareModel]");
+
+    sp<PreparedModelCallback> preparedModelCallback = new PreparedModelCallback();
+    ASSERT_NE(nullptr, preparedModelCallback.get());
+    Return<ErrorStatus> prepareLaunchStatus = device->prepareModel(model, preparedModelCallback);
+    ASSERT_TRUE(prepareLaunchStatus.isOk());
+    ASSERT_EQ(ErrorStatus::INVALID_ARGUMENT, static_cast<ErrorStatus>(prepareLaunchStatus));
+
+    preparedModelCallback->wait();
+    ErrorStatus prepareReturnStatus = preparedModelCallback->getStatus();
+    ASSERT_EQ(ErrorStatus::INVALID_ARGUMENT, prepareReturnStatus);
+    sp<IPreparedModel> preparedModel = preparedModelCallback->getPreparedModel();
+    ASSERT_EQ(nullptr, preparedModel.get());
+}
+
+// Primary validation function. This function will take a valid model, apply a
+// mutation to it to invalidate the model, then pass it to interface calls that
+// use the model. Note that the model here is passed by value, and any mutation
+// to the model does not leave this function.
+static void validate(const sp<IDevice>& device, const std::string& message, V1_0::Model model,
+                     const std::function<void(Model*)>& mutation) {
+    mutation(&model);
+    validateGetSupportedOperations(device, message, model);
+    validatePrepareModel(device, message, model);
+}
+
+// Delete element from hidl_vec. hidl_vec doesn't support a "remove" operation,
+// so this is efficiently accomplished by moving the element to the end and
+// resizing the hidl_vec to one less.
+template <typename Type>
+static void hidl_vec_removeAt(hidl_vec<Type>* vec, uint32_t index) {
+    if (vec) {
+        std::rotate(vec->begin() + index, vec->begin() + index + 1, vec->end());
+        vec->resize(vec->size() - 1);
+    }
+}
+
+template <typename Type>
+static uint32_t hidl_vec_push_back(hidl_vec<Type>* vec, const Type& value) {
+    // assume vec is valid
+    const uint32_t index = vec->size();
+    vec->resize(index + 1);
+    (*vec)[index] = value;
+    return index;
+}
+
+static uint32_t addOperand(Model* model) {
+    return hidl_vec_push_back(&model->operands,
+                              {
+                                  .type = OperandType::INT32,
+                                  .dimensions = {},
+                                  .numberOfConsumers = 0,
+                                  .scale = 0.0f,
+                                  .zeroPoint = 0,
+                                  .lifetime = OperandLifeTime::MODEL_INPUT,
+                                  .location = {.poolIndex = 0, .offset = 0, .length = 0},
+                              });
+}
+
+static uint32_t addOperand(Model* model, OperandLifeTime lifetime) {
+    uint32_t index = addOperand(model);
+    model->operands[index].numberOfConsumers = 1;
+    model->operands[index].lifetime = lifetime;
+    return index;
+}
+
+///////////////////////// VALIDATE MODEL OPERAND TYPE /////////////////////////
+
+static const int32_t invalidOperandTypes[] = {
+    static_cast<int32_t>(OperandType::FLOAT32) - 1,              // lower bound fundamental
+    static_cast<int32_t>(OperandType::TENSOR_QUANT8_ASYMM) + 1,  // upper bound fundamental
+    static_cast<int32_t>(OperandType::OEM) - 1,                  // lower bound OEM
+    static_cast<int32_t>(OperandType::TENSOR_OEM_BYTE) + 1,      // upper bound OEM
+};
+
+static void mutateOperandTypeTest(const sp<IDevice>& device, const V1_0::Model& model) {
+    for (size_t operand = 0; operand < model.operands.size(); ++operand) {
+        for (int32_t invalidOperandType : invalidOperandTypes) {
+            const std::string message = "mutateOperandTypeTest: operand " +
+                                        std::to_string(operand) + " set to value " +
+                                        std::to_string(invalidOperandType);
+            validate(device, message, model, [operand, invalidOperandType](Model* model) {
+                model->operands[operand].type = static_cast<OperandType>(invalidOperandType);
+            });
+        }
+    }
+}
+
+///////////////////////// VALIDATE OPERAND RANK /////////////////////////
+
+static uint32_t getInvalidRank(OperandType type) {
+    switch (type) {
+        case OperandType::FLOAT32:
+        case OperandType::INT32:
+        case OperandType::UINT32:
+            return 1;
+        case OperandType::TENSOR_FLOAT32:
+        case OperandType::TENSOR_INT32:
+        case OperandType::TENSOR_QUANT8_ASYMM:
+            return 0;
+        default:
+            return 0;
+    }
+}
+
+static void mutateOperandRankTest(const sp<IDevice>& device, const V1_0::Model& model) {
+    for (size_t operand = 0; operand < model.operands.size(); ++operand) {
+        const uint32_t invalidRank = getInvalidRank(model.operands[operand].type);
+        const std::string message = "mutateOperandRankTest: operand " + std::to_string(operand) +
+                                    " has rank of " + std::to_string(invalidRank);
+        validate(device, message, model, [operand, invalidRank](Model* model) {
+            model->operands[operand].dimensions = std::vector<uint32_t>(invalidRank, 0);
+        });
+    }
+}
+
+///////////////////////// VALIDATE OPERAND SCALE /////////////////////////
+
+static float getInvalidScale(OperandType type) {
+    switch (type) {
+        case OperandType::FLOAT32:
+        case OperandType::INT32:
+        case OperandType::UINT32:
+        case OperandType::TENSOR_FLOAT32:
+            return 1.0f;
+        case OperandType::TENSOR_INT32:
+            return -1.0f;
+        case OperandType::TENSOR_QUANT8_ASYMM:
+            return 0.0f;
+        default:
+            return 0.0f;
+    }
+}
+
+static void mutateOperandScaleTest(const sp<IDevice>& device, const V1_0::Model& model) {
+    for (size_t operand = 0; operand < model.operands.size(); ++operand) {
+        const float invalidScale = getInvalidScale(model.operands[operand].type);
+        const std::string message = "mutateOperandScaleTest: operand " + std::to_string(operand) +
+                                    " has scale of " + std::to_string(invalidScale);
+        validate(device, message, model, [operand, invalidScale](Model* model) {
+            model->operands[operand].scale = invalidScale;
+        });
+    }
+}
+
+///////////////////////// VALIDATE OPERAND ZERO POINT /////////////////////////
+
+static std::vector<int32_t> getInvalidZeroPoints(OperandType type) {
+    switch (type) {
+        case OperandType::FLOAT32:
+        case OperandType::INT32:
+        case OperandType::UINT32:
+        case OperandType::TENSOR_FLOAT32:
+        case OperandType::TENSOR_INT32:
+            return {1};
+        case OperandType::TENSOR_QUANT8_ASYMM:
+            return {-1, 256};
+        default:
+            return {};
+    }
+}
+
+static void mutateOperandZeroPointTest(const sp<IDevice>& device, const V1_0::Model& model) {
+    for (size_t operand = 0; operand < model.operands.size(); ++operand) {
+        const std::vector<int32_t> invalidZeroPoints =
+            getInvalidZeroPoints(model.operands[operand].type);
+        for (int32_t invalidZeroPoint : invalidZeroPoints) {
+            const std::string message = "mutateOperandZeroPointTest: operand " +
+                                        std::to_string(operand) + " has zero point of " +
+                                        std::to_string(invalidZeroPoint);
+            validate(device, message, model, [operand, invalidZeroPoint](Model* model) {
+                model->operands[operand].zeroPoint = invalidZeroPoint;
+            });
+        }
+    }
+}
+
+///////////////////////// VALIDATE EXTRA ??? /////////////////////////
+
+// TODO: Operand::lifetime
+// TODO: Operand::location
+
+///////////////////////// VALIDATE OPERATION OPERAND TYPE /////////////////////////
+
+static void mutateOperand(Operand* operand, OperandType type) {
+    Operand newOperand = *operand;
+    newOperand.type = type;
+    switch (type) {
+        case OperandType::FLOAT32:
+        case OperandType::INT32:
+        case OperandType::UINT32:
+            newOperand.dimensions = hidl_vec<uint32_t>();
+            newOperand.scale = 0.0f;
+            newOperand.zeroPoint = 0;
+            break;
+        case OperandType::TENSOR_FLOAT32:
+            newOperand.dimensions =
+                operand->dimensions.size() > 0 ? operand->dimensions : hidl_vec<uint32_t>({1});
+            newOperand.scale = 0.0f;
+            newOperand.zeroPoint = 0;
+            break;
+        case OperandType::TENSOR_INT32:
+            newOperand.dimensions =
+                operand->dimensions.size() > 0 ? operand->dimensions : hidl_vec<uint32_t>({1});
+            newOperand.zeroPoint = 0;
+            break;
+        case OperandType::TENSOR_QUANT8_ASYMM:
+            newOperand.dimensions =
+                operand->dimensions.size() > 0 ? operand->dimensions : hidl_vec<uint32_t>({1});
+            newOperand.scale = operand->scale != 0.0f ? operand->scale : 1.0f;
+            break;
+        case OperandType::OEM:
+        case OperandType::TENSOR_OEM_BYTE:
+        default:
+            break;
+    }
+    *operand = newOperand;
+}
+
+static bool mutateOperationOperandTypeSkip(size_t operand, const V1_0::Model& model) {
+    // LSH_PROJECTION's second argument is allowed to have any type. This is the
+    // only operation that currently has a type that can be anything independent
+    // from any other type. Changing the operand type to any other type will
+    // result in a valid model for LSH_PROJECTION. If this is the case, skip the
+    // test.
+    for (const Operation& operation : model.operations) {
+        if (operation.type == OperationType::LSH_PROJECTION && operand == operation.inputs[1]) {
+            return true;
+        }
+    }
+    return false;
+}
+
+static void mutateOperationOperandTypeTest(const sp<IDevice>& device, const V1_0::Model& model) {
+    for (size_t operand = 0; operand < model.operands.size(); ++operand) {
+        if (mutateOperationOperandTypeSkip(operand, model)) {
+            continue;
+        }
+        for (OperandType invalidOperandType : hidl_enum_iterator<OperandType>{}) {
+            // Do not test OEM types
+            if (invalidOperandType == model.operands[operand].type ||
+                invalidOperandType == OperandType::OEM ||
+                invalidOperandType == OperandType::TENSOR_OEM_BYTE) {
+                continue;
+            }
+            const std::string message = "mutateOperationOperandTypeTest: operand " +
+                                        std::to_string(operand) + " set to type " +
+                                        toString(invalidOperandType);
+            validate(device, message, model, [operand, invalidOperandType](Model* model) {
+                mutateOperand(&model->operands[operand], invalidOperandType);
+            });
+        }
+    }
+}
+
+///////////////////////// VALIDATE MODEL OPERATION TYPE /////////////////////////
+
+static const int32_t invalidOperationTypes[] = {
+    static_cast<int32_t>(OperationType::ADD) - 1,            // lower bound fundamental
+    static_cast<int32_t>(OperationType::TANH) + 1,           // upper bound fundamental
+    static_cast<int32_t>(OperationType::OEM_OPERATION) - 1,  // lower bound OEM
+    static_cast<int32_t>(OperationType::OEM_OPERATION) + 1,  // upper bound OEM
+};
+
+static void mutateOperationTypeTest(const sp<IDevice>& device, const V1_0::Model& model) {
+    for (size_t operation = 0; operation < model.operations.size(); ++operation) {
+        for (int32_t invalidOperationType : invalidOperationTypes) {
+            const std::string message = "mutateOperationTypeTest: operation " +
+                                        std::to_string(operation) + " set to value " +
+                                        std::to_string(invalidOperationType);
+            validate(device, message, model, [operation, invalidOperationType](Model* model) {
+                model->operations[operation].type =
+                    static_cast<OperationType>(invalidOperationType);
+            });
+        }
+    }
+}
+
+///////////////////////// VALIDATE MODEL OPERATION INPUT OPERAND INDEX /////////////////////////
+
+static void mutateOperationInputOperandIndexTest(const sp<IDevice>& device,
+                                                 const V1_0::Model& model) {
+    for (size_t operation = 0; operation < model.operations.size(); ++operation) {
+        const uint32_t invalidOperand = model.operands.size();
+        for (size_t input = 0; input < model.operations[operation].inputs.size(); ++input) {
+            const std::string message = "mutateOperationInputOperandIndexTest: operation " +
+                                        std::to_string(operation) + " input " +
+                                        std::to_string(input);
+            validate(device, message, model, [operation, input, invalidOperand](Model* model) {
+                model->operations[operation].inputs[input] = invalidOperand;
+            });
+        }
+    }
+}
+
+///////////////////////// VALIDATE MODEL OPERATION OUTPUT OPERAND INDEX /////////////////////////
+
+static void mutateOperationOutputOperandIndexTest(const sp<IDevice>& device,
+                                                  const V1_0::Model& model) {
+    for (size_t operation = 0; operation < model.operations.size(); ++operation) {
+        const uint32_t invalidOperand = model.operands.size();
+        for (size_t output = 0; output < model.operations[operation].outputs.size(); ++output) {
+            const std::string message = "mutateOperationOutputOperandIndexTest: operation " +
+                                        std::to_string(operation) + " output " +
+                                        std::to_string(output);
+            validate(device, message, model, [operation, output, invalidOperand](Model* model) {
+                model->operations[operation].outputs[output] = invalidOperand;
+            });
+        }
+    }
+}
+
+///////////////////////// REMOVE OPERAND FROM EVERYTHING /////////////////////////
+
+static void removeValueAndDecrementGreaterValues(hidl_vec<uint32_t>* vec, uint32_t value) {
+    if (vec) {
+        // remove elements matching "value"
+        auto last = std::remove(vec->begin(), vec->end(), value);
+        vec->resize(std::distance(vec->begin(), last));
+
+        // decrement elements exceeding "value"
+        std::transform(vec->begin(), vec->end(), vec->begin(),
+                       [value](uint32_t v) { return v > value ? v-- : v; });
+    }
+}
+
+static void removeOperand(Model* model, uint32_t index) {
+    hidl_vec_removeAt(&model->operands, index);
+    for (Operation& operation : model->operations) {
+        removeValueAndDecrementGreaterValues(&operation.inputs, index);
+        removeValueAndDecrementGreaterValues(&operation.outputs, index);
+    }
+    removeValueAndDecrementGreaterValues(&model->inputIndexes, index);
+    removeValueAndDecrementGreaterValues(&model->outputIndexes, index);
+}
+
+static void removeOperandTest(const sp<IDevice>& device, const V1_0::Model& model) {
+    for (size_t operand = 0; operand < model.operands.size(); ++operand) {
+        const std::string message = "removeOperandTest: operand " + std::to_string(operand);
+        validate(device, message, model,
+                 [operand](Model* model) { removeOperand(model, operand); });
+    }
+}
+
+///////////////////////// REMOVE OPERATION /////////////////////////
+
+static void removeOperation(Model* model, uint32_t index) {
+    for (uint32_t operand : model->operations[index].inputs) {
+        model->operands[operand].numberOfConsumers--;
+    }
+    hidl_vec_removeAt(&model->operations, index);
+}
+
+static void removeOperationTest(const sp<IDevice>& device, const V1_0::Model& model) {
+    for (size_t operation = 0; operation < model.operations.size(); ++operation) {
+        const std::string message = "removeOperationTest: operation " + std::to_string(operation);
+        validate(device, message, model,
+                 [operation](Model* model) { removeOperation(model, operation); });
+    }
+}
+
+///////////////////////// REMOVE OPERATION INPUT /////////////////////////
+
+static void removeOperationInputTest(const sp<IDevice>& device, const V1_0::Model& model) {
+    for (size_t operation = 0; operation < model.operations.size(); ++operation) {
+        for (size_t input = 0; input < model.operations[operation].inputs.size(); ++input) {
+            const V1_0::Operation& op = model.operations[operation];
+            // CONCATENATION has at least 2 inputs, with the last element being
+            // INT32. Skip this test if removing one of CONCATENATION's
+            // inputs still produces a valid model.
+            if (op.type == V1_0::OperationType::CONCATENATION && op.inputs.size() > 2 &&
+                input != op.inputs.size() - 1) {
+                continue;
+            }
+            const std::string message = "removeOperationInputTest: operation " +
+                                        std::to_string(operation) + ", input " +
+                                        std::to_string(input);
+            validate(device, message, model, [operation, input](Model* model) {
+                uint32_t operand = model->operations[operation].inputs[input];
+                model->operands[operand].numberOfConsumers--;
+                hidl_vec_removeAt(&model->operations[operation].inputs, input);
+            });
+        }
+    }
+}
+
+///////////////////////// REMOVE OPERATION OUTPUT /////////////////////////
+
+static void removeOperationOutputTest(const sp<IDevice>& device, const V1_0::Model& model) {
+    for (size_t operation = 0; operation < model.operations.size(); ++operation) {
+        for (size_t output = 0; output < model.operations[operation].outputs.size(); ++output) {
+            const std::string message = "removeOperationOutputTest: operation " +
+                                        std::to_string(operation) + ", output " +
+                                        std::to_string(output);
+            validate(device, message, model, [operation, output](Model* model) {
+                hidl_vec_removeAt(&model->operations[operation].outputs, output);
+            });
+        }
+    }
+}
+
+///////////////////////// MODEL VALIDATION /////////////////////////
+
+// TODO: remove model input
+// TODO: remove model output
+// TODO: add unused operation
+
+///////////////////////// ADD OPERATION INPUT /////////////////////////
+
+static void addOperationInputTest(const sp<IDevice>& device, const V1_0::Model& model) {
+    for (size_t operation = 0; operation < model.operations.size(); ++operation) {
+        const std::string message = "addOperationInputTest: operation " + std::to_string(operation);
+        validate(device, message, model, [operation](Model* model) {
+            uint32_t index = addOperand(model, OperandLifeTime::MODEL_INPUT);
+            hidl_vec_push_back(&model->operations[operation].inputs, index);
+            hidl_vec_push_back(&model->inputIndexes, index);
+        });
+    }
+}
+
+///////////////////////// ADD OPERATION OUTPUT /////////////////////////
+
+static void addOperationOutputTest(const sp<IDevice>& device, const V1_0::Model& model) {
+    for (size_t operation = 0; operation < model.operations.size(); ++operation) {
+        const std::string message =
+            "addOperationOutputTest: operation " + std::to_string(operation);
+        validate(device, message, model, [operation](Model* model) {
+            uint32_t index = addOperand(model, OperandLifeTime::MODEL_OUTPUT);
+            hidl_vec_push_back(&model->operations[operation].outputs, index);
+            hidl_vec_push_back(&model->outputIndexes, index);
+        });
+    }
+}
+
+////////////////////////// ENTRY POINT //////////////////////////////
+
+void ValidationTest::validateModel(const V1_0::Model& model) {
+    mutateOperandTypeTest(device, model);
+    mutateOperandRankTest(device, model);
+    mutateOperandScaleTest(device, model);
+    mutateOperandZeroPointTest(device, model);
+    mutateOperationOperandTypeTest(device, model);
+    mutateOperationTypeTest(device, model);
+    mutateOperationInputOperandIndexTest(device, model);
+    mutateOperationOutputOperandIndexTest(device, model);
+    removeOperandTest(device, model);
+    removeOperationTest(device, model);
+    removeOperationInputTest(device, model);
+    removeOperationOutputTest(device, model);
+    addOperationInputTest(device, model);
+    addOperationOutputTest(device, model);
+}
+
+}  // namespace functional
+}  // namespace vts
+}  // namespace V1_0
+}  // namespace neuralnetworks
+}  // namespace hardware
+}  // namespace android
diff --git a/neuralnetworks/1.0/vts/functional/ValidateRequest.cpp b/neuralnetworks/1.0/vts/functional/ValidateRequest.cpp
new file mode 100644
index 0000000..08f2613
--- /dev/null
+++ b/neuralnetworks/1.0/vts/functional/ValidateRequest.cpp
@@ -0,0 +1,261 @@
+/*
+ * Copyright (C) 2018 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#define LOG_TAG "neuralnetworks_hidl_hal_test"
+
+#include "VtsHalNeuralnetworks.h"
+
+#include "Callbacks.h"
+#include "TestHarness.h"
+#include "Utils.h"
+
+#include <android-base/logging.h>
+#include <android/hidl/memory/1.0/IMemory.h>
+#include <hidlmemory/mapping.h>
+
+namespace android {
+namespace hardware {
+namespace neuralnetworks {
+namespace V1_0 {
+namespace vts {
+namespace functional {
+
+using ::android::hardware::neuralnetworks::V1_0::implementation::ExecutionCallback;
+using ::android::hardware::neuralnetworks::V1_0::implementation::PreparedModelCallback;
+using ::android::hidl::memory::V1_0::IMemory;
+using generated_tests::MixedTyped;
+using generated_tests::MixedTypedExampleType;
+using generated_tests::for_all;
+
+///////////////////////// UTILITY FUNCTIONS /////////////////////////
+
+static void createPreparedModel(const sp<IDevice>& device, const V1_0::Model& model,
+                                sp<IPreparedModel>* preparedModel) {
+    ASSERT_NE(nullptr, preparedModel);
+
+    // see if service can handle model
+    bool fullySupportsModel = false;
+    Return<void> supportedOpsLaunchStatus = device->getSupportedOperations(
+        model, [&fullySupportsModel](ErrorStatus status, const hidl_vec<bool>& supported) {
+            ASSERT_EQ(ErrorStatus::NONE, status);
+            ASSERT_NE(0ul, supported.size());
+            fullySupportsModel =
+                std::all_of(supported.begin(), supported.end(), [](bool valid) { return valid; });
+        });
+    ASSERT_TRUE(supportedOpsLaunchStatus.isOk());
+
+    // launch prepare model
+    sp<PreparedModelCallback> preparedModelCallback = new PreparedModelCallback();
+    ASSERT_NE(nullptr, preparedModelCallback.get());
+    Return<ErrorStatus> prepareLaunchStatus = device->prepareModel(model, preparedModelCallback);
+    ASSERT_TRUE(prepareLaunchStatus.isOk());
+    ASSERT_EQ(ErrorStatus::NONE, static_cast<ErrorStatus>(prepareLaunchStatus));
+
+    // retrieve prepared model
+    preparedModelCallback->wait();
+    ErrorStatus prepareReturnStatus = preparedModelCallback->getStatus();
+    *preparedModel = preparedModelCallback->getPreparedModel();
+
+    // The getSupportedOperations call returns a list of operations that are
+    // guaranteed not to fail if prepareModel is called, and
+    // 'fullySupportsModel' is true i.f.f. the entire model is guaranteed.
+    // If a driver has any doubt that it can prepare an operation, it must
+    // return false. So here, if a driver isn't sure if it can support an
+    // operation, but reports that it successfully prepared the model, the test
+    // can continue.
+    if (!fullySupportsModel && prepareReturnStatus != ErrorStatus::NONE) {
+        ASSERT_EQ(nullptr, preparedModel->get());
+        LOG(INFO) << "NN VTS: Unable to test Request validation because vendor service cannot "
+                     "prepare model that it does not support.";
+        std::cout << "[          ]   Unable to test Request validation because vendor service "
+                     "cannot prepare model that it does not support."
+                  << std::endl;
+        return;
+    }
+    ASSERT_EQ(ErrorStatus::NONE, prepareReturnStatus);
+    ASSERT_NE(nullptr, preparedModel->get());
+}
+
+// Primary validation function. This function will take a valid request, apply a
+// mutation to it to invalidate the request, then pass it to interface calls
+// that use the request. Note that the request here is passed by value, and any
+// mutation to the request does not leave this function.
+static void validate(const sp<IPreparedModel>& preparedModel, const std::string& message,
+                     Request request, const std::function<void(Request*)>& mutation) {
+    mutation(&request);
+    SCOPED_TRACE(message + " [execute]");
+
+    sp<ExecutionCallback> executionCallback = new ExecutionCallback();
+    ASSERT_NE(nullptr, executionCallback.get());
+    Return<ErrorStatus> executeLaunchStatus = preparedModel->execute(request, executionCallback);
+    ASSERT_TRUE(executeLaunchStatus.isOk());
+    ASSERT_EQ(ErrorStatus::INVALID_ARGUMENT, static_cast<ErrorStatus>(executeLaunchStatus));
+
+    executionCallback->wait();
+    ErrorStatus executionReturnStatus = executionCallback->getStatus();
+    ASSERT_EQ(ErrorStatus::INVALID_ARGUMENT, executionReturnStatus);
+}
+
+// Delete element from hidl_vec. hidl_vec doesn't support a "remove" operation,
+// so this is efficiently accomplished by moving the element to the end and
+// resizing the hidl_vec to one less.
+template <typename Type>
+static void hidl_vec_removeAt(hidl_vec<Type>* vec, uint32_t index) {
+    if (vec) {
+        std::rotate(vec->begin() + index, vec->begin() + index + 1, vec->end());
+        vec->resize(vec->size() - 1);
+    }
+}
+
+template <typename Type>
+static uint32_t hidl_vec_push_back(hidl_vec<Type>* vec, const Type& value) {
+    // assume vec is valid
+    const uint32_t index = vec->size();
+    vec->resize(index + 1);
+    (*vec)[index] = value;
+    return index;
+}
+
+///////////////////////// REMOVE INPUT ////////////////////////////////////
+
+static void removeInputTest(const sp<IPreparedModel>& preparedModel, const Request& request) {
+    for (size_t input = 0; input < request.inputs.size(); ++input) {
+        const std::string message = "removeInput: removed input " + std::to_string(input);
+        validate(preparedModel, message, request,
+                 [input](Request* request) { hidl_vec_removeAt(&request->inputs, input); });
+    }
+}
+
+///////////////////////// REMOVE OUTPUT ////////////////////////////////////
+
+static void removeOutputTest(const sp<IPreparedModel>& preparedModel, const Request& request) {
+    for (size_t output = 0; output < request.outputs.size(); ++output) {
+        const std::string message = "removeOutput: removed Output " + std::to_string(output);
+        validate(preparedModel, message, request,
+                 [output](Request* request) { hidl_vec_removeAt(&request->outputs, output); });
+    }
+}
+
+///////////////////////////// ENTRY POINT //////////////////////////////////
+
+std::vector<Request> createRequests(const std::vector<MixedTypedExampleType>& examples) {
+    const uint32_t INPUT = 0;
+    const uint32_t OUTPUT = 1;
+
+    std::vector<Request> requests;
+
+    for (auto& example : examples) {
+        const MixedTyped& inputs = example.first;
+        const MixedTyped& outputs = example.second;
+
+        std::vector<RequestArgument> inputs_info, outputs_info;
+        uint32_t inputSize = 0, outputSize = 0;
+
+        // This function only partially specifies the metadata (vector of RequestArguments).
+        // The contents are copied over below.
+        for_all(inputs, [&inputs_info, &inputSize](int index, auto, auto s) {
+            if (inputs_info.size() <= static_cast<size_t>(index)) inputs_info.resize(index + 1);
+            RequestArgument arg = {
+                .location = {.poolIndex = INPUT, .offset = 0, .length = static_cast<uint32_t>(s)},
+                .dimensions = {},
+            };
+            RequestArgument arg_empty = {
+                .hasNoValue = true,
+            };
+            inputs_info[index] = s ? arg : arg_empty;
+            inputSize += s;
+        });
+        // Compute offset for inputs 1 and so on
+        {
+            size_t offset = 0;
+            for (auto& i : inputs_info) {
+                if (!i.hasNoValue) i.location.offset = offset;
+                offset += i.location.length;
+            }
+        }
+
+        // Go through all outputs, initialize RequestArgument descriptors
+        for_all(outputs, [&outputs_info, &outputSize](int index, auto, auto s) {
+            if (outputs_info.size() <= static_cast<size_t>(index)) outputs_info.resize(index + 1);
+            RequestArgument arg = {
+                .location = {.poolIndex = OUTPUT, .offset = 0, .length = static_cast<uint32_t>(s)},
+                .dimensions = {},
+            };
+            outputs_info[index] = arg;
+            outputSize += s;
+        });
+        // Compute offset for outputs 1 and so on
+        {
+            size_t offset = 0;
+            for (auto& i : outputs_info) {
+                i.location.offset = offset;
+                offset += i.location.length;
+            }
+        }
+        std::vector<hidl_memory> pools = {nn::allocateSharedMemory(inputSize),
+                                          nn::allocateSharedMemory(outputSize)};
+        if (pools[INPUT].size() == 0 || pools[OUTPUT].size() == 0) {
+            return {};
+        }
+
+        // map pool
+        sp<IMemory> inputMemory = mapMemory(pools[INPUT]);
+        if (inputMemory == nullptr) {
+            return {};
+        }
+        char* inputPtr = reinterpret_cast<char*>(static_cast<void*>(inputMemory->getPointer()));
+        if (inputPtr == nullptr) {
+            return {};
+        }
+
+        // initialize pool
+        inputMemory->update();
+        for_all(inputs, [&inputs_info, inputPtr](int index, auto p, auto s) {
+            char* begin = (char*)p;
+            char* end = begin + s;
+            // TODO: handle more than one input
+            std::copy(begin, end, inputPtr + inputs_info[index].location.offset);
+        });
+        inputMemory->commit();
+
+        requests.push_back({.inputs = inputs_info, .outputs = outputs_info, .pools = pools});
+    }
+
+    return requests;
+}
+
+void ValidationTest::validateRequests(const V1_0::Model& model,
+                                      const std::vector<Request>& requests) {
+    // create IPreparedModel
+    sp<IPreparedModel> preparedModel;
+    ASSERT_NO_FATAL_FAILURE(createPreparedModel(device, model, &preparedModel));
+    if (preparedModel == nullptr) {
+        return;
+    }
+
+    // validate each request
+    for (const Request& request : requests) {
+        removeInputTest(preparedModel, request);
+        removeOutputTest(preparedModel, request);
+    }
+}
+
+}  // namespace functional
+}  // namespace vts
+}  // namespace V1_0
+}  // namespace neuralnetworks
+}  // namespace hardware
+}  // namespace android
diff --git a/neuralnetworks/1.0/vts/functional/ValidationTests.cpp b/neuralnetworks/1.0/vts/functional/ValidationTests.cpp
new file mode 100644
index 0000000..98fc1c5
--- /dev/null
+++ b/neuralnetworks/1.0/vts/functional/ValidationTests.cpp
@@ -0,0 +1,50 @@
+/*
+ * Copyright (C) 2018 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#define LOG_TAG "neuralnetworks_hidl_hal_test"
+
+#include "Models.h"
+#include "VtsHalNeuralnetworks.h"
+
+namespace android {
+namespace hardware {
+namespace neuralnetworks {
+namespace V1_0 {
+namespace vts {
+namespace functional {
+
+// forward declarations
+std::vector<Request> createRequests(const std::vector<MixedTypedExample>& examples);
+
+// generate validation tests
+#define VTS_CURRENT_TEST_CASE(TestName)                                           \
+    TEST_F(ValidationTest, TestName) {                                            \
+        const Model model = TestName::createTestModel();                          \
+        const std::vector<Request> requests = createRequests(TestName::examples); \
+        validateModel(model);                                                     \
+        validateRequests(model, requests);                                        \
+    }
+
+FOR_EACH_TEST_MODEL(VTS_CURRENT_TEST_CASE)
+
+#undef VTS_CURRENT_TEST_CASE
+
+}  // namespace functional
+}  // namespace vts
+}  // namespace V1_0
+}  // namespace neuralnetworks
+}  // namespace hardware
+}  // namespace android
diff --git a/neuralnetworks/1.0/vts/functional/VtsHalNeuralnetworksV1_0.cpp b/neuralnetworks/1.0/vts/functional/VtsHalNeuralnetworks.cpp
similarity index 64%
rename from neuralnetworks/1.0/vts/functional/VtsHalNeuralnetworksV1_0.cpp
rename to neuralnetworks/1.0/vts/functional/VtsHalNeuralnetworks.cpp
index b14fb2c..1ff3b66 100644
--- a/neuralnetworks/1.0/vts/functional/VtsHalNeuralnetworksV1_0.cpp
+++ b/neuralnetworks/1.0/vts/functional/VtsHalNeuralnetworks.cpp
@@ -16,15 +16,7 @@
 
 #define LOG_TAG "neuralnetworks_hidl_hal_test"
 
-#include "VtsHalNeuralnetworksV1_0.h"
-#include "Utils.h"
-
-#include <android-base/logging.h>
-
-using ::android::hardware::hidl_memory;
-using ::android::hidl::allocator::V1_0::IAllocator;
-using ::android::hidl::memory::V1_0::IMemory;
-using ::android::sp;
+#include "VtsHalNeuralnetworks.h"
 
 namespace android {
 namespace hardware {
@@ -33,11 +25,6 @@
 namespace vts {
 namespace functional {
 
-// allocator helper
-hidl_memory allocateSharedMemory(int64_t size) {
-    return nn::allocateSharedMemory(size);
-}
-
 // A class for test environment setup
 NeuralnetworksHidlEnvironment::NeuralnetworksHidlEnvironment() {}
 
@@ -51,23 +38,49 @@
 }
 
 void NeuralnetworksHidlEnvironment::registerTestServices() {
-    registerTestService<V1_0::IDevice>();
+    registerTestService<IDevice>();
 }
 
 // The main test class for NEURALNETWORK HIDL HAL.
+NeuralnetworksHidlTest::NeuralnetworksHidlTest() {}
+
 NeuralnetworksHidlTest::~NeuralnetworksHidlTest() {}
 
 void NeuralnetworksHidlTest::SetUp() {
-    device = ::testing::VtsHalHidlTargetTestBase::getService<V1_0::IDevice>(
+    ::testing::VtsHalHidlTargetTestBase::SetUp();
+    device = ::testing::VtsHalHidlTargetTestBase::getService<IDevice>(
         NeuralnetworksHidlEnvironment::getInstance());
     ASSERT_NE(nullptr, device.get());
 }
 
-void NeuralnetworksHidlTest::TearDown() {}
+void NeuralnetworksHidlTest::TearDown() {
+    device = nullptr;
+    ::testing::VtsHalHidlTargetTestBase::TearDown();
+}
 
 }  // namespace functional
 }  // namespace vts
+
+::std::ostream& operator<<(::std::ostream& os, ErrorStatus errorStatus) {
+    return os << toString(errorStatus);
+}
+
+::std::ostream& operator<<(::std::ostream& os, DeviceStatus deviceStatus) {
+    return os << toString(deviceStatus);
+}
+
 }  // namespace V1_0
 }  // namespace neuralnetworks
 }  // namespace hardware
 }  // namespace android
+
+using android::hardware::neuralnetworks::V1_0::vts::functional::NeuralnetworksHidlEnvironment;
+
+int main(int argc, char** argv) {
+    ::testing::AddGlobalTestEnvironment(NeuralnetworksHidlEnvironment::getInstance());
+    ::testing::InitGoogleTest(&argc, argv);
+    NeuralnetworksHidlEnvironment::getInstance()->init(&argc, argv);
+
+    int status = RUN_ALL_TESTS();
+    return status;
+}
diff --git a/neuralnetworks/1.0/vts/functional/VtsHalNeuralnetworksV1_0.h b/neuralnetworks/1.0/vts/functional/VtsHalNeuralnetworks.h
similarity index 60%
rename from neuralnetworks/1.0/vts/functional/VtsHalNeuralnetworksV1_0.h
rename to neuralnetworks/1.0/vts/functional/VtsHalNeuralnetworks.h
index fbb1607..e79129b 100644
--- a/neuralnetworks/1.0/vts/functional/VtsHalNeuralnetworksV1_0.h
+++ b/neuralnetworks/1.0/vts/functional/VtsHalNeuralnetworks.h
@@ -18,16 +18,15 @@
 #define VTS_HAL_NEURALNETWORKS_V1_0_TARGET_TESTS_H
 
 #include <android/hardware/neuralnetworks/1.0/IDevice.h>
-#include <android/hardware/neuralnetworks/1.0/IExecutionCallback.h>
-#include <android/hardware/neuralnetworks/1.0/IPreparedModel.h>
-#include <android/hardware/neuralnetworks/1.0/IPreparedModelCallback.h>
 #include <android/hardware/neuralnetworks/1.0/types.h>
-#include <android/hidl/allocator/1.0/IAllocator.h>
 
 #include <VtsHalHidlTargetTestBase.h>
 #include <VtsHalHidlTargetTestEnvBase.h>
+
+#include <android-base/macros.h>
 #include <gtest/gtest.h>
-#include <string>
+#include <iostream>
+#include <vector>
 
 namespace android {
 namespace hardware {
@@ -36,47 +35,47 @@
 namespace vts {
 namespace functional {
 
-hidl_memory allocateSharedMemory(int64_t size);
-
 // A class for test environment setup
 class NeuralnetworksHidlEnvironment : public ::testing::VtsHalHidlTargetTestEnvBase {
+    DISALLOW_COPY_AND_ASSIGN(NeuralnetworksHidlEnvironment);
     NeuralnetworksHidlEnvironment();
-    NeuralnetworksHidlEnvironment(const NeuralnetworksHidlEnvironment&) = delete;
-    NeuralnetworksHidlEnvironment(NeuralnetworksHidlEnvironment&&) = delete;
-    NeuralnetworksHidlEnvironment& operator=(const NeuralnetworksHidlEnvironment&) = delete;
-    NeuralnetworksHidlEnvironment& operator=(NeuralnetworksHidlEnvironment&&) = delete;
+    ~NeuralnetworksHidlEnvironment() override;
 
    public:
-    ~NeuralnetworksHidlEnvironment() override;
     static NeuralnetworksHidlEnvironment* getInstance();
     void registerTestServices() override;
 };
 
 // The main test class for NEURALNETWORKS HIDL HAL.
 class NeuralnetworksHidlTest : public ::testing::VtsHalHidlTargetTestBase {
+    DISALLOW_COPY_AND_ASSIGN(NeuralnetworksHidlTest);
+
    public:
+    NeuralnetworksHidlTest();
     ~NeuralnetworksHidlTest() override;
     void SetUp() override;
     void TearDown() override;
 
-    sp<V1_0::IDevice> device;
+   protected:
+    sp<IDevice> device;
 };
+
+// Tag for the validation tests
+class ValidationTest : public NeuralnetworksHidlTest {
+   protected:
+    void validateModel(const Model& model);
+    void validateRequests(const Model& model, const std::vector<Request>& request);
+};
+
+// Tag for the generated tests
+class GeneratedTest : public NeuralnetworksHidlTest {};
+
 }  // namespace functional
 }  // namespace vts
 
 // pretty-print values for error messages
-
-template <typename CharT, typename Traits>
-::std::basic_ostream<CharT, Traits>& operator<<(::std::basic_ostream<CharT, Traits>& os,
-                                                V1_0::ErrorStatus errorStatus) {
-    return os << toString(errorStatus);
-}
-
-template <typename CharT, typename Traits>
-::std::basic_ostream<CharT, Traits>& operator<<(::std::basic_ostream<CharT, Traits>& os,
-                                                V1_0::DeviceStatus deviceStatus) {
-    return os << toString(deviceStatus);
-}
+::std::ostream& operator<<(::std::ostream& os, ErrorStatus errorStatus);
+::std::ostream& operator<<(::std::ostream& os, DeviceStatus deviceStatus);
 
 }  // namespace V1_0
 }  // namespace neuralnetworks
diff --git a/neuralnetworks/1.0/vts/functional/VtsHalNeuralnetworksV1_0BasicTest.cpp b/neuralnetworks/1.0/vts/functional/VtsHalNeuralnetworksV1_0BasicTest.cpp
deleted file mode 100644
index 59e5b80..0000000
--- a/neuralnetworks/1.0/vts/functional/VtsHalNeuralnetworksV1_0BasicTest.cpp
+++ /dev/null
@@ -1,293 +0,0 @@
-/*
- * Copyright (C) 2018 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-#define LOG_TAG "neuralnetworks_hidl_hal_test"
-
-#include "VtsHalNeuralnetworksV1_0.h"
-
-#include "Callbacks.h"
-#include "Models.h"
-#include "TestHarness.h"
-
-#include <android-base/logging.h>
-#include <android/hidl/memory/1.0/IMemory.h>
-#include <hidlmemory/mapping.h>
-
-using ::android::hardware::neuralnetworks::V1_0::IDevice;
-using ::android::hardware::neuralnetworks::V1_0::IPreparedModel;
-using ::android::hardware::neuralnetworks::V1_0::Capabilities;
-using ::android::hardware::neuralnetworks::V1_0::DeviceStatus;
-using ::android::hardware::neuralnetworks::V1_0::FusedActivationFunc;
-using ::android::hardware::neuralnetworks::V1_0::Model;
-using ::android::hardware::neuralnetworks::V1_0::OperationType;
-using ::android::hardware::neuralnetworks::V1_0::PerformanceInfo;
-using ::android::hardware::Return;
-using ::android::hardware::Void;
-using ::android::hardware::hidl_memory;
-using ::android::hardware::hidl_string;
-using ::android::hardware::hidl_vec;
-using ::android::hidl::allocator::V1_0::IAllocator;
-using ::android::hidl::memory::V1_0::IMemory;
-using ::android::sp;
-
-namespace android {
-namespace hardware {
-namespace neuralnetworks {
-namespace V1_0 {
-namespace vts {
-namespace functional {
-using ::android::hardware::neuralnetworks::V1_0::implementation::ExecutionCallback;
-using ::android::hardware::neuralnetworks::V1_0::implementation::PreparedModelCallback;
-
-static void doPrepareModelShortcut(const sp<IDevice>& device, sp<IPreparedModel>* preparedModel) {
-    ASSERT_NE(nullptr, preparedModel);
-    Model model = createValidTestModel_1_0();
-
-    // see if service can handle model
-    bool fullySupportsModel = false;
-    Return<void> supportedOpsLaunchStatus = device->getSupportedOperations(
-        model, [&fullySupportsModel](ErrorStatus status, const hidl_vec<bool>& supported) {
-            ASSERT_EQ(ErrorStatus::NONE, status);
-            ASSERT_NE(0ul, supported.size());
-            fullySupportsModel =
-                std::all_of(supported.begin(), supported.end(), [](bool valid) { return valid; });
-        });
-    ASSERT_TRUE(supportedOpsLaunchStatus.isOk());
-
-    // launch prepare model
-    sp<PreparedModelCallback> preparedModelCallback = new PreparedModelCallback();
-    ASSERT_NE(nullptr, preparedModelCallback.get());
-    Return<ErrorStatus> prepareLaunchStatus = device->prepareModel(model, preparedModelCallback);
-    ASSERT_TRUE(prepareLaunchStatus.isOk());
-    ASSERT_EQ(ErrorStatus::NONE, static_cast<ErrorStatus>(prepareLaunchStatus));
-
-    // retrieve prepared model
-    preparedModelCallback->wait();
-    ErrorStatus prepareReturnStatus = preparedModelCallback->getStatus();
-    *preparedModel = preparedModelCallback->getPreparedModel();
-
-    // The getSupportedOperations call returns a list of operations that are
-    // guaranteed not to fail if prepareModel is called, and
-    // 'fullySupportsModel' is true i.f.f. the entire model is guaranteed.
-    // If a driver has any doubt that it can prepare an operation, it must
-    // return false. So here, if a driver isn't sure if it can support an
-    // operation, but reports that it successfully prepared the model, the test
-    // can continue.
-    if (!fullySupportsModel && prepareReturnStatus != ErrorStatus::NONE) {
-        ASSERT_EQ(nullptr, preparedModel->get());
-        LOG(INFO) << "NN VTS: Early termination of test because vendor service cannot "
-                     "prepare model that it does not support.";
-        std::cout << "[          ]   Early termination of test because vendor service cannot "
-                     "prepare model that it does not support."
-                  << std::endl;
-        return;
-    }
-    ASSERT_EQ(ErrorStatus::NONE, prepareReturnStatus);
-    ASSERT_NE(nullptr, preparedModel->get());
-}
-
-// create device test
-TEST_F(NeuralnetworksHidlTest, CreateDevice) {}
-
-// status test
-TEST_F(NeuralnetworksHidlTest, StatusTest) {
-    Return<DeviceStatus> status = device->getStatus();
-    ASSERT_TRUE(status.isOk());
-    EXPECT_EQ(DeviceStatus::AVAILABLE, static_cast<DeviceStatus>(status));
-}
-
-// initialization
-TEST_F(NeuralnetworksHidlTest, GetCapabilitiesTest) {
-    Return<void> ret =
-        device->getCapabilities([](ErrorStatus status, const Capabilities& capabilities) {
-            EXPECT_EQ(ErrorStatus::NONE, status);
-            EXPECT_LT(0.0f, capabilities.float32Performance.execTime);
-            EXPECT_LT(0.0f, capabilities.float32Performance.powerUsage);
-            EXPECT_LT(0.0f, capabilities.quantized8Performance.execTime);
-            EXPECT_LT(0.0f, capabilities.quantized8Performance.powerUsage);
-        });
-    EXPECT_TRUE(ret.isOk());
-}
-
-// supported operations positive test
-TEST_F(NeuralnetworksHidlTest, SupportedOperationsPositiveTest) {
-    Model model = createValidTestModel_1_0();
-    Return<void> ret = device->getSupportedOperations(
-        model, [&](ErrorStatus status, const hidl_vec<bool>& supported) {
-            EXPECT_EQ(ErrorStatus::NONE, status);
-            EXPECT_EQ(model.operations.size(), supported.size());
-        });
-    EXPECT_TRUE(ret.isOk());
-}
-
-// supported operations negative test 1
-TEST_F(NeuralnetworksHidlTest, SupportedOperationsNegativeTest1) {
-    Model model = createInvalidTestModel1_1_0();
-    Return<void> ret = device->getSupportedOperations(
-        model, [&](ErrorStatus status, const hidl_vec<bool>& supported) {
-            EXPECT_EQ(ErrorStatus::INVALID_ARGUMENT, status);
-            (void)supported;
-        });
-    EXPECT_TRUE(ret.isOk());
-}
-
-// supported operations negative test 2
-TEST_F(NeuralnetworksHidlTest, SupportedOperationsNegativeTest2) {
-    Model model = createInvalidTestModel2_1_0();
-    Return<void> ret = device->getSupportedOperations(
-        model, [&](ErrorStatus status, const hidl_vec<bool>& supported) {
-            EXPECT_EQ(ErrorStatus::INVALID_ARGUMENT, status);
-            (void)supported;
-        });
-    EXPECT_TRUE(ret.isOk());
-}
-
-// prepare simple model positive test
-TEST_F(NeuralnetworksHidlTest, SimplePrepareModelPositiveTest) {
-    sp<IPreparedModel> preparedModel;
-    doPrepareModelShortcut(device, &preparedModel);
-}
-
-// prepare simple model negative test 1
-TEST_F(NeuralnetworksHidlTest, SimplePrepareModelNegativeTest1) {
-    Model model = createInvalidTestModel1_1_0();
-    sp<PreparedModelCallback> preparedModelCallback = new PreparedModelCallback();
-    ASSERT_NE(nullptr, preparedModelCallback.get());
-    Return<ErrorStatus> prepareLaunchStatus = device->prepareModel(model, preparedModelCallback);
-    ASSERT_TRUE(prepareLaunchStatus.isOk());
-    EXPECT_EQ(ErrorStatus::INVALID_ARGUMENT, static_cast<ErrorStatus>(prepareLaunchStatus));
-
-    preparedModelCallback->wait();
-    ErrorStatus prepareReturnStatus = preparedModelCallback->getStatus();
-    EXPECT_EQ(ErrorStatus::INVALID_ARGUMENT, prepareReturnStatus);
-    sp<IPreparedModel> preparedModel = preparedModelCallback->getPreparedModel();
-    EXPECT_EQ(nullptr, preparedModel.get());
-}
-
-// prepare simple model negative test 2
-TEST_F(NeuralnetworksHidlTest, SimplePrepareModelNegativeTest2) {
-    Model model = createInvalidTestModel2_1_0();
-    sp<PreparedModelCallback> preparedModelCallback = new PreparedModelCallback();
-    ASSERT_NE(nullptr, preparedModelCallback.get());
-    Return<ErrorStatus> prepareLaunchStatus = device->prepareModel(model, preparedModelCallback);
-    ASSERT_TRUE(prepareLaunchStatus.isOk());
-    EXPECT_EQ(ErrorStatus::INVALID_ARGUMENT, static_cast<ErrorStatus>(prepareLaunchStatus));
-
-    preparedModelCallback->wait();
-    ErrorStatus prepareReturnStatus = preparedModelCallback->getStatus();
-    EXPECT_EQ(ErrorStatus::INVALID_ARGUMENT, prepareReturnStatus);
-    sp<IPreparedModel> preparedModel = preparedModelCallback->getPreparedModel();
-    EXPECT_EQ(nullptr, preparedModel.get());
-}
-
-// execute simple graph positive test
-TEST_F(NeuralnetworksHidlTest, SimpleExecuteGraphPositiveTest) {
-    std::vector<float> outputData = {-1.0f, -1.0f, -1.0f, -1.0f};
-    std::vector<float> expectedData = {6.0f, 8.0f, 10.0f, 12.0f};
-    const uint32_t OUTPUT = 1;
-
-    sp<IPreparedModel> preparedModel;
-    ASSERT_NO_FATAL_FAILURE(doPrepareModelShortcut(device, &preparedModel));
-    if (preparedModel == nullptr) {
-        return;
-    }
-    Request request = createValidTestRequest();
-
-    auto postWork = [&] {
-        sp<IMemory> outputMemory = mapMemory(request.pools[OUTPUT]);
-        if (outputMemory == nullptr) {
-            return false;
-        }
-        float* outputPtr = reinterpret_cast<float*>(static_cast<void*>(outputMemory->getPointer()));
-        if (outputPtr == nullptr) {
-            return false;
-        }
-        outputMemory->read();
-        std::copy(outputPtr, outputPtr + outputData.size(), outputData.begin());
-        outputMemory->commit();
-        return true;
-    };
-
-    sp<ExecutionCallback> executionCallback = new ExecutionCallback();
-    ASSERT_NE(nullptr, executionCallback.get());
-    executionCallback->on_finish(postWork);
-    Return<ErrorStatus> executeLaunchStatus = preparedModel->execute(request, executionCallback);
-    ASSERT_TRUE(executeLaunchStatus.isOk());
-    EXPECT_EQ(ErrorStatus::NONE, static_cast<ErrorStatus>(executeLaunchStatus));
-
-    executionCallback->wait();
-    ErrorStatus executionReturnStatus = executionCallback->getStatus();
-    EXPECT_EQ(ErrorStatus::NONE, executionReturnStatus);
-    EXPECT_EQ(expectedData, outputData);
-}
-
-// execute simple graph negative test 1
-TEST_F(NeuralnetworksHidlTest, SimpleExecuteGraphNegativeTest1) {
-    sp<IPreparedModel> preparedModel;
-    ASSERT_NO_FATAL_FAILURE(doPrepareModelShortcut(device, &preparedModel));
-    if (preparedModel == nullptr) {
-        return;
-    }
-    Request request = createInvalidTestRequest1();
-
-    sp<ExecutionCallback> executionCallback = new ExecutionCallback();
-    ASSERT_NE(nullptr, executionCallback.get());
-    Return<ErrorStatus> executeLaunchStatus = preparedModel->execute(request, executionCallback);
-    ASSERT_TRUE(executeLaunchStatus.isOk());
-    EXPECT_EQ(ErrorStatus::INVALID_ARGUMENT, static_cast<ErrorStatus>(executeLaunchStatus));
-
-    executionCallback->wait();
-    ErrorStatus executionReturnStatus = executionCallback->getStatus();
-    EXPECT_EQ(ErrorStatus::INVALID_ARGUMENT, executionReturnStatus);
-}
-
-// execute simple graph negative test 2
-TEST_F(NeuralnetworksHidlTest, SimpleExecuteGraphNegativeTest2) {
-    sp<IPreparedModel> preparedModel;
-    ASSERT_NO_FATAL_FAILURE(doPrepareModelShortcut(device, &preparedModel));
-    if (preparedModel == nullptr) {
-        return;
-    }
-    Request request = createInvalidTestRequest2();
-
-    sp<ExecutionCallback> executionCallback = new ExecutionCallback();
-    ASSERT_NE(nullptr, executionCallback.get());
-    Return<ErrorStatus> executeLaunchStatus = preparedModel->execute(request, executionCallback);
-    ASSERT_TRUE(executeLaunchStatus.isOk());
-    EXPECT_EQ(ErrorStatus::INVALID_ARGUMENT, static_cast<ErrorStatus>(executeLaunchStatus));
-
-    executionCallback->wait();
-    ErrorStatus executionReturnStatus = executionCallback->getStatus();
-    EXPECT_EQ(ErrorStatus::INVALID_ARGUMENT, executionReturnStatus);
-}
-
-}  // namespace functional
-}  // namespace vts
-}  // namespace V1_0
-}  // namespace neuralnetworks
-}  // namespace hardware
-}  // namespace android
-
-using android::hardware::neuralnetworks::V1_0::vts::functional::NeuralnetworksHidlEnvironment;
-
-int main(int argc, char** argv) {
-    ::testing::AddGlobalTestEnvironment(NeuralnetworksHidlEnvironment::getInstance());
-    ::testing::InitGoogleTest(&argc, argv);
-    NeuralnetworksHidlEnvironment::getInstance()->init(&argc, argv);
-
-    int status = RUN_ALL_TESTS();
-    return status;
-}
diff --git a/neuralnetworks/1.1/vts/functional/Android.bp b/neuralnetworks/1.1/vts/functional/Android.bp
index 947ca2c..f755c20 100644
--- a/neuralnetworks/1.1/vts/functional/Android.bp
+++ b/neuralnetworks/1.1/vts/functional/Android.bp
@@ -17,9 +17,12 @@
 cc_test {
     name: "VtsHalNeuralnetworksV1_1TargetTest",
     srcs: [
-        "VtsHalNeuralnetworksV1_1.cpp",
-        "VtsHalNeuralnetworksV1_1BasicTest.cpp",
-        "VtsHalNeuralnetworksV1_1GeneratedTest.cpp",
+        "BasicTests.cpp",
+        "GeneratedTests.cpp",
+        "ValidateModel.cpp",
+        "ValidateRequest.cpp",
+        "ValidationTests.cpp",
+        "VtsHalNeuralnetworks.cpp",
     ],
     defaults: ["VtsHalTargetTestDefaults"],
     static_libs: [
diff --git a/neuralnetworks/1.1/vts/functional/BasicTests.cpp b/neuralnetworks/1.1/vts/functional/BasicTests.cpp
new file mode 100644
index 0000000..ed59a2d
--- /dev/null
+++ b/neuralnetworks/1.1/vts/functional/BasicTests.cpp
@@ -0,0 +1,58 @@
+/*
+ * Copyright (C) 2018 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#define LOG_TAG "neuralnetworks_hidl_hal_test"
+
+#include "VtsHalNeuralnetworks.h"
+
+namespace android {
+namespace hardware {
+namespace neuralnetworks {
+namespace V1_1 {
+namespace vts {
+namespace functional {
+
+// create device test
+TEST_F(NeuralnetworksHidlTest, CreateDevice) {}
+
+// status test
+TEST_F(NeuralnetworksHidlTest, StatusTest) {
+    Return<DeviceStatus> status = device->getStatus();
+    ASSERT_TRUE(status.isOk());
+    EXPECT_EQ(DeviceStatus::AVAILABLE, static_cast<DeviceStatus>(status));
+}
+
+// initialization
+TEST_F(NeuralnetworksHidlTest, GetCapabilitiesTest) {
+    Return<void> ret =
+        device->getCapabilities_1_1([](ErrorStatus status, const Capabilities& capabilities) {
+            EXPECT_EQ(ErrorStatus::NONE, status);
+            EXPECT_LT(0.0f, capabilities.float32Performance.execTime);
+            EXPECT_LT(0.0f, capabilities.float32Performance.powerUsage);
+            EXPECT_LT(0.0f, capabilities.quantized8Performance.execTime);
+            EXPECT_LT(0.0f, capabilities.quantized8Performance.powerUsage);
+            EXPECT_LT(0.0f, capabilities.relaxedFloat32toFloat16Performance.execTime);
+            EXPECT_LT(0.0f, capabilities.relaxedFloat32toFloat16Performance.powerUsage);
+        });
+    EXPECT_TRUE(ret.isOk());
+}
+
+}  // namespace functional
+}  // namespace vts
+}  // namespace V1_1
+}  // namespace neuralnetworks
+}  // namespace hardware
+}  // namespace android
diff --git a/neuralnetworks/1.1/vts/functional/GeneratedTests.cpp b/neuralnetworks/1.1/vts/functional/GeneratedTests.cpp
new file mode 100644
index 0000000..1f1cc7a
--- /dev/null
+++ b/neuralnetworks/1.1/vts/functional/GeneratedTests.cpp
@@ -0,0 +1,59 @@
+/*
+ * Copyright (C) 2018 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#define LOG_TAG "neuralnetworks_hidl_hal_test"
+
+#include "VtsHalNeuralnetworks.h"
+
+#include "Callbacks.h"
+#include "TestHarness.h"
+#include "Utils.h"
+
+#include <android-base/logging.h>
+#include <android/hidl/memory/1.0/IMemory.h>
+#include <hidlmemory/mapping.h>
+
+namespace android {
+namespace hardware {
+namespace neuralnetworks {
+
+namespace generated_tests {
+using ::generated_tests::MixedTypedExampleType;
+extern void Execute(const sp<V1_1::IDevice>&, std::function<V1_1::Model(void)>,
+                    std::function<bool(int)>, const std::vector<MixedTypedExampleType>&);
+}  // namespace generated_tests
+
+namespace V1_1 {
+namespace vts {
+namespace functional {
+
+using ::android::hardware::neuralnetworks::V1_0::implementation::ExecutionCallback;
+using ::android::hardware::neuralnetworks::V1_0::implementation::PreparedModelCallback;
+using ::android::nn::allocateSharedMemory;
+
+// Mixed-typed examples
+typedef generated_tests::MixedTypedExampleType MixedTypedExample;
+
+// in frameworks/ml/nn/runtime/tests/generated/
+#include "all_generated_V1_0_vts_tests.cpp"
+#include "all_generated_V1_1_vts_tests.cpp"
+
+}  // namespace functional
+}  // namespace vts
+}  // namespace V1_1
+}  // namespace neuralnetworks
+}  // namespace hardware
+}  // namespace android
diff --git a/neuralnetworks/1.1/vts/functional/Models.h b/neuralnetworks/1.1/vts/functional/Models.h
new file mode 100644
index 0000000..c3cadb5
--- /dev/null
+++ b/neuralnetworks/1.1/vts/functional/Models.h
@@ -0,0 +1,323 @@
+/*
+ * Copyright (C) 2018 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef VTS_HAL_NEURALNETWORKS_V1_1_VTS_FUNCTIONAL_MODELS_H
+#define VTS_HAL_NEURALNETWORKS_V1_1_VTS_FUNCTIONAL_MODELS_H
+
+#define LOG_TAG "neuralnetworks_hidl_hal_test"
+
+#include "TestHarness.h"
+
+#include <android/hardware/neuralnetworks/1.0/types.h>
+#include <android/hardware/neuralnetworks/1.1/types.h>
+
+namespace android {
+namespace hardware {
+namespace neuralnetworks {
+namespace V1_1 {
+namespace vts {
+namespace functional {
+
+using MixedTypedExample = generated_tests::MixedTypedExampleType;
+
+#define FOR_EACH_TEST_MODEL(FN)                                \
+    FN(add)                                                    \
+    FN(add_broadcast_quant8)                                   \
+    FN(add_quant8)                                             \
+    FN(add_relaxed)                                            \
+    FN(avg_pool_float_1)                                       \
+    FN(avg_pool_float_1_relaxed)                               \
+    FN(avg_pool_float_2)                                       \
+    FN(avg_pool_float_2_relaxed)                               \
+    FN(avg_pool_float_3)                                       \
+    FN(avg_pool_float_3_relaxed)                               \
+    FN(avg_pool_float_4)                                       \
+    FN(avg_pool_float_4_relaxed)                               \
+    FN(avg_pool_float_5)                                       \
+    FN(avg_pool_quant8_1)                                      \
+    FN(avg_pool_quant8_2)                                      \
+    FN(avg_pool_quant8_3)                                      \
+    FN(avg_pool_quant8_4)                                      \
+    FN(avg_pool_quant8_5)                                      \
+    FN(batch_to_space)                                         \
+    FN(batch_to_space_float_1)                                 \
+    FN(batch_to_space_quant8_1)                                \
+    FN(concat_float_1)                                         \
+    FN(concat_float_1_relaxed)                                 \
+    FN(concat_float_2)                                         \
+    FN(concat_float_2_relaxed)                                 \
+    FN(concat_float_3)                                         \
+    FN(concat_float_3_relaxed)                                 \
+    FN(concat_quant8_1)                                        \
+    FN(concat_quant8_2)                                        \
+    FN(concat_quant8_3)                                        \
+    FN(conv_1_h3_w2_SAME)                                      \
+    FN(conv_1_h3_w2_SAME_relaxed)                              \
+    FN(conv_1_h3_w2_VALID)                                     \
+    FN(conv_1_h3_w2_VALID_relaxed)                             \
+    FN(conv_3_h3_w2_SAME)                                      \
+    FN(conv_3_h3_w2_SAME_relaxed)                              \
+    FN(conv_3_h3_w2_VALID)                                     \
+    FN(conv_3_h3_w2_VALID_relaxed)                             \
+    FN(conv_float)                                             \
+    FN(conv_float_2)                                           \
+    FN(conv_float_channels)                                    \
+    FN(conv_float_channels_relaxed)                            \
+    FN(conv_float_channels_weights_as_inputs)                  \
+    FN(conv_float_channels_weights_as_inputs_relaxed)          \
+    FN(conv_float_large)                                       \
+    FN(conv_float_large_relaxed)                               \
+    FN(conv_float_large_weights_as_inputs)                     \
+    FN(conv_float_large_weights_as_inputs_relaxed)             \
+    FN(conv_float_relaxed)                                     \
+    FN(conv_float_weights_as_inputs)                           \
+    FN(conv_float_weights_as_inputs_relaxed)                   \
+    FN(conv_quant8)                                            \
+    FN(conv_quant8_2)                                          \
+    FN(conv_quant8_channels)                                   \
+    FN(conv_quant8_channels_weights_as_inputs)                 \
+    FN(conv_quant8_large)                                      \
+    FN(conv_quant8_large_weights_as_inputs)                    \
+    FN(conv_quant8_overflow)                                   \
+    FN(conv_quant8_overflow_weights_as_inputs)                 \
+    FN(conv_quant8_weights_as_inputs)                          \
+    FN(depth_to_space_float_1)                                 \
+    FN(depth_to_space_float_1_relaxed)                         \
+    FN(depth_to_space_float_2)                                 \
+    FN(depth_to_space_float_2_relaxed)                         \
+    FN(depth_to_space_float_3)                                 \
+    FN(depth_to_space_float_3_relaxed)                         \
+    FN(depth_to_space_quant8_1)                                \
+    FN(depth_to_space_quant8_2)                                \
+    FN(depthwise_conv)                                         \
+    FN(depthwise_conv2d_float)                                 \
+    FN(depthwise_conv2d_float_2)                               \
+    FN(depthwise_conv2d_float_large)                           \
+    FN(depthwise_conv2d_float_large_2)                         \
+    FN(depthwise_conv2d_float_large_2_weights_as_inputs)       \
+    FN(depthwise_conv2d_float_large_relaxed)                   \
+    FN(depthwise_conv2d_float_large_weights_as_inputs)         \
+    FN(depthwise_conv2d_float_large_weights_as_inputs_relaxed) \
+    FN(depthwise_conv2d_float_weights_as_inputs)               \
+    FN(depthwise_conv2d_quant8)                                \
+    FN(depthwise_conv2d_quant8_2)                              \
+    FN(depthwise_conv2d_quant8_large)                          \
+    FN(depthwise_conv2d_quant8_large_weights_as_inputs)        \
+    FN(depthwise_conv2d_quant8_weights_as_inputs)              \
+    FN(depthwise_conv_relaxed)                                 \
+    FN(dequantize)                                             \
+    FN(div)                                                    \
+    FN(embedding_lookup)                                       \
+    FN(embedding_lookup_relaxed)                               \
+    FN(floor)                                                  \
+    FN(floor_relaxed)                                          \
+    FN(fully_connected_float)                                  \
+    FN(fully_connected_float_2)                                \
+    FN(fully_connected_float_large)                            \
+    FN(fully_connected_float_large_weights_as_inputs)          \
+    FN(fully_connected_float_relaxed)                          \
+    FN(fully_connected_float_weights_as_inputs)                \
+    FN(fully_connected_float_weights_as_inputs_relaxed)        \
+    FN(fully_connected_quant8)                                 \
+    FN(fully_connected_quant8_2)                               \
+    FN(fully_connected_quant8_large)                           \
+    FN(fully_connected_quant8_large_weights_as_inputs)         \
+    FN(fully_connected_quant8_weights_as_inputs)               \
+    FN(hashtable_lookup_float)                                 \
+    FN(hashtable_lookup_float_relaxed)                         \
+    FN(hashtable_lookup_quant8)                                \
+    FN(l2_normalization)                                       \
+    FN(l2_normalization_2)                                     \
+    FN(l2_normalization_large)                                 \
+    FN(l2_normalization_large_relaxed)                         \
+    FN(l2_normalization_relaxed)                               \
+    FN(l2_pool_float)                                          \
+    FN(l2_pool_float_2)                                        \
+    FN(l2_pool_float_large)                                    \
+    FN(l2_pool_float_relaxed)                                  \
+    FN(local_response_norm_float_1)                            \
+    FN(local_response_norm_float_1_relaxed)                    \
+    FN(local_response_norm_float_2)                            \
+    FN(local_response_norm_float_2_relaxed)                    \
+    FN(local_response_norm_float_3)                            \
+    FN(local_response_norm_float_3_relaxed)                    \
+    FN(local_response_norm_float_4)                            \
+    FN(local_response_norm_float_4_relaxed)                    \
+    FN(logistic_float_1)                                       \
+    FN(logistic_float_1_relaxed)                               \
+    FN(logistic_float_2)                                       \
+    FN(logistic_float_2_relaxed)                               \
+    FN(logistic_quant8_1)                                      \
+    FN(logistic_quant8_2)                                      \
+    FN(lsh_projection)                                         \
+    FN(lsh_projection_2)                                       \
+    FN(lsh_projection_2_relaxed)                               \
+    FN(lsh_projection_relaxed)                                 \
+    FN(lsh_projection_weights_as_inputs)                       \
+    FN(lsh_projection_weights_as_inputs_relaxed)               \
+    FN(lstm)                                                   \
+    FN(lstm2)                                                  \
+    FN(lstm2_relaxed)                                          \
+    FN(lstm2_state)                                            \
+    FN(lstm2_state2)                                           \
+    FN(lstm2_state2_relaxed)                                   \
+    FN(lstm2_state_relaxed)                                    \
+    FN(lstm3)                                                  \
+    FN(lstm3_relaxed)                                          \
+    FN(lstm3_state)                                            \
+    FN(lstm3_state2)                                           \
+    FN(lstm3_state2_relaxed)                                   \
+    FN(lstm3_state3)                                           \
+    FN(lstm3_state3_relaxed)                                   \
+    FN(lstm3_state_relaxed)                                    \
+    FN(lstm_relaxed)                                           \
+    FN(lstm_state)                                             \
+    FN(lstm_state2)                                            \
+    FN(lstm_state2_relaxed)                                    \
+    FN(lstm_state_relaxed)                                     \
+    FN(max_pool_float_1)                                       \
+    FN(max_pool_float_1_relaxed)                               \
+    FN(max_pool_float_2)                                       \
+    FN(max_pool_float_2_relaxed)                               \
+    FN(max_pool_float_3)                                       \
+    FN(max_pool_float_3_relaxed)                               \
+    FN(max_pool_float_4)                                       \
+    FN(max_pool_quant8_1)                                      \
+    FN(max_pool_quant8_2)                                      \
+    FN(max_pool_quant8_3)                                      \
+    FN(max_pool_quant8_4)                                      \
+    FN(mean)                                                   \
+    FN(mean_float_1)                                           \
+    FN(mean_float_2)                                           \
+    FN(mean_quant8_1)                                          \
+    FN(mean_quant8_2)                                          \
+    FN(mobilenet_224_gender_basic_fixed)                       \
+    FN(mobilenet_224_gender_basic_fixed_relaxed)               \
+    FN(mobilenet_quantized)                                    \
+    FN(mul)                                                    \
+    FN(mul_broadcast_quant8)                                   \
+    FN(mul_quant8)                                             \
+    FN(mul_relaxed)                                            \
+    FN(mul_relu)                                               \
+    FN(mul_relu_relaxed)                                       \
+    FN(pad)                                                    \
+    FN(pad_float_1)                                            \
+    FN(relu1_float_1)                                          \
+    FN(relu1_float_1_relaxed)                                  \
+    FN(relu1_float_2)                                          \
+    FN(relu1_float_2_relaxed)                                  \
+    FN(relu1_quant8_1)                                         \
+    FN(relu1_quant8_2)                                         \
+    FN(relu6_float_1)                                          \
+    FN(relu6_float_1_relaxed)                                  \
+    FN(relu6_float_2)                                          \
+    FN(relu6_float_2_relaxed)                                  \
+    FN(relu6_quant8_1)                                         \
+    FN(relu6_quant8_2)                                         \
+    FN(relu_float_1)                                           \
+    FN(relu_float_1_relaxed)                                   \
+    FN(relu_float_2)                                           \
+    FN(relu_quant8_1)                                          \
+    FN(relu_quant8_2)                                          \
+    FN(reshape)                                                \
+    FN(reshape_quant8)                                         \
+    FN(reshape_quant8_weights_as_inputs)                       \
+    FN(reshape_relaxed)                                        \
+    FN(reshape_weights_as_inputs)                              \
+    FN(reshape_weights_as_inputs_relaxed)                      \
+    FN(resize_bilinear)                                        \
+    FN(resize_bilinear_2)                                      \
+    FN(resize_bilinear_relaxed)                                \
+    FN(rnn)                                                    \
+    FN(rnn_relaxed)                                            \
+    FN(rnn_state)                                              \
+    FN(rnn_state_relaxed)                                      \
+    FN(softmax_float_1)                                        \
+    FN(softmax_float_1_relaxed)                                \
+    FN(softmax_float_2)                                        \
+    FN(softmax_float_2_relaxed)                                \
+    FN(softmax_quant8_1)                                       \
+    FN(softmax_quant8_2)                                       \
+    FN(space_to_batch)                                         \
+    FN(space_to_batch_float_1)                                 \
+    FN(space_to_batch_float_2)                                 \
+    FN(space_to_batch_float_3)                                 \
+    FN(space_to_batch_quant8_1)                                \
+    FN(space_to_batch_quant8_2)                                \
+    FN(space_to_batch_quant8_3)                                \
+    FN(space_to_depth_float_1)                                 \
+    FN(space_to_depth_float_1_relaxed)                         \
+    FN(space_to_depth_float_2)                                 \
+    FN(space_to_depth_float_2_relaxed)                         \
+    FN(space_to_depth_float_3)                                 \
+    FN(space_to_depth_float_3_relaxed)                         \
+    FN(space_to_depth_quant8_1)                                \
+    FN(space_to_depth_quant8_2)                                \
+    FN(squeeze)                                                \
+    FN(squeeze_float_1)                                        \
+    FN(squeeze_quant8_1)                                       \
+    FN(strided_slice)                                          \
+    FN(strided_slice_float_1)                                  \
+    FN(strided_slice_float_10)                                 \
+    FN(strided_slice_float_2)                                  \
+    FN(strided_slice_float_3)                                  \
+    FN(strided_slice_float_4)                                  \
+    FN(strided_slice_float_5)                                  \
+    FN(strided_slice_float_6)                                  \
+    FN(strided_slice_float_7)                                  \
+    FN(strided_slice_float_8)                                  \
+    FN(strided_slice_float_9)                                  \
+    FN(strided_slice_qaunt8_10)                                \
+    FN(strided_slice_quant8_1)                                 \
+    FN(strided_slice_quant8_2)                                 \
+    FN(strided_slice_quant8_3)                                 \
+    FN(strided_slice_quant8_4)                                 \
+    FN(strided_slice_quant8_5)                                 \
+    FN(strided_slice_quant8_6)                                 \
+    FN(strided_slice_quant8_7)                                 \
+    FN(strided_slice_quant8_8)                                 \
+    FN(strided_slice_quant8_9)                                 \
+    FN(sub)                                                    \
+    FN(svdf)                                                   \
+    FN(svdf2)                                                  \
+    FN(svdf2_relaxed)                                          \
+    FN(svdf_relaxed)                                           \
+    FN(svdf_state)                                             \
+    FN(svdf_state_relaxed)                                     \
+    FN(tanh)                                                   \
+    FN(tanh_relaxed)                                           \
+    FN(transpose)                                              \
+    FN(transpose_float_1)                                      \
+    FN(transpose_quant8_1)
+
+#define FORWARD_DECLARE_GENERATED_OBJECTS(function) \
+    namespace function {                            \
+    extern std::vector<MixedTypedExample> examples; \
+    Model createTestModel();                        \
+    }
+
+FOR_EACH_TEST_MODEL(FORWARD_DECLARE_GENERATED_OBJECTS)
+
+#undef FORWARD_DECLARE_GENERATED_OBJECTS
+
+}  // namespace functional
+}  // namespace vts
+}  // namespace V1_1
+}  // namespace neuralnetworks
+}  // namespace hardware
+}  // namespace android
+
+#endif  // VTS_HAL_NEURALNETWORKS_V1_1_VTS_FUNCTIONAL_MODELS_H
diff --git a/neuralnetworks/1.1/vts/functional/ValidateModel.cpp b/neuralnetworks/1.1/vts/functional/ValidateModel.cpp
new file mode 100644
index 0000000..7a20e26
--- /dev/null
+++ b/neuralnetworks/1.1/vts/functional/ValidateModel.cpp
@@ -0,0 +1,513 @@
+/*
+ * Copyright (C) 2018 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#define LOG_TAG "neuralnetworks_hidl_hal_test"
+
+#include "VtsHalNeuralnetworks.h"
+
+#include "Callbacks.h"
+
+namespace android {
+namespace hardware {
+namespace neuralnetworks {
+namespace V1_1 {
+
+using V1_0::IPreparedModel;
+using V1_0::Operand;
+using V1_0::OperandLifeTime;
+using V1_0::OperandType;
+
+namespace vts {
+namespace functional {
+
+using ::android::hardware::neuralnetworks::V1_0::implementation::ExecutionCallback;
+using ::android::hardware::neuralnetworks::V1_0::implementation::PreparedModelCallback;
+
+///////////////////////// UTILITY FUNCTIONS /////////////////////////
+
+static void validateGetSupportedOperations(const sp<IDevice>& device, const std::string& message,
+                                           const V1_1::Model& model) {
+    SCOPED_TRACE(message + " [getSupportedOperations_1_1]");
+
+    Return<void> ret =
+        device->getSupportedOperations_1_1(model, [&](ErrorStatus status, const hidl_vec<bool>&) {
+            EXPECT_EQ(ErrorStatus::INVALID_ARGUMENT, status);
+        });
+    EXPECT_TRUE(ret.isOk());
+}
+
+static void validatePrepareModel(const sp<IDevice>& device, const std::string& message,
+                                 const V1_1::Model& model) {
+    SCOPED_TRACE(message + " [prepareModel_1_1]");
+
+    sp<PreparedModelCallback> preparedModelCallback = new PreparedModelCallback();
+    ASSERT_NE(nullptr, preparedModelCallback.get());
+    Return<ErrorStatus> prepareLaunchStatus =
+        device->prepareModel_1_1(model, preparedModelCallback);
+    ASSERT_TRUE(prepareLaunchStatus.isOk());
+    ASSERT_EQ(ErrorStatus::INVALID_ARGUMENT, static_cast<ErrorStatus>(prepareLaunchStatus));
+
+    preparedModelCallback->wait();
+    ErrorStatus prepareReturnStatus = preparedModelCallback->getStatus();
+    ASSERT_EQ(ErrorStatus::INVALID_ARGUMENT, prepareReturnStatus);
+    sp<IPreparedModel> preparedModel = preparedModelCallback->getPreparedModel();
+    ASSERT_EQ(nullptr, preparedModel.get());
+}
+
+// Primary validation function. This function will take a valid model, apply a
+// mutation to it to invalidate the model, then pass it to interface calls that
+// use the model. Note that the model here is passed by value, and any mutation
+// to the model does not leave this function.
+static void validate(const sp<IDevice>& device, const std::string& message, V1_1::Model model,
+                     const std::function<void(Model*)>& mutation) {
+    mutation(&model);
+    validateGetSupportedOperations(device, message, model);
+    validatePrepareModel(device, message, model);
+}
+
+// Delete element from hidl_vec. hidl_vec doesn't support a "remove" operation,
+// so this is efficiently accomplished by moving the element to the end and
+// resizing the hidl_vec to one less.
+template <typename Type>
+static void hidl_vec_removeAt(hidl_vec<Type>* vec, uint32_t index) {
+    if (vec) {
+        std::rotate(vec->begin() + index, vec->begin() + index + 1, vec->end());
+        vec->resize(vec->size() - 1);
+    }
+}
+
+template <typename Type>
+static uint32_t hidl_vec_push_back(hidl_vec<Type>* vec, const Type& value) {
+    // assume vec is valid
+    const uint32_t index = vec->size();
+    vec->resize(index + 1);
+    (*vec)[index] = value;
+    return index;
+}
+
+static uint32_t addOperand(Model* model) {
+    return hidl_vec_push_back(&model->operands,
+                              {
+                                  .type = OperandType::INT32,
+                                  .dimensions = {},
+                                  .numberOfConsumers = 0,
+                                  .scale = 0.0f,
+                                  .zeroPoint = 0,
+                                  .lifetime = OperandLifeTime::MODEL_INPUT,
+                                  .location = {.poolIndex = 0, .offset = 0, .length = 0},
+                              });
+}
+
+static uint32_t addOperand(Model* model, OperandLifeTime lifetime) {
+    uint32_t index = addOperand(model);
+    model->operands[index].numberOfConsumers = 1;
+    model->operands[index].lifetime = lifetime;
+    return index;
+}
+
+///////////////////////// VALIDATE MODEL OPERAND TYPE /////////////////////////
+
+static const int32_t invalidOperandTypes[] = {
+    static_cast<int32_t>(OperandType::FLOAT32) - 1,              // lower bound fundamental
+    static_cast<int32_t>(OperandType::TENSOR_QUANT8_ASYMM) + 1,  // upper bound fundamental
+    static_cast<int32_t>(OperandType::OEM) - 1,                  // lower bound OEM
+    static_cast<int32_t>(OperandType::TENSOR_OEM_BYTE) + 1,      // upper bound OEM
+};
+
+static void mutateOperandTypeTest(const sp<IDevice>& device, const V1_1::Model& model) {
+    for (size_t operand = 0; operand < model.operands.size(); ++operand) {
+        for (int32_t invalidOperandType : invalidOperandTypes) {
+            const std::string message = "mutateOperandTypeTest: operand " +
+                                        std::to_string(operand) + " set to value " +
+                                        std::to_string(invalidOperandType);
+            validate(device, message, model, [operand, invalidOperandType](Model* model) {
+                model->operands[operand].type = static_cast<OperandType>(invalidOperandType);
+            });
+        }
+    }
+}
+
+///////////////////////// VALIDATE OPERAND RANK /////////////////////////
+
+static uint32_t getInvalidRank(OperandType type) {
+    switch (type) {
+        case OperandType::FLOAT32:
+        case OperandType::INT32:
+        case OperandType::UINT32:
+            return 1;
+        case OperandType::TENSOR_FLOAT32:
+        case OperandType::TENSOR_INT32:
+        case OperandType::TENSOR_QUANT8_ASYMM:
+            return 0;
+        default:
+            return 0;
+    }
+}
+
+static void mutateOperandRankTest(const sp<IDevice>& device, const V1_1::Model& model) {
+    for (size_t operand = 0; operand < model.operands.size(); ++operand) {
+        const uint32_t invalidRank = getInvalidRank(model.operands[operand].type);
+        const std::string message = "mutateOperandRankTest: operand " + std::to_string(operand) +
+                                    " has rank of " + std::to_string(invalidRank);
+        validate(device, message, model, [operand, invalidRank](Model* model) {
+            model->operands[operand].dimensions = std::vector<uint32_t>(invalidRank, 0);
+        });
+    }
+}
+
+///////////////////////// VALIDATE OPERAND SCALE /////////////////////////
+
+static float getInvalidScale(OperandType type) {
+    switch (type) {
+        case OperandType::FLOAT32:
+        case OperandType::INT32:
+        case OperandType::UINT32:
+        case OperandType::TENSOR_FLOAT32:
+            return 1.0f;
+        case OperandType::TENSOR_INT32:
+            return -1.0f;
+        case OperandType::TENSOR_QUANT8_ASYMM:
+            return 0.0f;
+        default:
+            return 0.0f;
+    }
+}
+
+static void mutateOperandScaleTest(const sp<IDevice>& device, const V1_1::Model& model) {
+    for (size_t operand = 0; operand < model.operands.size(); ++operand) {
+        const float invalidScale = getInvalidScale(model.operands[operand].type);
+        const std::string message = "mutateOperandScaleTest: operand " + std::to_string(operand) +
+                                    " has scale of " + std::to_string(invalidScale);
+        validate(device, message, model, [operand, invalidScale](Model* model) {
+            model->operands[operand].scale = invalidScale;
+        });
+    }
+}
+
+///////////////////////// VALIDATE OPERAND ZERO POINT /////////////////////////
+
+static std::vector<int32_t> getInvalidZeroPoints(OperandType type) {
+    switch (type) {
+        case OperandType::FLOAT32:
+        case OperandType::INT32:
+        case OperandType::UINT32:
+        case OperandType::TENSOR_FLOAT32:
+        case OperandType::TENSOR_INT32:
+            return {1};
+        case OperandType::TENSOR_QUANT8_ASYMM:
+            return {-1, 256};
+        default:
+            return {};
+    }
+}
+
+static void mutateOperandZeroPointTest(const sp<IDevice>& device, const V1_1::Model& model) {
+    for (size_t operand = 0; operand < model.operands.size(); ++operand) {
+        const std::vector<int32_t> invalidZeroPoints =
+            getInvalidZeroPoints(model.operands[operand].type);
+        for (int32_t invalidZeroPoint : invalidZeroPoints) {
+            const std::string message = "mutateOperandZeroPointTest: operand " +
+                                        std::to_string(operand) + " has zero point of " +
+                                        std::to_string(invalidZeroPoint);
+            validate(device, message, model, [operand, invalidZeroPoint](Model* model) {
+                model->operands[operand].zeroPoint = invalidZeroPoint;
+            });
+        }
+    }
+}
+
+///////////////////////// VALIDATE EXTRA ??? /////////////////////////
+
+// TODO: Operand::lifetime
+// TODO: Operand::location
+
+///////////////////////// VALIDATE OPERATION OPERAND TYPE /////////////////////////
+
+static void mutateOperand(Operand* operand, OperandType type) {
+    Operand newOperand = *operand;
+    newOperand.type = type;
+    switch (type) {
+        case OperandType::FLOAT32:
+        case OperandType::INT32:
+        case OperandType::UINT32:
+            newOperand.dimensions = hidl_vec<uint32_t>();
+            newOperand.scale = 0.0f;
+            newOperand.zeroPoint = 0;
+            break;
+        case OperandType::TENSOR_FLOAT32:
+            newOperand.dimensions =
+                operand->dimensions.size() > 0 ? operand->dimensions : hidl_vec<uint32_t>({1});
+            newOperand.scale = 0.0f;
+            newOperand.zeroPoint = 0;
+            break;
+        case OperandType::TENSOR_INT32:
+            newOperand.dimensions =
+                operand->dimensions.size() > 0 ? operand->dimensions : hidl_vec<uint32_t>({1});
+            newOperand.zeroPoint = 0;
+            break;
+        case OperandType::TENSOR_QUANT8_ASYMM:
+            newOperand.dimensions =
+                operand->dimensions.size() > 0 ? operand->dimensions : hidl_vec<uint32_t>({1});
+            newOperand.scale = operand->scale != 0.0f ? operand->scale : 1.0f;
+            break;
+        case OperandType::OEM:
+        case OperandType::TENSOR_OEM_BYTE:
+        default:
+            break;
+    }
+    *operand = newOperand;
+}
+
+static bool mutateOperationOperandTypeSkip(size_t operand, const V1_1::Model& model) {
+    // LSH_PROJECTION's second argument is allowed to have any type. This is the
+    // only operation that currently has a type that can be anything independent
+    // from any other type. Changing the operand type to any other type will
+    // result in a valid model for LSH_PROJECTION. If this is the case, skip the
+    // test.
+    for (const Operation& operation : model.operations) {
+        if (operation.type == OperationType::LSH_PROJECTION && operand == operation.inputs[1]) {
+            return true;
+        }
+    }
+    return false;
+}
+
+static void mutateOperationOperandTypeTest(const sp<IDevice>& device, const V1_1::Model& model) {
+    for (size_t operand = 0; operand < model.operands.size(); ++operand) {
+        if (mutateOperationOperandTypeSkip(operand, model)) {
+            continue;
+        }
+        for (OperandType invalidOperandType : hidl_enum_iterator<OperandType>{}) {
+            // Do not test OEM types
+            if (invalidOperandType == model.operands[operand].type ||
+                invalidOperandType == OperandType::OEM ||
+                invalidOperandType == OperandType::TENSOR_OEM_BYTE) {
+                continue;
+            }
+            const std::string message = "mutateOperationOperandTypeTest: operand " +
+                                        std::to_string(operand) + " set to type " +
+                                        toString(invalidOperandType);
+            validate(device, message, model, [operand, invalidOperandType](Model* model) {
+                mutateOperand(&model->operands[operand], invalidOperandType);
+            });
+        }
+    }
+}
+
+///////////////////////// VALIDATE MODEL OPERATION TYPE /////////////////////////
+
+static const int32_t invalidOperationTypes[] = {
+    static_cast<int32_t>(OperationType::ADD) - 1,            // lower bound fundamental
+    static_cast<int32_t>(OperationType::TRANSPOSE) + 1,      // upper bound fundamental
+    static_cast<int32_t>(OperationType::OEM_OPERATION) - 1,  // lower bound OEM
+    static_cast<int32_t>(OperationType::OEM_OPERATION) + 1,  // upper bound OEM
+};
+
+static void mutateOperationTypeTest(const sp<IDevice>& device, const V1_1::Model& model) {
+    for (size_t operation = 0; operation < model.operations.size(); ++operation) {
+        for (int32_t invalidOperationType : invalidOperationTypes) {
+            const std::string message = "mutateOperationTypeTest: operation " +
+                                        std::to_string(operation) + " set to value " +
+                                        std::to_string(invalidOperationType);
+            validate(device, message, model, [operation, invalidOperationType](Model* model) {
+                model->operations[operation].type =
+                    static_cast<OperationType>(invalidOperationType);
+            });
+        }
+    }
+}
+
+///////////////////////// VALIDATE MODEL OPERATION INPUT OPERAND INDEX /////////////////////////
+
+static void mutateOperationInputOperandIndexTest(const sp<IDevice>& device,
+                                                 const V1_1::Model& model) {
+    for (size_t operation = 0; operation < model.operations.size(); ++operation) {
+        const uint32_t invalidOperand = model.operands.size();
+        for (size_t input = 0; input < model.operations[operation].inputs.size(); ++input) {
+            const std::string message = "mutateOperationInputOperandIndexTest: operation " +
+                                        std::to_string(operation) + " input " +
+                                        std::to_string(input);
+            validate(device, message, model, [operation, input, invalidOperand](Model* model) {
+                model->operations[operation].inputs[input] = invalidOperand;
+            });
+        }
+    }
+}
+
+///////////////////////// VALIDATE MODEL OPERATION OUTPUT OPERAND INDEX /////////////////////////
+
+static void mutateOperationOutputOperandIndexTest(const sp<IDevice>& device,
+                                                  const V1_1::Model& model) {
+    for (size_t operation = 0; operation < model.operations.size(); ++operation) {
+        const uint32_t invalidOperand = model.operands.size();
+        for (size_t output = 0; output < model.operations[operation].outputs.size(); ++output) {
+            const std::string message = "mutateOperationOutputOperandIndexTest: operation " +
+                                        std::to_string(operation) + " output " +
+                                        std::to_string(output);
+            validate(device, message, model, [operation, output, invalidOperand](Model* model) {
+                model->operations[operation].outputs[output] = invalidOperand;
+            });
+        }
+    }
+}
+
+///////////////////////// REMOVE OPERAND FROM EVERYTHING /////////////////////////
+
+static void removeValueAndDecrementGreaterValues(hidl_vec<uint32_t>* vec, uint32_t value) {
+    if (vec) {
+        // remove elements matching "value"
+        auto last = std::remove(vec->begin(), vec->end(), value);
+        vec->resize(std::distance(vec->begin(), last));
+
+        // decrement elements exceeding "value"
+        std::transform(vec->begin(), vec->end(), vec->begin(),
+                       [value](uint32_t v) { return v > value ? v-- : v; });
+    }
+}
+
+static void removeOperand(Model* model, uint32_t index) {
+    hidl_vec_removeAt(&model->operands, index);
+    for (Operation& operation : model->operations) {
+        removeValueAndDecrementGreaterValues(&operation.inputs, index);
+        removeValueAndDecrementGreaterValues(&operation.outputs, index);
+    }
+    removeValueAndDecrementGreaterValues(&model->inputIndexes, index);
+    removeValueAndDecrementGreaterValues(&model->outputIndexes, index);
+}
+
+static void removeOperandTest(const sp<IDevice>& device, const V1_1::Model& model) {
+    for (size_t operand = 0; operand < model.operands.size(); ++operand) {
+        const std::string message = "removeOperandTest: operand " + std::to_string(operand);
+        validate(device, message, model,
+                 [operand](Model* model) { removeOperand(model, operand); });
+    }
+}
+
+///////////////////////// REMOVE OPERATION /////////////////////////
+
+static void removeOperation(Model* model, uint32_t index) {
+    for (uint32_t operand : model->operations[index].inputs) {
+        model->operands[operand].numberOfConsumers--;
+    }
+    hidl_vec_removeAt(&model->operations, index);
+}
+
+static void removeOperationTest(const sp<IDevice>& device, const V1_1::Model& model) {
+    for (size_t operation = 0; operation < model.operations.size(); ++operation) {
+        const std::string message = "removeOperationTest: operation " + std::to_string(operation);
+        validate(device, message, model,
+                 [operation](Model* model) { removeOperation(model, operation); });
+    }
+}
+
+///////////////////////// REMOVE OPERATION INPUT /////////////////////////
+
+static void removeOperationInputTest(const sp<IDevice>& device, const V1_1::Model& model) {
+    for (size_t operation = 0; operation < model.operations.size(); ++operation) {
+        for (size_t input = 0; input < model.operations[operation].inputs.size(); ++input) {
+            const V1_1::Operation& op = model.operations[operation];
+            // CONCATENATION has at least 2 inputs, with the last element being
+            // INT32. Skip this test if removing one of CONCATENATION's
+            // inputs still produces a valid model.
+            if (op.type == V1_1::OperationType::CONCATENATION && op.inputs.size() > 2 &&
+                input != op.inputs.size() - 1) {
+                continue;
+            }
+            const std::string message = "removeOperationInputTest: operation " +
+                                        std::to_string(operation) + ", input " +
+                                        std::to_string(input);
+            validate(device, message, model, [operation, input](Model* model) {
+                uint32_t operand = model->operations[operation].inputs[input];
+                model->operands[operand].numberOfConsumers--;
+                hidl_vec_removeAt(&model->operations[operation].inputs, input);
+            });
+        }
+    }
+}
+
+///////////////////////// REMOVE OPERATION OUTPUT /////////////////////////
+
+static void removeOperationOutputTest(const sp<IDevice>& device, const V1_1::Model& model) {
+    for (size_t operation = 0; operation < model.operations.size(); ++operation) {
+        for (size_t output = 0; output < model.operations[operation].outputs.size(); ++output) {
+            const std::string message = "removeOperationOutputTest: operation " +
+                                        std::to_string(operation) + ", output " +
+                                        std::to_string(output);
+            validate(device, message, model, [operation, output](Model* model) {
+                hidl_vec_removeAt(&model->operations[operation].outputs, output);
+            });
+        }
+    }
+}
+
+///////////////////////// MODEL VALIDATION /////////////////////////
+
+// TODO: remove model input
+// TODO: remove model output
+// TODO: add unused operation
+
+///////////////////////// ADD OPERATION INPUT /////////////////////////
+
+static void addOperationInputTest(const sp<IDevice>& device, const V1_1::Model& model) {
+    for (size_t operation = 0; operation < model.operations.size(); ++operation) {
+        const std::string message = "addOperationInputTest: operation " + std::to_string(operation);
+        validate(device, message, model, [operation](Model* model) {
+            uint32_t index = addOperand(model, OperandLifeTime::MODEL_INPUT);
+            hidl_vec_push_back(&model->operations[operation].inputs, index);
+            hidl_vec_push_back(&model->inputIndexes, index);
+        });
+    }
+}
+
+///////////////////////// ADD OPERATION OUTPUT /////////////////////////
+
+static void addOperationOutputTest(const sp<IDevice>& device, const V1_1::Model& model) {
+    for (size_t operation = 0; operation < model.operations.size(); ++operation) {
+        const std::string message =
+            "addOperationOutputTest: operation " + std::to_string(operation);
+        validate(device, message, model, [operation](Model* model) {
+            uint32_t index = addOperand(model, OperandLifeTime::MODEL_OUTPUT);
+            hidl_vec_push_back(&model->operations[operation].outputs, index);
+            hidl_vec_push_back(&model->outputIndexes, index);
+        });
+    }
+}
+
+////////////////////////// ENTRY POINT //////////////////////////////
+
+void ValidationTest::validateModel(const V1_1::Model& model) {
+    mutateOperandTypeTest(device, model);
+    mutateOperandRankTest(device, model);
+    mutateOperandScaleTest(device, model);
+    mutateOperandZeroPointTest(device, model);
+    mutateOperationOperandTypeTest(device, model);
+    mutateOperationTypeTest(device, model);
+    mutateOperationInputOperandIndexTest(device, model);
+    mutateOperationOutputOperandIndexTest(device, model);
+    removeOperandTest(device, model);
+    removeOperationTest(device, model);
+    removeOperationInputTest(device, model);
+    removeOperationOutputTest(device, model);
+    addOperationInputTest(device, model);
+    addOperationOutputTest(device, model);
+}
+
+}  // namespace functional
+}  // namespace vts
+}  // namespace V1_1
+}  // namespace neuralnetworks
+}  // namespace hardware
+}  // namespace android
diff --git a/neuralnetworks/1.1/vts/functional/ValidateRequest.cpp b/neuralnetworks/1.1/vts/functional/ValidateRequest.cpp
new file mode 100644
index 0000000..bd96614
--- /dev/null
+++ b/neuralnetworks/1.1/vts/functional/ValidateRequest.cpp
@@ -0,0 +1,262 @@
+/*
+ * Copyright (C) 2018 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#define LOG_TAG "neuralnetworks_hidl_hal_test"
+
+#include "VtsHalNeuralnetworks.h"
+
+#include "Callbacks.h"
+#include "TestHarness.h"
+#include "Utils.h"
+
+#include <android-base/logging.h>
+#include <android/hidl/memory/1.0/IMemory.h>
+#include <hidlmemory/mapping.h>
+
+namespace android {
+namespace hardware {
+namespace neuralnetworks {
+namespace V1_1 {
+namespace vts {
+namespace functional {
+
+using ::android::hardware::neuralnetworks::V1_0::implementation::ExecutionCallback;
+using ::android::hardware::neuralnetworks::V1_0::implementation::PreparedModelCallback;
+using ::android::hidl::memory::V1_0::IMemory;
+using generated_tests::MixedTyped;
+using generated_tests::MixedTypedExampleType;
+using generated_tests::for_all;
+
+///////////////////////// UTILITY FUNCTIONS /////////////////////////
+
+static void createPreparedModel(const sp<IDevice>& device, const V1_1::Model& model,
+                                sp<IPreparedModel>* preparedModel) {
+    ASSERT_NE(nullptr, preparedModel);
+
+    // see if service can handle model
+    bool fullySupportsModel = false;
+    Return<void> supportedOpsLaunchStatus = device->getSupportedOperations_1_1(
+        model, [&fullySupportsModel](ErrorStatus status, const hidl_vec<bool>& supported) {
+            ASSERT_EQ(ErrorStatus::NONE, status);
+            ASSERT_NE(0ul, supported.size());
+            fullySupportsModel =
+                std::all_of(supported.begin(), supported.end(), [](bool valid) { return valid; });
+        });
+    ASSERT_TRUE(supportedOpsLaunchStatus.isOk());
+
+    // launch prepare model
+    sp<PreparedModelCallback> preparedModelCallback = new PreparedModelCallback();
+    ASSERT_NE(nullptr, preparedModelCallback.get());
+    Return<ErrorStatus> prepareLaunchStatus =
+        device->prepareModel_1_1(model, preparedModelCallback);
+    ASSERT_TRUE(prepareLaunchStatus.isOk());
+    ASSERT_EQ(ErrorStatus::NONE, static_cast<ErrorStatus>(prepareLaunchStatus));
+
+    // retrieve prepared model
+    preparedModelCallback->wait();
+    ErrorStatus prepareReturnStatus = preparedModelCallback->getStatus();
+    *preparedModel = preparedModelCallback->getPreparedModel();
+
+    // The getSupportedOperations_1_1 call returns a list of operations that are
+    // guaranteed not to fail if prepareModel_1_1 is called, and
+    // 'fullySupportsModel' is true i.f.f. the entire model is guaranteed.
+    // If a driver has any doubt that it can prepare an operation, it must
+    // return false. So here, if a driver isn't sure if it can support an
+    // operation, but reports that it successfully prepared the model, the test
+    // can continue.
+    if (!fullySupportsModel && prepareReturnStatus != ErrorStatus::NONE) {
+        ASSERT_EQ(nullptr, preparedModel->get());
+        LOG(INFO) << "NN VTS: Unable to test Request validation because vendor service cannot "
+                     "prepare model that it does not support.";
+        std::cout << "[          ]   Unable to test Request validation because vendor service "
+                     "cannot prepare model that it does not support."
+                  << std::endl;
+        return;
+    }
+    ASSERT_EQ(ErrorStatus::NONE, prepareReturnStatus);
+    ASSERT_NE(nullptr, preparedModel->get());
+}
+
+// Primary validation function. This function will take a valid request, apply a
+// mutation to it to invalidate the request, then pass it to interface calls
+// that use the request. Note that the request here is passed by value, and any
+// mutation to the request does not leave this function.
+static void validate(const sp<IPreparedModel>& preparedModel, const std::string& message,
+                     Request request, const std::function<void(Request*)>& mutation) {
+    mutation(&request);
+    SCOPED_TRACE(message + " [execute]");
+
+    sp<ExecutionCallback> executionCallback = new ExecutionCallback();
+    ASSERT_NE(nullptr, executionCallback.get());
+    Return<ErrorStatus> executeLaunchStatus = preparedModel->execute(request, executionCallback);
+    ASSERT_TRUE(executeLaunchStatus.isOk());
+    ASSERT_EQ(ErrorStatus::INVALID_ARGUMENT, static_cast<ErrorStatus>(executeLaunchStatus));
+
+    executionCallback->wait();
+    ErrorStatus executionReturnStatus = executionCallback->getStatus();
+    ASSERT_EQ(ErrorStatus::INVALID_ARGUMENT, executionReturnStatus);
+}
+
+// Delete element from hidl_vec. hidl_vec doesn't support a "remove" operation,
+// so this is efficiently accomplished by moving the element to the end and
+// resizing the hidl_vec to one less.
+template <typename Type>
+static void hidl_vec_removeAt(hidl_vec<Type>* vec, uint32_t index) {
+    if (vec) {
+        std::rotate(vec->begin() + index, vec->begin() + index + 1, vec->end());
+        vec->resize(vec->size() - 1);
+    }
+}
+
+template <typename Type>
+static uint32_t hidl_vec_push_back(hidl_vec<Type>* vec, const Type& value) {
+    // assume vec is valid
+    const uint32_t index = vec->size();
+    vec->resize(index + 1);
+    (*vec)[index] = value;
+    return index;
+}
+
+///////////////////////// REMOVE INPUT ////////////////////////////////////
+
+static void removeInputTest(const sp<IPreparedModel>& preparedModel, const Request& request) {
+    for (size_t input = 0; input < request.inputs.size(); ++input) {
+        const std::string message = "removeInput: removed input " + std::to_string(input);
+        validate(preparedModel, message, request,
+                 [input](Request* request) { hidl_vec_removeAt(&request->inputs, input); });
+    }
+}
+
+///////////////////////// REMOVE OUTPUT ////////////////////////////////////
+
+static void removeOutputTest(const sp<IPreparedModel>& preparedModel, const Request& request) {
+    for (size_t output = 0; output < request.outputs.size(); ++output) {
+        const std::string message = "removeOutput: removed Output " + std::to_string(output);
+        validate(preparedModel, message, request,
+                 [output](Request* request) { hidl_vec_removeAt(&request->outputs, output); });
+    }
+}
+
+///////////////////////////// ENTRY POINT //////////////////////////////////
+
+std::vector<Request> createRequests(const std::vector<MixedTypedExampleType>& examples) {
+    const uint32_t INPUT = 0;
+    const uint32_t OUTPUT = 1;
+
+    std::vector<Request> requests;
+
+    for (auto& example : examples) {
+        const MixedTyped& inputs = example.first;
+        const MixedTyped& outputs = example.second;
+
+        std::vector<RequestArgument> inputs_info, outputs_info;
+        uint32_t inputSize = 0, outputSize = 0;
+
+        // This function only partially specifies the metadata (vector of RequestArguments).
+        // The contents are copied over below.
+        for_all(inputs, [&inputs_info, &inputSize](int index, auto, auto s) {
+            if (inputs_info.size() <= static_cast<size_t>(index)) inputs_info.resize(index + 1);
+            RequestArgument arg = {
+                .location = {.poolIndex = INPUT, .offset = 0, .length = static_cast<uint32_t>(s)},
+                .dimensions = {},
+            };
+            RequestArgument arg_empty = {
+                .hasNoValue = true,
+            };
+            inputs_info[index] = s ? arg : arg_empty;
+            inputSize += s;
+        });
+        // Compute offset for inputs 1 and so on
+        {
+            size_t offset = 0;
+            for (auto& i : inputs_info) {
+                if (!i.hasNoValue) i.location.offset = offset;
+                offset += i.location.length;
+            }
+        }
+
+        // Go through all outputs, initialize RequestArgument descriptors
+        for_all(outputs, [&outputs_info, &outputSize](int index, auto, auto s) {
+            if (outputs_info.size() <= static_cast<size_t>(index)) outputs_info.resize(index + 1);
+            RequestArgument arg = {
+                .location = {.poolIndex = OUTPUT, .offset = 0, .length = static_cast<uint32_t>(s)},
+                .dimensions = {},
+            };
+            outputs_info[index] = arg;
+            outputSize += s;
+        });
+        // Compute offset for outputs 1 and so on
+        {
+            size_t offset = 0;
+            for (auto& i : outputs_info) {
+                i.location.offset = offset;
+                offset += i.location.length;
+            }
+        }
+        std::vector<hidl_memory> pools = {nn::allocateSharedMemory(inputSize),
+                                          nn::allocateSharedMemory(outputSize)};
+        if (pools[INPUT].size() == 0 || pools[OUTPUT].size() == 0) {
+            return {};
+        }
+
+        // map pool
+        sp<IMemory> inputMemory = mapMemory(pools[INPUT]);
+        if (inputMemory == nullptr) {
+            return {};
+        }
+        char* inputPtr = reinterpret_cast<char*>(static_cast<void*>(inputMemory->getPointer()));
+        if (inputPtr == nullptr) {
+            return {};
+        }
+
+        // initialize pool
+        inputMemory->update();
+        for_all(inputs, [&inputs_info, inputPtr](int index, auto p, auto s) {
+            char* begin = (char*)p;
+            char* end = begin + s;
+            // TODO: handle more than one input
+            std::copy(begin, end, inputPtr + inputs_info[index].location.offset);
+        });
+        inputMemory->commit();
+
+        requests.push_back({.inputs = inputs_info, .outputs = outputs_info, .pools = pools});
+    }
+
+    return requests;
+}
+
+void ValidationTest::validateRequests(const V1_1::Model& model,
+                                      const std::vector<Request>& requests) {
+    // create IPreparedModel
+    sp<IPreparedModel> preparedModel;
+    ASSERT_NO_FATAL_FAILURE(createPreparedModel(device, model, &preparedModel));
+    if (preparedModel == nullptr) {
+        return;
+    }
+
+    // validate each request
+    for (const Request& request : requests) {
+        removeInputTest(preparedModel, request);
+        removeOutputTest(preparedModel, request);
+    }
+}
+
+}  // namespace functional
+}  // namespace vts
+}  // namespace V1_1
+}  // namespace neuralnetworks
+}  // namespace hardware
+}  // namespace android
diff --git a/neuralnetworks/1.1/vts/functional/ValidationTests.cpp b/neuralnetworks/1.1/vts/functional/ValidationTests.cpp
new file mode 100644
index 0000000..1c35ba8
--- /dev/null
+++ b/neuralnetworks/1.1/vts/functional/ValidationTests.cpp
@@ -0,0 +1,50 @@
+/*
+ * Copyright (C) 2018 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#define LOG_TAG "neuralnetworks_hidl_hal_test"
+
+#include "Models.h"
+#include "VtsHalNeuralnetworks.h"
+
+namespace android {
+namespace hardware {
+namespace neuralnetworks {
+namespace V1_1 {
+namespace vts {
+namespace functional {
+
+// forward declarations
+std::vector<Request> createRequests(const std::vector<MixedTypedExample>& examples);
+
+// generate validation tests
+#define VTS_CURRENT_TEST_CASE(TestName)                                           \
+    TEST_F(ValidationTest, TestName) {                                            \
+        const Model model = TestName::createTestModel();                          \
+        const std::vector<Request> requests = createRequests(TestName::examples); \
+        validateModel(model);                                                     \
+        validateRequests(model, requests);                                        \
+    }
+
+FOR_EACH_TEST_MODEL(VTS_CURRENT_TEST_CASE)
+
+#undef VTS_CURRENT_TEST_CASE
+
+}  // namespace functional
+}  // namespace vts
+}  // namespace V1_1
+}  // namespace neuralnetworks
+}  // namespace hardware
+}  // namespace android
diff --git a/neuralnetworks/1.1/vts/functional/VtsHalNeuralnetworksV1_1.cpp b/neuralnetworks/1.1/vts/functional/VtsHalNeuralnetworks.cpp
similarity index 64%
rename from neuralnetworks/1.1/vts/functional/VtsHalNeuralnetworksV1_1.cpp
rename to neuralnetworks/1.1/vts/functional/VtsHalNeuralnetworks.cpp
index b1d3be7..62381e6 100644
--- a/neuralnetworks/1.1/vts/functional/VtsHalNeuralnetworksV1_1.cpp
+++ b/neuralnetworks/1.1/vts/functional/VtsHalNeuralnetworks.cpp
@@ -16,16 +16,7 @@
 
 #define LOG_TAG "neuralnetworks_hidl_hal_test"
 
-#include "VtsHalNeuralnetworksV1_1.h"
-#include "Utils.h"
-
-#include <android-base/logging.h>
-#include <hidlmemory/mapping.h>
-
-using ::android::hardware::hidl_memory;
-using ::android::hidl::allocator::V1_0::IAllocator;
-using ::android::hidl::memory::V1_0::IMemory;
-using ::android::sp;
+#include "VtsHalNeuralnetworks.h"
 
 namespace android {
 namespace hardware {
@@ -34,11 +25,6 @@
 namespace vts {
 namespace functional {
 
-// allocator helper
-hidl_memory allocateSharedMemory(int64_t size) {
-    return nn::allocateSharedMemory(size);
-}
-
 // A class for test environment setup
 NeuralnetworksHidlEnvironment::NeuralnetworksHidlEnvironment() {}
 
@@ -52,23 +38,49 @@
 }
 
 void NeuralnetworksHidlEnvironment::registerTestServices() {
-    registerTestService<V1_1::IDevice>();
+    registerTestService<IDevice>();
 }
 
 // The main test class for NEURALNETWORK HIDL HAL.
+NeuralnetworksHidlTest::NeuralnetworksHidlTest() {}
+
 NeuralnetworksHidlTest::~NeuralnetworksHidlTest() {}
 
 void NeuralnetworksHidlTest::SetUp() {
-    device = ::testing::VtsHalHidlTargetTestBase::getService<V1_1::IDevice>(
+    ::testing::VtsHalHidlTargetTestBase::SetUp();
+    device = ::testing::VtsHalHidlTargetTestBase::getService<IDevice>(
         NeuralnetworksHidlEnvironment::getInstance());
     ASSERT_NE(nullptr, device.get());
 }
 
-void NeuralnetworksHidlTest::TearDown() {}
+void NeuralnetworksHidlTest::TearDown() {
+    device = nullptr;
+    ::testing::VtsHalHidlTargetTestBase::TearDown();
+}
 
 }  // namespace functional
 }  // namespace vts
+
+::std::ostream& operator<<(::std::ostream& os, ErrorStatus errorStatus) {
+    return os << toString(errorStatus);
+}
+
+::std::ostream& operator<<(::std::ostream& os, DeviceStatus deviceStatus) {
+    return os << toString(deviceStatus);
+}
+
 }  // namespace V1_1
 }  // namespace neuralnetworks
 }  // namespace hardware
 }  // namespace android
+
+using android::hardware::neuralnetworks::V1_1::vts::functional::NeuralnetworksHidlEnvironment;
+
+int main(int argc, char** argv) {
+    ::testing::AddGlobalTestEnvironment(NeuralnetworksHidlEnvironment::getInstance());
+    ::testing::InitGoogleTest(&argc, argv);
+    NeuralnetworksHidlEnvironment::getInstance()->init(&argc, argv);
+
+    int status = RUN_ALL_TESTS();
+    return status;
+}
diff --git a/neuralnetworks/1.1/vts/functional/VtsHalNeuralnetworksV1_1.h b/neuralnetworks/1.1/vts/functional/VtsHalNeuralnetworks.h
similarity index 60%
rename from neuralnetworks/1.1/vts/functional/VtsHalNeuralnetworksV1_1.h
rename to neuralnetworks/1.1/vts/functional/VtsHalNeuralnetworks.h
index 426246c..0050e52 100644
--- a/neuralnetworks/1.1/vts/functional/VtsHalNeuralnetworksV1_1.h
+++ b/neuralnetworks/1.1/vts/functional/VtsHalNeuralnetworks.h
@@ -17,65 +17,71 @@
 #ifndef VTS_HAL_NEURALNETWORKS_V1_1_H
 #define VTS_HAL_NEURALNETWORKS_V1_1_H
 
-#include <android/hardware/neuralnetworks/1.0/IExecutionCallback.h>
-#include <android/hardware/neuralnetworks/1.0/IPreparedModel.h>
-#include <android/hardware/neuralnetworks/1.0/IPreparedModelCallback.h>
+#include <android/hardware/neuralnetworks/1.0/types.h>
 #include <android/hardware/neuralnetworks/1.1/IDevice.h>
 #include <android/hardware/neuralnetworks/1.1/types.h>
-#include <android/hidl/allocator/1.0/IAllocator.h>
 
 #include <VtsHalHidlTargetTestBase.h>
 #include <VtsHalHidlTargetTestEnvBase.h>
+
+#include <android-base/macros.h>
 #include <gtest/gtest.h>
-#include <string>
+#include <iostream>
+#include <vector>
 
 namespace android {
 namespace hardware {
 namespace neuralnetworks {
 namespace V1_1 {
+
+using V1_0::Request;
+using V1_0::DeviceStatus;
+using V1_0::ErrorStatus;
+
 namespace vts {
 namespace functional {
-hidl_memory allocateSharedMemory(int64_t size);
 
 // A class for test environment setup
 class NeuralnetworksHidlEnvironment : public ::testing::VtsHalHidlTargetTestEnvBase {
+    DISALLOW_COPY_AND_ASSIGN(NeuralnetworksHidlEnvironment);
     NeuralnetworksHidlEnvironment();
-    NeuralnetworksHidlEnvironment(const NeuralnetworksHidlEnvironment&) = delete;
-    NeuralnetworksHidlEnvironment(NeuralnetworksHidlEnvironment&&) = delete;
-    NeuralnetworksHidlEnvironment& operator=(const NeuralnetworksHidlEnvironment&) = delete;
-    NeuralnetworksHidlEnvironment& operator=(NeuralnetworksHidlEnvironment&&) = delete;
+    ~NeuralnetworksHidlEnvironment() override;
 
    public:
-    ~NeuralnetworksHidlEnvironment() override;
     static NeuralnetworksHidlEnvironment* getInstance();
     void registerTestServices() override;
 };
 
 // The main test class for NEURALNETWORKS HIDL HAL.
 class NeuralnetworksHidlTest : public ::testing::VtsHalHidlTargetTestBase {
+    DISALLOW_COPY_AND_ASSIGN(NeuralnetworksHidlTest);
+
    public:
+    NeuralnetworksHidlTest();
     ~NeuralnetworksHidlTest() override;
     void SetUp() override;
     void TearDown() override;
 
-    sp<V1_1::IDevice> device;
+   protected:
+    sp<IDevice> device;
 };
+
+// Tag for the validation tests
+class ValidationTest : public NeuralnetworksHidlTest {
+   protected:
+    void validateModel(const Model& model);
+    void validateRequests(const Model& model, const std::vector<Request>& request);
+};
+
+// Tag for the generated tests
+class GeneratedTest : public NeuralnetworksHidlTest {};
+
 }  // namespace functional
 }  // namespace vts
 
 // pretty-print values for error messages
-
-template <typename CharT, typename Traits>
-::std::basic_ostream<CharT, Traits>& operator<<(::std::basic_ostream<CharT, Traits>& os,
-                                                V1_0::ErrorStatus errorStatus) {
-    return os << toString(errorStatus);
-}
-
-template <typename CharT, typename Traits>
-::std::basic_ostream<CharT, Traits>& operator<<(::std::basic_ostream<CharT, Traits>& os,
-                                                V1_0::DeviceStatus deviceStatus) {
-    return os << toString(deviceStatus);
-}
+::std::ostream& operator<<(::std::ostream& os, ErrorStatus errorStatus);
+::std::ostream& operator<<(::std::ostream& os, DeviceStatus deviceStatus);
 
 }  // namespace V1_1
 }  // namespace neuralnetworks
diff --git a/neuralnetworks/1.1/vts/functional/VtsHalNeuralnetworksV1_1BasicTest.cpp b/neuralnetworks/1.1/vts/functional/VtsHalNeuralnetworksV1_1BasicTest.cpp
deleted file mode 100644
index 10591dc..0000000
--- a/neuralnetworks/1.1/vts/functional/VtsHalNeuralnetworksV1_1BasicTest.cpp
+++ /dev/null
@@ -1,468 +0,0 @@
-/*
- * Copyright (C) 2018 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-#define LOG_TAG "neuralnetworks_hidl_hal_test"
-
-#include "VtsHalNeuralnetworksV1_1.h"
-
-#include "Callbacks.h"
-#include "Models.h"
-#include "TestHarness.h"
-
-#include <android-base/logging.h>
-#include <android/hardware/neuralnetworks/1.1/IDevice.h>
-#include <android/hardware/neuralnetworks/1.1/types.h>
-#include <android/hidl/memory/1.0/IMemory.h>
-#include <hidlmemory/mapping.h>
-
-using ::android::hardware::neuralnetworks::V1_0::IPreparedModel;
-using ::android::hardware::neuralnetworks::V1_0::DeviceStatus;
-using ::android::hardware::neuralnetworks::V1_0::ErrorStatus;
-using ::android::hardware::neuralnetworks::V1_0::FusedActivationFunc;
-using ::android::hardware::neuralnetworks::V1_0::Operand;
-using ::android::hardware::neuralnetworks::V1_0::OperandLifeTime;
-using ::android::hardware::neuralnetworks::V1_0::OperandType;
-using ::android::hardware::neuralnetworks::V1_0::Request;
-using ::android::hardware::neuralnetworks::V1_1::Capabilities;
-using ::android::hardware::neuralnetworks::V1_1::IDevice;
-using ::android::hardware::neuralnetworks::V1_1::Model;
-using ::android::hardware::neuralnetworks::V1_1::Operation;
-using ::android::hardware::neuralnetworks::V1_1::OperationType;
-using ::android::hardware::Return;
-using ::android::hardware::Void;
-using ::android::hardware::hidl_memory;
-using ::android::hardware::hidl_string;
-using ::android::hardware::hidl_vec;
-using ::android::hidl::allocator::V1_0::IAllocator;
-using ::android::hidl::memory::V1_0::IMemory;
-using ::android::sp;
-
-namespace android {
-namespace hardware {
-namespace neuralnetworks {
-namespace V1_1 {
-namespace vts {
-namespace functional {
-using ::android::hardware::neuralnetworks::V1_0::implementation::ExecutionCallback;
-using ::android::hardware::neuralnetworks::V1_0::implementation::PreparedModelCallback;
-
-static void doPrepareModelShortcut(const sp<IDevice>& device, sp<IPreparedModel>* preparedModel) {
-    ASSERT_NE(nullptr, preparedModel);
-    Model model = createValidTestModel_1_1();
-
-    // see if service can handle model
-    bool fullySupportsModel = false;
-    Return<void> supportedOpsLaunchStatus = device->getSupportedOperations_1_1(
-        model, [&fullySupportsModel](ErrorStatus status, const hidl_vec<bool>& supported) {
-            ASSERT_EQ(ErrorStatus::NONE, status);
-            ASSERT_NE(0ul, supported.size());
-            fullySupportsModel =
-                std::all_of(supported.begin(), supported.end(), [](bool valid) { return valid; });
-        });
-    ASSERT_TRUE(supportedOpsLaunchStatus.isOk());
-
-    // launch prepare model
-    sp<PreparedModelCallback> preparedModelCallback = new PreparedModelCallback();
-    ASSERT_NE(nullptr, preparedModelCallback.get());
-    Return<ErrorStatus> prepareLaunchStatus =
-        device->prepareModel_1_1(model, preparedModelCallback);
-    ASSERT_TRUE(prepareLaunchStatus.isOk());
-    ASSERT_EQ(ErrorStatus::NONE, static_cast<ErrorStatus>(prepareLaunchStatus));
-
-    // retrieve prepared model
-    preparedModelCallback->wait();
-    ErrorStatus prepareReturnStatus = preparedModelCallback->getStatus();
-    *preparedModel = preparedModelCallback->getPreparedModel();
-
-    // The getSupportedOperations call returns a list of operations that are
-    // guaranteed not to fail if prepareModel is called, and
-    // 'fullySupportsModel' is true i.f.f. the entire model is guaranteed.
-    // If a driver has any doubt that it can prepare an operation, it must
-    // return false. So here, if a driver isn't sure if it can support an
-    // operation, but reports that it successfully prepared the model, the test
-    // can continue.
-    if (!fullySupportsModel && prepareReturnStatus != ErrorStatus::NONE) {
-        ASSERT_EQ(nullptr, preparedModel->get());
-        LOG(INFO) << "NN VTS: Early termination of test because vendor service cannot "
-                     "prepare model that it does not support.";
-        std::cout << "[          ]   Early termination of test because vendor service cannot "
-                     "prepare model that it does not support."
-                  << std::endl;
-        return;
-    }
-    ASSERT_EQ(ErrorStatus::NONE, prepareReturnStatus);
-    ASSERT_NE(nullptr, preparedModel->get());
-}
-
-// create device test
-TEST_F(NeuralnetworksHidlTest, CreateDevice) {}
-
-// status test
-TEST_F(NeuralnetworksHidlTest, StatusTest) {
-    Return<DeviceStatus> status = device->getStatus();
-    ASSERT_TRUE(status.isOk());
-    EXPECT_EQ(DeviceStatus::AVAILABLE, static_cast<DeviceStatus>(status));
-}
-
-// initialization
-TEST_F(NeuralnetworksHidlTest, GetCapabilitiesTest) {
-    Return<void> ret =
-        device->getCapabilities_1_1([](ErrorStatus status, const Capabilities& capabilities) {
-            EXPECT_EQ(ErrorStatus::NONE, status);
-            EXPECT_LT(0.0f, capabilities.float32Performance.execTime);
-            EXPECT_LT(0.0f, capabilities.float32Performance.powerUsage);
-            EXPECT_LT(0.0f, capabilities.quantized8Performance.execTime);
-            EXPECT_LT(0.0f, capabilities.quantized8Performance.powerUsage);
-            EXPECT_LT(0.0f, capabilities.relaxedFloat32toFloat16Performance.execTime);
-            EXPECT_LT(0.0f, capabilities.relaxedFloat32toFloat16Performance.powerUsage);
-        });
-    EXPECT_TRUE(ret.isOk());
-}
-
-// supported operations positive test
-TEST_F(NeuralnetworksHidlTest, SupportedOperationsPositiveTest) {
-    Model model = createValidTestModel_1_1();
-    Return<void> ret = device->getSupportedOperations_1_1(
-        model, [&](ErrorStatus status, const hidl_vec<bool>& supported) {
-            EXPECT_EQ(ErrorStatus::NONE, status);
-            EXPECT_EQ(model.operations.size(), supported.size());
-        });
-    EXPECT_TRUE(ret.isOk());
-}
-
-// supported operations negative test 1
-TEST_F(NeuralnetworksHidlTest, SupportedOperationsNegativeTest1) {
-    Model model = createInvalidTestModel1_1_1();
-    Return<void> ret = device->getSupportedOperations_1_1(
-        model, [&](ErrorStatus status, const hidl_vec<bool>& supported) {
-            EXPECT_EQ(ErrorStatus::INVALID_ARGUMENT, status);
-            (void)supported;
-        });
-    EXPECT_TRUE(ret.isOk());
-}
-
-// supported operations negative test 2
-TEST_F(NeuralnetworksHidlTest, SupportedOperationsNegativeTest2) {
-    Model model = createInvalidTestModel2_1_1();
-    Return<void> ret = device->getSupportedOperations_1_1(
-        model, [&](ErrorStatus status, const hidl_vec<bool>& supported) {
-            EXPECT_EQ(ErrorStatus::INVALID_ARGUMENT, status);
-            (void)supported;
-        });
-    EXPECT_TRUE(ret.isOk());
-}
-
-// prepare simple model positive test
-TEST_F(NeuralnetworksHidlTest, SimplePrepareModelPositiveTest) {
-    sp<IPreparedModel> preparedModel;
-    doPrepareModelShortcut(device, &preparedModel);
-}
-
-// prepare simple model negative test 1
-TEST_F(NeuralnetworksHidlTest, SimplePrepareModelNegativeTest1) {
-    Model model = createInvalidTestModel1_1_1();
-    sp<PreparedModelCallback> preparedModelCallback = new PreparedModelCallback();
-    ASSERT_NE(nullptr, preparedModelCallback.get());
-    Return<ErrorStatus> prepareLaunchStatus =
-        device->prepareModel_1_1(model, preparedModelCallback);
-    ASSERT_TRUE(prepareLaunchStatus.isOk());
-    EXPECT_EQ(ErrorStatus::INVALID_ARGUMENT, static_cast<ErrorStatus>(prepareLaunchStatus));
-
-    preparedModelCallback->wait();
-    ErrorStatus prepareReturnStatus = preparedModelCallback->getStatus();
-    EXPECT_EQ(ErrorStatus::INVALID_ARGUMENT, prepareReturnStatus);
-    sp<IPreparedModel> preparedModel = preparedModelCallback->getPreparedModel();
-    EXPECT_EQ(nullptr, preparedModel.get());
-}
-
-// prepare simple model negative test 2
-TEST_F(NeuralnetworksHidlTest, SimplePrepareModelNegativeTest2) {
-    Model model = createInvalidTestModel2_1_1();
-    sp<PreparedModelCallback> preparedModelCallback = new PreparedModelCallback();
-    ASSERT_NE(nullptr, preparedModelCallback.get());
-    Return<ErrorStatus> prepareLaunchStatus =
-        device->prepareModel_1_1(model, preparedModelCallback);
-    ASSERT_TRUE(prepareLaunchStatus.isOk());
-    EXPECT_EQ(ErrorStatus::INVALID_ARGUMENT, static_cast<ErrorStatus>(prepareLaunchStatus));
-
-    preparedModelCallback->wait();
-    ErrorStatus prepareReturnStatus = preparedModelCallback->getStatus();
-    EXPECT_EQ(ErrorStatus::INVALID_ARGUMENT, prepareReturnStatus);
-    sp<IPreparedModel> preparedModel = preparedModelCallback->getPreparedModel();
-    EXPECT_EQ(nullptr, preparedModel.get());
-}
-
-// execute simple graph positive test
-TEST_F(NeuralnetworksHidlTest, SimpleExecuteGraphPositiveTest) {
-    std::vector<float> outputData = {-1.0f, -1.0f, -1.0f, -1.0f};
-    std::vector<float> expectedData = {6.0f, 8.0f, 10.0f, 12.0f};
-    const uint32_t OUTPUT = 1;
-
-    sp<IPreparedModel> preparedModel;
-    ASSERT_NO_FATAL_FAILURE(doPrepareModelShortcut(device, &preparedModel));
-    if (preparedModel == nullptr) {
-        return;
-    }
-    Request request = createValidTestRequest();
-
-    auto postWork = [&] {
-        sp<IMemory> outputMemory = mapMemory(request.pools[OUTPUT]);
-        if (outputMemory == nullptr) {
-            return false;
-        }
-        float* outputPtr = reinterpret_cast<float*>(static_cast<void*>(outputMemory->getPointer()));
-        if (outputPtr == nullptr) {
-            return false;
-        }
-        outputMemory->read();
-        std::copy(outputPtr, outputPtr + outputData.size(), outputData.begin());
-        outputMemory->commit();
-        return true;
-    };
-
-    sp<ExecutionCallback> executionCallback = new ExecutionCallback();
-    ASSERT_NE(nullptr, executionCallback.get());
-    executionCallback->on_finish(postWork);
-    Return<ErrorStatus> executeLaunchStatus = preparedModel->execute(request, executionCallback);
-    ASSERT_TRUE(executeLaunchStatus.isOk());
-    EXPECT_EQ(ErrorStatus::NONE, static_cast<ErrorStatus>(executeLaunchStatus));
-
-    executionCallback->wait();
-    ErrorStatus executionReturnStatus = executionCallback->getStatus();
-    EXPECT_EQ(ErrorStatus::NONE, executionReturnStatus);
-    EXPECT_EQ(expectedData, outputData);
-}
-
-// execute simple graph negative test 1
-TEST_F(NeuralnetworksHidlTest, SimpleExecuteGraphNegativeTest1) {
-    sp<IPreparedModel> preparedModel;
-    ASSERT_NO_FATAL_FAILURE(doPrepareModelShortcut(device, &preparedModel));
-    if (preparedModel == nullptr) {
-        return;
-    }
-    Request request = createInvalidTestRequest1();
-
-    sp<ExecutionCallback> executionCallback = new ExecutionCallback();
-    ASSERT_NE(nullptr, executionCallback.get());
-    Return<ErrorStatus> executeLaunchStatus = preparedModel->execute(request, executionCallback);
-    ASSERT_TRUE(executeLaunchStatus.isOk());
-    EXPECT_EQ(ErrorStatus::INVALID_ARGUMENT, static_cast<ErrorStatus>(executeLaunchStatus));
-
-    executionCallback->wait();
-    ErrorStatus executionReturnStatus = executionCallback->getStatus();
-    EXPECT_EQ(ErrorStatus::INVALID_ARGUMENT, executionReturnStatus);
-}
-
-// execute simple graph negative test 2
-TEST_F(NeuralnetworksHidlTest, SimpleExecuteGraphNegativeTest2) {
-    sp<IPreparedModel> preparedModel;
-    ASSERT_NO_FATAL_FAILURE(doPrepareModelShortcut(device, &preparedModel));
-    if (preparedModel == nullptr) {
-        return;
-    }
-    Request request = createInvalidTestRequest2();
-
-    sp<ExecutionCallback> executionCallback = new ExecutionCallback();
-    ASSERT_NE(nullptr, executionCallback.get());
-    Return<ErrorStatus> executeLaunchStatus = preparedModel->execute(request, executionCallback);
-    ASSERT_TRUE(executeLaunchStatus.isOk());
-    EXPECT_EQ(ErrorStatus::INVALID_ARGUMENT, static_cast<ErrorStatus>(executeLaunchStatus));
-
-    executionCallback->wait();
-    ErrorStatus executionReturnStatus = executionCallback->getStatus();
-    EXPECT_EQ(ErrorStatus::INVALID_ARGUMENT, executionReturnStatus);
-}
-
-class NeuralnetworksInputsOutputsTest
-    : public NeuralnetworksHidlTest,
-      public ::testing::WithParamInterface<std::tuple<bool, bool>> {
-   protected:
-    virtual void SetUp() { NeuralnetworksHidlTest::SetUp(); }
-    virtual void TearDown() { NeuralnetworksHidlTest::TearDown(); }
-    V1_1::Model createModel(const std::vector<uint32_t>& inputs,
-                            const std::vector<uint32_t>& outputs) {
-        // We set up the operands as floating-point with no designated
-        // model inputs and outputs, and then patch type and lifetime
-        // later on in this function.
-
-        std::vector<Operand> operands = {
-            {
-                .type = OperandType::TENSOR_FLOAT32,
-                .dimensions = {1},
-                .numberOfConsumers = 1,
-                .scale = 0.0f,
-                .zeroPoint = 0,
-                .lifetime = OperandLifeTime::TEMPORARY_VARIABLE,
-                .location = {.poolIndex = 0, .offset = 0, .length = 0},
-            },
-            {
-                .type = OperandType::TENSOR_FLOAT32,
-                .dimensions = {1},
-                .numberOfConsumers = 1,
-                .scale = 0.0f,
-                .zeroPoint = 0,
-                .lifetime = OperandLifeTime::TEMPORARY_VARIABLE,
-                .location = {.poolIndex = 0, .offset = 0, .length = 0},
-            },
-            {
-                .type = OperandType::INT32,
-                .dimensions = {},
-                .numberOfConsumers = 1,
-                .scale = 0.0f,
-                .zeroPoint = 0,
-                .lifetime = OperandLifeTime::CONSTANT_COPY,
-                .location = {.poolIndex = 0, .offset = 0, .length = sizeof(int32_t)},
-            },
-            {
-                .type = OperandType::TENSOR_FLOAT32,
-                .dimensions = {1},
-                .numberOfConsumers = 0,
-                .scale = 0.0f,
-                .zeroPoint = 0,
-                .lifetime = OperandLifeTime::TEMPORARY_VARIABLE,
-                .location = {.poolIndex = 0, .offset = 0, .length = 0},
-            },
-        };
-
-        const std::vector<Operation> operations = {{
-            .type = OperationType::ADD, .inputs = {0, 1, 2}, .outputs = {3},
-        }};
-
-        std::vector<uint8_t> operandValues;
-        int32_t activation[1] = {static_cast<int32_t>(FusedActivationFunc::NONE)};
-        operandValues.insert(operandValues.end(), reinterpret_cast<const uint8_t*>(&activation[0]),
-                             reinterpret_cast<const uint8_t*>(&activation[1]));
-
-        if (kQuantized) {
-            for (auto& operand : operands) {
-                if (operand.type == OperandType::TENSOR_FLOAT32) {
-                    operand.type = OperandType::TENSOR_QUANT8_ASYMM;
-                    operand.scale = 1.0f;
-                    operand.zeroPoint = 0;
-                }
-            }
-        }
-
-        auto patchLifetime = [&operands](const std::vector<uint32_t>& operandIndexes,
-                                         OperandLifeTime lifetime) {
-            for (uint32_t index : operandIndexes) {
-                operands[index].lifetime = lifetime;
-            }
-        };
-        if (kInputHasPrecedence) {
-            patchLifetime(outputs, OperandLifeTime::MODEL_OUTPUT);
-            patchLifetime(inputs, OperandLifeTime::MODEL_INPUT);
-        } else {
-            patchLifetime(inputs, OperandLifeTime::MODEL_INPUT);
-            patchLifetime(outputs, OperandLifeTime::MODEL_OUTPUT);
-        }
-
-        return {
-            .operands = operands,
-            .operations = operations,
-            .inputIndexes = inputs,
-            .outputIndexes = outputs,
-            .operandValues = operandValues,
-            .pools = {},
-        };
-    }
-    void check(const std::string& name,
-               bool expectation,  // true = success
-               const std::vector<uint32_t>& inputs, const std::vector<uint32_t>& outputs) {
-        SCOPED_TRACE(name + " (HAL calls should " + (expectation ? "succeed" : "fail") + ", " +
-                     (kInputHasPrecedence ? "input" : "output") + " precedence, " +
-                     (kQuantized ? "quantized" : "float"));
-
-        V1_1::Model model = createModel(inputs, outputs);
-
-        // ensure that getSupportedOperations_1_1() checks model validity
-        ErrorStatus supportedOpsErrorStatus = ErrorStatus::GENERAL_FAILURE;
-        Return<void> supportedOpsReturn = device->getSupportedOperations_1_1(
-            model, [&model, &supportedOpsErrorStatus](ErrorStatus status,
-                                                      const hidl_vec<bool>& supported) {
-                supportedOpsErrorStatus = status;
-                if (status == ErrorStatus::NONE) {
-                    ASSERT_EQ(supported.size(), model.operations.size());
-                }
-            });
-        ASSERT_TRUE(supportedOpsReturn.isOk());
-        ASSERT_EQ(supportedOpsErrorStatus,
-                  (expectation ? ErrorStatus::NONE : ErrorStatus::INVALID_ARGUMENT));
-
-        // ensure that prepareModel_1_1() checks model validity
-        sp<PreparedModelCallback> preparedModelCallback = new PreparedModelCallback;
-        ASSERT_NE(preparedModelCallback.get(), nullptr);
-        Return<ErrorStatus> prepareLaunchReturn =
-            device->prepareModel_1_1(model, preparedModelCallback);
-        ASSERT_TRUE(prepareLaunchReturn.isOk());
-        ASSERT_TRUE(prepareLaunchReturn == ErrorStatus::NONE ||
-                    prepareLaunchReturn == ErrorStatus::INVALID_ARGUMENT);
-        bool preparationOk = (prepareLaunchReturn == ErrorStatus::NONE);
-        if (preparationOk) {
-            preparedModelCallback->wait();
-            preparationOk = (preparedModelCallback->getStatus() == ErrorStatus::NONE);
-        }
-
-        if (preparationOk) {
-            ASSERT_TRUE(expectation);
-        } else {
-            // Preparation can fail for reasons other than an invalid model --
-            // for example, perhaps not all operations are supported, or perhaps
-            // the device hit some kind of capacity limit.
-            bool invalid = prepareLaunchReturn == ErrorStatus::INVALID_ARGUMENT ||
-                           preparedModelCallback->getStatus() == ErrorStatus::INVALID_ARGUMENT;
-            ASSERT_NE(expectation, invalid);
-        }
-    }
-
-    // Indicates whether an operand that appears in both the inputs
-    // and outputs vector should have lifetime appropriate for input
-    // rather than for output.
-    const bool kInputHasPrecedence = std::get<0>(GetParam());
-
-    // Indicates whether we should test TENSOR_QUANT8_ASYMM rather
-    // than TENSOR_FLOAT32.
-    const bool kQuantized = std::get<1>(GetParam());
-};
-
-TEST_P(NeuralnetworksInputsOutputsTest, Validate) {
-    check("Ok", true, {0, 1}, {3});
-    check("InputIsOutput", false, {0, 1}, {3, 0});
-    check("OutputIsInput", false, {0, 1, 3}, {3});
-    check("DuplicateInputs", false, {0, 1, 0}, {3});
-    check("DuplicateOutputs", false, {0, 1}, {3, 3});
-}
-
-INSTANTIATE_TEST_CASE_P(Flavor, NeuralnetworksInputsOutputsTest,
-                        ::testing::Combine(::testing::Bool(), ::testing::Bool()));
-
-}  // namespace functional
-}  // namespace vts
-}  // namespace V1_1
-}  // namespace neuralnetworks
-}  // namespace hardware
-}  // namespace android
-
-using android::hardware::neuralnetworks::V1_1::vts::functional::NeuralnetworksHidlEnvironment;
-
-int main(int argc, char** argv) {
-    ::testing::AddGlobalTestEnvironment(NeuralnetworksHidlEnvironment::getInstance());
-    ::testing::InitGoogleTest(&argc, argv);
-    NeuralnetworksHidlEnvironment::getInstance()->init(&argc, argv);
-
-    int status = RUN_ALL_TESTS();
-    return status;
-}
diff --git a/neuralnetworks/1.1/vts/functional/VtsHalNeuralnetworksV1_1GeneratedTest.cpp b/neuralnetworks/1.1/vts/functional/VtsHalNeuralnetworksV1_1GeneratedTest.cpp
deleted file mode 100644
index 025d9fe..0000000
--- a/neuralnetworks/1.1/vts/functional/VtsHalNeuralnetworksV1_1GeneratedTest.cpp
+++ /dev/null
@@ -1,80 +0,0 @@
-/*
- * Copyright (C) 2018 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-#define LOG_TAG "neuralnetworks_hidl_hal_test"
-
-#include "VtsHalNeuralnetworksV1_1.h"
-
-#include "Callbacks.h"
-#include "TestHarness.h"
-
-#include <android-base/logging.h>
-#include <android/hardware/neuralnetworks/1.1/IDevice.h>
-#include <android/hardware/neuralnetworks/1.1/types.h>
-#include <android/hidl/memory/1.0/IMemory.h>
-#include <hidlmemory/mapping.h>
-
-using ::android::hardware::neuralnetworks::V1_0::IPreparedModel;
-using ::android::hardware::neuralnetworks::V1_0::Capabilities;
-using ::android::hardware::neuralnetworks::V1_0::DeviceStatus;
-using ::android::hardware::neuralnetworks::V1_0::ErrorStatus;
-using ::android::hardware::neuralnetworks::V1_0::FusedActivationFunc;
-using ::android::hardware::neuralnetworks::V1_0::Operand;
-using ::android::hardware::neuralnetworks::V1_0::OperandLifeTime;
-using ::android::hardware::neuralnetworks::V1_0::OperandType;
-using ::android::hardware::neuralnetworks::V1_0::Request;
-using ::android::hardware::neuralnetworks::V1_1::IDevice;
-using ::android::hardware::neuralnetworks::V1_1::Model;
-using ::android::hardware::neuralnetworks::V1_1::Operation;
-using ::android::hardware::neuralnetworks::V1_1::OperationType;
-using ::android::hardware::Return;
-using ::android::hardware::Void;
-using ::android::hardware::hidl_memory;
-using ::android::hardware::hidl_string;
-using ::android::hardware::hidl_vec;
-using ::android::hidl::allocator::V1_0::IAllocator;
-using ::android::hidl::memory::V1_0::IMemory;
-using ::android::sp;
-
-namespace android {
-namespace hardware {
-namespace neuralnetworks {
-
-namespace generated_tests {
-using ::generated_tests::MixedTypedExampleType;
-extern void Execute(sp<V1_1::IDevice>&, std::function<Model(void)>, std::function<bool(int)>,
-                    const std::vector<MixedTypedExampleType>&);
-}  // namespace generated_tests
-
-namespace V1_1 {
-namespace vts {
-namespace functional {
-using ::android::hardware::neuralnetworks::V1_0::implementation::ExecutionCallback;
-using ::android::hardware::neuralnetworks::V1_0::implementation::PreparedModelCallback;
-
-// Mixed-typed examples
-typedef generated_tests::MixedTypedExampleType MixedTypedExample;
-
-// in frameworks/ml/nn/runtime/tests/generated/
-#include "all_generated_V1_0_vts_tests.cpp"
-#include "all_generated_V1_1_vts_tests.cpp"
-
-}  // namespace functional
-}  // namespace vts
-}  // namespace V1_1
-}  // namespace neuralnetworks
-}  // namespace hardware
-}  // namespace android
diff --git a/nfc/1.1/types.hal b/nfc/1.1/types.hal
index 469e878..e9ffd16 100644
--- a/nfc/1.1/types.hal
+++ b/nfc/1.1/types.hal
@@ -77,6 +77,9 @@
     /** Default system code route. 0x00 if there aren't any. Refer NCI spec */
     uint8_t defaultSystemCodeRoute;
 
+    /** Default power state for system code route. 0x00 if there aren't any. Refer NCI spec */
+    uint8_t defaultSystemCodePowerState;
+
     /**
      * Default route for all remaining protocols and technology which haven't
      * been configured.
diff --git a/radio/1.2/Android.bp b/radio/1.2/Android.bp
index a9c80b7..c90a03c 100644
--- a/radio/1.2/Android.bp
+++ b/radio/1.2/Android.bp
@@ -24,6 +24,7 @@
         "Call",
         "CardStatus",
         "CellConnectionStatus",
+        "CellIdentity",
         "CellIdentityCdma",
         "CellIdentityGsm",
         "CellIdentityLte",
@@ -36,6 +37,7 @@
         "CellInfoLte",
         "CellInfoTdscdma",
         "CellInfoWcdma",
+        "DataRegStateResult",
         "DataRequestReason",
         "IncrementalResultsPeriodicityRange",
         "IndicationFilter",
@@ -48,6 +50,7 @@
         "ScanIntervalRange",
         "SignalStrength",
         "TdscdmaSignalStrength",
+        "VoiceRegStateResult",
         "WcdmaSignalStrength",
     ],
     gen_java: true,
diff --git a/radio/1.2/IRadioResponse.hal b/radio/1.2/IRadioResponse.hal
index f26c9ec..300aa37 100644
--- a/radio/1.2/IRadioResponse.hal
+++ b/radio/1.2/IRadioResponse.hal
@@ -98,4 +98,31 @@
      *   RadioError:INTERNAL_ERR
      */
     oneway getSignalStrengthResponse_1_2(RadioResponseInfo info, SignalStrength signalStrength);
+
+    /**
+     * @param info Response info struct containing response type, serial no. and error
+     * @param voiceRegResponse Current Voice registration response as defined by VoiceRegStateResult
+     *        in types.hal
+     *
+     * Valid errors returned:
+     *   RadioError:NONE
+     *   RadioError:RADIO_NOT_AVAILABLE
+     *   RadioError:INTERNAL_ERR
+     */
+    oneway getVoiceRegistrationStateResponse_1_2(RadioResponseInfo info,
+            VoiceRegStateResult voiceRegResponse);
+
+    /**
+     * @param info Response info struct containing response type, serial no. and error
+     * @param dataRegResponse Current Data registration response as defined by DataRegStateResult in
+     *        types.hal
+     *
+     * Valid errors returned:
+     *   RadioError:NONE
+     *   RadioError:RADIO_NOT_AVAILABLE
+     *   RadioError:INTERNAL_ERR
+     *   RadioError:NOT_PROVISIONED
+     */
+    oneway getDataRegistrationStateResponse_1_2(RadioResponseInfo info,
+            DataRegStateResult dataRegResponse);
 };
diff --git a/radio/1.2/types.hal b/radio/1.2/types.hal
index 5e72b3b..4715fac 100644
--- a/radio/1.2/types.hal
+++ b/radio/1.2/types.hal
@@ -32,6 +32,7 @@
 import @1.0::LteSignalStrength;
 import @1.0::RadioConst;
 import @1.0::RadioError;
+import @1.0::RegState;
 import @1.0::SignalStrength;
 import @1.0::TdScdmaSignalStrength;
 import @1.0::TimeStampType;
@@ -462,3 +463,129 @@
     TdScdmaSignalStrength tdScdma;
     WcdmaSignalStrength wcdma;
 };
+
+struct CellIdentity {
+    /**
+     * Cell type for selecting from union CellInfo.
+     * Only one of the below vectors must be of size 1 based on a
+     * valid CellInfoType and others must be of size 0.
+     * If cell info type is NONE, then all the vectors must be of size 0.
+     */
+    CellInfoType cellInfoType;
+    vec<CellIdentityGsm> cellIdentityGsm;
+    vec<CellIdentityWcdma> cellIdentityWcdma;
+    vec<CellIdentityCdma> cellIdentityCdma;
+    vec<CellIdentityLte> cellIdentityLte;
+    vec<CellIdentityTdscdma> cellIdentityTdscdma;
+};
+
+struct VoiceRegStateResult {
+    /**
+     * Valid reg states are NOT_REG_MT_NOT_SEARCHING_OP,
+     * REG_HOME, NOT_REG_MT_SEARCHING_OP, REG_DENIED,
+     * UNKNOWN, REG_ROAMING defined in RegState
+     */
+    RegState regState;
+    /**
+     * Indicates the available voice radio technology, valid values as
+     * defined by RadioTechnology.
+     */
+    int32_t rat;
+    /**
+     * concurrent services support indicator. if registered on a CDMA system.
+     * false - Concurrent services not supported,
+     * true - Concurrent services supported
+     */
+    bool cssSupported;
+    /**
+     * TSB-58 Roaming Indicator if registered on a CDMA or EVDO system or -1 if not.
+     * Valid values are 0-255.
+     */
+    int32_t roamingIndicator;
+    /**
+     * Indicates whether the current system is in the PRL if registered on a CDMA or EVDO system
+     * or -1 if not. 0=not in the PRL, 1=in the PRL
+     */
+    int32_t systemIsInPrl;
+    /**
+     * Default Roaming Indicator from the PRL if registered on a CDMA or EVDO system or -1 if not.
+     * Valid values are 0-255.
+     */
+    int32_t defaultRoamingIndicator;
+    /**
+     * reasonForDenial if registration state is 3
+     * (Registration denied) this is an enumerated reason why
+     * registration was denied. See 3GPP TS 24.008,
+     * 10.5.3.6 and Annex G.
+     * 0 - General
+     * 1 - Authentication Failure
+     * 2 - IMSI unknown in HLR
+     * 3 - Illegal MS
+     * 4 - Illegal ME
+     * 5 - PLMN not allowed
+     * 6 - Location area not allowed
+     * 7 - Roaming not allowed
+     * 8 - No Suitable Cells in this Location Area
+     * 9 - Network failure
+     * 10 - Persistent location update reject
+     * 11 - PLMN not allowed
+     * 12 - Location area not allowed
+     * 13 - Roaming not allowed in this Location Area
+     * 15 - No Suitable Cells in this Location Area
+     * 17 - Network Failure
+     * 20 - MAC Failure
+     * 21 - Sync Failure
+     * 22 - Congestion
+     * 23 - GSM Authentication unacceptable
+     * 25 - Not Authorized for this CSG
+     * 32 - Service option not supported
+     * 33 - Requested service option not subscribed
+     * 34 - Service option temporarily out of order
+     * 38 - Call cannot be identified
+     * 48-63 - Retry upon entry into a new cell
+     * 95 - Semantically incorrect message
+     * 96 - Invalid mandatory information
+     * 97 - Message type non-existent or not implemented
+     * 98 - Message type not compatible with protocol state
+     * 99 - Information element non-existent or not implemented
+     * 100 - Conditional IE error
+     * 101 - Message not compatible with protocol state
+     * 111 - Protocol error, unspecified
+     */
+    int32_t reasonForDenial;
+
+    CellIdentity cellIdentity;
+};
+
+struct DataRegStateResult {
+    /**
+     * Valid reg states are NOT_REG_MT_NOT_SEARCHING_OP,
+     * REG_HOME, NOT_REG_MT_SEARCHING_OP, REG_DENIED,
+     * UNKNOWN, REG_ROAMING defined in RegState
+     */
+    RegState regState;
+    /**
+     * Indicates the available data radio technology,
+     * valid values as defined by RadioTechnology.
+     */
+    int32_t rat;
+    /**
+     * If registration state is 3 (Registration
+     * denied) this is an enumerated reason why
+     * registration was denied. See 3GPP TS 24.008,
+     * Annex G.6 "Additional cause codes for GMM".
+     * 7 == GPRS services not allowed
+     * 8 == GPRS services and non-GPRS services not allowed
+     * 9 == MS identity cannot be derived by the network
+     * 10 == Implicitly detached
+     * 14 == GPRS services not allowed in this PLMN
+     * 16 == MSC temporarily not reachable
+     * 40 == No PDP context activated
+     */
+    int32_t reasonDataDenied;
+    /**
+     * The maximum number of simultaneous Data Calls must be established using setupDataCall().
+     */
+    int32_t maxDataCalls;
+    CellIdentity cellIdentity;
+};
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 34a87e1..ee130f8 100644
--- a/radio/1.2/vts/functional/radio_hidl_hal_api.cpp
+++ b/radio/1.2/vts/functional/radio_hidl_hal_api.cpp
@@ -673,3 +673,40 @@
     ASSERT_TRUE(CheckAnyOfErrors(radioRsp_v1_2->rspInfo.error,
                                  {RadioError::NONE, RadioError::NO_NETWORK_FOUND}));
 }
+
+/*
+ * Test IRadio.getVoiceRegistrationState() for the response returned.
+ */
+TEST_F(RadioHidlTest_v1_2, getVoiceRegistrationState) {
+    int serial = GetRandomSerialNumber();
+
+    Return<void> res = radio_v1_2->getVoiceRegistrationState(serial);
+    ASSERT_OK(res);
+    EXPECT_EQ(std::cv_status::no_timeout, wait());
+    EXPECT_EQ(RadioResponseType::SOLICITED, radioRsp_v1_2->rspInfo.type);
+    EXPECT_EQ(serial, radioRsp_v1_2->rspInfo.serial);
+
+    ALOGI("getVoiceRegistrationStateResponse_1_2, rspInfo.error = %s\n",
+          toString(radioRsp_v1_2->rspInfo.error).c_str());
+    ASSERT_TRUE(CheckAnyOfErrors(radioRsp_v1_2->rspInfo.error,
+                                 {RadioError::NONE, RadioError::RADIO_NOT_AVAILABLE}));
+}
+
+/*
+ * Test IRadio.getDataRegistrationState() for the response returned.
+ */
+TEST_F(RadioHidlTest_v1_2, getDataRegistrationState) {
+    int serial = GetRandomSerialNumber();
+
+    Return<void> res = radio_v1_2->getDataRegistrationState(serial);
+    ASSERT_OK(res);
+    EXPECT_EQ(std::cv_status::no_timeout, wait());
+    EXPECT_EQ(RadioResponseType::SOLICITED, radioRsp_v1_2->rspInfo.type);
+    EXPECT_EQ(serial, radioRsp_v1_2->rspInfo.serial);
+
+    ALOGI("getVoiceRegistrationStateResponse_1_2, rspInfo.error = %s\n",
+          toString(radioRsp_v1_2->rspInfo.error).c_str());
+    ASSERT_TRUE(CheckAnyOfErrors(
+        radioRsp_v1_2->rspInfo.error,
+        {RadioError::NONE, RadioError::RADIO_NOT_AVAILABLE, RadioError::NOT_PROVISIONED}));
+}
diff --git a/radio/1.2/vts/functional/radio_hidl_hal_utils_v1_2.h b/radio/1.2/vts/functional/radio_hidl_hal_utils_v1_2.h
index 66d8ca4..c61913c 100644
--- a/radio/1.2/vts/functional/radio_hidl_hal_utils_v1_2.h
+++ b/radio/1.2/vts/functional/radio_hidl_hal_utils_v1_2.h
@@ -417,6 +417,12 @@
 
     Return<void> getCellInfoListResponse_1_2(
         const RadioResponseInfo& info, const ::android::hardware::hidl_vec<CellInfo>& cellInfo);
+
+    Return<void> getVoiceRegistrationStateResponse_1_2(
+        const RadioResponseInfo& info, const V1_2::VoiceRegStateResult& voiceRegResponse);
+
+    Return<void> getDataRegistrationStateResponse_1_2(
+        const RadioResponseInfo& info, const V1_2::DataRegStateResult& dataRegResponse);
 };
 
 /* Callback class for radio indication */
diff --git a/radio/1.2/vts/functional/radio_response.cpp b/radio/1.2/vts/functional/radio_response.cpp
index d96f76b..9195689 100644
--- a/radio/1.2/vts/functional/radio_response.cpp
+++ b/radio/1.2/vts/functional/radio_response.cpp
@@ -731,4 +731,14 @@
     rspInfo = info;
     parent_v1_2.notify();
     return Void();
-}
\ No newline at end of file
+}
+
+Return<void> RadioResponse_v1_2::getVoiceRegistrationStateResponse_1_2(
+    const RadioResponseInfo& /*info*/, const V1_2::VoiceRegStateResult& /*voiceRegResponse*/) {
+    return Void();
+}
+
+Return<void> RadioResponse_v1_2::getDataRegistrationStateResponse_1_2(
+    const RadioResponseInfo& /*info*/, const V1_2::DataRegStateResult& /*dataRegResponse*/) {
+    return Void();
+}
diff --git a/secure_element/1.0/vts/functional/VtsHalSecureElementV1_0TargetTest.cpp b/secure_element/1.0/vts/functional/VtsHalSecureElementV1_0TargetTest.cpp
index 59c354f..dab81e2 100644
--- a/secure_element/1.0/vts/functional/VtsHalSecureElementV1_0TargetTest.cpp
+++ b/secure_element/1.0/vts/functional/VtsHalSecureElementV1_0TargetTest.cpp
@@ -34,14 +34,13 @@
 using ::android::sp;
 using ::testing::VtsHalHidlTargetTestEnvBase;
 
-#define SELECT_ISD \
-    { 0x00, 0xA4, 0x04, 0x00, 0x00 }
-#define SEQUENCE_COUNTER \
-    { 0x80, 0xCA, 0x00, 0xC1, 0x00 }
-#define MANAGE_SELECT \
-    { 0x00, 0xA4, 0x04, 0x00, 0x00 }
-#define CRS_AID \
-    { 0xA0, 0x00, 0x00, 0x01, 0x51, 0x43, 0x52, 0x53, 0x00 }
+#define DATA_APDU \
+    { 0x00, 0x08, 0x00, 0x00, 0x00 }
+#define ANDROID_TEST_AID                                                                          \
+    {                                                                                             \
+        0xA0, 0x00, 0x00, 0x04, 0x76, 0x41, 0x6E, 0x64, 0x72, 0x6F, 0x69, 0x64, 0x43, 0x54, 0x53, \
+            0x31                                                                                  \
+    }
 
 constexpr char kCallbackNameOnStateChange[] = "onStateChange";
 
@@ -115,7 +114,7 @@
  * Check status word in the response
  */
 TEST_F(SecureElementHidlTest, transmit) {
-    std::vector<uint8_t> aid = CRS_AID;
+    std::vector<uint8_t> aid = ANDROID_TEST_AID;
     SecureElementStatus statusReturned;
     LogicalChannelResponse response;
     se_->openLogicalChannel(
@@ -132,9 +131,9 @@
             }
         });
     EXPECT_EQ(SecureElementStatus::SUCCESS, statusReturned);
-    EXPECT_LE((unsigned int)3, response.selectResponse.size());
+    EXPECT_LE((unsigned int)2, response.selectResponse.size());
     EXPECT_LE(1, response.channelNumber);
-    std::vector<uint8_t> command = SELECT_ISD;
+    std::vector<uint8_t> command = DATA_APDU;
     std::vector<uint8_t> transmitResponse;
     se_->transmit(command, [&transmitResponse](std::vector<uint8_t> res) {
         transmitResponse.resize(res.size());
@@ -145,16 +144,6 @@
     EXPECT_LE((unsigned int)3, transmitResponse.size());
     EXPECT_EQ(0x90, transmitResponse[transmitResponse.size() - 2]);
     EXPECT_EQ(0x00, transmitResponse[transmitResponse.size() - 1]);
-    command = SEQUENCE_COUNTER;
-    se_->transmit(command, [&transmitResponse](std::vector<uint8_t> res) {
-        transmitResponse.resize(res.size());
-        for (size_t i = 0; i < res.size(); i++) {
-            transmitResponse[i] = res[i];
-        }
-    });
-    EXPECT_LE((unsigned int)3, transmitResponse.size());
-    EXPECT_EQ(0x90, transmitResponse[transmitResponse.size() - 2]);
-    EXPECT_EQ(0x00, transmitResponse[transmitResponse.size() - 1]);
     EXPECT_EQ(SecureElementStatus::SUCCESS, se_->closeChannel(response.channelNumber));
 }
 
@@ -164,7 +153,7 @@
  *  open channel, check the length of selectResponse and close the channel
  */
 TEST_F(SecureElementHidlTest, openBasicChannel) {
-    std::vector<uint8_t> aid = CRS_AID;
+    std::vector<uint8_t> aid = ANDROID_TEST_AID;
     SecureElementStatus statusReturned;
     std::vector<uint8_t> response;
     se_->openBasicChannel(aid, 0x00,
@@ -180,17 +169,6 @@
                           });
     if (statusReturned == SecureElementStatus::SUCCESS) {
         EXPECT_LE((unsigned int)3, response.size());
-        std::vector<uint8_t> command = SELECT_ISD;
-        std::vector<uint8_t> transmitResponse;
-        se_->transmit(command, [&transmitResponse](std::vector<uint8_t> res) {
-            transmitResponse.resize(res.size());
-            for (size_t i = 0; i < res.size(); i++) {
-                transmitResponse[i] = res[i];
-            }
-        });
-        EXPECT_LE((unsigned int)3, transmitResponse.size());
-        EXPECT_EQ(0x90, transmitResponse[transmitResponse.size() - 2]);
-        EXPECT_EQ(0x00, transmitResponse[transmitResponse.size() - 1]);
         return;
     }
     EXPECT_EQ(SecureElementStatus::UNSUPPORTED_OPERATION, statusReturned);
@@ -221,7 +199,7 @@
  * Close Channel
  */
 TEST_F(SecureElementHidlTest, openCloseLogicalChannel) {
-    std::vector<uint8_t> aid = CRS_AID;
+    std::vector<uint8_t> aid = ANDROID_TEST_AID;
     SecureElementStatus statusReturned;
     LogicalChannelResponse response;
     se_->openLogicalChannel(
@@ -238,7 +216,7 @@
             }
         });
     EXPECT_EQ(SecureElementStatus::SUCCESS, statusReturned);
-    EXPECT_LE((unsigned int)3, response.selectResponse.size());
+    EXPECT_LE((unsigned int)2, response.selectResponse.size());
     EXPECT_LE(1, response.channelNumber);
     EXPECT_EQ(SecureElementStatus::SUCCESS, se_->closeChannel(response.channelNumber));
 }
diff --git a/wifi/1.2/IWifiStaIface.hal b/wifi/1.2/IWifiStaIface.hal
index be4e537..3a7f777 100644
--- a/wifi/1.2/IWifiStaIface.hal
+++ b/wifi/1.2/IWifiStaIface.hal
@@ -17,6 +17,7 @@
 package android.hardware.wifi@1.2;
 
 import @1.0::WifiStatus;
+import @1.0::MacAddress;
 import @1.0::IWifiStaIface;
 
 /**
@@ -51,4 +52,17 @@
      * @see installApfPacketFilter()
      */
     readApfPacketFilterData() generates (WifiStatus status, vec<uint8_t> data);
+
+    /**
+     * Changes the MAC address of the Sta Interface to the given
+     * MAC address.
+     *
+     * @param mac MAC address to change into.
+     * @return status WifiStatus of the operation.
+     *         Possible status codes:
+     *         |WifiStatusCode.SUCCESS|,
+     *         |WifiStatusCode.ERROR_WIFI_IFACE_INVALID|,
+     *         |WifiStatusCode.ERROR_UNKNOWN|
+     */
+    setMacAddress(MacAddress mac) generates (WifiStatus status);
 };
diff --git a/wifi/1.2/default/wifi_sta_iface.cpp b/wifi/1.2/default/wifi_sta_iface.cpp
index ab99daa..daa5610 100644
--- a/wifi/1.2/default/wifi_sta_iface.cpp
+++ b/wifi/1.2/default/wifi_sta_iface.cpp
@@ -241,6 +241,13 @@
                            hidl_status_cb);
 }
 
+Return<void> WifiStaIface::setMacAddress(const hidl_array<uint8_t, 6>& mac,
+                                         setMacAddress_cb hidl_status_cb) {
+    return validateAndCall(this, WifiStatusCode::ERROR_WIFI_IFACE_INVALID,
+                           &WifiStaIface::setMacAddressInternal, hidl_status_cb,
+                           mac);
+}
+
 std::pair<WifiStatus, std::string> WifiStaIface::getNameInternal() {
     return {createWifiStatus(WifiStatusCode::SUCCESS), ifname_};
 }
@@ -594,6 +601,26 @@
     return {createWifiStatus(WifiStatusCode::SUCCESS), hidl_fates};
 }
 
+WifiStatus WifiStaIface::setMacAddressInternal(
+    const std::array<uint8_t, 6>& mac) {
+    if (!iface_tool_.SetWifiUpState(false)) {
+        LOG(ERROR) << "SetWifiUpState(false) failed.";
+        return createWifiStatus(WifiStatusCode::ERROR_UNKNOWN);
+    }
+
+    if (!iface_tool_.SetMacAddress(ifname_.c_str(), mac)) {
+        LOG(ERROR) << "SetMacAddress failed.";
+        return createWifiStatus(WifiStatusCode::ERROR_UNKNOWN);
+    }
+
+    if (!iface_tool_.SetWifiUpState(true)) {
+        LOG(ERROR) << "SetWifiUpState(true) failed.";
+        return createWifiStatus(WifiStatusCode::ERROR_UNKNOWN);
+    }
+    LOG(DEBUG) << "Successfully SetMacAddress.";
+    return createWifiStatus(WifiStatusCode::SUCCESS);
+}
+
 }  // namespace implementation
 }  // namespace V1_2
 }  // namespace wifi
diff --git a/wifi/1.2/default/wifi_sta_iface.h b/wifi/1.2/default/wifi_sta_iface.h
index a212888..71cd17d 100644
--- a/wifi/1.2/default/wifi_sta_iface.h
+++ b/wifi/1.2/default/wifi_sta_iface.h
@@ -21,6 +21,8 @@
 #include <android/hardware/wifi/1.0/IWifiStaIfaceEventCallback.h>
 #include <android/hardware/wifi/1.2/IWifiStaIface.h>
 
+#include <wifi_system/interface_tool.h>
+
 #include "hidl_callback_util.h"
 #include "wifi_legacy_hal.h"
 
@@ -103,6 +105,8 @@
         getDebugTxPacketFates_cb hidl_status_cb) override;
     Return<void> getDebugRxPacketFates(
         getDebugRxPacketFates_cb hidl_status_cb) override;
+    Return<void> setMacAddress(const hidl_array<uint8_t, 6>& mac,
+                               setMacAddress_cb hidl_status_cb) override;
 
    private:
     // Corresponding worker functions for the HIDL methods.
@@ -146,12 +150,14 @@
     getDebugTxPacketFatesInternal();
     std::pair<WifiStatus, std::vector<WifiDebugRxPacketFateReport>>
     getDebugRxPacketFatesInternal();
+    WifiStatus setMacAddressInternal(const std::array<uint8_t, 6>& mac);
 
     std::string ifname_;
     std::weak_ptr<legacy_hal::WifiLegacyHal> legacy_hal_;
     bool is_valid_;
     hidl_callback_util::HidlCallbackHandler<IWifiStaIfaceEventCallback>
         event_cb_handler_;
+    wifi_system::InterfaceTool iface_tool_;
 
     DISALLOW_COPY_AND_ASSIGN(WifiStaIface);
 };
diff --git a/wifi/1.2/vts/functional/Android.bp b/wifi/1.2/vts/functional/Android.bp
index d85d42e..918e4a4 100644
--- a/wifi/1.2/vts/functional/Android.bp
+++ b/wifi/1.2/vts/functional/Android.bp
@@ -20,6 +20,7 @@
     srcs: [
         "VtsHalWifiV1_2TargetTest.cpp",
         "wifi_chip_hidl_test.cpp",
+        "wifi_sta_iface_hidl_test.cpp",
     ],
     static_libs: [
         "VtsHalWifiV1_0TargetTestUtil",
diff --git a/wifi/1.2/vts/functional/wifi_sta_iface_hidl_test.cpp b/wifi/1.2/vts/functional/wifi_sta_iface_hidl_test.cpp
new file mode 100644
index 0000000..fd4a671
--- /dev/null
+++ b/wifi/1.2/vts/functional/wifi_sta_iface_hidl_test.cpp
@@ -0,0 +1,56 @@
+/*
+ * Copyright (C) 2018 The Android Open Source Project
+ *
+ * Licensed under the Staache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include <android-base/logging.h>
+
+#include <android/hardware/wifi/1.2/IWifiStaIface.h>
+
+#include <VtsHalHidlTargetTestBase.h>
+
+#include "wifi_hidl_call_util.h"
+#include "wifi_hidl_test_utils.h"
+
+using ::android::sp;
+using ::android::hardware::wifi::V1_2::IWifiStaIface;
+using ::android::hardware::wifi::V1_0::WifiStatusCode;
+
+/**
+ * Fixture to use for all STA Iface HIDL interface tests.
+ */
+class WifiStaIfaceHidlTest : public ::testing::VtsHalHidlTargetTestBase {
+   public:
+    virtual void SetUp() override {
+        wifi_sta_iface_ = IWifiStaIface::castFrom(getWifiStaIface());
+        ASSERT_NE(nullptr, wifi_sta_iface_.get());
+    }
+
+    virtual void TearDown() override { stopWifi(); }
+
+   protected:
+    sp<IWifiStaIface> wifi_sta_iface_;
+};
+
+/*
+ * SetMacAddress:
+ * Ensures that calls to set MAC address will return a success status
+ * code.
+ */
+TEST_F(WifiStaIfaceHidlTest, SetMacAddress) {
+    const android::hardware::hidl_array<uint8_t, 6> kMac{
+        std::array<uint8_t, 6>{{0x12, 0x22, 0x33, 0x52, 0x10, 0x41}}};
+    EXPECT_EQ(WifiStatusCode::SUCCESS,
+              HIDL_INVOKE(wifi_sta_iface_, setMacAddress, kMac).code);
+}
diff --git a/wifi/supplicant/1.1/Android.bp b/wifi/supplicant/1.1/Android.bp
index fafd6ad..832d1ad 100644
--- a/wifi/supplicant/1.1/Android.bp
+++ b/wifi/supplicant/1.1/Android.bp
@@ -8,6 +8,8 @@
     },
     srcs: [
         "ISupplicant.hal",
+        "ISupplicantStaIface.hal",
+        "ISupplicantStaIfaceCallback.hal",
         "ISupplicantStaNetwork.hal",
     ],
     interfaces: [
diff --git a/wifi/supplicant/1.1/ISupplicantStaIface.hal b/wifi/supplicant/1.1/ISupplicantStaIface.hal
new file mode 100644
index 0000000..025cc6a
--- /dev/null
+++ b/wifi/supplicant/1.1/ISupplicantStaIface.hal
@@ -0,0 +1,48 @@
+/*
+ * Copyright 2018 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.hardware.wifi.supplicant@1.1;
+
+import @1.0::ISupplicantStaIface;
+import @1.1::ISupplicantStaIfaceCallback;
+import @1.0::SupplicantStatus;
+
+/**
+ * Interface exposed by the supplicant for each station mode network
+ * interface (e.g wlan0) it controls.
+ */
+interface ISupplicantStaIface extends @1.0::ISupplicantStaIface {
+
+    /**
+     * Register for callbacks from this interface.
+     *
+     * These callbacks are invoked for events that are specific to this interface.
+     * Registration of multiple callback objects is supported. These objects must
+     * be automatically deleted when the corresponding client process is dead or
+     * if this interface is removed.
+     *
+     * @param callback An instance of the |ISupplicantStaIfaceCallback| HIDL
+     *        interface object.
+     * @return status Status of the operation.
+     *         Possible status codes:
+     *         |SupplicantStatusCode.SUCCESS|,
+     *         |SupplicantStatusCode.FAILURE_UNKNOWN|,
+     *         |SupplicantStatusCode.FAILURE_IFACE_INVALID|
+     */
+    registerCallback_1_1(ISupplicantStaIfaceCallback callback)
+        generates (SupplicantStatus status);
+};
+
diff --git a/wifi/supplicant/1.1/ISupplicantStaIfaceCallback.hal b/wifi/supplicant/1.1/ISupplicantStaIfaceCallback.hal
new file mode 100644
index 0000000..8b92ee5
--- /dev/null
+++ b/wifi/supplicant/1.1/ISupplicantStaIfaceCallback.hal
@@ -0,0 +1,45 @@
+/*
+ * Copyright 2018 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.hardware.wifi.supplicant@1.1;
+
+import @1.0::ISupplicantStaIfaceCallback;
+
+/**
+ * Callback Interface exposed by the supplicant service
+ * for each station mode interface (ISupplicantStaIface).
+ *
+ * Clients need to host an instance of this HIDL interface object and
+ * pass a reference of the object to the supplicant via the
+ * corresponding |ISupplicantStaIface.registerCallback_1_1| method.
+ */
+interface ISupplicantStaIfaceCallback extends @1.0::ISupplicantStaIfaceCallback {
+
+    /* EapErrorCode: Error code for EAP or EAP Method as per RFC-4186 */
+    enum EapErrorCode : uint32_t {
+        SIM_GENERAL_FAILURE_AFTER_AUTH = 0,
+        SIM_TEMPORARILY_DENIED = 1026,
+        SIM_NOT_SUBSCRIBED = 1031,
+        SIM_GENERAL_FAILURE_BEFORE_AUTH = 16384,
+        SIM_VENDOR_SPECIFIC_EXPIRED_CERT = 16385,
+    };
+
+    /**
+     * Used to indicate an EAP authentication failure.
+     */
+    oneway onEapFailure_1_1(EapErrorCode errorCode);
+};
+
diff --git a/wifi/supplicant/1.1/vts/functional/Android.bp b/wifi/supplicant/1.1/vts/functional/Android.bp
index 3efe15d..3e65453 100644
--- a/wifi/supplicant/1.1/vts/functional/Android.bp
+++ b/wifi/supplicant/1.1/vts/functional/Android.bp
@@ -40,6 +40,7 @@
     srcs: [
         "VtsHalWifiSupplicantV1_1TargetTest.cpp",
         "supplicant_hidl_test.cpp",
+        "supplicant_sta_iface_hidl_test.cpp",
         "supplicant_sta_network_hidl_test.cpp",
     ],
     static_libs: [
diff --git a/wifi/supplicant/1.1/vts/functional/supplicant_hidl_test_utils_1_1.cpp b/wifi/supplicant/1.1/vts/functional/supplicant_hidl_test_utils_1_1.cpp
index 3f17740..04a5ed9 100644
--- a/wifi/supplicant/1.1/vts/functional/supplicant_hidl_test_utils_1_1.cpp
+++ b/wifi/supplicant/1.1/vts/functional/supplicant_hidl_test_utils_1_1.cpp
@@ -21,6 +21,7 @@
 #include "supplicant_hidl_test_utils_1_1.h"
 
 using ::android::hardware::wifi::supplicant::V1_1::ISupplicant;
+using ::android::hardware::wifi::supplicant::V1_1::ISupplicantStaIface;
 using ::android::hardware::wifi::supplicant::V1_1::ISupplicantStaNetwork;
 using ::android::sp;
 
@@ -28,6 +29,10 @@
     return ISupplicant::castFrom(getSupplicant());
 }
 
+sp<ISupplicantStaIface> getSupplicantStaIface_1_1() {
+    return ISupplicantStaIface::castFrom(getSupplicantStaIface());
+}
+
 sp<ISupplicantStaNetwork> createSupplicantStaNetwork_1_1() {
     return ISupplicantStaNetwork::castFrom(createSupplicantStaNetwork());
 }
diff --git a/wifi/supplicant/1.1/vts/functional/supplicant_hidl_test_utils_1_1.h b/wifi/supplicant/1.1/vts/functional/supplicant_hidl_test_utils_1_1.h
index e7ce54a..1c13325 100644
--- a/wifi/supplicant/1.1/vts/functional/supplicant_hidl_test_utils_1_1.h
+++ b/wifi/supplicant/1.1/vts/functional/supplicant_hidl_test_utils_1_1.h
@@ -18,11 +18,15 @@
 #define SUPPLICANT_HIDL_TEST_UTILS_1_1_H
 
 #include <android/hardware/wifi/supplicant/1.1/ISupplicant.h>
+#include <android/hardware/wifi/supplicant/1.1/ISupplicantStaIface.h>
 #include <android/hardware/wifi/supplicant/1.1/ISupplicantStaNetwork.h>
 
 android::sp<android::hardware::wifi::supplicant::V1_1::ISupplicant>
     getSupplicant_1_1();
 
+android::sp<android::hardware::wifi::supplicant::V1_1::ISupplicantStaIface>
+    getSupplicantStaIface_1_1();
+
 android::sp<android::hardware::wifi::supplicant::V1_1::ISupplicantStaNetwork>
     createSupplicantStaNetwork_1_1();
 
diff --git a/wifi/supplicant/1.1/vts/functional/supplicant_sta_iface_hidl_test.cpp b/wifi/supplicant/1.1/vts/functional/supplicant_sta_iface_hidl_test.cpp
new file mode 100644
index 0000000..c5e6319
--- /dev/null
+++ b/wifi/supplicant/1.1/vts/functional/supplicant_sta_iface_hidl_test.cpp
@@ -0,0 +1,139 @@
+/*
+ * Copyright (C) 2018 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include <android-base/logging.h>
+
+#include <VtsHalHidlTargetTestBase.h>
+
+#include <android/hardware/wifi/supplicant/1.1/ISupplicantStaIface.h>
+
+#include "supplicant_hidl_test_utils.h"
+#include "supplicant_hidl_test_utils_1_1.h"
+
+using ::android::sp;
+using ::android::hardware::hidl_array;
+using ::android::hardware::hidl_string;
+using ::android::hardware::hidl_vec;
+using ::android::hardware::Return;
+using ::android::hardware::Void;
+using ::android::hardware::wifi::supplicant::V1_1::ISupplicantStaIface;
+using ::android::hardware::wifi::supplicant::V1_1::ISupplicantStaIfaceCallback;
+using ::android::hardware::wifi::supplicant::V1_0::SupplicantStatus;
+using ::android::hardware::wifi::supplicant::V1_0::SupplicantStatusCode;
+
+class SupplicantStaIfaceHidlTest
+    : public ::testing::VtsHalHidlTargetTestBase {
+ public:
+  virtual void SetUp() override {
+      startSupplicantAndWaitForHidlService();
+      EXPECT_TRUE(turnOnExcessiveLogging());
+      sta_iface_ = getSupplicantStaIface_1_1();
+      ASSERT_NE(sta_iface_.get(), nullptr);
+  }
+
+  virtual void TearDown() override { stopSupplicant(); }
+
+ protected:
+  // ISupplicantStaIface object used for all tests in this fixture.
+  sp<ISupplicantStaIface> sta_iface_;
+};
+
+class IfaceCallback : public ISupplicantStaIfaceCallback {
+    Return<void> onNetworkAdded(uint32_t /* id */) override { return Void(); }
+    Return<void> onNetworkRemoved(uint32_t /* id */) override { return Void(); }
+    Return<void> onStateChanged(
+        ISupplicantStaIfaceCallback::State /* newState */,
+        const hidl_array<uint8_t, 6>& /*bssid */, uint32_t /* id */,
+        const hidl_vec<uint8_t>& /* ssid */) override {
+        return Void();
+    }
+    Return<void> onAnqpQueryDone(
+        const hidl_array<uint8_t, 6>& /* bssid */,
+        const ISupplicantStaIfaceCallback::AnqpData& /* data */,
+        const ISupplicantStaIfaceCallback::Hs20AnqpData& /* hs20Data */)
+        override {
+        return Void();
+    }
+    virtual Return<void> onHs20IconQueryDone(
+        const hidl_array<uint8_t, 6>& /* bssid */,
+        const hidl_string& /* fileName */,
+        const hidl_vec<uint8_t>& /* data */) override {
+        return Void();
+    }
+    virtual Return<void> onHs20SubscriptionRemediation(
+        const hidl_array<uint8_t, 6>& /* bssid */,
+        ISupplicantStaIfaceCallback::OsuMethod /* osuMethod */,
+        const hidl_string& /* url*/) override {
+        return Void();
+    }
+    Return<void> onHs20DeauthImminentNotice(
+        const hidl_array<uint8_t, 6>& /* bssid */, uint32_t /* reasonCode */,
+        uint32_t /* reAuthDelayInSec */,
+        const hidl_string& /* url */) override {
+        return Void();
+    }
+    Return<void> onDisconnected(const hidl_array<uint8_t, 6>& /* bssid */,
+                                bool /* locallyGenerated */,
+                                ISupplicantStaIfaceCallback::ReasonCode
+                                /* reasonCode */) override {
+        return Void();
+    }
+    Return<void> onAssociationRejected(
+        const hidl_array<uint8_t, 6>& /* bssid */,
+        ISupplicantStaIfaceCallback::StatusCode /* statusCode */,
+        bool /*timedOut */) override {
+        return Void();
+    }
+    Return<void> onAuthenticationTimeout(
+        const hidl_array<uint8_t, 6>& /* bssid */) override {
+        return Void();
+    }
+    Return<void> onBssidChanged(
+        ISupplicantStaIfaceCallback::BssidChangeReason /* reason */,
+        const hidl_array<uint8_t, 6>& /* bssid */) override {
+        return Void();
+    }
+    Return<void> onEapFailure() override { return Void(); }
+    Return<void> onEapFailure_1_1(
+        ISupplicantStaIfaceCallback::EapErrorCode /* eapErrorCode */) override {
+        return Void();
+    }
+    Return<void> onWpsEventSuccess() override { return Void(); }
+    Return<void> onWpsEventFail(
+        const hidl_array<uint8_t, 6>& /* bssid */,
+        ISupplicantStaIfaceCallback::WpsConfigError /* configError */,
+        ISupplicantStaIfaceCallback::WpsErrorIndication /* errorInd */)
+        override {
+        return Void();
+    }
+    Return<void> onWpsEventPbcOverlap() override { return Void(); }
+    Return<void> onExtRadioWorkStart(uint32_t /* id */) override {
+        return Void();
+    }
+    Return<void> onExtRadioWorkTimeout(uint32_t /* id*/) override {
+        return Void();
+    }
+};
+
+/*
+ * RegisterCallback_1_1
+ */
+TEST_F(SupplicantStaIfaceHidlTest, RegisterCallback_1_1) {
+  sta_iface_->registerCallback_1_1(
+      new IfaceCallback(), [](const SupplicantStatus& status) {
+          EXPECT_EQ(SupplicantStatusCode::SUCCESS, status.code);
+      });
+}