Merge "Instead of including wifi_hal.h in the legacy_hal namespace, import the types."
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/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/power/stats/aidl/aidl_api/android.hardware.power.stats/current/android/hardware/power/stats/EnergyConsumerAttribution.aidl b/power/stats/aidl/aidl_api/android.hardware.power.stats/current/android/hardware/power/stats/EnergyConsumerAttribution.aidl
new file mode 100644
index 0000000..0a7cff7
--- /dev/null
+++ b/power/stats/aidl/aidl_api/android.hardware.power.stats/current/android/hardware/power/stats/EnergyConsumerAttribution.aidl
@@ -0,0 +1,23 @@
+///////////////////////////////////////////////////////////////////////////////
+// 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.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/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/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/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/KeyMintTest.cpp b/security/keymint/aidl/vts/functional/KeyMintTest.cpp
index 3060153..eeb7491 100644
--- a/security/keymint/aidl/vts/functional/KeyMintTest.cpp
+++ b/security/keymint/aidl/vts/functional/KeyMintTest.cpp
@@ -2056,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.
diff --git a/security/keymint/support/authorization_set.cpp b/security/keymint/support/authorization_set.cpp
index f98851c..3d44dff 100644
--- a/security/keymint/support/authorization_set.cpp
+++ b/security/keymint/support/authorization_set.cpp
@@ -227,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 4ff1705..596bb89 100644
--- a/security/keymint/support/include/keymint_support/authorization_set.h
+++ b/security/keymint/support/include/keymint_support/authorization_set.h
@@ -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/keymint_tags.h b/security/keymint/support/include/keymint_support/keymint_tags.h
index d932b40..76aecb7 100644
--- a/security/keymint/support/include/keymint_support/keymint_tags.h
+++ b/security/keymint/support/include/keymint_support/keymint_tags.h
@@ -124,6 +124,7 @@
 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
 
@@ -239,6 +240,7 @@
 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