Merge "Add recovery code to NN ResilientPreparedModel and *Buffer"
diff --git a/audio/7.0/IStreamOutEventCallback.hal b/audio/7.0/IStreamOutEventCallback.hal
index 52e65d3..4de767f 100644
--- a/audio/7.0/IStreamOutEventCallback.hal
+++ b/audio/7.0/IStreamOutEventCallback.hal
@@ -42,7 +42,7 @@
      * is TEST(metadata_tests, compatibility_R) [3].  The test for R compatibility for JNI
      * marshalling is android.media.cts.AudioMetadataTest#testCompatibilityR [4].
      *
-     * R (audio HAL 7.0) defined keys are as follows [2]:
+     * R (audio HAL 6.0) defined keys are as follows [2]:
      * "bitrate", int32
      * "channel-mask", int32
      * "mime", string
diff --git a/audio/common/7.0/types.hal b/audio/common/7.0/types.hal
index ed56c73..b14ebd4 100644
--- a/audio/common/7.0/types.hal
+++ b/audio/common/7.0/types.hal
@@ -274,10 +274,21 @@
     uint64_t frameCount;
 };
 
+/**
+ * AudioTag is an additional use case qualifier complementing
+ * AudioUsage and AudioContentType. Tags are set by vendor specific applications
+ * and must be prefixed by "VX_". Vendor must namespace their tag
+ * names to avoid conflicts.
+ */
+typedef string AudioTag;
+
 /** Metadata of a playback track for a StreamOut. */
 struct PlaybackTrackMetadata {
     AudioUsage usage;
     AudioContentType contentType;
+    /** Tags from AudioTrack audio atttributes */
+    vec<AudioTag> tags;
+    AudioChannelMask channelMask;
     /**
      * Positive linear gain applied to the track samples. 0 being muted and 1 is no attenuation,
      * 2 means double amplification...
@@ -294,6 +305,9 @@
 /** Metadata of a record track for a StreamIn. */
 struct RecordTrackMetadata {
     AudioSource source;
+    /** Tags from AudioTrack audio atttributes */
+    vec<AudioTag> tags;
+    AudioChannelMask channelMask;
     /**
      * Positive linear gain applied to the track samples. 0 being muted and 1 is no attenuation,
      * 2 means double amplification...
diff --git a/audio/common/all-versions/default/HidlUtils.h b/audio/common/all-versions/default/HidlUtils.h
index a0bd1bc..d8b7ba4 100644
--- a/audio/common/all-versions/default/HidlUtils.h
+++ b/audio/common/all-versions/default/HidlUtils.h
@@ -77,6 +77,8 @@
 #endif
 
 #if MAJOR_VERSION >= 7
+    static constexpr char sAudioTagSeparator = ';';
+
     static status_t audioChannelMaskFromHal(audio_channel_mask_t halChannelMask, bool isInput,
                                             AudioChannelMask* channelMask);
     static status_t audioChannelMasksFromHal(const std::vector<std::string>& halChannelMasks,
@@ -126,6 +128,7 @@
                                                struct audio_port_config_device_ext* device,
                                                struct audio_port_config_mix_ext* mix,
                                                struct audio_port_config_session_ext* session);
+
 #endif  // MAJOR_VERSION >= 7
 
     // V4 and below have DeviceAddress defined in the 'core' interface.
diff --git a/audio/core/all-versions/default/StreamIn.cpp b/audio/core/all-versions/default/StreamIn.cpp
index ead7204..a673554 100644
--- a/audio/core/all-versions/default/StreamIn.cpp
+++ b/audio/core/all-versions/default/StreamIn.cpp
@@ -478,29 +478,85 @@
 }
 
 #if MAJOR_VERSION >= 4
-Return<void> StreamIn::updateSinkMetadata(const SinkMetadata& sinkMetadata) {
-    if (mStream->update_sink_metadata == nullptr) {
-        return Void();  // not supported by the HAL
+
+record_track_metadata StreamIn::convertRecordTrackMetadata(
+        const RecordTrackMetadata& trackMetadata) {
+    record_track_metadata halTrackMetadata = {.gain = trackMetadata.gain};
+    (void)HidlUtils::audioSourceToHal(trackMetadata.source, &halTrackMetadata.source);
+#if MAJOR_VERSION >= 5
+    if (trackMetadata.destination.getDiscriminator() ==
+        RecordTrackMetadata::Destination::hidl_discriminator::device) {
+        (void)deviceAddressToHal(trackMetadata.destination.device(), &halTrackMetadata.dest_device,
+                                 halTrackMetadata.dest_device_address);
     }
+#endif
+    return halTrackMetadata;
+}
+
+void StreamIn::doUpdateSinkMetadata(const SinkMetadata& sinkMetadata) {
     std::vector<record_track_metadata> halTracks;
     halTracks.reserve(sinkMetadata.tracks.size());
     for (auto& metadata : sinkMetadata.tracks) {
-        record_track_metadata halTrackMetadata = {.gain = metadata.gain};
-        (void)HidlUtils::audioSourceToHal(metadata.source, &halTrackMetadata.source);
-#if MAJOR_VERSION >= 5
-        if (metadata.destination.getDiscriminator() ==
-            RecordTrackMetadata::Destination::hidl_discriminator::device) {
-            (void)deviceAddressToHal(metadata.destination.device(), &halTrackMetadata.dest_device,
-                                     halTrackMetadata.dest_device_address);
-        }
-#endif
-        halTracks.push_back(halTrackMetadata);
+        halTracks.push_back(convertRecordTrackMetadata(metadata));
     }
     const sink_metadata_t halMetadata = {
         .track_count = halTracks.size(),
         .tracks = halTracks.data(),
     };
     mStream->update_sink_metadata(mStream, &halMetadata);
+}
+
+#if MAJOR_VERSION >= 7
+record_track_metadata_v7 StreamIn::convertRecordTrackMetadataV7(
+        const RecordTrackMetadata& trackMetadata) {
+    record_track_metadata_v7 halTrackMetadata;
+    halTrackMetadata.base = convertRecordTrackMetadata(trackMetadata);
+    (void)HidlUtils::audioChannelMaskToHal(trackMetadata.channelMask,
+                                           &halTrackMetadata.channel_mask);
+    std::string halTags;
+    for (const auto& tag : trackMetadata.tags) {
+        if (&tag != &trackMetadata.tags[0]) {
+            halTags += HidlUtils::sAudioTagSeparator;
+        }
+        halTags += tag.c_str();
+    }
+    strncpy(halTrackMetadata.tags, halTags.c_str(), AUDIO_ATTRIBUTES_TAGS_MAX_SIZE);
+    return halTrackMetadata;
+}
+
+void StreamIn::doUpdateSinkMetadataV7(const SinkMetadata& sinkMetadata) {
+    std::vector<record_track_metadata_v7> halTracks;
+    halTracks.reserve(sinkMetadata.tracks.size());
+    for (auto& metadata : sinkMetadata.tracks) {
+        halTracks.push_back(convertRecordTrackMetadataV7(metadata));
+    }
+    const sink_metadata_v7_t halMetadata = {
+            .track_count = halTracks.size(),
+            .tracks = halTracks.data(),
+    };
+    mStream->update_sink_metadata_v7(mStream, &halMetadata);
+}
+#endif  //  MAJOR_VERSION >= 7
+
+Return<void> StreamIn::updateSinkMetadata(const SinkMetadata& sinkMetadata) {
+#if MAJOR_VERSION < 7
+    if (mStream->update_sink_metadata == nullptr) {
+        return Void();  // not supported by the HAL
+    }
+    doUpdateSinkMetadata(sinkMetadata);
+#else
+    if (mDevice->version() < AUDIO_DEVICE_API_VERSION_3_2) {
+        if (mStream->update_sink_metadata == nullptr) {
+            return Void();  // not supported by the HAL
+        }
+        doUpdateSinkMetadata(sinkMetadata);
+    } else {
+        if (mStream->update_sink_metadata_v7 == nullptr) {
+            return Void();  // not supported by the HAL
+        }
+        doUpdateSinkMetadataV7(sinkMetadata);
+    }
+#endif  //  MAJOR_VERSION < 7
     return Void();
 }
 
diff --git a/audio/core/all-versions/default/StreamOut.cpp b/audio/core/all-versions/default/StreamOut.cpp
index 5633cbb..2451b9e 100644
--- a/audio/core/all-versions/default/StreamOut.cpp
+++ b/audio/core/all-versions/default/StreamOut.cpp
@@ -585,26 +585,82 @@
 }
 
 #if MAJOR_VERSION >= 4
-Return<void> StreamOut::updateSourceMetadata(const SourceMetadata& sourceMetadata) {
-    if (mStream->update_source_metadata == nullptr) {
-        return Void();  // not supported by the HAL
-    }
+playback_track_metadata StreamOut::convertPlaybackTrackMetadata(
+        const PlaybackTrackMetadata& trackMetadata) {
+    playback_track_metadata_t halTrackMetadata = {.gain = trackMetadata.gain};
+    (void)HidlUtils::audioUsageToHal(trackMetadata.usage, &halTrackMetadata.usage);
+    (void)HidlUtils::audioContentTypeToHal(trackMetadata.contentType,
+                                           &halTrackMetadata.content_type);
+    return halTrackMetadata;
+}
+
+void StreamOut::doUpdateSourceMetadata(const SourceMetadata& sourceMetadata) {
     std::vector<playback_track_metadata_t> halTracks;
     halTracks.reserve(sourceMetadata.tracks.size());
     for (auto& metadata : sourceMetadata.tracks) {
-        playback_track_metadata_t halTrackMetadata = {.gain = metadata.gain};
-        (void)HidlUtils::audioUsageToHal(metadata.usage, &halTrackMetadata.usage);
-        (void)HidlUtils::audioContentTypeToHal(metadata.contentType,
-                                               &halTrackMetadata.content_type);
-        halTracks.push_back(std::move(halTrackMetadata));
+        halTracks.push_back(convertPlaybackTrackMetadata(metadata));
     }
     const source_metadata_t halMetadata = {
         .track_count = halTracks.size(),
         .tracks = halTracks.data(),
     };
     mStream->update_source_metadata(mStream, &halMetadata);
+}
+
+#if MAJOR_VERSION >= 7
+playback_track_metadata_v7 StreamOut::convertPlaybackTrackMetadataV7(
+        const PlaybackTrackMetadata& trackMetadata) {
+    playback_track_metadata_v7 halTrackMetadata;
+    halTrackMetadata.base = convertPlaybackTrackMetadata(trackMetadata);
+    (void)HidlUtils::audioChannelMaskToHal(trackMetadata.channelMask,
+                                           &halTrackMetadata.channel_mask);
+    std::string halTags;
+    for (const auto& tag : trackMetadata.tags) {
+        if (&tag != &trackMetadata.tags[0]) {
+            halTags += HidlUtils::sAudioTagSeparator;
+        }
+        halTags += tag.c_str();
+    }
+    strncpy(halTrackMetadata.tags, halTags.c_str(), AUDIO_ATTRIBUTES_TAGS_MAX_SIZE);
+    return halTrackMetadata;
+}
+
+void StreamOut::doUpdateSourceMetadataV7(const SourceMetadata& sourceMetadata) {
+    std::vector<playback_track_metadata_v7> halTracks;
+    halTracks.reserve(sourceMetadata.tracks.size());
+    for (auto& metadata : sourceMetadata.tracks) {
+        halTracks.push_back(convertPlaybackTrackMetadataV7(metadata));
+    }
+    const source_metadata_v7_t halMetadata = {
+            .track_count = halTracks.size(),
+            .tracks = halTracks.data(),
+    };
+    mStream->update_source_metadata_v7(mStream, &halMetadata);
+}
+#endif  //  MAJOR_VERSION >= 7
+
+Return<void> StreamOut::updateSourceMetadata(const SourceMetadata& sourceMetadata) {
+#if MAJOR_VERSION < 7
+    if (mStream->update_source_metadata == nullptr) {
+        return Void();  // not supported by the HAL
+    }
+    doUpdateSourceMetadata(sourceMetadata);
+#else
+    if (mDevice->version() < AUDIO_DEVICE_API_VERSION_3_2) {
+        if (mStream->update_source_metadata == nullptr) {
+            return Void();  // not supported by the HAL
+        }
+        doUpdateSourceMetadata(sourceMetadata);
+    } else {
+        if (mStream->update_source_metadata_v7 == nullptr) {
+            return Void();  // not supported by the HAL
+        }
+        doUpdateSourceMetadataV7(sourceMetadata);
+    }
+#endif  //  MAJOR_VERSION < 7
     return Void();
 }
+
 Return<Result> StreamOut::selectPresentation(int32_t /*presentationId*/, int32_t /*programId*/) {
     return Result::NOT_SUPPORTED;  // TODO: propagate to legacy
 }
diff --git a/audio/core/all-versions/default/include/core/default/Device.h b/audio/core/all-versions/default/include/core/default/Device.h
index 461c253..2a4d226 100644
--- a/audio/core/all-versions/default/include/core/default/Device.h
+++ b/audio/core/all-versions/default/include/core/default/Device.h
@@ -146,6 +146,8 @@
     void closeOutputStream(audio_stream_out_t* stream);
     audio_hw_device_t* device() const { return mDevice; }
 
+    uint32_t version() const { return mDevice->common.version; }
+
   private:
     bool mIsClosed;
     audio_hw_device_t* mDevice;
@@ -161,8 +163,6 @@
     // Methods from ParametersUtil.
     char* halGetParameters(const char* keys) override;
     int halSetParameters(const char* keysAndValues) override;
-
-    uint32_t version() const { return mDevice->common.version; }
 };
 
 }  // namespace implementation
diff --git a/audio/core/all-versions/default/include/core/default/StreamIn.h b/audio/core/all-versions/default/include/core/default/StreamIn.h
index b861c6c..512da55 100644
--- a/audio/core/all-versions/default/include/core/default/StreamIn.h
+++ b/audio/core/all-versions/default/include/core/default/StreamIn.h
@@ -124,7 +124,16 @@
     static Result getCapturePositionImpl(audio_stream_in_t* stream, uint64_t* frames,
                                          uint64_t* time);
 
-   private:
+  private:
+#if MAJOR_VERSION >= 4
+    record_track_metadata convertRecordTrackMetadata(const RecordTrackMetadata& trackMetadata);
+    void doUpdateSinkMetadata(const SinkMetadata& sinkMetadata);
+#if MAJOR_VERSION >= 7
+    record_track_metadata_v7 convertRecordTrackMetadataV7(const RecordTrackMetadata& trackMetadata);
+    void doUpdateSinkMetadataV7(const SinkMetadata& sinkMetadata);
+#endif
+#endif
+
     const sp<Device> mDevice;
     audio_stream_in_t* mStream;
     const sp<Stream> mStreamCommon;
diff --git a/audio/core/all-versions/default/include/core/default/StreamOut.h b/audio/core/all-versions/default/include/core/default/StreamOut.h
index 9f64e3e..8da940d 100644
--- a/audio/core/all-versions/default/include/core/default/StreamOut.h
+++ b/audio/core/all-versions/default/include/core/default/StreamOut.h
@@ -143,6 +143,17 @@
 #endif
 
   private:
+#if MAJOR_VERSION >= 4
+    playback_track_metadata convertPlaybackTrackMetadata(
+            const PlaybackTrackMetadata& trackMetadata);
+    void doUpdateSourceMetadata(const SourceMetadata& sourceMetadata);
+#if MAJOR_VERSION >= 7
+    playback_track_metadata_v7 convertPlaybackTrackMetadataV7(
+            const PlaybackTrackMetadata& trackMetadata);
+    void doUpdateSourceMetadataV7(const SourceMetadata& sourceMetadata);
+#endif
+#endif
+
     const sp<Device> mDevice;
     audio_stream_out_t* mStream;
     const sp<Stream> mStreamCommon;
diff --git a/audio/core/all-versions/vts/functional/4.0/AudioPrimaryHidlHalTest.cpp b/audio/core/all-versions/vts/functional/4.0/AudioPrimaryHidlHalTest.cpp
index 9a4a8b2..c53ae8d 100644
--- a/audio/core/all-versions/vts/functional/4.0/AudioPrimaryHidlHalTest.cpp
+++ b/audio/core/all-versions/vts/functional/4.0/AudioPrimaryHidlHalTest.cpp
@@ -72,7 +72,10 @@
         config.base.format = toString(xsd::AudioFormat::AUDIO_FORMAT_PCM_16_BIT);
         hidl_vec<hidl_string> flags;
         const SinkMetadata initMetadata = {
-                {{.source = toString(xsd::AudioSource::AUDIO_SOURCE_MIC), .gain = 1}}};
+                {{.source = toString(xsd::AudioSource::AUDIO_SOURCE_MIC),
+                  .gain = 1,
+                  .tags = {},
+                  .channelMask = toString(xsd::AudioChannelMask::AUDIO_CHANNEL_IN_MONO)}}};
 #endif
         EventFlag* efGroup;
         for (auto microphone : microphones) {
@@ -246,7 +249,11 @@
 #if MAJOR_VERSION <= 6
             const SinkMetadata metadata = {{{.source = source, .gain = volume}}};
 #elif MAJOR_VERSION >= 7
-            const SinkMetadata metadata = {{{.source = toString(source), .gain = volume}}};
+            const SinkMetadata metadata = {
+                    {{.source = toString(source),
+                      .gain = volume,
+                      .tags = {},
+                      .channelMask = toString(xsd::AudioChannelMask::AUDIO_CHANNEL_IN_MONO)}}};
 #endif
             ASSERT_OK(stream->updateSinkMetadata(metadata))
                 << "source=" << toString(source) << ", volume=" << volume;
@@ -284,7 +291,12 @@
 #if MAJOR_VERSION <= 6
                 const SourceMetadata metadata = {{{usage, content, volume}}};
 #elif MAJOR_VERSION >= 7
-                const SourceMetadata metadata = {{{toString(usage), toString(content), volume}}};
+                const SourceMetadata metadata = {
+                        {{toString(usage),
+                          toString(content),
+                          {} /* tags */,
+                          toString(xsd::AudioChannelMask::AUDIO_CHANNEL_OUT_STEREO),
+                          volume}}};
 #endif
                 ASSERT_OK(stream->updateSourceMetadata(metadata))
                     << "usage=" << toString(usage) << ", content=" << toString(content)
@@ -303,13 +315,25 @@
           {AudioUsage::ASSISTANT, AudioContentType::UNKNOWN, 0.3}}}
 #elif MAJOR_VERSION >= 7
         {{{toString(xsd::AudioUsage::AUDIO_USAGE_MEDIA),
-                      toString(xsd::AudioContentType::AUDIO_CONTENT_TYPE_MUSIC), 0.1},
+                      toString(xsd::AudioContentType::AUDIO_CONTENT_TYPE_MUSIC),
+                      {},
+                      toString(xsd::AudioChannelMask::AUDIO_CHANNEL_OUT_STEREO),
+                      0.1},
           {toString(xsd::AudioUsage::AUDIO_USAGE_VOICE_COMMUNICATION),
-                      toString(xsd::AudioContentType::AUDIO_CONTENT_TYPE_SPEECH), 1.0},
+                      toString(xsd::AudioContentType::AUDIO_CONTENT_TYPE_SPEECH),
+                      {}, // tags
+                      toString(xsd::AudioChannelMask::AUDIO_CHANNEL_OUT_MONO),
+                      1.0},
           {toString(xsd::AudioUsage::AUDIO_USAGE_ALARM),
-                      toString(xsd::AudioContentType::AUDIO_CONTENT_TYPE_SONIFICATION), 0.0},
+                      toString(xsd::AudioContentType::AUDIO_CONTENT_TYPE_SONIFICATION),
+                      {}, // tags
+                      toString(xsd::AudioChannelMask::AUDIO_CHANNEL_OUT_STEREO),
+                      0.0},
           {toString(xsd::AudioUsage::AUDIO_USAGE_ASSISTANT),
-                      toString(xsd::AudioContentType::AUDIO_CONTENT_TYPE_UNKNOWN), 0.3}}}
+                      toString(xsd::AudioContentType::AUDIO_CONTENT_TYPE_UNKNOWN),
+                      {},
+                      toString(xsd::AudioChannelMask::AUDIO_CHANNEL_OUT_MONO),
+                      0.3}}}
 #endif
     ));
     // clang-format on
diff --git a/audio/core/all-versions/vts/functional/6.0/AudioPrimaryHidlHalTest.cpp b/audio/core/all-versions/vts/functional/6.0/AudioPrimaryHidlHalTest.cpp
index bd8de2d..5ad38de 100644
--- a/audio/core/all-versions/vts/functional/6.0/AudioPrimaryHidlHalTest.cpp
+++ b/audio/core/all-versions/vts/functional/6.0/AudioPrimaryHidlHalTest.cpp
@@ -98,9 +98,11 @@
     auto flags = hidl_bitfield<AudioOutputFlag>(AudioOutputFlag::NONE);
 #elif MAJOR_VERSION >= 7
     DeviceAddress address{.deviceType = toString(xsd::AudioDevice::AUDIO_DEVICE_OUT_DEFAULT)};
-    SourceMetadata initMetadata = {
-            {{toString(xsd::AudioUsage::AUDIO_USAGE_MEDIA),
-              toString(xsd::AudioContentType::AUDIO_CONTENT_TYPE_MUSIC), 1 /* gain */}}};
+    SourceMetadata initMetadata = {{{toString(xsd::AudioUsage::AUDIO_USAGE_MEDIA),
+                                     toString(xsd::AudioContentType::AUDIO_CONTENT_TYPE_MUSIC),
+                                     {} /* tags */,
+                                     toString(xsd::AudioChannelMask::AUDIO_CHANNEL_OUT_STEREO),
+                                     1 /* gain */}}};
     hidl_vec<AudioInOutFlag> flags;
 #endif
     AudioConfig config{};
@@ -131,7 +133,10 @@
 #elif MAJOR_VERSION >= 7
     DeviceAddress address{.deviceType = toString(xsd::AudioDevice::AUDIO_DEVICE_IN_DEFAULT)};
     SinkMetadata initMetadata = {
-            {{.source = toString(xsd::AudioSource::AUDIO_SOURCE_MIC), .gain = 1}}};
+            {{.source = toString(xsd::AudioSource::AUDIO_SOURCE_MIC),
+              .gain = 1,
+              .tags = {},
+              .channelMask = toString(xsd::AudioChannelMask::AUDIO_CHANNEL_IN_MONO)}}};
     hidl_vec<AudioInOutFlag> flags;
 #endif
     AudioConfig config{};
diff --git a/audio/core/all-versions/vts/functional/AudioPrimaryHidlHalTest.h b/audio/core/all-versions/vts/functional/AudioPrimaryHidlHalTest.h
index 43c44cb..a16a0fb 100644
--- a/audio/core/all-versions/vts/functional/AudioPrimaryHidlHalTest.h
+++ b/audio/core/all-versions/vts/functional/AudioPrimaryHidlHalTest.h
@@ -926,6 +926,8 @@
     const SourceMetadata initMetadata = {
             { { toString(xsd::AudioUsage::AUDIO_USAGE_MEDIA),
                 toString(xsd::AudioContentType::AUDIO_CONTENT_TYPE_MUSIC),
+                {},
+                toString(xsd::AudioChannelMask::AUDIO_CHANNEL_OUT_STEREO),
                 1 /* gain */ } }};
 #endif
 };
@@ -991,7 +993,10 @@
      const SinkMetadata initMetadata = {{ {.source = AudioSource::DEFAULT, .gain = 1 } }};
 #elif MAJOR_VERSION >= 7
      const SinkMetadata initMetadata = {
-             {{.source = toString(xsd::AudioSource::AUDIO_SOURCE_DEFAULT), .gain = 1}}};
+             {{.source = toString(xsd::AudioSource::AUDIO_SOURCE_DEFAULT),
+               .gain = 1,
+               .tags = {},
+               .channelMask = toString(xsd::AudioChannelMask::AUDIO_CHANNEL_IN_MONO)}}};
 #endif
 };
 
diff --git a/automotive/can/1.0/default/libnl++/Android.bp b/automotive/can/1.0/default/libnl++/Android.bp
index 90e1002..a69e302 100644
--- a/automotive/can/1.0/default/libnl++/Android.bp
+++ b/automotive/can/1.0/default/libnl++/Android.bp
@@ -22,6 +22,7 @@
         "protocols/common/Empty.cpp",
         "protocols/common/Error.cpp",
         "protocols/generic/Ctrl.cpp",
+        "protocols/generic/FamilyTracker.cpp",
         "protocols/generic/Generic.cpp",
         "protocols/generic/GenericMessageBase.cpp",
         "protocols/generic/Unknown.cpp",
@@ -34,6 +35,7 @@
         "protocols/all.cpp",
         "Attributes.cpp",
         "MessageFactory.cpp",
+        "MessageMutator.cpp",
         "Socket.cpp",
         "common.cpp",
         "printer.cpp",
diff --git a/automotive/can/1.0/default/libnl++/MessageMutator.cpp b/automotive/can/1.0/default/libnl++/MessageMutator.cpp
new file mode 100644
index 0000000..00b48a6
--- /dev/null
+++ b/automotive/can/1.0/default/libnl++/MessageMutator.cpp
@@ -0,0 +1,50 @@
+/*
+ * Copyright (C) 2020 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 <libnl++/MessageMutator.h>
+
+namespace android::nl {
+
+MessageMutator::MessageMutator(nlmsghdr* buffer, size_t totalLen)
+    : mConstBuffer(buffer, totalLen), mMutableBuffer(buffer) {
+    CHECK(totalLen >= sizeof(nlmsghdr));
+}
+
+nlmsghdr* MessageMutator::operator->() const {
+    return mMutableBuffer;
+}
+
+MessageMutator::operator Buffer<nlmsghdr>() const {
+    return mConstBuffer;
+}
+
+uint64_t MessageMutator::read(Buffer<nlattr> attr) const {
+    return attr.data<uint64_t>().copyFirst();
+}
+
+void MessageMutator::write(Buffer<nlattr> attr, uint64_t val) const {
+    const auto attrData = attr.data<uint64_t>();
+    const auto offset = mConstBuffer.getOffset(attrData);
+    CHECK(offset.has_value()) << "Trying to write attribute that's not a member of this message";
+
+    const auto writeableBuffer = reinterpret_cast<uint8_t*>(mMutableBuffer) + *offset;
+    const auto attrSize = attrData.getRaw().len();
+
+    if (attrSize > sizeof(val)) memset(writeableBuffer, 0, attrSize);
+    memcpy(writeableBuffer, &val, std::min(sizeof(val), attrSize));
+}
+
+}  // namespace android::nl
diff --git a/automotive/can/1.0/default/libnl++/include/libnl++/Attributes.h b/automotive/can/1.0/default/libnl++/include/libnl++/Attributes.h
index f16d997..a438a69 100644
--- a/automotive/can/1.0/default/libnl++/include/libnl++/Attributes.h
+++ b/automotive/can/1.0/default/libnl++/include/libnl++/Attributes.h
@@ -93,14 +93,29 @@
      */
     template <typename T>
     T get(nlattrtype_t attrtype) const {
-        const auto& ind = index();
-        const auto it = ind.find(attrtype);
-        if (it == ind.end()) {
+        const auto buffer = getBuffer(attrtype);
+        if (!buffer.has_value()) {
             LOG(WARNING) << "Netlink attribute is missing: " << attrtype;
             return T{};
         }
 
-        return parse<T>(it->second);
+        return parse<T>(*buffer);
+    }
+
+    /**
+     * Fetches underlying buffer of a given attribute.
+     *
+     * This is a low-level access method unlikely to be useful in most cases. Please consider
+     * using #get instead.
+     *
+     * \param attrtype Attribute to fetch
+     * \return Attribute buffer.
+     */
+    std::optional<Buffer<nlattr>> getBuffer(nlattrtype_t attrtype) const {
+        const auto& ind = index();
+        const auto it = ind.find(attrtype);
+        if (it == ind.end()) return std::nullopt;
+        return it->second;
     }
 
     /**
diff --git a/automotive/can/1.0/default/libnl++/include/libnl++/Buffer.h b/automotive/can/1.0/default/libnl++/include/libnl++/Buffer.h
index bf83fbc..d759a0a 100644
--- a/automotive/can/1.0/default/libnl++/include/libnl++/Buffer.h
+++ b/automotive/can/1.0/default/libnl++/include/libnl++/Buffer.h
@@ -91,6 +91,18 @@
         return {impl::data<const T, const D>(mData, offset), dataEnd()};
     }
 
+    template <typename B>
+    std::optional<uintptr_t> getOffset(Buffer<B> inner) const {
+        const auto selfStart = uintptr_t(mData);
+        const auto selfEnd = uintptr_t(mBufferEnd);
+        const auto innerStart = uintptr_t(inner.mData);
+        const auto innerEnd = uintptr_t(inner.mBufferEnd);
+
+        if (innerStart < selfStart || innerEnd > selfEnd) return std::nullopt;
+
+        return innerStart - selfStart;
+    }
+
     class iterator {
       public:
         iterator() : mCurrent(nullptr, size_t(0)) {
diff --git a/automotive/can/1.0/default/libnl++/include/libnl++/MessageMutator.h b/automotive/can/1.0/default/libnl++/include/libnl++/MessageMutator.h
new file mode 100644
index 0000000..7d495e9
--- /dev/null
+++ b/automotive/can/1.0/default/libnl++/include/libnl++/MessageMutator.h
@@ -0,0 +1,61 @@
+/*
+ * Copyright (C) 2020 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#pragma once
+
+#include <libnl++/Message.h>
+
+namespace android::nl {
+
+/**
+ * In-place message mutator.
+ *
+ * Useful for making small changes (such as adjusting const-sized attributes or struct fields)
+ * efficiently and in-place. However, if you need to rebuild the message (e.g. to modify variable
+ * sized attributes or add/remove them), you need to use MessageFactory instead.
+ */
+class MessageMutator {
+  public:
+    /**
+     * Construct message mutator object from editable buffer.
+     */
+    MessageMutator(nlmsghdr* buffer, size_t totalLen);
+
+    nlmsghdr* operator->() const;
+    operator Buffer<nlmsghdr>() const;
+
+    /**
+     * Read current attribute value.
+     *
+     * \param Read-only attribute buffer.
+     * \returns Attribute value.
+     */
+    uint64_t read(Buffer<nlattr> attr) const;
+
+    /**
+     * Write new attribute value.
+     *
+     * \param Read-only attribute buffer.
+     * \param val New value to set.
+     */
+    void write(Buffer<nlattr> attr, uint64_t val) const;
+
+  private:
+    const Buffer<nlmsghdr> mConstBuffer;
+    nlmsghdr* mMutableBuffer;
+};
+
+}  // namespace android::nl
diff --git a/automotive/can/1.0/default/libnl++/include/libnl++/generic/FamilyTracker.h b/automotive/can/1.0/default/libnl++/include/libnl++/generic/FamilyTracker.h
new file mode 100644
index 0000000..2530035
--- /dev/null
+++ b/automotive/can/1.0/default/libnl++/include/libnl++/generic/FamilyTracker.h
@@ -0,0 +1,62 @@
+/*
+ * Copyright (C) 2020 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#pragma once
+
+#include <libnl++/Buffer.h>
+#include <libnl++/Message.h>
+
+#include <linux/genetlink.h>
+
+#include <optional>
+
+namespace android::nl::generic {
+
+/**
+ * Tracker of Netlink family ID registrations.
+ */
+class FamilyTracker {
+  public:
+    /**
+     * Try parsing NL80211 message.
+     *
+     * Proper parsing of NL80211 nessages requires prior parsing of control message for Generic
+     * Netlink protocol.
+     *
+     * \param msg Message to parse
+     * \returns Parsed NL80211 message or std::nullopt if it wasn't one
+     */
+    std::optional<Message<genlmsghdr>> parseNl80211(Buffer<nlmsghdr> msg);
+
+  private:
+    /* For efficiency, we use a single hardcoded family ID. However, if we supported multiple family
+     * types, this should probably be a map.
+     */
+    std::optional<uint16_t> mNl80211FamilyId;
+
+    /**
+     * Track Generic protocol messages.
+     *
+     * This method is looking for family registration messages.
+     *
+     * \param msg Message to track
+     * \returns True, if the message was a control message (regardless of carrying
+     *          family info or not)
+     */
+    bool track(const Buffer<nlmsghdr>& msg);
+};
+
+}  // namespace android::nl::generic
diff --git a/automotive/can/1.0/default/libnl++/protocols/generic/FamilyTracker.cpp b/automotive/can/1.0/default/libnl++/protocols/generic/FamilyTracker.cpp
new file mode 100644
index 0000000..900560e
--- /dev/null
+++ b/automotive/can/1.0/default/libnl++/protocols/generic/FamilyTracker.cpp
@@ -0,0 +1,50 @@
+/*
+ * Copyright (C) 2020 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 <libnl++/generic/FamilyTracker.h>
+
+#include <android-base/logging.h>
+
+namespace android::nl::generic {
+
+bool FamilyTracker::track(const Buffer<nlmsghdr>& buffer) {
+    const auto msgMaybe = nl::Message<genlmsghdr>::parse(buffer, {GENL_ID_CTRL});
+    if (!msgMaybe.has_value()) return false;
+
+    const auto msg = *msgMaybe;
+    if (msg->cmd != CTRL_CMD_NEWFAMILY) return true;
+
+    const auto familyName = msg.attributes.get<std::string>(CTRL_ATTR_FAMILY_NAME);
+    const auto familyId = msg.attributes.get<uint16_t>(CTRL_ATTR_FAMILY_ID);
+
+    if (familyId < GENL_START_ALLOC) {
+        LOG(WARNING) << "Invalid family ID: " << familyId;
+        return true;
+    }
+
+    if (familyName == "nl80211") mNl80211FamilyId = familyId;
+
+    return true;
+}
+
+std::optional<Message<genlmsghdr>> FamilyTracker::parseNl80211(Buffer<nlmsghdr> msg) {
+    if (track(msg)) return std::nullopt;
+    if (!mNl80211FamilyId.has_value()) return std::nullopt;
+
+    return nl::Message<genlmsghdr>::parse(msg, {*mNl80211FamilyId});
+}
+
+}  // namespace android::nl::generic
diff --git a/automotive/vehicle/2.0/types.hal b/automotive/vehicle/2.0/types.hal
index 931fee4..0488b57 100644
--- a/automotive/vehicle/2.0/types.hal
+++ b/automotive/vehicle/2.0/types.hal
@@ -2773,7 +2773,7 @@
      *
      * int32[0]: 42  // request id
      * int32[1]: 11  // Android id of the created user
-     * int32[2]: 3   // Android flags (ephemeral guest) of the created user
+     * int32[2]: 6   // Android flags (ephemeral guest) of the created user
      * int32[3]: 10  // current user
      * int32[4]: 0   // current user flags (none)
      * int32[5]: 3   // number of users
@@ -2782,7 +2782,7 @@
      * int32[8]: 10  // 2nd user (user 10)
      * int32[9]: 0   // 2nd user flags (none)
      * int32[19]: 11 // 3rd user (user 11)
-     * int32[11]: 3  // 3rd user flags (ephemeral guest)
+     * int32[11]: 6  // 3rd user flags (ephemeral guest)
      * string: "ElGuesto" // name of the new user
      *
      * Then if the request succeeded, the HAL would return:
diff --git a/compatibility_matrices/compatibility_matrix.current.xml b/compatibility_matrices/compatibility_matrix.current.xml
index b16ae40..e12d920 100644
--- a/compatibility_matrices/compatibility_matrix.current.xml
+++ b/compatibility_matrices/compatibility_matrix.current.xml
@@ -354,6 +354,13 @@
             <instance>default</instance>
         </interface>
     </hal>
+    <hal format="aidl" optional="true">
+        <name>android.hardware.memtrack</name>
+        <interface>
+            <name>IMemtrack</name>
+            <instance>default</instance>
+        </interface>
+    </hal>
     <hal format="hidl" optional="true">
         <name>android.hardware.memtrack</name>
         <version>1.0</version>
diff --git a/contexthub/1.1/default/Contexthub.cpp b/contexthub/1.1/default/Contexthub.cpp
index e7fde84..2d4fbae 100644
--- a/contexthub/1.1/default/Contexthub.cpp
+++ b/contexthub/1.1/default/Contexthub.cpp
@@ -23,10 +23,29 @@
 namespace V1_1 {
 namespace implementation {
 
+using ::android::hardware::contexthub::V1_0::Result;
+
 Return<void> Contexthub::onSettingChanged(Setting /*setting*/, SettingValue /*newValue*/) {
     return Void();
 }
 
+Return<Result> Contexthub::registerCallback(uint32_t hubId, const sp<IContexthubCallback>& cb) {
+    if (hubId == kMockHubId) {
+        mCallback = cb;
+        return Result::OK;
+    }
+    return Result::BAD_PARAMS;
+}
+
+Return<Result> Contexthub::queryApps(uint32_t hubId) {
+    if (hubId == kMockHubId && mCallback != nullptr) {
+        std::vector<HubAppInfo> nanoapps;
+        mCallback->handleAppsInfo(nanoapps);
+        return Result::OK;
+    }
+    return Result::BAD_PARAMS;
+}
+
 }  // namespace implementation
 }  // namespace V1_1
 }  // namespace contexthub
diff --git a/contexthub/1.1/default/Contexthub.h b/contexthub/1.1/default/Contexthub.h
index 1468fcf..648749e 100644
--- a/contexthub/1.1/default/Contexthub.h
+++ b/contexthub/1.1/default/Contexthub.h
@@ -27,9 +27,19 @@
 
 class Contexthub
     : public ::android::hardware::contexthub::V1_X::implementation::ContextHub<IContexthub> {
+    using Result = ::android::hardware::contexthub::V1_0::Result;
+
   public:
+    // Methods from V1_0::IContexthub
+    Return<Result> registerCallback(uint32_t hubId, const sp<IContexthubCallback>& cb) override;
+
+    Return<Result> queryApps(uint32_t hubId) override;
+
     // Methods from V1_1::IContexthub
     Return<void> onSettingChanged(Setting setting, SettingValue newValue) override;
+
+  private:
+    sp<IContexthubCallback> mCallback;
 };
 
 }  // namespace implementation
diff --git a/contexthub/1.2/Android.bp b/contexthub/1.2/Android.bp
index e819482..9722a97 100644
--- a/contexthub/1.2/Android.bp
+++ b/contexthub/1.2/Android.bp
@@ -6,6 +6,7 @@
     srcs: [
         "types.hal",
         "IContexthub.hal",
+        "IContexthubCallback.hal",
     ],
     interfaces: [
         "android.hardware.contexthub@1.0",
diff --git a/contexthub/1.2/IContexthub.hal b/contexthub/1.2/IContexthub.hal
index 819fc1d..3488b74 100644
--- a/contexthub/1.2/IContexthub.hal
+++ b/contexthub/1.2/IContexthub.hal
@@ -16,11 +16,41 @@
 
 package android.hardware.contexthub@1.2;
 
+import @1.0::Result;
 import @1.1::IContexthub;
 import @1.1::SettingValue;
+import IContexthubCallback;
 
 interface IContexthub extends @1.1::IContexthub {
     /**
+     * Register a callback for the HAL implementation to send asynchronous
+     * messages to the service from a context hub. There can be a maximum of
+     * one callback registered with the HAL. A call to this function when a
+     * callback has already been registered must override the previous
+     * registration.
+     *
+     * @param hubId    identifier for the hub
+     * @param callback an implementation of the IContextHubCallbacks
+     *
+     * @return result OK on success
+     *                BAD_VALUE if parameters are not valid
+     *
+     */
+    registerCallback_1_2(uint32_t hubId, IContexthubCallback cb) generates (Result result);
+
+    /**
+     * Send a message to a hub
+     *
+     * @param hubId identifier for hub to send message to
+     * @param msg   message to be sent
+     *
+     * @return result OK if successful, error code otherwise
+     *                BAD_VALUE if parameters are not valid
+     *                TRANSACTION_FAILED if message send failed
+     */
+    sendMessageToHub_1_2(uint32_t hubId, ContextHubMsg msg) generates (Result result);
+
+    /**
      * Notification sent by the framework to indicate that the user
      * has changed a setting.
      *
diff --git a/contexthub/1.2/IContexthubCallback.hal b/contexthub/1.2/IContexthubCallback.hal
new file mode 100644
index 0000000..0236160
--- /dev/null
+++ b/contexthub/1.2/IContexthubCallback.hal
@@ -0,0 +1,45 @@
+/*
+ * Copyright (C) 2020 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.contexthub@1.2;
+
+import @1.0::IContexthubCallback;
+
+interface IContexthubCallback extends @1.0::IContexthubCallback {
+    /**
+     * This callback is passed by the Contexthub service to the HAL
+     * implementation to allow the HAL to send asynchronous messages back
+     * to the service and registered clients of the ContextHub service.
+     *
+     * @param msg message that should be delivered to host app clients
+     *
+     */
+    handleClientMsg_1_2(ContextHubMsg msg);
+
+    /**
+     * This callback is passed by the Contexthub service to the HAL
+     * implementation to allow the HAL to send information about the
+     * currently loaded and active nanoapps on the hub.
+     *
+     * @param appInfo vector of HubAppinfo structure for each nanoApp
+     *                on the hub that can be enabled, disabled and
+     *                unloaded by the service. Any nanoApps that cannot
+     *                be controlled by the service must not be reported.
+     *                All nanoApps that can be controlled by the service
+     *                must be reported.
+     */
+    handleAppsInfo_1_2(vec<HubAppInfo> appInfo);
+};
diff --git a/contexthub/1.2/default/Android.bp b/contexthub/1.2/default/Android.bp
index 49b54fc..0a31325 100644
--- a/contexthub/1.2/default/Android.bp
+++ b/contexthub/1.2/default/Android.bp
@@ -41,6 +41,7 @@
     ],
     header_libs: [
         "android.hardware.contexthub@1.X-common-impl",
+        "android.hardware.contexthub@1.X-common-utils",
     ],
     vintf_fragments: ["android.hardware.contexthub@1.2.xml"],
 }
diff --git a/contexthub/1.2/default/Contexthub.cpp b/contexthub/1.2/default/Contexthub.cpp
index d7ac7bf..db0c5bc 100644
--- a/contexthub/1.2/default/Contexthub.cpp
+++ b/contexthub/1.2/default/Contexthub.cpp
@@ -23,6 +23,43 @@
 namespace V1_2 {
 namespace implementation {
 
+using ::android::hardware::contexthub::V1_0::Result;
+using ::android::hardware::contexthub::V1_X::implementation::IContextHubCallbackWrapperV1_0;
+using ::android::hardware::contexthub::V1_X::implementation::IContextHubCallbackWrapperV1_2;
+
+Return<Result> Contexthub::registerCallback(uint32_t hubId,
+                                            const sp<V1_0::IContexthubCallback>& cb) {
+    if (hubId == kMockHubId) {
+        mCallback = new IContextHubCallbackWrapperV1_0(cb);
+        return Result::OK;
+    }
+    return Result::BAD_PARAMS;
+}
+
+Return<Result> Contexthub::queryApps(uint32_t hubId) {
+    if (hubId == kMockHubId && mCallback != nullptr) {
+        std::vector<V1_2::HubAppInfo> nanoapps;
+        mCallback->handleAppsInfo(nanoapps);
+        return Result::OK;
+    }
+    return Result::BAD_PARAMS;
+}
+
+Return<Result> Contexthub::registerCallback_1_2(uint32_t hubId,
+                                                const sp<V1_2::IContexthubCallback>& cb) {
+    if (hubId == kMockHubId) {
+        mCallback = new IContextHubCallbackWrapperV1_2(cb);
+        return Result::OK;
+    }
+    return Result::BAD_PARAMS;
+}
+
+// We don't expose any nanoapps, therefore all nanoapp-related API calls return with BAD_PARAMS
+Return<Result> Contexthub::sendMessageToHub_1_2(uint32_t /* hubId */,
+                                                const ContextHubMsg& /* msg */) {
+    return Result::BAD_PARAMS;
+}
+
 Return<void> Contexthub::onSettingChanged(SettingV1_1 /*setting*/, SettingValue /*newValue*/) {
     return Void();
 }
diff --git a/contexthub/1.2/default/Contexthub.h b/contexthub/1.2/default/Contexthub.h
index d2f8d69..8b89824 100644
--- a/contexthub/1.2/default/Contexthub.h
+++ b/contexthub/1.2/default/Contexthub.h
@@ -16,6 +16,7 @@
 #pragma once
 
 #include "ContextHub.h"
+#include "IContextHubCallbackWrapper.h"
 
 #include <android/hardware/contexthub/1.2/IContexthub.h>
 
@@ -27,15 +28,34 @@
 
 class Contexthub
     : public ::android::hardware::contexthub::V1_X::implementation::ContextHub<IContexthub> {
+    using ContextHubMsg = ::android::hardware::contexthub::V1_2::ContextHubMsg;
+    using IContexthubCallback = ::android::hardware::contexthub::V1_2::IContexthubCallback;
+    using IContextHubCallbackWrapperBase =
+            ::android::hardware::contexthub::V1_X::implementation::IContextHubCallbackWrapperBase;
+    using Result = ::android::hardware::contexthub::V1_0::Result;
     using SettingValue = ::android::hardware::contexthub::V1_1::SettingValue;
     using SettingV1_1 = ::android::hardware::contexthub::V1_1::Setting;
 
   public:
+    // Methods from V1_0::IContexthub
+    Return<Result> registerCallback(uint32_t hubId,
+                                    const sp<V1_0::IContexthubCallback>& cb) override;
+
+    Return<Result> queryApps(uint32_t hubId) override;
+
     // Methods from V1_1::IContexthub
     Return<void> onSettingChanged(SettingV1_1 setting, SettingValue newValue) override;
 
     // Methods from V1_2::IContexthub
     Return<void> onSettingChanged_1_2(Setting setting, SettingValue newValue) override;
+
+    Return<Result> registerCallback_1_2(uint32_t hubId,
+                                        const sp<V1_2::IContexthubCallback>& cb) override;
+
+    Return<Result> sendMessageToHub_1_2(uint32_t hubId, const ContextHubMsg& msg) override;
+
+  private:
+    sp<IContextHubCallbackWrapperBase> mCallback;
 };
 
 }  // namespace implementation
diff --git a/contexthub/1.2/types.hal b/contexthub/1.2/types.hal
index 38f9f7a..e6c8acc 100644
--- a/contexthub/1.2/types.hal
+++ b/contexthub/1.2/types.hal
@@ -16,6 +16,8 @@
 
 package android.hardware.contexthub@1.2;
 
+import @1.0::ContextHubMsg;
+import @1.0::HubAppInfo;
 import @1.1::Setting;
 
 /**
@@ -32,3 +34,36 @@
     WIFI_AVAILABLE,
     AIRPLANE_MODE,
 };
+
+struct ContextHubMsg {
+    @1.0::ContextHubMsg msg_1_0;
+
+    /**
+     * The list of Android permissions that the sender of this message has at
+     * the time the message was sent.
+     *
+     * The HAL MUST drop messages to nanoapps if this list of permissions is not
+     * a superset of those of the receiving nanoapp(s).
+     *
+     * The framework MUST drop messages to host apps that don't have a superset
+     * of the permissions that the sending nanoapp is using.
+     */
+    vec<string> permissions;
+};
+
+struct HubAppInfo {
+    @1.0::HubAppInfo info_1_0;
+
+    /**
+     * The list of Android permissions used by this nanoapp. This list MUST
+     * correspond to the permissions required for an equivalent Android app to
+     * sample similar signals through the Android framework.
+     *
+     * For example, if a nanoapp used location-based signals, the permissions
+     * list MUST contains android.permission.ACCESS_FINE_LOCATION and
+     * android.permission.ACCESS_BACKGROUND_LOCATION. If it were to also list to
+     * audio data, it would require adding android.permission.RECORD_AUDIO to
+     * this list.
+     */
+    vec<string> permissions;
+};
diff --git a/contexthub/common/default/1.X/ContextHub.h b/contexthub/common/default/1.X/ContextHub.h
index 73d0631..00f74af 100644
--- a/contexthub/common/default/1.X/ContextHub.h
+++ b/contexthub/common/default/1.X/ContextHub.h
@@ -60,14 +60,6 @@
         return Void();
     }
 
-    Return<Result> registerCallback(uint32_t hubId, const sp<IContexthubCallback>& cb) override {
-        if (hubId == kMockHubId) {
-            mCallback = cb;
-            return Result::OK;
-        }
-        return Result::BAD_PARAMS;
-    }
-
     // We don't expose any nanoapps, therefore all nanoapp-related API calls return with BAD_PARAMS
     Return<Result> sendMessageToHub(uint32_t /*hubId*/, const ContextHubMsg& /*msg*/) override {
         return Result::BAD_PARAMS;
@@ -93,19 +85,8 @@
         return Result::BAD_PARAMS;
     }
 
-    Return<Result> queryApps(uint32_t hubId) override {
-        if (hubId == kMockHubId && mCallback != nullptr) {
-            std::vector<HubAppInfo> nanoapps;
-            mCallback->handleAppsInfo(nanoapps);
-            return Result::OK;
-        }
-        return Result::BAD_PARAMS;
-    }
-
-  private:
+  protected:
     static constexpr uint32_t kMockHubId = 0;
-
-    sp<IContexthubCallback> mCallback;
 };
 
 }  // namespace implementation
diff --git a/contexthub/common/default/1.X/OWNERS b/contexthub/common/default/1.X/OWNERS
new file mode 100644
index 0000000..90c2330
--- /dev/null
+++ b/contexthub/common/default/1.X/OWNERS
@@ -0,0 +1,3 @@
+arthuri@google.com
+bduddie@google.com
+stange@google.com
diff --git a/contexthub/common/default/1.X/utils/Android.bp b/contexthub/common/default/1.X/utils/Android.bp
new file mode 100644
index 0000000..c74b647
--- /dev/null
+++ b/contexthub/common/default/1.X/utils/Android.bp
@@ -0,0 +1,30 @@
+//
+// Copyright (C) 2020 The Android Open Source Project
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+//      http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+cc_library_headers {
+    name: "android.hardware.contexthub@1.X-common-utils",
+    vendor_available: true,
+    defaults: ["hidl_defaults"],
+    export_include_dirs: ["."],
+    shared_libs: [
+        "android.hardware.contexthub@1.0",
+        "android.hardware.contexthub@1.1",
+        "android.hardware.contexthub@1.2",
+        "libbinder",
+        "libcutils",
+        "libhidlbase",
+        "libutils",
+    ],
+}
diff --git a/contexthub/common/default/1.X/utils/IContextHubCallbackWrapper.h b/contexthub/common/default/1.X/utils/IContextHubCallbackWrapper.h
new file mode 100644
index 0000000..df78438
--- /dev/null
+++ b/contexthub/common/default/1.X/utils/IContextHubCallbackWrapper.h
@@ -0,0 +1,123 @@
+/*
+ * Copyright (C) 2020 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef ANDROID_HARDWARE_CONTEXTHUB_V1_X_ICONTEXTHUBCALLBACKWRAPPER_H
+#define ANDROID_HARDWARE_CONTEXTHUB_V1_X_ICONTEXTHUBCALLBACKWRAPPER_H
+
+#include "android/hardware/contexthub/1.0/IContexthub.h"
+#include "android/hardware/contexthub/1.0/IContexthubCallback.h"
+#include "android/hardware/contexthub/1.0/types.h"
+#include "android/hardware/contexthub/1.2/IContexthubCallback.h"
+#include "android/hardware/contexthub/1.2/types.h"
+
+#include <utils/LightRefBase.h>
+
+#include <cassert>
+
+namespace android {
+namespace hardware {
+namespace contexthub {
+namespace V1_X {
+namespace implementation {
+
+inline V1_0::ContextHubMsg convertToOldMsg(V1_2::ContextHubMsg msg) {
+    return msg.msg_1_0;
+}
+
+inline hidl_vec<V1_0::HubAppInfo> convertToOldAppInfo(hidl_vec<V1_2::HubAppInfo> appInfos) {
+    hidl_vec<V1_0::HubAppInfo> convertedInfo(appInfos.size());
+    for (int i = 0; i < appInfos.size(); ++i) {
+        convertedInfo[i] = appInfos[i].info_1_0;
+    }
+
+    return convertedInfo;
+}
+
+/**
+ * The IContexthubCallback classes below abstract away the common logic between both the V1.0, and
+ * V1.2 versions of the Contexthub HAL callback interface. This allows users of these classes to
+ * only care about the HAL version at init time and then interact with either version of the
+ * callback without worrying about the class type by utilizing the base class.
+ */
+class IContextHubCallbackWrapperBase : public VirtualLightRefBase {
+  public:
+    virtual Return<void> handleClientMsg(V1_2::ContextHubMsg msg) = 0;
+
+    virtual Return<void> handleTxnResult(uint32_t txnId, V1_0::TransactionResult result) = 0;
+
+    virtual Return<void> handleHubEvent(V1_0::AsyncEventType evt) = 0;
+
+    virtual Return<void> handleAppAbort(uint64_t appId, uint32_t abortCode) = 0;
+
+    virtual Return<void> handleAppsInfo(hidl_vec<V1_2::HubAppInfo> appInfo) = 0;
+};
+
+template <typename T>
+class ContextHubCallbackWrapper : public IContextHubCallbackWrapperBase {
+  public:
+    ContextHubCallbackWrapper(sp<T> callback) : mCallback(callback){};
+
+    virtual Return<void> handleClientMsg(V1_2::ContextHubMsg msg) override {
+        return mCallback->handleClientMsg(convertToOldMsg(msg));
+    }
+
+    virtual Return<void> handleTxnResult(uint32_t txnId, V1_0::TransactionResult result) override {
+        return mCallback->handleTxnResult(txnId, result);
+    }
+
+    virtual Return<void> handleHubEvent(V1_0::AsyncEventType evt) override {
+        return mCallback->handleHubEvent(evt);
+    }
+
+    virtual Return<void> handleAppAbort(uint64_t appId, uint32_t abortCode) override {
+        return mCallback->handleAppAbort(appId, abortCode);
+    }
+
+    virtual Return<void> handleAppsInfo(hidl_vec<V1_2::HubAppInfo> appInfo) override {
+        return mCallback->handleAppsInfo(convertToOldAppInfo(appInfo));
+    }
+
+  protected:
+    sp<T> mCallback;
+};
+
+class IContextHubCallbackWrapperV1_0 : public ContextHubCallbackWrapper<V1_0::IContexthubCallback> {
+  public:
+    IContextHubCallbackWrapperV1_0(sp<V1_0::IContexthubCallback> callback)
+        : ContextHubCallbackWrapper(callback){};
+};
+
+class IContextHubCallbackWrapperV1_2 : public ContextHubCallbackWrapper<V1_2::IContexthubCallback> {
+  public:
+    IContextHubCallbackWrapperV1_2(sp<V1_2::IContexthubCallback> callback)
+        : ContextHubCallbackWrapper(callback){};
+
+    Return<void> handleClientMsg(V1_2::ContextHubMsg msg) override {
+        return mCallback->handleClientMsg_1_2(msg);
+    }
+
+    Return<void> handleAppsInfo(hidl_vec<V1_2::HubAppInfo> appInfo) override {
+        return mCallback->handleAppsInfo_1_2(appInfo);
+    }
+};
+
+}  // namespace implementation
+}  // namespace V1_X
+}  // namespace contexthub
+}  // namespace hardware
+}  // namespace android
+
+#endif  // ANDROID_HARDWARE_CONTEXTHUB_V1_X_ICONTEXTHUBCALLBACKWRAPPER_H
\ No newline at end of file
diff --git a/current.txt b/current.txt
index 8623fc0..0b88a7a 100644
--- a/current.txt
+++ b/current.txt
@@ -787,6 +787,4 @@
 
 # HALs released in Android S
 # NOTE: waiting to freeze HALs until later in the release
-# NOTE: new HALs are recommended to be in AIDL
-6e64b33f1b720b66b0deb5e08dee37a99deaa94e2e9ebf7806703cabab56e21d android.hardware.contexthub@1.2::IContexthub
-3fb83f4539cab2c7bf9fdbecf7265d1c1dd6e8de9694046fe512b493c127ccea android.hardware.contexthub@1.2::types
+# NOTE: new HALs are recommended to be in AIDL
\ No newline at end of file
diff --git a/gnss/common/utils/default/Utils.cpp b/gnss/common/utils/default/Utils.cpp
index e383d51..21282f4 100644
--- a/gnss/common/utils/default/Utils.cpp
+++ b/gnss/common/utils/default/Utils.cpp
@@ -228,7 +228,8 @@
             .verticalAccuracyMeters = kMockVerticalAccuracyMeters,
             .speedAccuracyMetersPerSecond = kMockSpeedAccuracyMetersPerSecond,
             .bearingAccuracyDegrees = kMockBearingAccuracyDegrees,
-            .timestamp = kMockTimestamp};
+            .timestamp =
+                    static_cast<int64_t>(kMockTimestamp + ::android::elapsedRealtimeNano() / 1e6)};
     return location;
 }
 
diff --git a/graphics/composer/2.4/vts/functional/VtsHalGraphicsComposerV2_4TargetTest.cpp b/graphics/composer/2.4/vts/functional/VtsHalGraphicsComposerV2_4TargetTest.cpp
index d8312a2..25c990b 100644
--- a/graphics/composer/2.4/vts/functional/VtsHalGraphicsComposerV2_4TargetTest.cpp
+++ b/graphics/composer/2.4/vts/functional/VtsHalGraphicsComposerV2_4TargetTest.cpp
@@ -19,6 +19,8 @@
 #include <algorithm>
 #include <regex>
 #include <thread>
+#include <unordered_map>
+#include <utility>
 
 #include <android-base/logging.h>
 #include <android-base/properties.h>
@@ -152,9 +154,9 @@
 
     void execute() { mComposerClient->execute(mReader.get(), mWriter.get()); }
 
-    const native_handle_t* allocate() {
+    const native_handle_t* allocate(int32_t width, int32_t height) {
         return mGralloc->allocate(
-                /*width*/ 64, /*height*/ 64, /*layerCount*/ 1,
+                width, height, /*layerCount*/ 1,
                 static_cast<common::V1_1::PixelFormat>(PixelFormat::RGBA_8888),
                 static_cast<uint64_t>(BufferUsage::CPU_WRITE_OFTEN | BufferUsage::CPU_READ_OFTEN));
     }
@@ -285,6 +287,59 @@
     }
 }
 
+TEST_P(GraphicsComposerHidlTest, GetDisplayAttribute_2_4_ConfigsInAGroupDifferOnlyByVsyncPeriod) {
+    struct Resolution {
+        int32_t width, height;
+    };
+    struct Dpi {
+        int32_t x, y;
+    };
+    for (const auto& display : mDisplays) {
+        std::vector<Config> configs = mComposerClient->getDisplayConfigs(display.get());
+        std::unordered_map<int32_t, Resolution> configGroupToResolutionMap;
+        std::unordered_map<int32_t, Dpi> configGroupToDpiMap;
+        for (auto config : configs) {
+            const auto configGroup = mComposerClient->getDisplayAttribute_2_4(
+                    display.get(), config, IComposerClient::Attribute::CONFIG_GROUP);
+            const auto width = mComposerClient->getDisplayAttribute_2_4(
+                    display.get(), config, IComposerClient::Attribute::WIDTH);
+            const auto height = mComposerClient->getDisplayAttribute_2_4(
+                    display.get(), config, IComposerClient::Attribute::HEIGHT);
+            if (configGroupToResolutionMap.find(configGroup) == configGroupToResolutionMap.end()) {
+                configGroupToResolutionMap[configGroup] = {width, height};
+            }
+            EXPECT_EQ(configGroupToResolutionMap[configGroup].width, width);
+            EXPECT_EQ(configGroupToResolutionMap[configGroup].height, height);
+
+            int32_t dpiX = -1;
+            mComposerClient->getRaw()->getDisplayAttribute_2_4(
+                    display.get(), config, IComposerClient::Attribute::DPI_X,
+                    [&](const auto& tmpError, const auto& value) {
+                        if (tmpError == Error::NONE) {
+                            dpiX = value;
+                        }
+                    });
+            int32_t dpiY = -1;
+            mComposerClient->getRaw()->getDisplayAttribute_2_4(
+                    display.get(), config, IComposerClient::Attribute::DPI_Y,
+                    [&](const auto& tmpError, const auto& value) {
+                        if (tmpError == Error::NONE) {
+                            dpiY = value;
+                        }
+                    });
+            if (dpiX == -1 && dpiY == -1) {
+                continue;
+            }
+
+            if (configGroupToDpiMap.find(configGroup) == configGroupToDpiMap.end()) {
+                configGroupToDpiMap[configGroup] = {dpiX, dpiY};
+            }
+            EXPECT_EQ(configGroupToDpiMap[configGroup].x, dpiX);
+            EXPECT_EQ(configGroupToDpiMap[configGroup].y, dpiY);
+        }
+    }
+}
+
 TEST_P(GraphicsComposerHidlTest, getDisplayVsyncPeriod_BadDisplay) {
     VsyncPeriodNanos vsyncPeriodNanos;
     EXPECT_EQ(Error::BAD_DISPLAY,
@@ -407,7 +462,10 @@
     mComposerClient->setPowerMode(display.get(), V2_1::IComposerClient::PowerMode::ON);
     mComposerClient->setColorMode_2_3(display.get(), ColorMode::NATIVE, RenderIntent::COLORIMETRIC);
 
-    auto handle = allocate();
+    IComposerClient::FRect displayCrop = display.getCrop();
+    int32_t displayWidth = static_cast<int32_t>(std::ceilf(displayCrop.right - displayCrop.left));
+    int32_t displayHeight = static_cast<int32_t>(std::ceilf(displayCrop.bottom - displayCrop.top));
+    auto handle = allocate(displayWidth, displayHeight);
     ASSERT_NE(nullptr, handle);
 
     Layer layer;
@@ -435,7 +493,7 @@
     ASSERT_EQ(0, mReader->mErrors.size());
 
     mWriter->selectLayer(layer);
-    auto handle2 = allocate();
+    auto handle2 = allocate(displayWidth, displayHeight);
     ASSERT_NE(nullptr, handle2);
 
     mWriter->setLayerBuffer(0, handle2, -1);
@@ -703,4 +761,4 @@
     }
 
     return RUN_ALL_TESTS();
-}
\ No newline at end of file
+}
diff --git a/identity/support/src/IdentityCredentialSupport.cpp b/identity/support/src/IdentityCredentialSupport.cpp
index 77b795b..093120d 100644
--- a/identity/support/src/IdentityCredentialSupport.cpp
+++ b/identity/support/src/IdentityCredentialSupport.cpp
@@ -935,18 +935,19 @@
 optional<vector<vector<uint8_t>>> createAttestation(
         const EVP_PKEY* key, const vector<uint8_t>& applicationId, const vector<uint8_t>& challenge,
         uint64_t activeTimeMilliSeconds, uint64_t expireTimeMilliSeconds, bool isTestCredential) {
-    const keymaster_cert_chain_t* attestation_chain =
-            ::keymaster::getAttestationChain(KM_ALGORITHM_EC, nullptr);
-    if (attestation_chain == nullptr) {
-        LOG(ERROR) << "Error getting attestation chain";
+    keymaster_error_t error;
+    ::keymaster::CertificateChain attestation_chain =
+            ::keymaster::getAttestationChain(KM_ALGORITHM_EC, &error);
+    if (KM_ERROR_OK != error) {
+        LOG(ERROR) << "Error getting attestation chain " << error;
         return {};
     }
     if (expireTimeMilliSeconds == 0) {
-        if (attestation_chain->entry_count < 1) {
+        if (attestation_chain.entry_count < 1) {
             LOG(ERROR) << "Expected at least one entry in attestation chain";
             return {};
         }
-        keymaster_blob_t* bcBlob = &(attestation_chain->entries[0]);
+        keymaster_blob_t* bcBlob = &(attestation_chain.entries[0]);
         const uint8_t* bcData = bcBlob->data;
         auto bc = X509_Ptr(d2i_X509(nullptr, &bcData, bcBlob->data_length));
         time_t bcNotAfter;
@@ -1015,34 +1016,30 @@
     }
     ::keymaster::AuthorizationSet hwEnforced(hwEnforcedBuilder);
 
-    keymaster_error_t error;
-    ::keymaster::CertChainPtr cert_chain_out;
-
     // Pretend to be implemented in a trusted environment just so we can pass
     // the VTS tests. Of course, this is a pretend-only game since hopefully no
     // relying party is ever going to trust our batch key and those keys above
     // it.
-    //
     ::keymaster::PureSoftKeymasterContext context(::keymaster::KmVersion::KEYMASTER_4_1,
                                                   KM_SECURITY_LEVEL_TRUSTED_ENVIRONMENT);
 
-    error = generate_attestation_from_EVP(key, swEnforced, hwEnforced, auth_set, context,
-                                          *attestation_chain, *attestation_signing_key,
-                                          &cert_chain_out);
+    ::keymaster::CertificateChain cert_chain_out = generate_attestation_from_EVP(
+            key, swEnforced, hwEnforced, auth_set, context, move(attestation_chain),
+            *attestation_signing_key, &error);
 
-    if (KM_ERROR_OK != error || !cert_chain_out) {
+    if (KM_ERROR_OK != error) {
         LOG(ERROR) << "Error generate attestation from EVP key" << error;
         return {};
     }
 
-    // translate certificate format from keymaster_cert_chain_t to vector<uint8_t>.
+    // translate certificate format from keymaster_cert_chain_t to vector<vector<uint8_t>>.
     vector<vector<uint8_t>> attestationCertificate;
-    for (int i = 0; i < cert_chain_out->entry_count; i++) {
+    for (int i = 0; i < cert_chain_out.entry_count; i++) {
         attestationCertificate.insert(
                 attestationCertificate.end(),
                 vector<uint8_t>(
-                        cert_chain_out->entries[i].data,
-                        cert_chain_out->entries[i].data + cert_chain_out->entries[i].data_length));
+                        cert_chain_out.entries[i].data,
+                        cert_chain_out.entries[i].data + cert_chain_out.entries[i].data_length));
     }
 
     return attestationCertificate;
diff --git a/memtrack/aidl/Android.bp b/memtrack/aidl/Android.bp
new file mode 100644
index 0000000..fe4d01b
--- /dev/null
+++ b/memtrack/aidl/Android.bp
@@ -0,0 +1,33 @@
+// Copyright (C) 2020 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.
+
+aidl_interface {
+    name: "android.hardware.memtrack",
+    vendor_available: true,
+    srcs: ["android/hardware/memtrack/*.aidl"],
+    stability: "vintf",
+    backend: {
+        cpp: {
+            enabled: false,
+        },
+        java: {
+            enabled: false,
+        },
+        ndk: {
+            vndk: {
+                enabled: true,
+            },
+        },
+    },
+}
diff --git a/security/keymint/aidl/aidl_api/android.hardware.security.keymint/current/android/hardware/security/keymint/KeyDerivationFunction.aidl b/memtrack/aidl/aidl_api/android.hardware.memtrack/current/android/hardware/memtrack/DeviceInfo.aidl
similarity index 79%
copy from security/keymint/aidl/aidl_api/android.hardware.security.keymint/current/android/hardware/security/keymint/KeyDerivationFunction.aidl
copy to memtrack/aidl/aidl_api/android.hardware.memtrack/current/android/hardware/memtrack/DeviceInfo.aidl
index 83b7e6e..00abff9 100644
--- a/security/keymint/aidl/aidl_api/android.hardware.security.keymint/current/android/hardware/security/keymint/KeyDerivationFunction.aidl
+++ b/memtrack/aidl/aidl_api/android.hardware.memtrack/current/android/hardware/memtrack/DeviceInfo.aidl
@@ -15,13 +15,9 @@
 // with such a backward incompatible change, it has a high risk of breaking
 // later when a module using the interface is updated, e.g., Mainline modules.
 
-package android.hardware.security.keymint;
-@Backing(type="int") @VintfStability
-enum KeyDerivationFunction {
-  NONE = 0,
-  RFC5869_SHA256 = 1,
-  ISO18033_2_KDF1_SHA1 = 2,
-  ISO18033_2_KDF1_SHA256 = 3,
-  ISO18033_2_KDF2_SHA1 = 4,
-  ISO18033_2_KDF2_SHA256 = 5,
+package android.hardware.memtrack;
+@VintfStability
+parcelable DeviceInfo {
+  int id;
+  @utf8InCpp String name;
 }
diff --git a/security/keymint/aidl/aidl_api/android.hardware.security.keymint/current/android/hardware/security/keymint/KeyDerivationFunction.aidl b/memtrack/aidl/aidl_api/android.hardware.memtrack/current/android/hardware/memtrack/IMemtrack.aidl
similarity index 79%
copy from security/keymint/aidl/aidl_api/android.hardware.security.keymint/current/android/hardware/security/keymint/KeyDerivationFunction.aidl
copy to memtrack/aidl/aidl_api/android.hardware.memtrack/current/android/hardware/memtrack/IMemtrack.aidl
index 83b7e6e..844a1bb 100644
--- a/security/keymint/aidl/aidl_api/android.hardware.security.keymint/current/android/hardware/security/keymint/KeyDerivationFunction.aidl
+++ b/memtrack/aidl/aidl_api/android.hardware.memtrack/current/android/hardware/memtrack/IMemtrack.aidl
@@ -15,13 +15,9 @@
 // with such a backward incompatible change, it has a high risk of breaking
 // later when a module using the interface is updated, e.g., Mainline modules.
 
-package android.hardware.security.keymint;
-@Backing(type="int") @VintfStability
-enum KeyDerivationFunction {
-  NONE = 0,
-  RFC5869_SHA256 = 1,
-  ISO18033_2_KDF1_SHA1 = 2,
-  ISO18033_2_KDF1_SHA256 = 3,
-  ISO18033_2_KDF2_SHA1 = 4,
-  ISO18033_2_KDF2_SHA256 = 5,
+package android.hardware.memtrack;
+@VintfStability
+interface IMemtrack {
+  android.hardware.memtrack.MemtrackRecord[] getMemory(in int pid, in android.hardware.memtrack.MemtrackType type);
+  android.hardware.memtrack.DeviceInfo[] getGpuDeviceInfo();
 }
diff --git a/security/keymint/aidl/aidl_api/android.hardware.security.keymint/current/android/hardware/security/keymint/KeyDerivationFunction.aidl b/memtrack/aidl/aidl_api/android.hardware.memtrack/current/android/hardware/memtrack/MemtrackRecord.aidl
similarity index 71%
copy from security/keymint/aidl/aidl_api/android.hardware.security.keymint/current/android/hardware/security/keymint/KeyDerivationFunction.aidl
copy to memtrack/aidl/aidl_api/android.hardware.memtrack/current/android/hardware/memtrack/MemtrackRecord.aidl
index 83b7e6e..09ecefc 100644
--- a/security/keymint/aidl/aidl_api/android.hardware.security.keymint/current/android/hardware/security/keymint/KeyDerivationFunction.aidl
+++ b/memtrack/aidl/aidl_api/android.hardware.memtrack/current/android/hardware/memtrack/MemtrackRecord.aidl
@@ -15,13 +15,18 @@
 // with such a backward incompatible change, it has a high risk of breaking
 // later when a module using the interface is updated, e.g., Mainline modules.
 
-package android.hardware.security.keymint;
-@Backing(type="int") @VintfStability
-enum KeyDerivationFunction {
-  NONE = 0,
-  RFC5869_SHA256 = 1,
-  ISO18033_2_KDF1_SHA1 = 2,
-  ISO18033_2_KDF1_SHA256 = 3,
-  ISO18033_2_KDF2_SHA1 = 4,
-  ISO18033_2_KDF2_SHA256 = 5,
+package android.hardware.memtrack;
+@VintfStability
+parcelable MemtrackRecord {
+  int flags;
+  long sizeInBytes;
+  const int FLAG_SMAPS_ACCOUNTED = 2;
+  const int FLAG_SMAPS_UNACCOUNTED = 4;
+  const int FLAG_SHARED = 8;
+  const int FLAG_SHARED_PSS = 16;
+  const int FLAG_PRIVATE = 32;
+  const int FLAG_SYSTEM = 64;
+  const int FLAG_DEDICATED = 128;
+  const int FLAG_NONSECURE = 256;
+  const int FLAG_SECURE = 512;
 }
diff --git a/security/keymint/aidl/aidl_api/android.hardware.security.keymint/current/android/hardware/security/keymint/KeyDerivationFunction.aidl b/memtrack/aidl/aidl_api/android.hardware.memtrack/current/android/hardware/memtrack/MemtrackType.aidl
similarity index 82%
rename from security/keymint/aidl/aidl_api/android.hardware.security.keymint/current/android/hardware/security/keymint/KeyDerivationFunction.aidl
rename to memtrack/aidl/aidl_api/android.hardware.memtrack/current/android/hardware/memtrack/MemtrackType.aidl
index 83b7e6e..7f3f939 100644
--- a/security/keymint/aidl/aidl_api/android.hardware.security.keymint/current/android/hardware/security/keymint/KeyDerivationFunction.aidl
+++ b/memtrack/aidl/aidl_api/android.hardware.memtrack/current/android/hardware/memtrack/MemtrackType.aidl
@@ -15,13 +15,13 @@
 // with such a backward incompatible change, it has a high risk of breaking
 // later when a module using the interface is updated, e.g., Mainline modules.
 
-package android.hardware.security.keymint;
+package android.hardware.memtrack;
 @Backing(type="int") @VintfStability
-enum KeyDerivationFunction {
-  NONE = 0,
-  RFC5869_SHA256 = 1,
-  ISO18033_2_KDF1_SHA1 = 2,
-  ISO18033_2_KDF1_SHA256 = 3,
-  ISO18033_2_KDF2_SHA1 = 4,
-  ISO18033_2_KDF2_SHA256 = 5,
+enum MemtrackType {
+  OTHER = 0,
+  GL = 1,
+  GRAPHICS = 2,
+  MULTIMEDIA = 3,
+  CAMERA = 4,
+  NUM_TYPES = 5,
 }
diff --git a/memtrack/aidl/android/hardware/memtrack/DeviceInfo.aidl b/memtrack/aidl/android/hardware/memtrack/DeviceInfo.aidl
new file mode 100644
index 0000000..bcba544
--- /dev/null
+++ b/memtrack/aidl/android/hardware/memtrack/DeviceInfo.aidl
@@ -0,0 +1,27 @@
+/*
+ * Copyright (C) 2020 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.memtrack;
+
+/*
+ * Contains the device name and the device id.
+ */
+@VintfStability
+parcelable DeviceInfo {
+    int id;
+    @utf8InCpp String name;
+}
+
diff --git a/memtrack/aidl/android/hardware/memtrack/IMemtrack.aidl b/memtrack/aidl/android/hardware/memtrack/IMemtrack.aidl
new file mode 100644
index 0000000..18587ee
--- /dev/null
+++ b/memtrack/aidl/android/hardware/memtrack/IMemtrack.aidl
@@ -0,0 +1,82 @@
+/*
+ * Copyright (C) 2020 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.memtrack;
+
+import android.hardware.memtrack.DeviceInfo;
+import android.hardware.memtrack.MemtrackRecord;
+import android.hardware.memtrack.MemtrackType;
+
+/**
+ * The Memory Tracker HAL is designed to return information about
+ * device-specific memory usage.
+ * The primary goal is to be able to track memory that is not
+ * trackable in any other way, for example texture memory that is allocated by
+ * a process, but not mapped in to that process's address space.
+ * A secondary goal is to be able to categorize memory used by a process into
+ * GL, graphics, etc. All memory sizes must be in real memory usage,
+ * accounting for stride, bit depth, rounding up to page size, etc.
+ *
+ * Constructor for the interface should be used to perform memtrack management
+ * setup actions and must be called once before any calls to getMemory().
+ */
+@VintfStability
+interface IMemtrack {
+    /**
+     * getMemory() populates MemtrackRecord vector with the sizes of memory
+     * plus associated flags for that memory.
+     *
+     * A process collecting memory statistics will call getMemory for each
+     * combination of pid and memory type. For each memory type that it
+     * recognizes, the HAL must fill out an array of memtrack_record
+     * structures breaking down the statistics of that memory type as much as
+     * possible. For example,
+     * getMemory(<pid>, GL) might return:
+     * { { 4096,  ACCOUNTED | PRIVATE | SYSTEM },
+     *   { 40960, UNACCOUNTED | PRIVATE | SYSTEM },
+     *   { 8192,  ACCOUNTED | PRIVATE | DEDICATED },
+     *   { 8192,  UNACCOUNTED | PRIVATE | DEDICATED } }
+     * If the HAL cannot differentiate between SYSTEM and DEDICATED memory, it
+     * could return:
+     * { { 12288,  ACCOUNTED | PRIVATE },
+     *   { 49152,  UNACCOUNTED | PRIVATE } }
+     *
+     * Memory must not overlap between types. For example, a graphics buffer
+     * that has been mapped into the GPU as a surface must show up when
+     * GRAPHICS is requested and not when GL
+     * is requested.
+     *
+     * @param pid process for which memory information is requested
+     * @param type memory type that information is being requested about
+     * @return vector of MemtrackRecord containing memory information
+     */
+    MemtrackRecord[] getMemory(in int pid, in MemtrackType type);
+
+    /**
+     * getGpuDeviceInfo() populates DeviceInfo with the ID and name
+     * of each GPU device.
+     *
+     * For example, getGpuDeviceInfor, might return:
+     * { { 0, <gpu-device-name> },
+     *   { 1, <gpu-device-name> } }
+     *
+     * This information is used to identify GPU devices for GPU specific
+     * memory accounting (e.g. DMA buffer usage).
+     *
+     * @return vector of DeviceInfo populated for all GPU devices.
+     */
+     DeviceInfo[] getGpuDeviceInfo();
+}
diff --git a/memtrack/aidl/android/hardware/memtrack/MemtrackRecord.aidl b/memtrack/aidl/android/hardware/memtrack/MemtrackRecord.aidl
new file mode 100644
index 0000000..dae026e
--- /dev/null
+++ b/memtrack/aidl/android/hardware/memtrack/MemtrackRecord.aidl
@@ -0,0 +1,41 @@
+/*
+ * Copyright (C) 2020 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.memtrack;
+
+/*
+ * Each record consists of the size of the memory used by the process and
+ * flags indicate all the MemtrackFlags that are valid for this record.
+ */
+@VintfStability
+parcelable MemtrackRecord {
+    /* Memtrack Flags */
+    const int FLAG_SMAPS_ACCOUNTED = 1 << 1;
+    const int FLAG_SMAPS_UNACCOUNTED = 1 << 2;
+    const int FLAG_SHARED = 1 << 3;
+    const int FLAG_SHARED_PSS = 1 << 4;
+    const int FLAG_PRIVATE = 1 << 5;
+    const int FLAG_SYSTEM = 1 << 6;
+    const int FLAG_DEDICATED = 1 << 7;
+    const int FLAG_NONSECURE = 1 << 8;
+    const int FLAG_SECURE = 1 << 9;
+
+    /* Bitfield indicating all flags that are valid for this record */
+    int flags;
+
+    long sizeInBytes;
+}
+
diff --git a/memtrack/aidl/android/hardware/memtrack/MemtrackType.aidl b/memtrack/aidl/android/hardware/memtrack/MemtrackType.aidl
new file mode 100644
index 0000000..715c6bf
--- /dev/null
+++ b/memtrack/aidl/android/hardware/memtrack/MemtrackType.aidl
@@ -0,0 +1,31 @@
+/*
+ * Copyright (C) 2020 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.memtrack;
+
+/**
+ * Tags which define the usage of the memory buffers.
+ */
+@VintfStability
+@Backing(type="int")
+enum MemtrackType {
+    OTHER = 0,
+    GL = 1,
+    GRAPHICS = 2,
+    MULTIMEDIA = 3,
+    CAMERA = 4,
+    NUM_TYPES,
+}
diff --git a/memtrack/aidl/default/Android.bp b/memtrack/aidl/default/Android.bp
new file mode 100644
index 0000000..52f88c8
--- /dev/null
+++ b/memtrack/aidl/default/Android.bp
@@ -0,0 +1,30 @@
+// Copyright (C) 2020 The Android Open Source Project
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+//       http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+cc_binary {
+    name: "android.hardware.memtrack-service.example",
+    relative_install_path: "hw",
+    init_rc: ["memtrack-default.rc"],
+    vintf_fragments: ["memtrack-default.xml"],
+    vendor: true,
+    shared_libs: [
+        "libbase",
+        "libbinder_ndk",
+        "android.hardware.memtrack-ndk_platform",
+    ],
+    srcs: [
+        "main.cpp",
+        "Memtrack.cpp",
+    ],
+}
diff --git a/memtrack/aidl/default/Memtrack.cpp b/memtrack/aidl/default/Memtrack.cpp
new file mode 100644
index 0000000..7361719
--- /dev/null
+++ b/memtrack/aidl/default/Memtrack.cpp
@@ -0,0 +1,44 @@
+/*
+ * Copyright (C) 2020 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 "Memtrack.h"
+
+namespace aidl {
+namespace android {
+namespace hardware {
+namespace memtrack {
+
+ndk::ScopedAStatus Memtrack::getMemory(int pid, MemtrackType type,
+                                       std::vector<MemtrackRecord>* _aidl_return) {
+    if (pid < 0) {
+        return ndk::ScopedAStatus(AStatus_fromExceptionCode(EX_ILLEGAL_ARGUMENT));
+    }
+    if (type < MemtrackType::OTHER || type >= MemtrackType::NUM_TYPES) {
+        return ndk::ScopedAStatus(AStatus_fromExceptionCode(EX_UNSUPPORTED_OPERATION));
+    }
+    _aidl_return->clear();
+    return ndk::ScopedAStatus::ok();
+}
+
+ndk::ScopedAStatus Memtrack::getGpuDeviceInfo(std::vector<DeviceInfo>* _aidl_return) {
+    _aidl_return->clear();
+    return ndk::ScopedAStatus::ok();
+}
+
+}  // namespace memtrack
+}  // namespace hardware
+}  // namespace android
+}  // namespace aidl
diff --git a/memtrack/aidl/default/Memtrack.h b/memtrack/aidl/default/Memtrack.h
new file mode 100644
index 0000000..f2ef60e
--- /dev/null
+++ b/memtrack/aidl/default/Memtrack.h
@@ -0,0 +1,39 @@
+/*
+ * Copyright (C) 2020 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#pragma once
+
+#include <aidl/android/hardware/memtrack/BnMemtrack.h>
+#include <aidl/android/hardware/memtrack/DeviceInfo.h>
+#include <aidl/android/hardware/memtrack/MemtrackRecord.h>
+#include <aidl/android/hardware/memtrack/MemtrackType.h>
+
+namespace aidl {
+namespace android {
+namespace hardware {
+namespace memtrack {
+
+class Memtrack : public BnMemtrack {
+    ndk::ScopedAStatus getMemory(int pid, MemtrackType type,
+                                 std::vector<MemtrackRecord>* _aidl_return) override;
+
+    ndk::ScopedAStatus getGpuDeviceInfo(std::vector<DeviceInfo>* _aidl_return) override;
+};
+
+}  // namespace memtrack
+}  // namespace hardware
+}  // namespace android
+}  // namespace aidl
diff --git a/memtrack/aidl/default/main.cpp b/memtrack/aidl/default/main.cpp
new file mode 100644
index 0000000..d063d2a
--- /dev/null
+++ b/memtrack/aidl/default/main.cpp
@@ -0,0 +1,36 @@
+/*
+ * Copyright (C) 2020 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 "Memtrack.h"
+
+#include <android-base/logging.h>
+#include <android/binder_manager.h>
+#include <android/binder_process.h>
+
+using aidl::android::hardware::memtrack::Memtrack;
+
+int main() {
+    ABinderProcess_setThreadPoolMaxThreadCount(0);
+    std::shared_ptr<Memtrack> memtrack = ndk::SharedRefBase::make<Memtrack>();
+
+    const std::string instance = std::string() + Memtrack::descriptor + "/default";
+    binder_status_t status =
+            AServiceManager_addService(memtrack->asBinder().get(), instance.c_str());
+    CHECK(status == STATUS_OK);
+
+    ABinderProcess_joinThreadPool();
+    return EXIT_FAILURE;  // Unreachable
+}
diff --git a/memtrack/aidl/default/memtrack-default.rc b/memtrack/aidl/default/memtrack-default.rc
new file mode 100644
index 0000000..1725cd0
--- /dev/null
+++ b/memtrack/aidl/default/memtrack-default.rc
@@ -0,0 +1,4 @@
+service vendor.memtrack-default /vendor/bin/hw/android.hardware.memtrack-service.example
+    class hal
+    user nobody
+    group system
diff --git a/memtrack/aidl/default/memtrack-default.xml b/memtrack/aidl/default/memtrack-default.xml
new file mode 100644
index 0000000..3e3e0f6
--- /dev/null
+++ b/memtrack/aidl/default/memtrack-default.xml
@@ -0,0 +1,7 @@
+<manifest version="1.0" type="device">
+    <hal format="aidl">
+        <name>android.hardware.memtrack</name>
+        <fqname>IMemtrack/default</fqname>
+    </hal>
+</manifest>
+
diff --git a/memtrack/aidl/vts/Android.bp b/memtrack/aidl/vts/Android.bp
new file mode 100644
index 0000000..ea36677
--- /dev/null
+++ b/memtrack/aidl/vts/Android.bp
@@ -0,0 +1,17 @@
+cc_test {
+    name: "VtsHalMemtrackTargetTest",
+    defaults: [
+        "VtsHalTargetTestDefaults",
+        "use_libaidlvintf_gtest_helper_static",
+    ],
+    srcs: ["VtsHalMemtrackTargetTest.cpp"],
+    shared_libs: [
+        "libbinder_ndk",
+    ],
+    static_libs: [
+        "android.hardware.memtrack-unstable-ndk_platform",
+    ],
+    test_suites: [
+        "vts-core",
+    ],
+}
diff --git a/memtrack/aidl/vts/VtsHalMemtrackTargetTest.cpp b/memtrack/aidl/vts/VtsHalMemtrackTargetTest.cpp
new file mode 100644
index 0000000..4d33101
--- /dev/null
+++ b/memtrack/aidl/vts/VtsHalMemtrackTargetTest.cpp
@@ -0,0 +1,91 @@
+/*
+ * Copyright (C) 2020 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 <aidl/Gtest.h>
+#include <aidl/Vintf.h>
+
+#include <aidl/android/hardware/memtrack/DeviceInfo.h>
+#include <aidl/android/hardware/memtrack/IMemtrack.h>
+#include <aidl/android/hardware/memtrack/MemtrackType.h>
+#include <android/binder_manager.h>
+#include <android/binder_process.h>
+
+using aidl::android::hardware::memtrack::DeviceInfo;
+using aidl::android::hardware::memtrack::IMemtrack;
+using aidl::android::hardware::memtrack::MemtrackRecord;
+using aidl::android::hardware::memtrack::MemtrackType;
+
+class MemtrackAidlTest : public testing::TestWithParam<std::string> {
+  public:
+    virtual void SetUp() override {
+        const auto instance = GetParam();
+        ASSERT_TRUE(AServiceManager_isDeclared(instance.c_str()));
+        auto memtrackBinder = ndk::SpAIBinder(AServiceManager_waitForService(instance.c_str()));
+        memtrack_ = IMemtrack::fromBinder(memtrackBinder);
+        ASSERT_NE(memtrack_, nullptr);
+    }
+
+    std::shared_ptr<IMemtrack> memtrack_;
+};
+
+TEST_P(MemtrackAidlTest, GetMemoryInvalidPid) {
+    int pid = -1;
+    MemtrackType type = MemtrackType::OTHER;
+    std::vector<MemtrackRecord> records;
+
+    auto status = memtrack_->getMemory(pid, type, &records);
+
+    EXPECT_EQ(status.getExceptionCode(), EX_ILLEGAL_ARGUMENT);
+}
+
+TEST_P(MemtrackAidlTest, GetMemoryInvalidType) {
+    int pid = 1;
+    MemtrackType type = MemtrackType::NUM_TYPES;
+    std::vector<MemtrackRecord> records;
+
+    auto status = memtrack_->getMemory(pid, type, &records);
+
+    EXPECT_EQ(status.getExceptionCode(), EX_UNSUPPORTED_OPERATION);
+}
+
+TEST_P(MemtrackAidlTest, GetMemory) {
+    int pid = 1;
+    MemtrackType type = MemtrackType::OTHER;
+    std::vector<MemtrackRecord> records;
+
+    auto status = memtrack_->getMemory(pid, type, &records);
+
+    EXPECT_TRUE(status.isOk());
+}
+
+TEST_P(MemtrackAidlTest, GetGpuDeviceInfo) {
+    std::vector<DeviceInfo> device_info;
+
+    auto status = memtrack_->getGpuDeviceInfo(&device_info);
+
+    EXPECT_TRUE(status.isOk());
+}
+
+GTEST_ALLOW_UNINSTANTIATED_PARAMETERIZED_TEST(MemtrackAidlTest);
+INSTANTIATE_TEST_SUITE_P(PerInstance, MemtrackAidlTest,
+                         testing::ValuesIn(android::getAidlHalInstanceNames(IMemtrack::descriptor)),
+                         android::PrintInstanceNameToString);
+
+int main(int argc, char** argv) {
+    ::testing::InitGoogleTest(&argc, argv);
+    ABinderProcess_setThreadPoolMaxThreadCount(1);
+    ABinderProcess_startThreadPool();
+    return RUN_ALL_TESTS();
+}
diff --git a/security/keymint/aidl/aidl_api/android.hardware.security.keymint/current/android/hardware/security/keymint/KeyDerivationFunction.aidl b/power/stats/aidl/aidl_api/android.hardware.power.stats/current/android/hardware/power/stats/EnergyConsumerAttribution.aidl
similarity index 79%
copy from security/keymint/aidl/aidl_api/android.hardware.security.keymint/current/android/hardware/security/keymint/KeyDerivationFunction.aidl
copy to power/stats/aidl/aidl_api/android.hardware.power.stats/current/android/hardware/power/stats/EnergyConsumerAttribution.aidl
index 83b7e6e..0a7cff7 100644
--- a/security/keymint/aidl/aidl_api/android.hardware.security.keymint/current/android/hardware/security/keymint/KeyDerivationFunction.aidl
+++ b/power/stats/aidl/aidl_api/android.hardware.power.stats/current/android/hardware/power/stats/EnergyConsumerAttribution.aidl
@@ -15,13 +15,9 @@
 // with such a backward incompatible change, it has a high risk of breaking
 // later when a module using the interface is updated, e.g., Mainline modules.
 
-package android.hardware.security.keymint;
-@Backing(type="int") @VintfStability
-enum KeyDerivationFunction {
-  NONE = 0,
-  RFC5869_SHA256 = 1,
-  ISO18033_2_KDF1_SHA1 = 2,
-  ISO18033_2_KDF1_SHA256 = 3,
-  ISO18033_2_KDF2_SHA1 = 4,
-  ISO18033_2_KDF2_SHA256 = 5,
+package android.hardware.power.stats;
+@VintfStability
+parcelable EnergyConsumerAttribution {
+  int uid;
+  long energyUWs;
 }
diff --git a/power/stats/aidl/aidl_api/android.hardware.power.stats/current/android/hardware/power/stats/EnergyConsumerResult.aidl b/power/stats/aidl/aidl_api/android.hardware.power.stats/current/android/hardware/power/stats/EnergyConsumerResult.aidl
index 6289a08..815316e 100644
--- a/power/stats/aidl/aidl_api/android.hardware.power.stats/current/android/hardware/power/stats/EnergyConsumerResult.aidl
+++ b/power/stats/aidl/aidl_api/android.hardware.power.stats/current/android/hardware/power/stats/EnergyConsumerResult.aidl
@@ -21,4 +21,5 @@
   android.hardware.power.stats.EnergyConsumerId energyConsumerId;
   long timestampMs;
   long energyUWs;
+  android.hardware.power.stats.EnergyConsumerAttribution[] attribution;
 }
diff --git a/power/stats/aidl/android/hardware/power/stats/EnergyConsumerAttribution.aidl b/power/stats/aidl/android/hardware/power/stats/EnergyConsumerAttribution.aidl
new file mode 100644
index 0000000..e07204a
--- /dev/null
+++ b/power/stats/aidl/android/hardware/power/stats/EnergyConsumerAttribution.aidl
@@ -0,0 +1,29 @@
+/*
+ * Copyright (C) 2020 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.power.stats;
+
+@VintfStability
+parcelable EnergyConsumerAttribution {
+    /**
+     * Android ID / Linux UID, the accumulated energy should be attributed to
+     */
+    int uid;
+    /**
+     * Accumulated energy since boot in microwatt-seconds (uWs) for this AID
+     */
+    long energyUWs;
+}
diff --git a/power/stats/aidl/android/hardware/power/stats/EnergyConsumerResult.aidl b/power/stats/aidl/android/hardware/power/stats/EnergyConsumerResult.aidl
index d2b902a..e8d3dd9 100644
--- a/power/stats/aidl/android/hardware/power/stats/EnergyConsumerResult.aidl
+++ b/power/stats/aidl/android/hardware/power/stats/EnergyConsumerResult.aidl
@@ -17,6 +17,7 @@
 package android.hardware.power.stats;
 
 import android.hardware.power.stats.EnergyConsumerId;
+import android.hardware.power.stats.EnergyConsumerAttribution;
 
 @VintfStability
 parcelable EnergyConsumerResult {
@@ -32,5 +33,9 @@
      * Accumulated energy since boot in microwatt-seconds (uWs)
      */
     long energyUWs;
+    /**
+     * Optional attribution per UID for this EnergyConsumer.
+     */
+    EnergyConsumerAttribution[] attribution;
 }
 
diff --git a/radio/1.6/IRadio.hal b/radio/1.6/IRadio.hal
index 3dc80b9..a398e7d 100644
--- a/radio/1.6/IRadio.hal
+++ b/radio/1.6/IRadio.hal
@@ -117,6 +117,9 @@
      * @param pduSessionId The pdu session id to be used for this data call.  A value of 0 means
      *     no pdu session id was attached to this call.
      *     Reference: 3GPP TS 24.007 section 11.2.3.1b
+     * @param sliceInfo SliceInfo to be used for the data connection when a handover occurs from
+     *     EPDG to 5G.  It is valid only when accessNetwork is AccessNetwork:NGRAN.  If the slice
+     *     passed from EPDG is rejected, then the data failure cause must be DataCallFailCause:SLICE_REJECTED.
      *
      * Response function is IRadioResponse.setupDataCallResponse_1_6()
      *
@@ -125,7 +128,7 @@
     oneway setupDataCall_1_6(int32_t serial, AccessNetwork accessNetwork,
             DataProfileInfo dataProfileInfo, bool roamingAllowed,
             DataRequestReason reason, vec<LinkAddress> addresses, vec<string> dnses,
-            int32_t pduSessionId);
+            int32_t pduSessionId, OptionalSliceInfo sliceInfo);
 
     /**
      * Send an SMS message
diff --git a/radio/1.6/types.hal b/radio/1.6/types.hal
index f4dc0bd..550e079 100644
--- a/radio/1.6/types.hal
+++ b/radio/1.6/types.hal
@@ -352,6 +352,12 @@
      * Reference: 3GPP TS 24.007 section 11.2.3.1b
      */
     int32_t pduSessionId;
+
+    /**
+     * Slice used for this data call. It is valid only when this data call is on
+     * AccessNetwork:NGRAN.
+     */
+    OptionalSliceInfo sliceInfo;
 };
 
 /**
@@ -405,7 +411,8 @@
     * This bandwidth estimate shall be the estimated maximum sustainable link bandwidth
     * (as would be measured at the Upper PDCP or SNDCP SAP). This is valid only
     * in if device is connected to both primary and secodary in dual connected
-    * mode. This must be filled with -1 if secondary is not connected.
+    * mode. This must be filled with -1 if secondary is not connected or if
+    * modem does not support this feature.
     */
    uint32_t secondaryDownlinkCapacityKbps;
 
@@ -414,7 +421,8 @@
     * This bandwidth estimate shall be the estimated
     * maximum sustainable link bandwidth (as would be measured at the Upper PDCP or SNDCP SAP).
     * This is valid only in if device is connected to both primary and secodary in dual connected
-    * mode.This must be filled with -1 if secondary is not connected.
+    * mode.This must be filled with -1 if secondary is not connected or if modem
+    * does not support this feature.
     */
    uint32_t secondaryUplinkCapacityKbps;
 };
@@ -733,3 +741,80 @@
      */
     string forwardedNumber;
 };
+
+/**
+ * This safe_union represents an optional slice info
+ */
+safe_union OptionalSliceInfo {
+    Monostate noinit;
+    SliceInfo value;
+};
+
+/**
+ * This struct represents a S-NSSAI as defined in 3GPP TS 24.501.
+ */
+struct SliceInfo {
+    /**
+     * The type of service provided by the slice.
+     *
+     * see: 3GPP TS 24.501 Section 9.11.2.8.
+     */
+    SliceServiceType sst;
+
+    /**
+     * Slice differentiator is the identifier of a slice that has
+     * SliceServiceType as SST. A value of -1 indicates that there is
+     * no corresponding SliceInfo of the HPLMN.
+     *
+     * see: 3GPP TS 24.501 Section 9.11.2.8.
+     */
+    int32_t sliceDifferentiator;
+
+    /**
+     * This SST corresponds to a SliceInfo (S-NSSAI) of the HPLMN; the SST is
+     * mapped to this value.
+     *
+     * see: 3GPP TS 24.501 Section 9.11.2.8.
+     */
+    SliceServiceType mappedHplmnSst;
+
+    /**
+     * Present only if both sliceDifferentiator and mappedHplmnSst are also
+     * present. This SD corresponds to a SliceInfo (S-NSSAI) of the HPLMN;
+     * sliceDifferentiator is mapped to this value. A value of -1 indicates that
+     * there is no corresponding SliceInfo of the HPLMN.
+     *
+     * see: 3GPP TS 24.501 Section 9.11.2.8.
+     */
+    int32_t mappedHplmnSD;
+};
+
+/**
+ * Slice/Service Type as defined in 3GPP TS 23.501.
+ */
+enum SliceServiceType : uint8_t {
+    /* Not specified */
+    NONE = 0,
+
+    /* Slice suitable for the handling of 5G enhanced Mobile Broadband */
+    EMBB = 1,
+
+    /**
+     * Slice suitable for the handling of ultra-reliable low latency
+     * communications
+     */
+    URLLC = 2,
+
+    /* Slice suitable for the handling of massive IoT */
+    MIOT = 3,
+};
+
+/**
+ * Expose more setup data call failures.
+ */
+enum DataCallFailCause : @1.4::DataCallFailCause {
+    /**
+     * Data call fail due to the slice not being allowed for the data call.
+     */
+    SLICE_REJECTED = 0x8CC,
+};
diff --git a/radio/1.6/vts/functional/radio_hidl_hal_api.cpp b/radio/1.6/vts/functional/radio_hidl_hal_api.cpp
index 47babed..8b87292 100644
--- a/radio/1.6/vts/functional/radio_hidl_hal_api.cpp
+++ b/radio/1.6/vts/functional/radio_hidl_hal_api.cpp
@@ -56,8 +56,12 @@
     ::android::hardware::radio::V1_2::DataRequestReason reason =
             ::android::hardware::radio::V1_2::DataRequestReason::NORMAL;
 
-    Return<void> res = radio_v1_6->setupDataCall_1_6(serial, accessNetwork, dataProfileInfo,
-                                                     roamingAllowed, reason, addresses, dnses, -1);
+    ::android::hardware::radio::V1_6::OptionalSliceInfo optionalSliceInfo;
+    memset(&optionalSliceInfo, 0, sizeof(optionalSliceInfo));
+
+    Return<void> res =
+            radio_v1_6->setupDataCall_1_6(serial, accessNetwork, dataProfileInfo, roamingAllowed,
+                                          reason, addresses, dnses, -1, optionalSliceInfo);
     ASSERT_OK(res);
 
     EXPECT_EQ(std::cv_status::no_timeout, wait());
diff --git a/security/keymint/aidl/aidl_api/android.hardware.security.keymint/current/android/hardware/security/keymint/ErrorCode.aidl b/security/keymint/aidl/aidl_api/android.hardware.security.keymint/current/android/hardware/security/keymint/ErrorCode.aidl
index cdcb08d..8694b32 100644
--- a/security/keymint/aidl/aidl_api/android.hardware.security.keymint/current/android/hardware/security/keymint/ErrorCode.aidl
+++ b/security/keymint/aidl/aidl_api/android.hardware.security.keymint/current/android/hardware/security/keymint/ErrorCode.aidl
@@ -94,6 +94,8 @@
   ATTESTATION_IDS_NOT_PROVISIONED = -75,
   INVALID_OPERATION = -76,
   STORAGE_KEY_UNSUPPORTED = -77,
+  INCOMPATIBLE_MGF_DIGEST = -78,
+  UNSUPPORTED_MGF_DIGEST = -79,
   UNIMPLEMENTED = -100,
   VERSION_MISMATCH = -101,
   UNKNOWN_ERROR = -1000,
diff --git a/security/keymint/aidl/aidl_api/android.hardware.security.keymint/current/android/hardware/security/keymint/KeyParameter.aidl b/security/keymint/aidl/aidl_api/android.hardware.security.keymint/current/android/hardware/security/keymint/KeyParameter.aidl
index 91f83e4..4985768 100644
--- a/security/keymint/aidl/aidl_api/android.hardware.security.keymint/current/android/hardware/security/keymint/KeyParameter.aidl
+++ b/security/keymint/aidl/aidl_api/android.hardware.security.keymint/current/android/hardware/security/keymint/KeyParameter.aidl
@@ -16,11 +16,8 @@
 // later when a module using the interface is updated, e.g., Mainline modules.
 
 package android.hardware.security.keymint;
-@VintfStability
+@RustDerive(Clone=true, Eq=true, Hash=true, Ord=true, PartialEq=true, PartialOrd=true) @VintfStability
 parcelable KeyParameter {
   android.hardware.security.keymint.Tag tag;
-  boolean boolValue;
-  int integer;
-  long longInteger;
-  byte[] blob;
+  android.hardware.security.keymint.KeyParameterValue value;
 }
diff --git a/security/keymint/aidl/aidl_api/android.hardware.security.keymint/current/android/hardware/security/keymint/KeyParameterValue.aidl b/security/keymint/aidl/aidl_api/android.hardware.security.keymint/current/android/hardware/security/keymint/KeyParameterValue.aidl
new file mode 100644
index 0000000..ecf20ad
--- /dev/null
+++ b/security/keymint/aidl/aidl_api/android.hardware.security.keymint/current/android/hardware/security/keymint/KeyParameterValue.aidl
@@ -0,0 +1,36 @@
+///////////////////////////////////////////////////////////////////////////////
+// THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE.                          //
+///////////////////////////////////////////////////////////////////////////////
+
+// This file is a snapshot of an AIDL interface (or parcelable). Do not try to
+// edit this file. It looks like you are doing that because you have modified
+// an AIDL interface in a backward-incompatible way, e.g., deleting a function
+// from an interface or a field from a parcelable and it broke the build. That
+// breakage is intended.
+//
+// You must not make a backward incompatible changes to the AIDL files built
+// with the aidl_interface module type with versions property set. The module
+// type is used to build AIDL files in a way that they can be used across
+// independently updatable components of the system. If a device is shipped
+// with such a backward incompatible change, it has a high risk of breaking
+// later when a module using the interface is updated, e.g., Mainline modules.
+
+package android.hardware.security.keymint;
+@RustDerive(Clone=true, Eq=true, Hash=true, Ord=true, PartialEq=true, PartialOrd=true) @VintfStability
+union KeyParameterValue {
+  int invalid;
+  android.hardware.security.keymint.Algorithm algorithm;
+  android.hardware.security.keymint.BlockMode blockMode;
+  android.hardware.security.keymint.PaddingMode paddingMode;
+  android.hardware.security.keymint.Digest digest;
+  android.hardware.security.keymint.EcCurve ecCurve;
+  android.hardware.security.keymint.KeyOrigin origin;
+  android.hardware.security.keymint.KeyPurpose keyPurpose;
+  android.hardware.security.keymint.HardwareAuthenticatorType hardwareAuthenticatorType;
+  android.hardware.security.keymint.SecurityLevel securityLevel;
+  boolean boolValue;
+  int integer;
+  long longInteger;
+  long dateTime;
+  byte[] blob;
+}
diff --git a/security/keymint/aidl/aidl_api/android.hardware.security.keymint/current/android/hardware/security/keymint/Tag.aidl b/security/keymint/aidl/aidl_api/android.hardware.security.keymint/current/android/hardware/security/keymint/Tag.aidl
index 38eb6e6..814405c 100644
--- a/security/keymint/aidl/aidl_api/android.hardware.security.keymint/current/android/hardware/security/keymint/Tag.aidl
+++ b/security/keymint/aidl/aidl_api/android.hardware.security.keymint/current/android/hardware/security/keymint/Tag.aidl
@@ -30,6 +30,7 @@
   EC_CURVE = 268435466,
   RSA_PUBLIC_EXPONENT = 1342177480,
   INCLUDE_UNIQUE_ID = 1879048394,
+  RSA_OAEP_MGF_DIGEST = 536871115,
   BLOB_USAGE_REQUIREMENTS = 268435757,
   BOOTLOADER_ONLY = 1879048494,
   ROLLBACK_RESISTANCE = 1879048495,
diff --git a/security/keymint/aidl/android/hardware/security/keymint/ErrorCode.aidl b/security/keymint/aidl/android/hardware/security/keymint/ErrorCode.aidl
index fb24ad1..b20601d 100644
--- a/security/keymint/aidl/android/hardware/security/keymint/ErrorCode.aidl
+++ b/security/keymint/aidl/android/hardware/security/keymint/ErrorCode.aidl
@@ -99,6 +99,8 @@
     ATTESTATION_IDS_NOT_PROVISIONED = -75,
     INVALID_OPERATION = -76,
     STORAGE_KEY_UNSUPPORTED = -77,
+    INCOMPATIBLE_MGF_DIGEST = -78,
+    UNSUPPORTED_MGF_DIGEST = -79,
 
     UNIMPLEMENTED = -100,
     VERSION_MISMATCH = -101,
diff --git a/security/keymint/aidl/android/hardware/security/keymint/KeyDerivationFunction.aidl b/security/keymint/aidl/android/hardware/security/keymint/KeyDerivationFunction.aidl
deleted file mode 100644
index e166ab6..0000000
--- a/security/keymint/aidl/android/hardware/security/keymint/KeyDerivationFunction.aidl
+++ /dev/null
@@ -1,37 +0,0 @@
-/*
- * Copyright (C) 2020 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.security.keymint;
-
-/**
- * Key derivation functions, mostly used in ECIES.
- */
-@VintfStability
-@Backing(type="int")
-enum KeyDerivationFunction {
-    /** Do not apply a key derivation function; use the raw agreed key */
-    NONE = 0,
-    /** HKDF defined in RFC 5869 with SHA256 */
-    RFC5869_SHA256 = 1,
-    /** KDF1 defined in ISO 18033-2 with SHA1 */
-    ISO18033_2_KDF1_SHA1 = 2,
-    /** KDF1 defined in ISO 18033-2 with SHA256 */
-    ISO18033_2_KDF1_SHA256 = 3,
-    /** KDF2 defined in ISO 18033-2 with SHA1 */
-    ISO18033_2_KDF2_SHA1 = 4,
-    /** KDF2 defined in ISO 18033-2 with SHA256 */
-    ISO18033_2_KDF2_SHA256 = 5,
-}
diff --git a/security/keymint/aidl/android/hardware/security/keymint/KeyParameter.aidl b/security/keymint/aidl/android/hardware/security/keymint/KeyParameter.aidl
index 938064c..f3ed96b 100644
--- a/security/keymint/aidl/android/hardware/security/keymint/KeyParameter.aidl
+++ b/security/keymint/aidl/android/hardware/security/keymint/KeyParameter.aidl
@@ -16,40 +16,16 @@
 
 package android.hardware.security.keymint;
 
-import android.hardware.security.keymint.Algorithm;
-import android.hardware.security.keymint.BlockMode;
-import android.hardware.security.keymint.Digest;
-import android.hardware.security.keymint.EcCurve;
-import android.hardware.security.keymint.HardwareAuthenticatorType;
-import android.hardware.security.keymint.KeyDerivationFunction;
-import android.hardware.security.keymint.KeyOrigin;
-import android.hardware.security.keymint.KeyPurpose;
-import android.hardware.security.keymint.PaddingMode;
-import android.hardware.security.keymint.SecurityLevel;
 import android.hardware.security.keymint.Tag;
-
+import android.hardware.security.keymint.KeyParameterValue;
 
 /**
  * Identifies the key authorization parameters to be used with keyMint.  This is usually
  * provided as an array of KeyParameters to IKeyMintDevice or Operation.
- *
- * TODO(seleneh): Union was not supported in aidl when this cl is first drafted.  So we just had
- * the Tags, and bool, int, long, int[], and we will cast to the appropate types base on the
- * Tag value.  We need to update this defination to distingish Algorithm, BlockMode,
- * PaddingMode, KeyOrigin...etc later, as union support is recently added to aidl.
- * b/173253030
  */
 @VintfStability
+@RustDerive(Clone=true, Eq=true, PartialEq=true, Ord=true, PartialOrd=true, Hash=true)
 parcelable KeyParameter {
-    /**
-     * Identify what type of key parameter this parcelable actually holds, and based on the type
-     * of tag is int, long, bool, or byte[], one of the fields below will be referenced.
-     */
     Tag tag;
-
-    boolean boolValue;
-    int integer;
-    long longInteger;
-    // TODO: change this to nullable.
-    byte[] blob;
+    KeyParameterValue value;
 }
diff --git a/security/keymint/aidl/android/hardware/security/keymint/KeyParameterValue.aidl b/security/keymint/aidl/android/hardware/security/keymint/KeyParameterValue.aidl
new file mode 100644
index 0000000..a4f5154
--- /dev/null
+++ b/security/keymint/aidl/android/hardware/security/keymint/KeyParameterValue.aidl
@@ -0,0 +1,54 @@
+/*
+ * Copyright (C) 2020 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.security.keymint;
+
+import android.hardware.security.keymint.Algorithm;
+import android.hardware.security.keymint.BlockMode;
+import android.hardware.security.keymint.Digest;
+import android.hardware.security.keymint.EcCurve;
+import android.hardware.security.keymint.HardwareAuthenticatorType;
+import android.hardware.security.keymint.KeyOrigin;
+import android.hardware.security.keymint.KeyPurpose;
+import android.hardware.security.keymint.PaddingMode;
+import android.hardware.security.keymint.SecurityLevel;
+
+@VintfStability
+@RustDerive(Clone=true, Eq=true, PartialEq=true, Ord=true, PartialOrd=true, Hash=true)
+union KeyParameterValue {
+
+    /* Represents an invalid value type. */
+    int invalid;
+
+    /* Enum types */
+    Algorithm algorithm;
+    BlockMode blockMode;
+    PaddingMode paddingMode;
+    Digest digest;
+    EcCurve ecCurve;
+    KeyOrigin origin;
+    KeyPurpose keyPurpose;
+    HardwareAuthenticatorType hardwareAuthenticatorType;
+    SecurityLevel securityLevel;
+
+    /* Other types */
+    boolean boolValue;  // Always true, if present.
+    int integer;
+    long longInteger;
+    long dateTime;
+
+    byte[] blob;
+}
diff --git a/security/keymint/aidl/android/hardware/security/keymint/Tag.aidl b/security/keymint/aidl/android/hardware/security/keymint/Tag.aidl
index 3bc3f16..9f41b4e 100644
--- a/security/keymint/aidl/android/hardware/security/keymint/Tag.aidl
+++ b/security/keymint/aidl/android/hardware/security/keymint/Tag.aidl
@@ -187,6 +187,22 @@
      */
     INCLUDE_UNIQUE_ID = (7 << 28) /* TagType:BOOL */ | 202,
 
+     /**
+      * Tag::RSA_OAEP_MGF_DIGEST specifies the MGF1 digest algorithms that may be used with
+      * RSA encryption/decryption with OAEP padding. If the key characteristics supports OAEP
+      * and this tag is absent then SHA1 digest is selected by default for MGF1.
+      *
+      * This tag is repeatable for key generation/import.  If this tag is present in the key
+      * characteristics with one or more values from @4.0::Digest, then for RSA cipher
+      * operations with OAEP Padding, the caller must specify a digest in the additionalParams
+      * argument of begin operation. If this tag is missing or the specified digest is not in
+      * the digests associated with the key then begin operation must fail with
+      * ErrorCode::INCOMPATIBLE_MGF_DIGEST.
+      *
+      * Must be hardware-enforced.
+      */
+     RSA_OAEP_MGF_DIGEST = (2 << 28) /* TagType:ENUM_REP */ | 203,
+
     /**
      * TODO(seleneh) this tag needs to be deleted from all codes.
      *
diff --git a/security/keymint/aidl/vts/functional/AndroidTest.xml b/security/keymint/aidl/vts/functional/AndroidTest.xml
index 43e7a8a..de543f1 100644
--- a/security/keymint/aidl/vts/functional/AndroidTest.xml
+++ b/security/keymint/aidl/vts/functional/AndroidTest.xml
@@ -13,7 +13,7 @@
      See the License for the specific language governing permissions and
      limitations under the License.
 -->
-<configuration description="Runs VtsAidlKeyMintV1_0TargetTest.">
+<configuration description="Runs VtsAidlKeyMintTargetTest.">
     <option name="test-suite-tag" value="apct" />
     <option name="test-suite-tag" value="apct-native" />
 
@@ -22,12 +22,13 @@
 
     <target_preparer class="com.android.tradefed.targetprep.PushFilePreparer">
         <option name="cleanup" value="true" />
-        <option name="push" value="VtsAidlKeyMintV1_0TargetTest->/data/local/tmp/VtsAidlKeyMintV1_0TargetTest" />
+        <option name="push"
+                value="VtsAidlKeyMintTargetTest->/data/local/tmp/VtsAidlKeyMintTargetTest" />
     </target_preparer>
 
     <test class="com.android.tradefed.testtype.GTest" >
         <option name="native-test-device-path" value="/data/local/tmp" />
-        <option name="module-name" value="VtsAidlKeyMintV1_0TargetTest" />
+        <option name="module-name" value="VtsAidlKeyMintTargetTest" />
         <option name="native-test-timeout" value="900000"/>
     </test>
 </configuration>
diff --git a/security/keymint/aidl/vts/functional/KeyMintAidlTestBase.cpp b/security/keymint/aidl/vts/functional/KeyMintAidlTestBase.cpp
index 9ba4099..94bc199 100644
--- a/security/keymint/aidl/vts/functional/KeyMintAidlTestBase.cpp
+++ b/security/keymint/aidl/vts/functional/KeyMintAidlTestBase.cpp
@@ -577,8 +577,8 @@
     string ciphertext = EncryptMessage(message, params, &out_params);
     EXPECT_EQ(1U, out_params.size());
     auto ivVal = out_params.GetTagValue(TAG_NONCE);
-    EXPECT_TRUE(ivVal.isOk());
-    if (ivVal.isOk()) *iv_out = ivVal.value();
+    EXPECT_TRUE(ivVal);
+    if (ivVal) *iv_out = *ivVal;
     return ciphertext;
 }
 
diff --git a/security/keymint/aidl/vts/functional/KeyMintTest.cpp b/security/keymint/aidl/vts/functional/KeyMintTest.cpp
index 6e38539..eeb7491 100644
--- a/security/keymint/aidl/vts/functional/KeyMintTest.cpp
+++ b/security/keymint/aidl/vts/functional/KeyMintTest.cpp
@@ -80,7 +80,10 @@
 template <TagType tag_type, Tag tag, typename ValueT>
 bool contains(vector<KeyParameter>& set, TypedTag<tag_type, tag> ttag, ValueT expected_value) {
     auto it = std::find_if(set.begin(), set.end(), [&](const KeyParameter& param) {
-        return param.tag == tag && accessTagValue(ttag, param) == expected_value;
+        if (auto p = authorizationValue(ttag, param)) {
+            return *p == expected_value;
+        }
+        return false;
     });
     return (it != set.end());
 }
@@ -251,10 +254,10 @@
 
         EXPECT_TRUE(auths.Contains(TAG_OS_VERSION, os_version()))
                 << "OS version is " << os_version() << " key reported "
-                << auths.GetTagValue(TAG_OS_VERSION);
+                << auths.GetTagValue(TAG_OS_VERSION)->get();
         EXPECT_TRUE(auths.Contains(TAG_OS_PATCHLEVEL, os_patch_level()))
                 << "OS patch level is " << os_patch_level() << " key reported "
-                << auths.GetTagValue(TAG_OS_PATCHLEVEL);
+                << auths.GetTagValue(TAG_OS_PATCHLEVEL)->get();
     }
 };
 
@@ -2053,6 +2056,107 @@
 }
 
 /*
+ * EncryptionOperationsTest.RsaOaepWithMGFDigestSuccess
+ *
+ * Verifies that RSA-OAEP encryption operations work, with all SHA 256 digests and all type of MGF1
+ * digests.
+ */
+TEST_P(EncryptionOperationsTest, RsaOaepWithMGFDigestSuccess) {
+    auto digests = ValidDigests(false /* withNone */, true /* withMD5 */);
+
+    size_t key_size = 2048;  // Need largish key for SHA-512 test.
+    ASSERT_EQ(ErrorCode::OK, GenerateKey(AuthorizationSetBuilder()
+                                                 .OaepMGFDigest(digests)
+                                                 .Authorization(TAG_NO_AUTH_REQUIRED)
+                                                 .RsaEncryptionKey(key_size, 65537)
+                                                 .Padding(PaddingMode::RSA_OAEP)
+                                                 .Digest(Digest::SHA_2_256)));
+
+    string message = "Hello";
+
+    for (auto digest : digests) {
+        auto params = AuthorizationSetBuilder()
+                              .Authorization(TAG_RSA_OAEP_MGF_DIGEST, digest)
+                              .Digest(Digest::SHA_2_256)
+                              .Padding(PaddingMode::RSA_OAEP);
+        string ciphertext1 = EncryptMessage(message, params);
+        if (HasNonfatalFailure()) std::cout << "-->" << digest << std::endl;
+        EXPECT_EQ(key_size / 8, ciphertext1.size());
+
+        string ciphertext2 = EncryptMessage(message, params);
+        EXPECT_EQ(key_size / 8, ciphertext2.size());
+
+        // OAEP randomizes padding so every result should be different (with astronomically high
+        // probability).
+        EXPECT_NE(ciphertext1, ciphertext2);
+
+        string plaintext1 = DecryptMessage(ciphertext1, params);
+        EXPECT_EQ(message, plaintext1) << "RSA-OAEP failed with digest " << digest;
+        string plaintext2 = DecryptMessage(ciphertext2, params);
+        EXPECT_EQ(message, plaintext2) << "RSA-OAEP failed with digest " << digest;
+
+        // Decrypting corrupted ciphertext should fail.
+        size_t offset_to_corrupt = random() % ciphertext1.size();
+        char corrupt_byte;
+        do {
+            corrupt_byte = static_cast<char>(random() % 256);
+        } while (corrupt_byte == ciphertext1[offset_to_corrupt]);
+        ciphertext1[offset_to_corrupt] = corrupt_byte;
+
+        EXPECT_EQ(ErrorCode::OK, Begin(KeyPurpose::DECRYPT, params));
+        string result;
+        EXPECT_EQ(ErrorCode::UNKNOWN_ERROR, Finish(ciphertext1, &result));
+        EXPECT_EQ(0U, result.size());
+    }
+}
+
+/*
+ * EncryptionOperationsTest.RsaOaepWithMGFIncompatibleDigest
+ *
+ * Verifies that RSA-OAEP encryption operations fail in the correct way when asked to operate
+ * with incompatible MGF digest.
+ */
+TEST_P(EncryptionOperationsTest, RsaOaepWithMGFIncompatibleDigest) {
+    ASSERT_EQ(ErrorCode::OK,
+              GenerateKey(AuthorizationSetBuilder()
+                                  .Authorization(TAG_RSA_OAEP_MGF_DIGEST, Digest::SHA_2_256)
+                                  .Authorization(TAG_NO_AUTH_REQUIRED)
+                                  .RsaEncryptionKey(2048, 65537)
+                                  .Padding(PaddingMode::RSA_OAEP)
+                                  .Digest(Digest::SHA_2_256)));
+    string message = "Hello World!";
+
+    auto params = AuthorizationSetBuilder()
+                          .Padding(PaddingMode::RSA_OAEP)
+                          .Digest(Digest::SHA_2_256)
+                          .Authorization(TAG_RSA_OAEP_MGF_DIGEST, Digest::SHA_2_224);
+    EXPECT_EQ(ErrorCode::INCOMPATIBLE_MGF_DIGEST, Begin(KeyPurpose::ENCRYPT, params));
+}
+
+/*
+ * EncryptionOperationsTest.RsaOaepWithMGFUnsupportedDigest
+ *
+ * Verifies that RSA-OAEP encryption operations fail in the correct way when asked to operate
+ * with unsupported MGF digest.
+ */
+TEST_P(EncryptionOperationsTest, RsaOaepWithMGFUnsupportedDigest) {
+    ASSERT_EQ(ErrorCode::OK,
+              GenerateKey(AuthorizationSetBuilder()
+                                  .Authorization(TAG_RSA_OAEP_MGF_DIGEST, Digest::SHA_2_256)
+                                  .Authorization(TAG_NO_AUTH_REQUIRED)
+                                  .RsaEncryptionKey(2048, 65537)
+                                  .Padding(PaddingMode::RSA_OAEP)
+                                  .Digest(Digest::SHA_2_256)));
+    string message = "Hello World!";
+
+    auto params = AuthorizationSetBuilder()
+                          .Padding(PaddingMode::RSA_OAEP)
+                          .Digest(Digest::SHA_2_256)
+                          .Authorization(TAG_RSA_OAEP_MGF_DIGEST, Digest::NONE);
+    EXPECT_EQ(ErrorCode::UNSUPPORTED_MGF_DIGEST, Begin(KeyPurpose::ENCRYPT, params));
+}
+
+/*
  * EncryptionOperationsTest.RsaPkcs1Success
  *
  * Verifies that RSA PKCS encryption/decrypts works.
@@ -2333,8 +2437,8 @@
 
 vector<uint8_t> CopyIv(const AuthorizationSet& set) {
     auto iv = set.GetTagValue(TAG_NONCE);
-    EXPECT_TRUE(iv.isOk());
-    return iv.value();
+    EXPECT_TRUE(iv);
+    return iv->get();
 }
 
 /*
@@ -2459,13 +2563,13 @@
                 case BlockMode::CBC:
                 case BlockMode::GCM:
                 case BlockMode::CTR:
-                    ASSERT_TRUE(iv.isOk()) << "No IV for block mode " << block_mode;
-                    EXPECT_EQ(block_mode == BlockMode::GCM ? 12U : 16U, iv.value().size());
-                    params.push_back(TAG_NONCE, iv.value());
+                    ASSERT_TRUE(iv) << "No IV for block mode " << block_mode;
+                    EXPECT_EQ(block_mode == BlockMode::GCM ? 12U : 16U, iv->get().size());
+                    params.push_back(TAG_NONCE, iv->get());
                     break;
 
                 case BlockMode::ECB:
-                    EXPECT_FALSE(iv.isOk()) << "ECB mode should not generate IV";
+                    EXPECT_FALSE(iv) << "ECB mode should not generate IV";
                     break;
             }
 
@@ -2649,9 +2753,9 @@
     AuthorizationSet out_params;
     string ciphertext = EncryptMessage(message, params, &out_params);
     EXPECT_EQ(message.size(), ciphertext.size());
-    EXPECT_EQ(16U, out_params.GetTagValue(TAG_NONCE).value().size());
+    EXPECT_EQ(16U, out_params.GetTagValue(TAG_NONCE)->get().size());
 
-    params.push_back(TAG_NONCE, out_params.GetTagValue(TAG_NONCE).value());
+    params.push_back(TAG_NONCE, out_params.GetTagValue(TAG_NONCE)->get());
     string plaintext = DecryptMessage(ciphertext, params);
     EXPECT_EQ(message, plaintext);
 
@@ -2697,9 +2801,9 @@
     AuthorizationSet out_params;
     string ciphertext = EncryptMessage(message, params, &out_params);
     EXPECT_EQ(message.size(), ciphertext.size());
-    EXPECT_EQ(16U, out_params.GetTagValue(TAG_NONCE).value().size());
+    EXPECT_EQ(16U, out_params.GetTagValue(TAG_NONCE)->get().size());
 
-    params.push_back(TAG_NONCE, out_params.GetTagValue(TAG_NONCE).value());
+    params.push_back(TAG_NONCE, out_params.GetTagValue(TAG_NONCE)->get());
     string plaintext = DecryptMessage(ciphertext, params);
     EXPECT_EQ(message, plaintext);
 
@@ -2893,7 +2997,7 @@
     AuthorizationSet begin_out_params;
     EXPECT_EQ(ErrorCode::OK, Begin(KeyPurpose::ENCRYPT, params, &begin_out_params));
     EXPECT_EQ(1U, begin_out_params.size());
-    ASSERT_TRUE(begin_out_params.GetTagValue(TAG_NONCE).isOk());
+    ASSERT_TRUE(begin_out_params.GetTagValue(TAG_NONCE));
 
     AuthorizationSet finish_out_params;
     string ciphertext;
diff --git a/security/keymint/support/authorization_set.cpp b/security/keymint/support/authorization_set.cpp
index 37b6cd1..3d44dff 100644
--- a/security/keymint/support/authorization_set.cpp
+++ b/security/keymint/support/authorization_set.cpp
@@ -106,10 +106,11 @@
     return false;
 }
 
-NullOr<const KeyParameter&> AuthorizationSet::GetEntry(Tag tag) const {
+std::optional<std::reference_wrapper<const KeyParameter>> AuthorizationSet::GetEntry(
+        Tag tag) const {
     int pos = find(tag);
     if (pos == -1) return {};
-    return data_[pos];
+    return std::reference_wrapper(data_[pos]);
 }
 
 AuthorizationSetBuilder& AuthorizationSetBuilder::RsaKey(uint32_t key_size,
@@ -226,6 +227,14 @@
     return *this;
 }
 
+AuthorizationSetBuilder& AuthorizationSetBuilder::OaepMGFDigest(
+        const std::vector<android::hardware::security::keymint::Digest>& digests) {
+    for (auto digest : digests) {
+        push_back(TAG_RSA_OAEP_MGF_DIGEST, digest);
+    }
+    return *this;
+}
+
 AuthorizationSetBuilder& AuthorizationSetBuilder::Padding(
         std::initializer_list<PaddingMode> paddingModes) {
     for (auto paddingMode : paddingModes) {
diff --git a/security/keymint/support/include/keymint_support/authorization_set.h b/security/keymint/support/include/keymint_support/authorization_set.h
index c85f305..596bb89 100644
--- a/security/keymint/support/include/keymint_support/authorization_set.h
+++ b/security/keymint/support/include/keymint_support/authorization_set.h
@@ -168,7 +168,7 @@
     bool Contains(TypedTag<tag_type, tag> ttag, const ValueT& value) const {
         for (const auto& param : data_) {
             auto entry = authorizationValue(ttag, param);
-            if (entry.isOk() && static_cast<ValueT>(entry.value()) == value) return true;
+            if (entry && static_cast<ValueT>(*entry) == value) return true;
         }
         return false;
     }
@@ -178,9 +178,9 @@
     size_t GetTagCount(Tag tag) const;
 
     template <typename T>
-    inline NullOr<const typename TypedTag2ValueType<T>::type&> GetTagValue(T tag) const {
+    inline auto GetTagValue(T tag) const -> decltype(authorizationValue(tag, KeyParameter())) {
         auto entry = GetEntry(tag);
-        if (entry.isOk()) return authorizationValue(tag, entry.value());
+        if (entry) return authorizationValue(tag, *entry);
         return {};
     }
 
@@ -219,7 +219,7 @@
     }
 
   private:
-    NullOr<const KeyParameter&> GetEntry(Tag tag) const;
+    std::optional<std::reference_wrapper<const KeyParameter>> GetEntry(Tag tag) const;
 
     std::vector<KeyParameter> data_;
 };
@@ -290,6 +290,7 @@
     AuthorizationSetBuilder& GcmModeMacLen(uint32_t macLength);
 
     AuthorizationSetBuilder& BlockMode(std::initializer_list<BlockMode> blockModes);
+    AuthorizationSetBuilder& OaepMGFDigest(const std::vector<Digest>& digests);
     AuthorizationSetBuilder& Digest(std::vector<Digest> digests);
     AuthorizationSetBuilder& Padding(std::initializer_list<PaddingMode> paddings);
 
diff --git a/security/keymint/support/include/keymint_support/key_param_output.h b/security/keymint/support/include/keymint_support/key_param_output.h
index 6e0e35d..5f004fe 100644
--- a/security/keymint/support/include/keymint_support/key_param_output.h
+++ b/security/keymint/support/include/keymint_support/key_param_output.h
@@ -71,7 +71,7 @@
 }
 
 template <typename ValueT>
-::std::ostream& operator<<(::std::ostream& os, const NullOr<ValueT>& value) {
+::std::ostream& operator<<(::std::ostream& os, const std::optional<ValueT>& value) {
     if (!value.isOk()) {
         os << "(value not present)";
     } else {
diff --git a/security/keymint/support/include/keymint_support/keymint_tags.h b/security/keymint/support/include/keymint_support/keymint_tags.h
index 4e3d7ff..76aecb7 100644
--- a/security/keymint/support/include/keymint_support/keymint_tags.h
+++ b/security/keymint/support/include/keymint_support/keymint_tags.h
@@ -58,6 +58,10 @@
     typedef TypedTag<typeFromTag(tag), tag> type;
 };
 
+#ifdef DECLARE_TYPED_TAG
+#undef DECLARE_TYPED_TAG
+#endif
+
 #define DECLARE_TYPED_TAG(name)                                    \
     typedef typename Tag2TypedTag<Tag::name>::type TAG_##name##_t; \
     static TAG_##name##_t TAG_##name;
@@ -72,9 +76,12 @@
 DECLARE_TYPED_TAG(ATTESTATION_CHALLENGE);
 DECLARE_TYPED_TAG(ATTESTATION_ID_BRAND);
 DECLARE_TYPED_TAG(ATTESTATION_ID_DEVICE);
-DECLARE_TYPED_TAG(ATTESTATION_ID_PRODUCT);
+DECLARE_TYPED_TAG(ATTESTATION_ID_IMEI);
 DECLARE_TYPED_TAG(ATTESTATION_ID_MANUFACTURER);
+DECLARE_TYPED_TAG(ATTESTATION_ID_MEID);
+DECLARE_TYPED_TAG(ATTESTATION_ID_PRODUCT);
 DECLARE_TYPED_TAG(ATTESTATION_ID_MODEL);
+DECLARE_TYPED_TAG(ATTESTATION_ID_SERIAL);
 DECLARE_TYPED_TAG(AUTH_TIMEOUT);
 DECLARE_TYPED_TAG(BLOCK_MODE);
 DECLARE_TYPED_TAG(BOOTLOADER_ONLY);
@@ -117,6 +124,9 @@
 DECLARE_TYPED_TAG(USER_ID);
 DECLARE_TYPED_TAG(USER_SECURE_ID);
 DECLARE_TYPED_TAG(VENDOR_PATCHLEVEL);
+DECLARE_TYPED_TAG(RSA_OAEP_MGF_DIGEST);
+
+#undef DECLARE_TYPED_TAG
 
 template <typename... Elems>
 struct MetaList {};
@@ -133,6 +143,7 @@
         TAG_OS_VERSION_t, TAG_OS_PATCHLEVEL_t, TAG_UNIQUE_ID_t, TAG_ATTESTATION_CHALLENGE_t,
         TAG_ATTESTATION_APPLICATION_ID_t, TAG_ATTESTATION_ID_BRAND_t, TAG_ATTESTATION_ID_DEVICE_t,
         TAG_ATTESTATION_ID_PRODUCT_t, TAG_ATTESTATION_ID_MANUFACTURER_t, TAG_ATTESTATION_ID_MODEL_t,
+        TAG_ATTESTATION_ID_SERIAL_t, TAG_ATTESTATION_ID_IMEI_t, TAG_ATTESTATION_ID_MEID_t,
         TAG_RESET_SINCE_ID_ROTATION_t, TAG_PURPOSE_t, TAG_ALGORITHM_t, TAG_BLOCK_MODE_t,
         TAG_DIGEST_t, TAG_PADDING_t, TAG_ORIGIN_t, TAG_USER_AUTH_TYPE_t, TAG_EC_CURVE_t,
         TAG_BOOT_PATCHLEVEL_t, TAG_VENDOR_PATCHLEVEL_t, TAG_TRUSTED_CONFIRMATION_REQUIRED_t,
@@ -141,72 +152,122 @@
 template <typename TypedTagType>
 struct TypedTag2ValueType;
 
-#define MAKE_TAG_VALUE_ACCESSOR(tag_type, field_name)                              \
-    template <Tag tag>                                                             \
-    struct TypedTag2ValueType<TypedTag<tag_type, tag>> {                           \
-        typedef decltype(static_cast<KeyParameter*>(nullptr)->field_name) type;    \
-    };                                                                             \
-    template <Tag tag>                                                             \
-    inline auto accessTagValue(TypedTag<tag_type, tag>, const KeyParameter& param) \
-            ->const decltype(param.field_name)& {                                  \
-        return param.field_name;                                                   \
-    }                                                                              \
-    template <Tag tag>                                                             \
-    inline auto accessTagValue(TypedTag<tag_type, tag>, KeyParameter& param)       \
-            ->decltype(param.field_name)& {                                        \
-        return param.field_name;                                                   \
+#ifdef MAKE_TAG_VALUE_ACCESSOR
+#undef MAKE_TAG_VALUE_ACCESSOR
+#endif
+
+#define MAKE_TAG_VALUE_ACCESSOR(tag_type, field_name)                                           \
+    template <Tag tag>                                                                          \
+    struct TypedTag2ValueType<TypedTag<tag_type, tag>> {                                        \
+        using type = std::remove_reference<                                                     \
+                decltype(static_cast<KeyParameterValue*>(nullptr)                               \
+                                 ->get<KeyParameterValue::field_name>())>::type;                \
+        static constexpr KeyParameterValue::Tag unionTag = KeyParameterValue::field_name;       \
+    };                                                                                          \
+    template <Tag tag>                                                                          \
+    inline std::optional<std::reference_wrapper<                                                \
+            const typename TypedTag2ValueType<TypedTag<tag_type, tag>>::type>>                  \
+    accessTagValue(TypedTag<tag_type, tag>, const KeyParameter& param) {                        \
+        if (param.value.getTag() == KeyParameterValue::field_name) {                            \
+            return std::optional(                                                               \
+                    std::reference_wrapper(param.value.get<KeyParameterValue::field_name>()));  \
+        } else {                                                                                \
+            return std::nullopt;                                                                \
+        }                                                                                       \
+    }                                                                                           \
+    template <Tag tag>                                                                          \
+    inline std::optional<                                                                       \
+            std::reference_wrapper<typename TypedTag2ValueType<TypedTag<tag_type, tag>>::type>> \
+    accessTagValue(TypedTag<tag_type, tag>, KeyParameter& param) {                              \
+        if (param.value.getTag() == KeyParameterValue::field_name) {                            \
+            return std::optional(                                                               \
+                    std::reference_wrapper(param.value.get<KeyParameterValue::field_name>()));  \
+        } else {                                                                                \
+            return std::nullopt;                                                                \
+        }                                                                                       \
     }
 
 MAKE_TAG_VALUE_ACCESSOR(TagType::ULONG, longInteger)
 MAKE_TAG_VALUE_ACCESSOR(TagType::ULONG_REP, longInteger)
-MAKE_TAG_VALUE_ACCESSOR(TagType::DATE, longInteger)
+MAKE_TAG_VALUE_ACCESSOR(TagType::DATE, dateTime)
 MAKE_TAG_VALUE_ACCESSOR(TagType::UINT, integer)
 MAKE_TAG_VALUE_ACCESSOR(TagType::UINT_REP, integer)
 MAKE_TAG_VALUE_ACCESSOR(TagType::BOOL, boolValue)
 MAKE_TAG_VALUE_ACCESSOR(TagType::BYTES, blob)
 MAKE_TAG_VALUE_ACCESSOR(TagType::BIGNUM, blob)
 
-//  TODO(seleneh) change these MAKE_TAG_ENUM_VALUE_ACCESSOR back to the 2 parameter
-//  version when aidl supports union
-#define MAKE_TAG_ENUM_VALUE_ACCESSOR(typed_tag, field_name, field_type)                 \
-    template <>                                                                         \
-    struct TypedTag2ValueType<decltype(typed_tag)> {                                    \
-        typedef field_type type;                                                        \
-    };                                                                                  \
-    inline auto accessTagValue(decltype(typed_tag), const KeyParameter& param)          \
-            ->const field_type& {                                                       \
-        return *reinterpret_cast<const field_type*>(&param.field_name);                 \
-    }                                                                                   \
-    inline auto accessTagValue(decltype(typed_tag), KeyParameter& param)->field_type& { \
-        return *reinterpret_cast<field_type*>(&param.field_name);                       \
+#undef MAKE_TAG_VALUE_ACCESSOR
+
+#ifdef MAKE_TAG_ENUM_VALUE_ACCESSOR
+#undef MAKE_TAG_ENUM_VALUE_ACCESSOR
+#endif
+
+#define MAKE_TAG_ENUM_VALUE_ACCESSOR(typed_tag, field_name)                                       \
+    template <>                                                                                   \
+    struct TypedTag2ValueType<decltype(typed_tag)> {                                              \
+        using type = std::remove_reference<                                                       \
+                decltype(static_cast<KeyParameterValue*>(nullptr)                                 \
+                                 ->get<KeyParameterValue::field_name>())>::type;                  \
+        static constexpr KeyParameterValue::Tag unionTag = KeyParameterValue::field_name;         \
+    };                                                                                            \
+    inline std::optional<                                                                         \
+            std::reference_wrapper<const typename TypedTag2ValueType<decltype(typed_tag)>::type>> \
+    accessTagValue(decltype(typed_tag), const KeyParameter& param) {                              \
+        if (param.value.getTag() == KeyParameterValue::field_name) {                              \
+            return std::optional(                                                                 \
+                    std::reference_wrapper(param.value.get<KeyParameterValue::field_name>()));    \
+        } else {                                                                                  \
+            return std::nullopt;                                                                  \
+        }                                                                                         \
+    }                                                                                             \
+    inline std::optional<                                                                         \
+            std::reference_wrapper<typename TypedTag2ValueType<decltype(typed_tag)>::type>>       \
+    accessTagValue(decltype(typed_tag), KeyParameter& param) {                                    \
+        if (param.value.getTag() == KeyParameterValue::field_name) {                              \
+            return std::optional(                                                                 \
+                    std::reference_wrapper(param.value.get<KeyParameterValue::field_name>()));    \
+        } else {                                                                                  \
+            return std::nullopt;                                                                  \
+        }                                                                                         \
     }
 
-MAKE_TAG_ENUM_VALUE_ACCESSOR(TAG_ALGORITHM, integer, Algorithm)
-MAKE_TAG_ENUM_VALUE_ACCESSOR(TAG_BLOCK_MODE, integer, BlockMode)
-MAKE_TAG_ENUM_VALUE_ACCESSOR(TAG_DIGEST, integer, Digest)
-MAKE_TAG_ENUM_VALUE_ACCESSOR(TAG_EC_CURVE, integer, EcCurve)
-MAKE_TAG_ENUM_VALUE_ACCESSOR(TAG_ORIGIN, integer, KeyOrigin)
-MAKE_TAG_ENUM_VALUE_ACCESSOR(TAG_PADDING, integer, PaddingMode)
-MAKE_TAG_ENUM_VALUE_ACCESSOR(TAG_PURPOSE, integer, KeyPurpose)
-MAKE_TAG_ENUM_VALUE_ACCESSOR(TAG_USER_AUTH_TYPE, integer, HardwareAuthenticatorType)
-MAKE_TAG_ENUM_VALUE_ACCESSOR(TAG_HARDWARE_TYPE, integer, SecurityLevel)
+MAKE_TAG_ENUM_VALUE_ACCESSOR(TAG_ALGORITHM, algorithm)
+MAKE_TAG_ENUM_VALUE_ACCESSOR(TAG_BLOCK_MODE, blockMode)
+MAKE_TAG_ENUM_VALUE_ACCESSOR(TAG_DIGEST, digest)
+MAKE_TAG_ENUM_VALUE_ACCESSOR(TAG_EC_CURVE, ecCurve)
+MAKE_TAG_ENUM_VALUE_ACCESSOR(TAG_ORIGIN, origin)
+MAKE_TAG_ENUM_VALUE_ACCESSOR(TAG_PADDING, paddingMode)
+MAKE_TAG_ENUM_VALUE_ACCESSOR(TAG_PURPOSE, keyPurpose)
+MAKE_TAG_ENUM_VALUE_ACCESSOR(TAG_USER_AUTH_TYPE, hardwareAuthenticatorType)
+MAKE_TAG_ENUM_VALUE_ACCESSOR(TAG_HARDWARE_TYPE, securityLevel)
+MAKE_TAG_ENUM_VALUE_ACCESSOR(TAG_RSA_OAEP_MGF_DIGEST, digest)
+
+#undef MAKE_TAG_ENUM_VALUE_ACCESSOR
 
 template <TagType tag_type, Tag tag, typename ValueT>
 inline KeyParameter makeKeyParameter(TypedTag<tag_type, tag> ttag, ValueT&& value) {
-    KeyParameter param;
-    param.tag = tag;
-    param.longInteger = 0;
-    accessTagValue(ttag, param) = std::forward<ValueT>(value);
-    return param;
+    KeyParameter retval;
+    retval.tag = tag;
+    retval.value = KeyParameterValue::make<TypedTag2ValueType<decltype(ttag)>::unionTag>(
+            std::forward<ValueT>(value));
+    return retval;
 }
 
 // the boolean case
 template <Tag tag>
 inline KeyParameter makeKeyParameter(TypedTag<TagType::BOOL, tag>) {
-    KeyParameter param;
-    param.tag = tag;
-    param.boolValue = true;
-    return param;
+    KeyParameter retval;
+    retval.tag = tag;
+    retval.value = KeyParameterValue::make<KeyParameterValue::boolValue>(true);
+    return retval;
+}
+
+// the invalid case
+inline KeyParameter makeKeyParameter(TypedTag<TagType::INVALID, Tag::INVALID>) {
+    KeyParameter retval;
+    retval.tag = Tag::INVALID;
+    retval.value = KeyParameterValue::make<KeyParameterValue::invalid>(0);
+    return retval;
 }
 
 template <typename... Pack>
@@ -239,89 +300,32 @@
     return makeKeyParameter(ttag, std::forward<Args>(args)...);
 }
 
-/**
- * This class wraps a (mostly return) value and stores whether or not the wrapped value is valid out
- * of band. Note that if the wrapped value is a reference it is unsafe to access the value if
- * !isOk(). If the wrapped type is a pointer or value and !isOk(), it is still safe to access the
- * wrapped value. In this case the pointer will be NULL though, and the value will be default
- * constructed.
- *
- * TODO(seleneh) replace this with std::optional.
- */
-template <typename ValueT>
-class NullOr {
-    using internal_t = std::conditional_t<std::is_lvalue_reference<ValueT>::value,
-                                          std::remove_reference_t<ValueT>*, ValueT>;
-
-    struct pointer_initializer {
-        static std::nullptr_t init() { return nullptr; }
-    };
-    struct value_initializer {
-        static ValueT init() { return ValueT(); }
-    };
-    struct value_pointer_deref_t {
-        static ValueT& deref(ValueT& v) { return v; }
-    };
-    struct reference_deref_t {
-        static auto& deref(internal_t v) { return *v; }
-    };
-    using initializer_t = std::conditional_t<std::is_lvalue_reference<ValueT>::value ||
-                                                     std::is_pointer<ValueT>::value,
-                                             pointer_initializer, value_initializer>;
-    using deref_t = std::conditional_t<std::is_lvalue_reference<ValueT>::value, reference_deref_t,
-                                       value_pointer_deref_t>;
-
-  public:
-    NullOr() : value_(initializer_t::init()), null_(true) {}
-    template <typename T>
-    NullOr(T&& value, typename std::enable_if<
-                              !std::is_lvalue_reference<ValueT>::value &&
-                                      std::is_same<std::decay_t<ValueT>, std::decay_t<T>>::value,
-                              int>::type = 0)
-        : value_(std::forward<ValueT>(value)), null_(false) {}
-    template <typename T>
-    NullOr(T& value, typename std::enable_if<
-                             std::is_lvalue_reference<ValueT>::value &&
-                                     std::is_same<std::decay_t<ValueT>, std::decay_t<T>>::value,
-                             int>::type = 0)
-        : value_(&value), null_(false) {}
-
-    bool isOk() const { return !null_; }
-
-    const ValueT& value() const& { return deref_t::deref(value_); }
-    ValueT& value() & { return deref_t::deref(value_); }
-    ValueT&& value() && { return std::move(deref_t::deref(value_)); }
-
-  private:
-    internal_t value_;
-    bool null_;
-};
-
 template <typename T>
 std::remove_reference_t<T> NullOrOr(T&& v) {
-    if (v.isOk()) return v;
+    if (v) return v;
     return {};
 }
 
 template <typename Head, typename... Tail>
 std::remove_reference_t<Head> NullOrOr(Head&& head, Tail&&... tail) {
-    if (head.isOk()) return head;
+    if (head) return head;
     return NullOrOr(std::forward<Tail>(tail)...);
 }
 
 template <typename Default, typename Wrapped>
-std::remove_reference_t<Wrapped> defaultOr(NullOr<Wrapped>&& optional, Default&& def) {
+std::remove_reference_t<Wrapped> defaultOr(std::optional<Wrapped>&& optional, Default&& def) {
     static_assert(std::is_convertible<std::remove_reference_t<Default>,
                                       std::remove_reference_t<Wrapped>>::value,
-                  "Type of default value must match the type wrapped by NullOr");
-    if (optional.isOk()) return optional.value();
+                  "Type of default value must match the type wrapped by std::optional");
+    if (optional) return *optional;
     return def;
 }
 
 template <TagType tag_type, Tag tag>
-inline NullOr<const typename TypedTag2ValueType<TypedTag<tag_type, tag>>::type&> authorizationValue(
-        TypedTag<tag_type, tag> ttag, const KeyParameter& param) {
-    if (tag != param.tag) return {};
+inline std::optional<
+        std::reference_wrapper<const typename TypedTag2ValueType<TypedTag<tag_type, tag>>::type>>
+authorizationValue(TypedTag<tag_type, tag> ttag, const KeyParameter& param) {
+    if (TypedTag2ValueType<TypedTag<tag_type, tag>>::unionTag != param.value.getTag()) return {};
     return accessTagValue(ttag, param);
 }
 
diff --git a/security/keymint/support/key_param_output.cpp b/security/keymint/support/key_param_output.cpp
index c56e035..0950eb6 100644
--- a/security/keymint/support/key_param_output.cpp
+++ b/security/keymint/support/key_param_output.cpp
@@ -35,38 +35,8 @@
     return os;
 }
 
-// TODO(seleneh) update this to a parsing that looks at each tags individually
-// such as ALGORITHM BLOCK_MODE when aidl union support is added.
 ostream& operator<<(ostream& os, const KeyParameter& param) {
-    os << param.tag << ": ";
-    switch (typeFromTag(param.tag)) {
-        case TagType::INVALID:
-            return os << " Invalid";
-        case TagType::ENUM_REP:
-        case TagType::ENUM:
-        case TagType::UINT_REP:
-        case TagType::UINT:
-            return os << param.integer;
-        case TagType::ULONG_REP:
-        case TagType::ULONG:
-        case TagType::DATE:
-            return os << param.longInteger;
-        case TagType::BOOL:
-            return os << "true";
-        case TagType::BIGNUM:
-            os << " Bignum: ";
-            for (size_t i = 0; i < param.blob.size(); ++i) {
-                os << std::hex << ::std::setw(2) << static_cast<int>(param.blob[i]) << ::std::dec;
-            }
-            return os;
-        case TagType::BYTES:
-            os << " Bytes: ";
-            for (size_t i = 0; i < param.blob.size(); ++i) {
-                os << ::std::hex << ::std::setw(2) << static_cast<int>(param.blob[i]) << ::std::dec;
-            }
-            return os;
-    }
-    return os << "UNKNOWN TAG TYPE!";
+    return os << param.toString();
 }
 
 }  // namespace aidl::android::hardware::security::keymint
diff --git a/wifi/1.5/default/wifi_legacy_hal.cpp b/wifi/1.5/default/wifi_legacy_hal.cpp
index 773dd9b..e1a5a8c 100644
--- a/wifi/1.5/default/wifi_legacy_hal.cpp
+++ b/wifi/1.5/default/wifi_legacy_hal.cpp
@@ -343,6 +343,43 @@
         on_nan_event_schedule_update_user_callback(*event);
     }
 }
+
+// Callbacks for the various TWT operations.
+std::function<void(const TwtSetupResponse&)>
+    on_twt_event_setup_response_callback;
+void onAsyncTwtEventSetupResponse(TwtSetupResponse* event) {
+    const auto lock = hidl_sync_util::acquireGlobalLock();
+    if (on_twt_event_setup_response_callback && event) {
+        on_twt_event_setup_response_callback(*event);
+    }
+}
+
+std::function<void(const TwtTeardownCompletion&)>
+    on_twt_event_teardown_completion_callback;
+void onAsyncTwtEventTeardownCompletion(TwtTeardownCompletion* event) {
+    const auto lock = hidl_sync_util::acquireGlobalLock();
+    if (on_twt_event_teardown_completion_callback && event) {
+        on_twt_event_teardown_completion_callback(*event);
+    }
+}
+
+std::function<void(const TwtInfoFrameReceived&)>
+    on_twt_event_info_frame_received_callback;
+void onAsyncTwtEventInfoFrameReceived(TwtInfoFrameReceived* event) {
+    const auto lock = hidl_sync_util::acquireGlobalLock();
+    if (on_twt_event_info_frame_received_callback && event) {
+        on_twt_event_info_frame_received_callback(*event);
+    }
+}
+
+std::function<void(const TwtDeviceNotify&)> on_twt_event_device_notify_callback;
+void onAsyncTwtEventDeviceNotify(TwtDeviceNotify* event) {
+    const auto lock = hidl_sync_util::acquireGlobalLock();
+    if (on_twt_event_device_notify_callback && event) {
+        on_twt_event_device_notify_callback(*event);
+    }
+}
+
 // End of the free-standing "C" style callbacks.
 
 WifiLegacyHal::WifiLegacyHal(
@@ -1529,6 +1566,70 @@
         restrictions);
 }
 
+wifi_error WifiLegacyHal::setVoipMode(const std::string& iface_name,
+                                      wifi_voip_mode mode) {
+    return global_func_table_.wifi_set_voip_mode(getIfaceHandle(iface_name),
+                                                 mode);
+}
+
+wifi_error WifiLegacyHal::twtRegisterHandler(
+    const std::string& iface_name, const TwtCallbackHandlers& user_callbacks) {
+    on_twt_event_setup_response_callback = user_callbacks.on_setup_response;
+    on_twt_event_teardown_completion_callback =
+        user_callbacks.on_teardown_completion;
+    on_twt_event_info_frame_received_callback =
+        user_callbacks.on_info_frame_received;
+    on_twt_event_device_notify_callback = user_callbacks.on_device_notify;
+
+    return global_func_table_.wifi_twt_register_handler(
+        getIfaceHandle(iface_name),
+        {onAsyncTwtEventSetupResponse, onAsyncTwtEventTeardownCompletion,
+         onAsyncTwtEventInfoFrameReceived, onAsyncTwtEventDeviceNotify});
+}
+
+std::pair<wifi_error, TwtCapabilitySet> WifiLegacyHal::twtGetCapability(
+    const std::string& iface_name) {
+    TwtCapabilitySet capSet;
+    wifi_error status = global_func_table_.wifi_twt_get_capability(
+        getIfaceHandle(iface_name), &capSet);
+    return {status, capSet};
+}
+
+wifi_error WifiLegacyHal::twtSetupRequest(const std::string& iface_name,
+                                          const TwtSetupRequest& msg) {
+    TwtSetupRequest msgInternal(msg);
+    return global_func_table_.wifi_twt_setup_request(getIfaceHandle(iface_name),
+                                                     &msgInternal);
+}
+
+wifi_error WifiLegacyHal::twtTearDownRequest(const std::string& iface_name,
+                                             const TwtTeardownRequest& msg) {
+    TwtTeardownRequest msgInternal(msg);
+    return global_func_table_.wifi_twt_teardown_request(
+        getIfaceHandle(iface_name), &msgInternal);
+}
+
+wifi_error WifiLegacyHal::twtInfoFrameRequest(const std::string& iface_name,
+                                              const TwtInfoFrameRequest& msg) {
+    TwtInfoFrameRequest msgInternal(msg);
+    return global_func_table_.wifi_twt_info_frame_request(
+        getIfaceHandle(iface_name), &msgInternal);
+}
+
+std::pair<wifi_error, TwtStats> WifiLegacyHal::twtGetStats(
+    const std::string& iface_name, uint8_t configId) {
+    TwtStats stats;
+    wifi_error status = global_func_table_.wifi_twt_get_stats(
+        getIfaceHandle(iface_name), configId, &stats);
+    return {status, stats};
+}
+
+wifi_error WifiLegacyHal::twtClearStats(const std::string& iface_name,
+                                        uint8_t configId) {
+    return global_func_table_.wifi_twt_clear_stats(getIfaceHandle(iface_name),
+                                                   configId);
+}
+
 void WifiLegacyHal::invalidate() {
     global_handle_ = nullptr;
     iface_name_to_handle_.clear();
@@ -1560,6 +1661,10 @@
     on_nan_event_range_request_user_callback = nullptr;
     on_nan_event_range_report_user_callback = nullptr;
     on_nan_event_schedule_update_user_callback = nullptr;
+    on_twt_event_setup_response_callback = nullptr;
+    on_twt_event_teardown_completion_callback = nullptr;
+    on_twt_event_info_frame_received_callback = nullptr;
+    on_twt_event_device_notify_callback = nullptr;
 }
 
 }  // namespace legacy_hal
diff --git a/wifi/1.5/default/wifi_legacy_hal.h b/wifi/1.5/default/wifi_legacy_hal.h
index 6266cf6..610a332 100644
--- a/wifi/1.5/default/wifi_legacy_hal.h
+++ b/wifi/1.5/default/wifi_legacy_hal.h
@@ -23,15 +23,9 @@
 #include <thread>
 #include <vector>
 
+#include <hardware_legacy/wifi_hal.h>
 #include <wifi_system/interface_tool.h>
 
-// HACK: The include inside the namespace below also transitively includes a
-// bunch of libc headers into the namespace, which leads to functions like
-// socketpair being defined in
-// android::hardware::wifi::V1_1::implementation::legacy_hal. Include this one
-// particular header as a hacky workaround until that's fixed.
-#include <sys/socket.h>
-
 namespace android {
 namespace hardware {
 namespace wifi {
@@ -40,9 +34,280 @@
 // This is in a separate namespace to prevent typename conflicts between
 // the legacy HAL types and the HIDL interface types.
 namespace legacy_hal {
-// Wrap all the types defined inside the legacy HAL header files inside this
+// Import all the types defined inside the legacy HAL header files into this
 // namespace.
-#include <hardware_legacy/wifi_hal.h>
+using ::FRAME_TYPE_80211_MGMT;
+using ::FRAME_TYPE_ETHERNET_II;
+using ::FRAME_TYPE_UNKNOWN;
+using ::NAN_CHANNEL_24G_BAND;
+using ::NAN_CHANNEL_5G_BAND_HIGH;
+using ::NAN_CHANNEL_5G_BAND_LOW;
+using ::NAN_DISABLE_RANGE_REPORT;
+using ::NAN_DO_NOT_USE_SRF;
+using ::NAN_DP_CHANNEL_NOT_REQUESTED;
+using ::NAN_DP_CONFIG_NO_SECURITY;
+using ::NAN_DP_CONFIG_SECURITY;
+using ::NAN_DP_END;
+using ::NAN_DP_FORCE_CHANNEL_SETUP;
+using ::NAN_DP_INITIATOR_RESPONSE;
+using ::NAN_DP_INTERFACE_CREATE;
+using ::NAN_DP_INTERFACE_DELETE;
+using ::NAN_DP_REQUEST_ACCEPT;
+using ::NAN_DP_REQUEST_CHANNEL_SETUP;
+using ::NAN_DP_REQUEST_REJECT;
+using ::NAN_DP_RESPONDER_RESPONSE;
+using ::NAN_GET_CAPABILITIES;
+using ::NAN_MATCH_ALG_MATCH_CONTINUOUS;
+using ::NAN_MATCH_ALG_MATCH_NEVER;
+using ::NAN_MATCH_ALG_MATCH_ONCE;
+using ::NAN_PUBLISH_TYPE_SOLICITED;
+using ::NAN_PUBLISH_TYPE_UNSOLICITED;
+using ::NAN_PUBLISH_TYPE_UNSOLICITED_SOLICITED;
+using ::NAN_RANGING_AUTO_RESPONSE_DISABLE;
+using ::NAN_RANGING_AUTO_RESPONSE_ENABLE;
+using ::NAN_RANGING_DISABLE;
+using ::NAN_RANGING_ENABLE;
+using ::NAN_RESPONSE_BEACON_SDF_PAYLOAD;
+using ::NAN_RESPONSE_CONFIG;
+using ::NAN_RESPONSE_DISABLED;
+using ::NAN_RESPONSE_ENABLED;
+using ::NAN_RESPONSE_ERROR;
+using ::NAN_RESPONSE_PUBLISH;
+using ::NAN_RESPONSE_PUBLISH_CANCEL;
+using ::NAN_RESPONSE_STATS;
+using ::NAN_RESPONSE_SUBSCRIBE;
+using ::NAN_RESPONSE_SUBSCRIBE_CANCEL;
+using ::NAN_RESPONSE_TCA;
+using ::NAN_RESPONSE_TRANSMIT_FOLLOWUP;
+using ::NAN_SECURITY_KEY_INPUT_PASSPHRASE;
+using ::NAN_SECURITY_KEY_INPUT_PASSPHRASE;
+using ::NAN_SECURITY_KEY_INPUT_PMK;
+using ::NAN_SECURITY_KEY_INPUT_PMK;
+using ::NAN_SERVICE_ACCEPT_POLICY_ALL;
+using ::NAN_SERVICE_ACCEPT_POLICY_NONE;
+using ::NAN_SRF_ATTR_BLOOM_FILTER;
+using ::NAN_SRF_ATTR_PARTIAL_MAC_ADDR;
+using ::NAN_SRF_INCLUDE_DO_NOT_RESPOND;
+using ::NAN_SRF_INCLUDE_RESPOND;
+using ::NAN_SSI_NOT_REQUIRED_IN_MATCH_IND;
+using ::NAN_SSI_REQUIRED_IN_MATCH_IND;
+using ::NAN_STATUS_ALREADY_ENABLED;
+using ::NAN_STATUS_FOLLOWUP_QUEUE_FULL;
+using ::NAN_STATUS_INTERNAL_FAILURE;
+using ::NAN_STATUS_INVALID_NDP_ID;
+using ::NAN_STATUS_INVALID_PARAM;
+using ::NAN_STATUS_INVALID_PUBLISH_SUBSCRIBE_ID;
+using ::NAN_STATUS_INVALID_REQUESTOR_INSTANCE_ID;
+using ::NAN_STATUS_NAN_NOT_ALLOWED;
+using ::NAN_STATUS_NO_OTA_ACK;
+using ::NAN_STATUS_NO_RESOURCE_AVAILABLE;
+using ::NAN_STATUS_PROTOCOL_FAILURE;
+using ::NAN_STATUS_SUCCESS;
+using ::NAN_STATUS_UNSUPPORTED_CONCURRENCY_NAN_DISABLED;
+using ::NAN_SUBSCRIBE_TYPE_ACTIVE;
+using ::NAN_SUBSCRIBE_TYPE_PASSIVE;
+using ::NAN_TRANSMIT_IN_DW;
+using ::NAN_TRANSMIT_IN_FAW;
+using ::NAN_TX_PRIORITY_HIGH;
+using ::NAN_TX_PRIORITY_NORMAL;
+using ::NAN_TX_TYPE_BROADCAST;
+using ::NAN_TX_TYPE_UNICAST;
+using ::NAN_USE_SRF;
+using ::NanBeaconSdfPayloadInd;
+using ::NanCapabilities;
+using ::NanChannelInfo;
+using ::NanConfigRequest;
+using ::NanDataPathChannelCfg;
+using ::NanDataPathConfirmInd;
+using ::NanDataPathEndInd;
+using ::NanDataPathIndicationResponse;
+using ::NanDataPathInitiatorRequest;
+using ::NanDataPathRequestInd;
+using ::NanDataPathScheduleUpdateInd;
+using ::NanDisabledInd;
+using ::NanDiscEngEventInd;
+using ::NanEnableRequest;
+using ::NanFollowupInd;
+using ::NanMatchAlg;
+using ::NanMatchExpiredInd;
+using ::NanMatchInd;
+using ::NanPublishCancelRequest;
+using ::NanPublishRequest;
+using ::NanPublishTerminatedInd;
+using ::NanPublishType;
+using ::NanRangeReportInd;
+using ::NanRangeRequestInd;
+using ::NanResponseMsg;
+using ::NanSRFType;
+using ::NanStatusType;
+using ::NanSubscribeCancelRequest;
+using ::NanSubscribeRequest;
+using ::NanSubscribeTerminatedInd;
+using ::NanSubscribeType;
+using ::NanTransmitFollowupInd;
+using ::NanTransmitFollowupRequest;
+using ::NanTxType;
+using ::ROAMING_DISABLE;
+using ::ROAMING_ENABLE;
+using ::RTT_PEER_AP;
+using ::RTT_PEER_NAN;
+using ::RTT_PEER_P2P_CLIENT;
+using ::RTT_PEER_P2P_GO;
+using ::RTT_PEER_STA;
+using ::RTT_STATUS_ABORTED;
+using ::RTT_STATUS_FAILURE;
+using ::RTT_STATUS_FAIL_AP_ON_DIFF_CHANNEL;
+using ::RTT_STATUS_FAIL_BUSY_TRY_LATER;
+using ::RTT_STATUS_FAIL_FTM_PARAM_OVERRIDE;
+using ::RTT_STATUS_FAIL_INVALID_TS;
+using ::RTT_STATUS_FAIL_NOT_SCHEDULED_YET;
+using ::RTT_STATUS_FAIL_NO_CAPABILITY;
+using ::RTT_STATUS_FAIL_NO_RSP;
+using ::RTT_STATUS_FAIL_PROTOCOL;
+using ::RTT_STATUS_FAIL_REJECTED;
+using ::RTT_STATUS_FAIL_SCHEDULE;
+using ::RTT_STATUS_FAIL_TM_TIMEOUT;
+using ::RTT_STATUS_INVALID_REQ;
+using ::RTT_STATUS_NAN_RANGING_CONCURRENCY_NOT_SUPPORTED;
+using ::RTT_STATUS_NAN_RANGING_PROTOCOL_FAILURE;
+using ::RTT_STATUS_NO_WIFI;
+using ::RTT_STATUS_SUCCESS;
+using ::RTT_TYPE_1_SIDED;
+using ::RTT_TYPE_2_SIDED;
+using ::RX_PKT_FATE_DRV_DROP_FILTER;
+using ::RX_PKT_FATE_DRV_DROP_INVALID;
+using ::RX_PKT_FATE_DRV_DROP_NOBUFS;
+using ::RX_PKT_FATE_DRV_DROP_OTHER;
+using ::RX_PKT_FATE_DRV_QUEUED;
+using ::RX_PKT_FATE_FW_DROP_FILTER;
+using ::RX_PKT_FATE_FW_DROP_INVALID;
+using ::RX_PKT_FATE_FW_DROP_NOBUFS;
+using ::RX_PKT_FATE_FW_DROP_OTHER;
+using ::RX_PKT_FATE_FW_QUEUED;
+using ::RX_PKT_FATE_SUCCESS;
+using ::TX_PKT_FATE_ACKED;
+using ::TX_PKT_FATE_DRV_DROP_INVALID;
+using ::TX_PKT_FATE_DRV_DROP_NOBUFS;
+using ::TX_PKT_FATE_DRV_DROP_OTHER;
+using ::TX_PKT_FATE_DRV_QUEUED;
+using ::TX_PKT_FATE_FW_DROP_INVALID;
+using ::TX_PKT_FATE_FW_DROP_NOBUFS;
+using ::TX_PKT_FATE_FW_DROP_OTHER;
+using ::TX_PKT_FATE_FW_QUEUED;
+using ::TX_PKT_FATE_SENT;
+using ::WIFI_AC_BE;
+using ::WIFI_AC_BK;
+using ::WIFI_AC_VI;
+using ::WIFI_AC_VO;
+using ::WIFI_BAND_A;
+using ::WIFI_BAND_ABG;
+using ::WIFI_BAND_ABG_WITH_DFS;
+using ::WIFI_BAND_A_DFS;
+using ::WIFI_BAND_A_WITH_DFS;
+using ::WIFI_BAND_BG;
+using ::WIFI_BAND_UNSPECIFIED;
+using ::WIFI_CHAN_WIDTH_10;
+using ::WIFI_CHAN_WIDTH_160;
+using ::WIFI_CHAN_WIDTH_20;
+using ::WIFI_CHAN_WIDTH_40;
+using ::WIFI_CHAN_WIDTH_5;
+using ::WIFI_CHAN_WIDTH_5;
+using ::WIFI_CHAN_WIDTH_80;
+using ::WIFI_CHAN_WIDTH_80P80;
+using ::WIFI_CHAN_WIDTH_INVALID;
+using ::WIFI_DUAL_STA_NON_TRANSIENT_UNBIASED;
+using ::WIFI_DUAL_STA_TRANSIENT_PREFER_PRIMARY;
+using ::WIFI_ERROR_BUSY;
+using ::WIFI_ERROR_INVALID_ARGS;
+using ::WIFI_ERROR_INVALID_REQUEST_ID;
+using ::WIFI_ERROR_NONE;
+using ::WIFI_ERROR_NOT_AVAILABLE;
+using ::WIFI_ERROR_NOT_SUPPORTED;
+using ::WIFI_ERROR_OUT_OF_MEMORY;
+using ::WIFI_ERROR_TIMED_OUT;
+using ::WIFI_ERROR_TOO_MANY_REQUESTS;
+using ::WIFI_ERROR_UNINITIALIZED;
+using ::WIFI_ERROR_UNKNOWN;
+using ::WIFI_INTERFACE_TYPE_AP;
+using ::WIFI_INTERFACE_TYPE_NAN;
+using ::WIFI_INTERFACE_TYPE_P2P;
+using ::WIFI_INTERFACE_TYPE_STA;
+using ::WIFI_LATENCY_MODE_LOW;
+using ::WIFI_LATENCY_MODE_NORMAL;
+using ::WIFI_LOGGER_CONNECT_EVENT_SUPPORTED;
+using ::WIFI_LOGGER_DRIVER_DUMP_SUPPORTED;
+using ::WIFI_LOGGER_MEMORY_DUMP_SUPPORTED;
+using ::WIFI_LOGGER_PACKET_FATE_SUPPORTED;
+using ::WIFI_LOGGER_POWER_EVENT_SUPPORTED;
+using ::WIFI_LOGGER_WAKE_LOCK_SUPPORTED;
+using ::WIFI_MOTION_EXPECTED;
+using ::WIFI_MOTION_NOT_EXPECTED;
+using ::WIFI_MOTION_UNKNOWN;
+using ::WIFI_POWER_SCENARIO_ON_BODY_CELL_OFF;
+using ::WIFI_POWER_SCENARIO_ON_BODY_CELL_ON;
+using ::WIFI_POWER_SCENARIO_ON_HEAD_CELL_OFF;
+using ::WIFI_POWER_SCENARIO_ON_HEAD_CELL_ON;
+using ::WIFI_POWER_SCENARIO_VOICE_CALL;
+using ::WIFI_RTT_BW_10;
+using ::WIFI_RTT_BW_160;
+using ::WIFI_RTT_BW_20;
+using ::WIFI_RTT_BW_40;
+using ::WIFI_RTT_BW_5;
+using ::WIFI_RTT_BW_80;
+using ::WIFI_RTT_PREAMBLE_HE;
+using ::WIFI_RTT_PREAMBLE_HT;
+using ::WIFI_RTT_PREAMBLE_LEGACY;
+using ::WIFI_RTT_PREAMBLE_VHT;
+using ::WIFI_SCAN_FLAG_INTERRUPTED;
+using ::WIFI_SUCCESS;
+using ::WLAN_MAC_2_4_BAND;
+using ::WLAN_MAC_5_0_BAND;
+using ::WLAN_MAC_6_0_BAND;
+using ::frame_info;
+using ::frame_type;
+using ::fw_roaming_state_t;
+using ::mac_addr;
+using ::rtt_peer_type;
+using ::ssid_t;
+using ::transaction_id;
+using ::wifi_band;
+using ::wifi_cached_scan_results;
+using ::wifi_channel_info;
+using ::wifi_channel_stat;
+using ::wifi_channel_width;
+using ::wifi_coex_restriction;
+using ::wifi_coex_unsafe_channel;
+using ::wifi_error;
+using ::wifi_gscan_capabilities;
+using ::wifi_hal_fn;
+using ::wifi_information_element;
+using ::wifi_interface_type;
+using ::wifi_latency_mode;
+using ::wifi_lci_information;
+using ::wifi_lcr_information;
+using ::wifi_motion_pattern;
+using ::wifi_multi_sta_use_case;
+using ::wifi_power_scenario;
+using ::wifi_rate;
+using ::wifi_request_id;
+using ::wifi_ring_buffer_status;
+using ::wifi_roaming_capabilities;
+using ::wifi_roaming_config;
+using ::wifi_rtt_bw;
+using ::wifi_rtt_capabilities;
+using ::wifi_rtt_config;
+using ::wifi_rtt_preamble;
+using ::wifi_rtt_responder;
+using ::wifi_rtt_result;
+using ::wifi_rtt_status;
+using ::wifi_rtt_type;
+using ::wifi_rx_packet_fate;
+using ::wifi_rx_report;
+using ::wifi_scan_bucket_spec;
+using ::wifi_scan_cmd_params;
+using ::wifi_scan_result;
+using ::wifi_tx_packet_fate;
+using ::wifi_tx_report;
 
 // APF capabilities supported by the iface.
 struct PacketFilterCapabilities {
@@ -164,6 +429,18 @@
 using on_radio_mode_change_callback =
     std::function<void(const std::vector<WifiMacInfo>&)>;
 
+// TWT response and event callbacks struct.
+struct TwtCallbackHandlers {
+    // Callback for TWT setup response
+    std::function<void(const TwtSetupResponse&)> on_setup_response;
+    // Callback for TWT teardown completion
+    std::function<void(const TwtTeardownCompletion&)> on_teardown_completion;
+    // Callback for TWT info frame received event
+    std::function<void(const TwtInfoFrameReceived&)> on_info_frame_received;
+    // Callback for TWT notification from the device
+    std::function<void(const TwtDeviceNotify&)> on_device_notify;
+};
+
 /**
  * Class that encapsulates all legacy HAL interactions.
  * This class manages the lifetime of the event loop thread used by legacy HAL.
@@ -391,6 +668,28 @@
         std::vector<wifi_coex_unsafe_channel> unsafe_channels,
         uint32_t restrictions);
 
+    wifi_error setVoipMode(const std::string& iface_name, wifi_voip_mode mode);
+
+    wifi_error twtRegisterHandler(const std::string& iface_name,
+                                  const TwtCallbackHandlers& handler);
+
+    std::pair<wifi_error, TwtCapabilitySet> twtGetCapability(
+        const std::string& iface_name);
+
+    wifi_error twtSetupRequest(const std::string& iface_name,
+                               const TwtSetupRequest& msg);
+
+    wifi_error twtTearDownRequest(const std::string& iface_name,
+                                  const TwtTeardownRequest& msg);
+
+    wifi_error twtInfoFrameRequest(const std::string& iface_name,
+                                   const TwtInfoFrameRequest& msg);
+
+    std::pair<wifi_error, TwtStats> twtGetStats(const std::string& iface_name,
+                                                uint8_t configId);
+
+    wifi_error twtClearStats(const std::string& iface_name, uint8_t configId);
+
    private:
     // Retrieve interface handles for all the available interfaces.
     wifi_error retrieveIfaceHandles();
diff --git a/wifi/1.5/default/wifi_legacy_hal_stubs.cpp b/wifi/1.5/default/wifi_legacy_hal_stubs.cpp
index b6c908b..4b005d6 100644
--- a/wifi/1.5/default/wifi_legacy_hal_stubs.cpp
+++ b/wifi/1.5/default/wifi_legacy_hal_stubs.cpp
@@ -150,7 +150,14 @@
     populateStubFor(&hal_fn->wifi_multi_sta_set_primary_connection);
     populateStubFor(&hal_fn->wifi_multi_sta_set_use_case);
     populateStubFor(&hal_fn->wifi_set_coex_unsafe_channels);
-
+    populateStubFor(&hal_fn->wifi_set_voip_mode);
+    populateStubFor(&hal_fn->wifi_twt_register_handler);
+    populateStubFor(&hal_fn->wifi_twt_get_capability);
+    populateStubFor(&hal_fn->wifi_twt_setup_request);
+    populateStubFor(&hal_fn->wifi_twt_teardown_request);
+    populateStubFor(&hal_fn->wifi_twt_info_frame_request);
+    populateStubFor(&hal_fn->wifi_twt_get_stats);
+    populateStubFor(&hal_fn->wifi_twt_clear_stats);
     return true;
 }
 }  // namespace legacy_hal
diff --git a/wifi/1.5/default/wifi_legacy_hal_stubs.h b/wifi/1.5/default/wifi_legacy_hal_stubs.h
index 7e4eb0a..480389b 100644
--- a/wifi/1.5/default/wifi_legacy_hal_stubs.h
+++ b/wifi/1.5/default/wifi_legacy_hal_stubs.h
@@ -17,13 +17,14 @@
 #ifndef WIFI_LEGACY_HAL_STUBS_H_
 #define WIFI_LEGACY_HAL_STUBS_H_
 
+#include <hardware_legacy/wifi_hal.h>
+
 namespace android {
 namespace hardware {
 namespace wifi {
 namespace V1_5 {
 namespace implementation {
 namespace legacy_hal {
-#include <hardware_legacy/wifi_hal.h>
 
 bool initHalFuncTableWithStubs(wifi_hal_fn* hal_fn);
 }  // namespace legacy_hal
diff --git a/wifi/hostapd/1.3/vts/functional/hostapd_hidl_test.cpp b/wifi/hostapd/1.3/vts/functional/hostapd_hidl_test.cpp
index bdbe651..a22252c 100644
--- a/wifi/hostapd/1.3/vts/functional/hostapd_hidl_test.cpp
+++ b/wifi/hostapd/1.3/vts/functional/hostapd_hidl_test.cpp
@@ -124,6 +124,7 @@
         // Newly added attributes in V1_3
         channelParams_1_3.channel = iface_params.channelParams.channel;
         channelParams_1_3.enableAcs = iface_params.channelParams.enableAcs;
+        channelParams_1_3.bandMask = iface_params_1_2.channelParams.bandMask;
         channelParams_1_3.V1_2 = iface_params_1_2.channelParams;
 
         vec_channelParams.push_back(channelParams_1_3);
@@ -147,7 +148,8 @@
             iface_params_1_3.V1_2.V1_1.V1_0.channelParams.enableAcs;
         iface_params_1_3.channelParamsList[0].V1_2 =
             iface_params_1_3.V1_2.channelParams;
-
+        iface_params_1_3.channelParamsList[0].bandMask =
+            iface_params_1_3.V1_2.channelParams.bandMask;
         return iface_params_1_3;
     }