Merge "Carrier restriction enhancements for Android Q"
diff --git a/.clang-format b/.clang-format
index 9b3f9d9..3494682 100644
--- a/.clang-format
+++ b/.clang-format
@@ -22,3 +22,4 @@
 TabWidth: 4
 UseTab: Never
 IndentWidth: 4
+ContinuationIndentWidth: 8
diff --git a/audio/5.0/IStreamIn.hal b/audio/5.0/IStreamIn.hal
index d33cfdc..b042960 100644
--- a/audio/5.0/IStreamIn.hal
+++ b/audio/5.0/IStreamIn.hal
@@ -165,4 +165,27 @@
      */
     getActiveMicrophones()
                generates(Result retval, vec<MicrophoneInfo> microphones);
+
+    /**
+     * Specifies the logical microphone (for processing).
+     *
+     * Optional method
+     *
+     * @param Direction constant
+     * @return retval OK if the call is successful, an error code otherwise.
+     */
+    setMicrophoneDirection(MicrophoneDirection direction)
+               generates(Result retval);
+
+    /**
+     * Specifies the zoom factor for the selected microphone (for processing).
+     *
+     * Optional method
+     *
+     * @param the desired field dimension of microphone capture. Range is from -1 (wide angle),
+     * though 0 (no zoom) to 1 (maximum zoom).
+     *
+     * @return retval OK if the call is not successful, an error code otherwise.
+     */
+    setMicrophoneFieldDimension(float zoom) generates(Result retval);
 };
diff --git a/audio/5.0/types.hal b/audio/5.0/types.hal
index 4932367..2c153c6 100644
--- a/audio/5.0/types.hal
+++ b/audio/5.0/types.hal
@@ -221,3 +221,29 @@
      */
     AudioMicrophoneCoordinate               orientation;
 };
+
+/**
+ * Constants used by the HAL to determine how to select microphones and process those inputs in
+ * order to optimize for capture in the specified direction.
+ *
+ * MicrophoneDirection Constants are defined in MicrophoneDirection.java.
+ */
+@export(name="audio_microphone_direction_t", value_prefix="MIC_DIRECTION_")
+enum MicrophoneDirection : int32_t {
+    /**
+     * Don't do any directionality processing of the activated microphone(s).
+     */
+    UNSPECIFIED = 0,
+    /**
+     * Optimize capture for audio coming from the screen-side of the device.
+     */
+    FRONT = 1,
+    /**
+     * Optimize capture for audio coming from the side of the device opposite the screen.
+     */
+    BACK = 2,
+    /**
+     * Optimize capture for audio coming from an off-device microphone.
+     */
+    EXTERNAL = 3,
+};
diff --git a/audio/common/5.0/types.hal b/audio/common/5.0/types.hal
index dab7464..b4e9470 100644
--- a/audio/common/5.0/types.hal
+++ b/audio/common/5.0/types.hal
@@ -133,7 +133,18 @@
      * and raw signal analysis.
      */
     UNPROCESSED         = 9,
-
+    /**
+     * Source for capturing audio meant to be processed in real time and played back for live
+     * performance (e.g karaoke). The capture path will minimize latency and coupling with
+     * playback path.
+     */
+    VOICE_PERFORMANCE    = 10,
+    /**
+     * Source for an echo canceller to capture the reference signal to be cancelled.
+     * The echo reference signal will be captured as close as possible to the DAC in order
+     * to include all post processing applied to the playback path.
+     */
+    ECHO_REFERENCE      = 1997,
     FM_TUNER            = 1998,
 };
 
@@ -598,6 +609,7 @@
     IN_PROXY                 = BIT_IN | 0x1000000,
     IN_USB_HEADSET           = BIT_IN | 0x2000000,
     IN_BLUETOOTH_BLE         = BIT_IN | 0x4000000,
+    IN_ECHO_REFERENCE        = BIT_IN | 0x10000000,
     IN_DEFAULT               = BIT_IN | BIT_DEFAULT,
 
     // Note that the 2.0 IN_ALL* have been moved to helper functions
diff --git a/audio/core/all-versions/default/Device.cpp b/audio/core/all-versions/default/Device.cpp
index 8e0b763..bec22df 100644
--- a/audio/core/all-versions/default/Device.cpp
+++ b/audio/core/all-versions/default/Device.cpp
@@ -137,12 +137,11 @@
     return Void();
 }
 
-Return<void> Device::openOutputStream(int32_t ioHandle, const DeviceAddress& device,
-                                      const AudioConfig& config, AudioOutputFlagBitfield flags,
-#if MAJOR_VERSION >= 4
-                                      const SourceMetadata& /* sourceMetadata */,
-#endif
-                                      openOutputStream_cb _hidl_cb) {
+std::tuple<Result, sp<IStreamOut>> Device::openOutputStreamImpl(int32_t ioHandle,
+                                                                const DeviceAddress& device,
+                                                                const AudioConfig& config,
+                                                                AudioOutputFlagBitfield flags,
+                                                                AudioConfig* suggestedConfig) {
     audio_config_t halConfig;
     HidlUtils::audioConfigToHal(config, &halConfig);
     audio_stream_out_t* halStream;
@@ -161,16 +160,13 @@
     if (status == OK) {
         streamOut = new StreamOut(this, halStream);
     }
-    AudioConfig suggestedConfig;
-    HidlUtils::audioConfigFromHal(halConfig, &suggestedConfig);
-    _hidl_cb(analyzeStatus("open_output_stream", status, {EINVAL} /* ignore */), streamOut,
-             suggestedConfig);
-    return Void();
+    HidlUtils::audioConfigFromHal(halConfig, suggestedConfig);
+    return {analyzeStatus("open_output_stream", status, {EINVAL} /*ignore*/), streamOut};
 }
 
-Return<void> Device::openInputStream(int32_t ioHandle, const DeviceAddress& device,
-                                     const AudioConfig& config, AudioInputFlagBitfield flags,
-                                     AudioSource source, openInputStream_cb _hidl_cb) {
+std::tuple<Result, sp<IStreamIn>> Device::openInputStreamImpl(
+    int32_t ioHandle, const DeviceAddress& device, const AudioConfig& config,
+    AudioInputFlagBitfield flags, AudioSource source, AudioConfig* suggestedConfig) {
     audio_config_t halConfig;
     HidlUtils::audioConfigToHal(config, &halConfig);
     audio_stream_in_t* halStream;
@@ -190,14 +186,46 @@
     if (status == OK) {
         streamIn = new StreamIn(this, halStream);
     }
+    HidlUtils::audioConfigFromHal(halConfig, suggestedConfig);
+    return {analyzeStatus("open_input_stream", status, {EINVAL} /*ignore*/), streamIn};
+}
+
+#if MAJOR_VERSION == 2
+Return<void> Device::openOutputStream(int32_t ioHandle, const DeviceAddress& device,
+                                      const AudioConfig& config, AudioOutputFlagBitfield flags,
+                                      openOutputStream_cb _hidl_cb) {
     AudioConfig suggestedConfig;
-    HidlUtils::audioConfigFromHal(halConfig, &suggestedConfig);
-    _hidl_cb(analyzeStatus("open_input_stream", status, {EINVAL} /* ignore */), streamIn,
-             suggestedConfig);
+    auto [result, streamOut] =
+        openOutputStreamImpl(ioHandle, device, config, flags, &suggestedConfig);
+    _hidl_cb(result, streamOut, suggestedConfig);
     return Void();
 }
 
-#if MAJOR_VERSION >= 4
+Return<void> Device::openInputStream(int32_t ioHandle, const DeviceAddress& device,
+                                     const AudioConfig& config, AudioInputFlagBitfield flags,
+                                     AudioSource source, openInputStream_cb _hidl_cb) {
+    AudioConfig suggestedConfig;
+    auto [result, streamIn] =
+        openInputStreamImpl(ioHandle, device, config, flags, source, &suggestedConfig);
+    _hidl_cb(result, streamIn, suggestedConfig);
+    return Void();
+}
+
+#elif MAJOR_VERSION >= 4
+Return<void> Device::openOutputStream(int32_t ioHandle, const DeviceAddress& device,
+                                      const AudioConfig& config, AudioOutputFlagBitfield flags,
+                                      const SourceMetadata& sourceMetadata,
+                                      openOutputStream_cb _hidl_cb) {
+    AudioConfig suggestedConfig;
+    auto [result, streamOut] =
+        openOutputStreamImpl(ioHandle, device, config, flags, &suggestedConfig);
+    if (streamOut) {
+        streamOut->updateSourceMetadata(sourceMetadata);
+    }
+    _hidl_cb(result, streamOut, suggestedConfig);
+    return Void();
+}
+
 Return<void> Device::openInputStream(int32_t ioHandle, const DeviceAddress& device,
                                      const AudioConfig& config, AudioInputFlagBitfield flags,
                                      const SinkMetadata& sinkMetadata,
@@ -209,11 +237,18 @@
         _hidl_cb(Result::INVALID_ARGUMENTS, nullptr, AudioConfig());
         return Void();
     }
-    // Pick the first one as the main until the legacy API is update
+    // Pick the first one as the main.
     AudioSource source = sinkMetadata.tracks[0].source;
-    return openInputStream(ioHandle, device, config, flags, source, _hidl_cb);
+    AudioConfig suggestedConfig;
+    auto [result, streamIn] =
+        openInputStreamImpl(ioHandle, device, config, flags, source, &suggestedConfig);
+    if (streamIn) {
+        streamIn->updateSinkMetadata(sinkMetadata);
+    }
+    _hidl_cb(result, streamIn, suggestedConfig);
+    return Void();
 }
-#endif
+#endif /* MAJOR_VERSION */
 
 Return<bool> Device::supportsAudioPatches() {
     return version() >= AUDIO_DEVICE_API_VERSION_3_0;
diff --git a/audio/core/all-versions/default/StreamIn.cpp b/audio/core/all-versions/default/StreamIn.cpp
index ac7c2cb..daba6f7 100644
--- a/audio/core/all-versions/default/StreamIn.cpp
+++ b/audio/core/all-versions/default/StreamIn.cpp
@@ -454,8 +454,19 @@
     std::vector<record_track_metadata> halTracks;
     halTracks.reserve(sinkMetadata.tracks.size());
     for (auto& metadata : sinkMetadata.tracks) {
-        halTracks.push_back(
-            {.source = static_cast<audio_source_t>(metadata.source), .gain = metadata.gain});
+        record_track_metadata halTrackMetadata = {
+            .source = static_cast<audio_source_t>(metadata.source), .gain = metadata.gain};
+#if MAJOR_VERSION >= 5
+        if (metadata.destination.getDiscriminator() ==
+            RecordTrackMetadata::Destination::hidl_discriminator::device) {
+            halTrackMetadata.dest_device =
+                static_cast<audio_devices_t>(metadata.destination.device().device);
+            strncpy(halTrackMetadata.dest_device_address,
+                    deviceAddressToHal(metadata.destination.device()).c_str(),
+                    AUDIO_DEVICE_MAX_ADDRESS_LEN);
+        }
+#endif
+        halTracks.push_back(halTrackMetadata);
     }
     const sink_metadata_t halMetadata = {
         .track_count = halTracks.size(),
@@ -485,6 +496,27 @@
 }
 #endif
 
+#if MAJOR_VERSION >= 5
+Return<Result> StreamIn::setMicrophoneDirection(MicrophoneDirection direction) {
+    if (mStream->set_microphone_direction == nullptr) {
+        return Result::NOT_SUPPORTED;
+    }
+    return Stream::analyzeStatus(
+            "set_microphone_direction",
+            mStream->set_microphone_direction(
+                    mStream, static_cast<audio_microphone_direction_t>(direction)));
+}
+
+Return<Result> StreamIn::setMicrophoneFieldDimension(float zoom) {
+    if (mStream->set_microphone_field_dimension == nullptr) {
+        return Result::NOT_SUPPORTED;
+    }
+    return Stream::analyzeStatus("set_microphone_field_dimension",
+                                 mStream->set_microphone_field_dimension(mStream, zoom));
+}
+
+#endif
+
 }  // namespace implementation
 }  // namespace CPP_VERSION
 }  // namespace audio
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 836259f..e64f00f 100644
--- a/audio/core/all-versions/default/include/core/default/Device.h
+++ b/audio/core/all-versions/default/include/core/default/Device.h
@@ -62,14 +62,21 @@
     Return<void> getInputBufferSize(const AudioConfig& config,
                                     getInputBufferSize_cb _hidl_cb) override;
 
-    // V2 openInputStream is called by V4 input stream thus present in both versions
-    Return<void> openInputStream(int32_t ioHandle, const DeviceAddress& device,
-                                 const AudioConfig& config, AudioInputFlagBitfield flags,
-                                 AudioSource source, openInputStream_cb _hidl_cb);
+    std::tuple<Result, sp<IStreamOut>> openOutputStreamImpl(int32_t ioHandle,
+                                                            const DeviceAddress& device,
+                                                            const AudioConfig& config,
+                                                            AudioOutputFlagBitfield flags,
+                                                            AudioConfig* suggestedConfig);
+    std::tuple<Result, sp<IStreamIn>> openInputStreamImpl(
+        int32_t ioHandle, const DeviceAddress& device, const AudioConfig& config,
+        AudioInputFlagBitfield flags, AudioSource source, AudioConfig* suggestedConfig);
 #if MAJOR_VERSION == 2
     Return<void> openOutputStream(int32_t ioHandle, const DeviceAddress& device,
                                   const AudioConfig& config, AudioOutputFlagBitfield flags,
                                   openOutputStream_cb _hidl_cb) override;
+    Return<void> openInputStream(int32_t ioHandle, const DeviceAddress& device,
+                                 const AudioConfig& config, AudioInputFlagBitfield flags,
+                                 AudioSource source, openInputStream_cb _hidl_cb) override;
 #elif MAJOR_VERSION >= 4
     Return<void> openOutputStream(int32_t ioHandle, const DeviceAddress& device,
                                   const AudioConfig& config, AudioOutputFlagBitfield flags,
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 7a658b3..6209b8f 100644
--- a/audio/core/all-versions/default/include/core/default/StreamIn.h
+++ b/audio/core/all-versions/default/include/core/default/StreamIn.h
@@ -112,7 +112,10 @@
     Return<void> updateSinkMetadata(const SinkMetadata& sinkMetadata) override;
     Return<void> getActiveMicrophones(getActiveMicrophones_cb _hidl_cb) override;
 #endif
-
+#if MAJOR_VERSION >= 5
+    Return<Result> setMicrophoneDirection(MicrophoneDirection direction) override;
+    Return<Result> setMicrophoneFieldDimension(float zoom) override;
+#endif
     static Result getCapturePositionImpl(audio_stream_in_t* stream, uint64_t* frames,
                                          uint64_t* time);
 
diff --git a/audio/effect/5.0/xml/Android.bp b/audio/effect/5.0/xml/Android.bp
new file mode 100644
index 0000000..967135c
--- /dev/null
+++ b/audio/effect/5.0/xml/Android.bp
@@ -0,0 +1,6 @@
+
+xsd_config {
+    name: "audio_effects_conf",
+    srcs: ["audio_effects_conf.xsd"],
+    package_name: "audio.effects.V5_0",
+}
diff --git a/audio/effect/5.0/xml/api/current.txt b/audio/effect/5.0/xml/api/current.txt
new file mode 100644
index 0000000..294501d
--- /dev/null
+++ b/audio/effect/5.0/xml/api/current.txt
@@ -0,0 +1,136 @@
+package audio.effects.V5_0 {
+
+  public class Audioeffectsconf {
+    ctor public Audioeffectsconf();
+    method public audio.effects.V5_0.EffectsType getEffects();
+    method public audio.effects.V5_0.LibrariesType getLibraries();
+    method public audio.effects.V5_0.Audioeffectsconf.Postprocess getPostprocess();
+    method public audio.effects.V5_0.Audioeffectsconf.Preprocess getPreprocess();
+    method public audio.effects.V5_0.VersionType getVersion();
+    method public void setEffects(audio.effects.V5_0.EffectsType);
+    method public void setLibraries(audio.effects.V5_0.LibrariesType);
+    method public void setPostprocess(audio.effects.V5_0.Audioeffectsconf.Postprocess);
+    method public void setPreprocess(audio.effects.V5_0.Audioeffectsconf.Preprocess);
+    method public void setVersion(audio.effects.V5_0.VersionType);
+  }
+
+  public static class Audioeffectsconf.Postprocess {
+    ctor public Audioeffectsconf.Postprocess();
+    method public java.util.List<audio.effects.V5_0.StreamPostprocessType> getStream();
+  }
+
+  public static class Audioeffectsconf.Preprocess {
+    ctor public Audioeffectsconf.Preprocess();
+    method public java.util.List<audio.effects.V5_0.StreamPreprocessType> getStream();
+  }
+
+  public class EffectImplType {
+    ctor public EffectImplType();
+    method public java.lang.String getLibrary();
+    method public java.lang.String getUuid();
+    method public void setLibrary(java.lang.String);
+    method public void setUuid(java.lang.String);
+  }
+
+  public class EffectProxyType extends audio.effects.V5_0.EffectType {
+    ctor public EffectProxyType();
+    method public audio.effects.V5_0.EffectImplType getLibhw();
+    method public audio.effects.V5_0.EffectImplType getLibsw();
+    method public void setLibhw(audio.effects.V5_0.EffectImplType);
+    method public void setLibsw(audio.effects.V5_0.EffectImplType);
+  }
+
+  public class EffectType extends audio.effects.V5_0.EffectImplType {
+    ctor public EffectType();
+    method public java.lang.String getName();
+    method public void setName(java.lang.String);
+  }
+
+  public class EffectsType {
+    ctor public EffectsType();
+    method public java.util.List<audio.effects.V5_0.EffectProxyType> getEffectProxy_optional();
+    method public java.util.List<audio.effects.V5_0.EffectType> getEffect_optional();
+  }
+
+  public class LibrariesType {
+    ctor public LibrariesType();
+    method public java.util.List<audio.effects.V5_0.LibrariesType.Library> getLibrary();
+  }
+
+  public static class LibrariesType.Library {
+    ctor public LibrariesType.Library();
+    method public java.lang.String getName();
+    method public java.lang.String getPath();
+    method public void setName(java.lang.String);
+    method public void setPath(java.lang.String);
+  }
+
+  public final class StreamInputType extends java.lang.Enum {
+    method public java.lang.String getRawName();
+    method public static audio.effects.V5_0.StreamInputType valueOf(java.lang.String);
+    method public static final audio.effects.V5_0.StreamInputType[] values();
+    enum_constant public static final audio.effects.V5_0.StreamInputType camcorder;
+    enum_constant public static final audio.effects.V5_0.StreamInputType mic;
+    enum_constant public static final audio.effects.V5_0.StreamInputType unprocessed;
+    enum_constant public static final audio.effects.V5_0.StreamInputType voice_call;
+    enum_constant public static final audio.effects.V5_0.StreamInputType voice_communication;
+    enum_constant public static final audio.effects.V5_0.StreamInputType voice_downlink;
+    enum_constant public static final audio.effects.V5_0.StreamInputType voice_recognition;
+    enum_constant public static final audio.effects.V5_0.StreamInputType voice_uplink;
+  }
+
+  public final class StreamOutputType extends java.lang.Enum {
+    method public java.lang.String getRawName();
+    method public static audio.effects.V5_0.StreamOutputType valueOf(java.lang.String);
+    method public static final audio.effects.V5_0.StreamOutputType[] values();
+    enum_constant public static final audio.effects.V5_0.StreamOutputType alarm;
+    enum_constant public static final audio.effects.V5_0.StreamOutputType bluetooth_sco;
+    enum_constant public static final audio.effects.V5_0.StreamOutputType dtmf;
+    enum_constant public static final audio.effects.V5_0.StreamOutputType enforced_audible;
+    enum_constant public static final audio.effects.V5_0.StreamOutputType music;
+    enum_constant public static final audio.effects.V5_0.StreamOutputType notification;
+    enum_constant public static final audio.effects.V5_0.StreamOutputType ring;
+    enum_constant public static final audio.effects.V5_0.StreamOutputType system;
+    enum_constant public static final audio.effects.V5_0.StreamOutputType tts;
+    enum_constant public static final audio.effects.V5_0.StreamOutputType voice_call;
+  }
+
+  public class StreamPostprocessType extends audio.effects.V5_0.StreamProcessingType {
+    ctor public StreamPostprocessType();
+    method public audio.effects.V5_0.StreamOutputType getType();
+    method public void setType(audio.effects.V5_0.StreamOutputType);
+  }
+
+  public class StreamPreprocessType extends audio.effects.V5_0.StreamProcessingType {
+    ctor public StreamPreprocessType();
+    method public audio.effects.V5_0.StreamInputType getType();
+    method public void setType(audio.effects.V5_0.StreamInputType);
+  }
+
+  public class StreamProcessingType {
+    ctor public StreamProcessingType();
+    method public java.util.List<audio.effects.V5_0.StreamProcessingType.Apply> getApply();
+  }
+
+  public static class StreamProcessingType.Apply {
+    ctor public StreamProcessingType.Apply();
+    method public java.lang.String getEffect();
+    method public void setEffect(java.lang.String);
+  }
+
+  public final class VersionType extends java.lang.Enum {
+    method public java.lang.String getRawName();
+    method public static audio.effects.V5_0.VersionType valueOf(java.lang.String);
+    method public static final audio.effects.V5_0.VersionType[] values();
+    enum_constant public static final audio.effects.V5_0.VersionType _2_0;
+  }
+
+  public class XmlParser {
+    ctor public XmlParser();
+    method public static audio.effects.V5_0.Audioeffectsconf read(java.io.InputStream) throws javax.xml.datatype.DatatypeConfigurationException, java.io.IOException, org.xmlpull.v1.XmlPullParserException;
+    method public static java.lang.String readText(org.xmlpull.v1.XmlPullParser) throws java.io.IOException, org.xmlpull.v1.XmlPullParserException;
+    method public static void skip(org.xmlpull.v1.XmlPullParser) throws java.io.IOException, org.xmlpull.v1.XmlPullParserException;
+  }
+
+}
+
diff --git a/audio/effect/5.0/xml/api/last_current.txt b/audio/effect/5.0/xml/api/last_current.txt
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/audio/effect/5.0/xml/api/last_current.txt
diff --git a/audio/effect/5.0/xml/api/last_removed.txt b/audio/effect/5.0/xml/api/last_removed.txt
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/audio/effect/5.0/xml/api/last_removed.txt
diff --git a/audio/effect/5.0/xml/api/removed.txt b/audio/effect/5.0/xml/api/removed.txt
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/audio/effect/5.0/xml/api/removed.txt
diff --git a/automotive/vehicle/2.0/default/impl/vhal_v2_0/DefaultConfig.h b/automotive/vehicle/2.0/default/impl/vhal_v2_0/DefaultConfig.h
index a5c8eb8..7614cad 100644
--- a/automotive/vehicle/2.0/default/impl/vhal_v2_0/DefaultConfig.h
+++ b/automotive/vehicle/2.0/default/impl/vhal_v2_0/DefaultConfig.h
@@ -36,10 +36,12 @@
 constexpr int DOOR_1_RIGHT = (int)VehicleAreaDoor::ROW_1_RIGHT;
 constexpr int DOOR_2_LEFT = (int)VehicleAreaDoor::ROW_2_LEFT;
 constexpr int DOOR_2_RIGHT = (int)VehicleAreaDoor::ROW_2_RIGHT;
+constexpr int DOOR_REAR = (int)VehicleAreaDoor::REAR;
 constexpr int WINDOW_1_LEFT = (int)VehicleAreaWindow::ROW_1_LEFT;
 constexpr int WINDOW_1_RIGHT = (int)VehicleAreaWindow::ROW_1_RIGHT;
 constexpr int WINDOW_2_LEFT = (int)VehicleAreaWindow::ROW_2_LEFT;
 constexpr int WINDOW_2_RIGHT = (int)VehicleAreaWindow::ROW_2_RIGHT;
+constexpr int WINDOW_ROOF_TOP_1 = (int)VehicleAreaWindow::ROOF_TOP_1;
 constexpr int FAN_DIRECTION_FACE = (int)VehicleHvacFanDirection::FACE;
 constexpr int FAN_DIRECTION_FLOOR = (int)VehicleHvacFanDirection::FLOOR;
 constexpr int OBD2_LIVE_FRAME = (int)VehicleProperty::OBD2_LIVE_FRAME;
@@ -581,17 +583,18 @@
                            {DOOR_2_LEFT, {.int32Values = {1}}},
                            {DOOR_2_RIGHT, {.int32Values = {1}}}}},
 
-    {.config = {.prop = toInt(VehicleProperty::DOOR_POS),
-                .access = VehiclePropertyAccess::READ_WRITE,
-                .changeMode = VehiclePropertyChangeMode::ON_CHANGE,
-                .areaConfigs = {VehicleAreaConfig{.areaId = DOOR_1_LEFT},
-                                VehicleAreaConfig{.areaId = DOOR_1_RIGHT},
-                                VehicleAreaConfig{.areaId = DOOR_2_LEFT},
-                                VehicleAreaConfig{.areaId = DOOR_2_RIGHT}}},
-     .initialAreaValues = {{DOOR_1_LEFT, {.int32Values = {0}}},
-                           {DOOR_1_RIGHT, {.int32Values = {0}}},
-                           {DOOR_2_LEFT, {.int32Values = {0}}},
-                           {DOOR_2_RIGHT, {.int32Values = {0}}}}},
+    {.config =
+         {
+             .prop = toInt(VehicleProperty::DOOR_POS),
+             .access = VehiclePropertyAccess::READ_WRITE,
+             .changeMode = VehiclePropertyChangeMode::ON_CHANGE,
+             .areaConfigs =
+                 {VehicleAreaConfig{.areaId = DOOR_1_LEFT, .minInt32Value = 0, .maxInt32Value = 1},
+                  VehicleAreaConfig{.areaId = DOOR_1_RIGHT, .minInt32Value = 0, .maxInt32Value = 1},
+                  VehicleAreaConfig{.areaId = DOOR_2_LEFT, .minInt32Value = 0, .maxInt32Value = 1},
+                  VehicleAreaConfig{.areaId = DOOR_2_RIGHT, .minInt32Value = 0, .maxInt32Value = 1},
+                  VehicleAreaConfig{.areaId = DOOR_REAR, .minInt32Value = 0, .maxInt32Value = 1}}},
+     .initialValue = {.int32Values = {0}}},
 
     {.config = {.prop = toInt(VehicleProperty::WINDOW_LOCK),
                 .access = VehiclePropertyAccess::READ_WRITE,
@@ -601,17 +604,19 @@
      .initialAreaValues = {{WINDOW_1_RIGHT | WINDOW_2_LEFT | WINDOW_2_RIGHT,
                             {.int32Values = {0}}}}},
 
-    {.config = {.prop = toInt(VehicleProperty::WINDOW_POS),
-                .access = VehiclePropertyAccess::READ_WRITE,
-                .changeMode = VehiclePropertyChangeMode::ON_CHANGE,
-                .areaConfigs = {VehicleAreaConfig{.areaId = WINDOW_1_LEFT},
-                                VehicleAreaConfig{.areaId = WINDOW_1_RIGHT},
-                                VehicleAreaConfig{.areaId = WINDOW_2_LEFT},
-                                VehicleAreaConfig{.areaId = WINDOW_2_RIGHT}}},
-     .initialAreaValues = {{WINDOW_1_LEFT, {.int32Values = {0}}},
-                           {WINDOW_1_RIGHT, {.int32Values = {0}}},
-                           {WINDOW_2_LEFT, {.int32Values = {0}}},
-                           {WINDOW_2_RIGHT, {.int32Values = {0}}}}},
+    {.config =
+         {.prop = toInt(VehicleProperty::WINDOW_POS),
+          .access =
+              VehiclePropertyAccess::READ_WRITE,
+          .changeMode = VehiclePropertyChangeMode::ON_CHANGE,
+          .areaConfigs =
+              {VehicleAreaConfig{.areaId = WINDOW_1_LEFT, .minInt32Value = 0, .maxInt32Value = 10},
+               VehicleAreaConfig{.areaId = WINDOW_1_RIGHT, .minInt32Value = 0, .maxInt32Value = 10},
+               VehicleAreaConfig{.areaId = WINDOW_2_LEFT, .minInt32Value = 0, .maxInt32Value = 10},
+               VehicleAreaConfig{.areaId = WINDOW_2_RIGHT, .minInt32Value = 0, .maxInt32Value = 10},
+               VehicleAreaConfig{
+                   .areaId = WINDOW_ROOF_TOP_1, .minInt32Value = -10, .maxInt32Value = 10}}},
+     .initialValue = {.int32Values = {0}}},
 
     {.config =
          {
diff --git a/bluetooth/audio/2.0/Android.bp b/bluetooth/audio/2.0/Android.bp
new file mode 100644
index 0000000..6049fe2
--- /dev/null
+++ b/bluetooth/audio/2.0/Android.bp
@@ -0,0 +1,32 @@
+hidl_interface {
+    name: "android.hardware.bluetooth.audio@2.0",
+    root: "android.hardware",
+    vndk: {
+        enabled: true,
+    },
+    srcs: [
+        "types.hal",
+        "IBluetoothAudioPort.hal",
+        "IBluetoothAudioProvider.hal",
+        "IBluetoothAudioProvidersFactory.hal",
+    ],
+    interfaces: [
+        "android.hidl.base@1.0",
+        "android.hardware.audio.common@5.0",
+    ],
+    types: [
+        "AacObjectType",
+        "BitsPerSample",
+        "ChannelMode",
+        "CodecConfiguration",
+        "CodecType",
+        "LdacChannelMode",
+        "SampleRate",
+        "SbcChannelMode",
+        "SessionType",
+        "Status",
+        "TimeSpec",
+    ],
+    gen_java: false,
+}
+
diff --git a/bluetooth/audio/2.0/IBluetoothAudioPort.hal b/bluetooth/audio/2.0/IBluetoothAudioPort.hal
new file mode 100644
index 0000000..17d13b8
--- /dev/null
+++ b/bluetooth/audio/2.0/IBluetoothAudioPort.hal
@@ -0,0 +1,82 @@
+/*
+ * Copyright 2018 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.hardware.bluetooth.audio@2.0;
+
+import android.hardware.audio.common@5.0::SourceMetadata;
+
+/**
+ * HAL interface from the Audio HAL to the Bluetooth stack
+ *
+ * The Audio HAL calls methods in this interface to start, suspend, and stop
+ * an audio stream. These calls return immediately and the results, if any,
+ * are sent over the IBluetoothAudioProvider interface.
+ *
+ * Moreover, the Audio HAL can also get the presentation position of the stream
+ * and provide stream metadata.
+ */
+interface IBluetoothAudioPort {
+    /**
+     * This indicates that the caller of this method has opened the data path
+     * and wants to start an audio stream. The caller must wait for a
+     * IBluetoothAudioProvider.streamStarted(Status) call.
+     */
+    startStream();
+
+    /**
+     * This indicates that the caller of this method wants to suspend the audio
+     * stream. The caller must wait for the Bluetooth process to call
+     * IBluetoothAudioProvider.streamSuspended(Status). The caller still keeps
+     * the data path open.
+     */
+    suspendStream();
+
+    /**
+     * This indicates that the caller of this method wants to stop the audio
+     * stream. The data path will be closed after this call. There is no
+     * callback from the IBluetoothAudioProvider interface even though the
+     * teardown is asynchronous.
+     */
+    stopStream();
+
+    /**
+     * Get the audio presentation position.
+     *
+     * @return status the command status
+     * @return remoteDeviceAudioDelayNanos the audio delay from when the remote
+     *    device (e.g. headset) receives audio data to when the device plays the
+     *    sound. If the delay is unknown, the value is set to zero.
+     * @return transmittedOctets the number of audio data octets that were sent
+     *    to a remote device. This excludes octets that have been written to the
+     *    data path but have not been sent to the remote device. The count is
+     *    not reset until stopStream() is called. If the software data path is
+     *    unused (e.g. A2DP Hardware Offload), the value is set to 0.
+     * @return transmittedOctetsTimeStamp the value of CLOCK_MONOTONIC
+     *    corresponding to transmittedOctets. If the software data path is
+     *    unused (e.g., for A2DP Hardware Offload), the value is set to zero.
+     */
+    getPresentationPosition() generates (Status status,
+        uint64_t remoteDeviceAudioDelayNanos, uint64_t transmittedOctets,
+        TimeSpec transmittedOctetsTimeStamp);
+
+    /**
+     * Called when the metadata of the stream's source has been changed.
+     *
+     * @param sourceMetadata Description of the audio that is played by the
+     *    clients.
+     */
+    updateMetadata(SourceMetadata sourceMetadata);
+};
diff --git a/bluetooth/audio/2.0/IBluetoothAudioProvider.hal b/bluetooth/audio/2.0/IBluetoothAudioProvider.hal
new file mode 100644
index 0000000..bb5eb1b
--- /dev/null
+++ b/bluetooth/audio/2.0/IBluetoothAudioProvider.hal
@@ -0,0 +1,75 @@
+/*
+ * Copyright 2018 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.hardware.bluetooth.audio@2.0;
+
+import IBluetoothAudioPort;
+
+/**
+ * HAL interface from the Bluetooth stack to the Audio HAL
+ *
+ * The Bluetooth stack calls methods in this interface to start and end audio
+ * sessions and sends callback events to the Audio HAL.
+ */
+interface IBluetoothAudioProvider {
+
+    /**
+     * This method indicates that the Bluetooth stack is ready to stream audio.
+     * It registers an instance of IBluetoothAudioPort with and provides the
+     * current negotiated codec to the Audio HAL. After this method is called,
+     * the Audio HAL can invoke IBluetoothAudioPort.startStream().
+     *
+     * Note: endSession() must be called to unregister this IBluetoothAudioPort
+     *
+     * @param hostIf An instance of IBluetoothAudioPort for stream control
+     * @param codecConfig The codec configuration negotiated with the remote
+     *    device
+     *
+     * @return status One of the following
+     *    SUCCESS if this IBluetoothAudioPort was successfully registered with
+     *        the Audio HAL
+     *    UNSUPPORTED_CODEC_CONFIGURATION if the Audio HAL cannot register this
+     *        IBluetoothAudioPort with the given codec configuration
+     *    FAILURE if the Audio HAL cannot register this IBluetoothAudioPort for
+     *        any other reason
+     * @return dataMQ The fast message queue for audio data from this provider.
+     *    Audio data will be in PCM format as specified by the
+     *    codecConfig.pcmDataConfiguration parameter.
+     *    nullptr if streaming is offloaded to hardware or on failure.
+     */
+    startSession(IBluetoothAudioPort hostIf, CodecConfiguration codecConfig)
+                generates (Status status, fmq_sync<uint8_t> dataMQ);
+
+    /**
+     * Callback for IBluetoothAudioPort.startStream()
+     *
+     * @param status SUCCESS or FAILURE
+     */
+    streamStarted(Status status);
+
+    /**
+     * Callback for IBluetoothAudioPort.suspendStream()
+     *
+     * @param status SUCCESS or FAILURE
+     */
+    streamSuspended(Status status);
+
+    /**
+     * Ends the current session and unregisters the IBluetoothAudioPort
+     * interface.
+     */
+    endSession();
+};
diff --git a/bluetooth/audio/2.0/IBluetoothAudioProvidersFactory.hal b/bluetooth/audio/2.0/IBluetoothAudioProvidersFactory.hal
new file mode 100644
index 0000000..56b8594
--- /dev/null
+++ b/bluetooth/audio/2.0/IBluetoothAudioProvidersFactory.hal
@@ -0,0 +1,46 @@
+/*
+ * Copyright 2018 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.hardware.bluetooth.audio@2.0;
+
+import IBluetoothAudioProvider;
+
+/**
+ * This factory allows a HAL implementation to be split into multiple
+ * independent providers.
+ *
+ * When the Bluetooth stack is ready to create an audio session, it must first
+ * obtain the IBluetoothAudioProvider for that session type by calling
+ * openProvider().
+ */
+interface IBluetoothAudioProvidersFactory {
+
+    /**
+     * Opens an audio provider for a session type. To close the provider, it is
+     * necessary to release references to the returned provider object.
+     *
+     * @param sessionType The session type (e.g.
+     *    A2DP_SOFTWARE_ENCODING_DATAPATH).
+     *
+     * @return status One of the following
+     *    SUCCESS if the Audio HAL successfully opens the provider with the
+     *        given session type
+     *    FAILURE if the Audio HAL cannot open the provider
+     * @return provider The provider of the specified session type
+     */
+    openProvider(SessionType sessionType)
+        generates (Status status, IBluetoothAudioProvider provider);
+};
diff --git a/bluetooth/audio/2.0/types.hal b/bluetooth/audio/2.0/types.hal
new file mode 100644
index 0000000..9286948
--- /dev/null
+++ b/bluetooth/audio/2.0/types.hal
@@ -0,0 +1,170 @@
+/*
+ * Copyright 2018 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.hardware.bluetooth.audio@2.0;
+
+/**
+ * POSIX timespec.
+ */
+struct TimeSpec {
+    uint64_t tvSec;   // seconds
+    uint64_t tvNSec;  // nanoseconds
+};
+
+enum Status : uint8_t {
+    SUCCESS = 0x00,
+    /** Codec configuration not supported by the audio platform */
+    UNSUPPORTED_CODEC_CONFIGURATION,
+    /** Any other failure */
+    FAILURE,
+};
+
+enum SessionType : uint8_t {
+    UNKNOWN,
+    /** A2DP legacy that AVDTP media is encoded by Bluetooth Stack */
+    A2DP_SOFTWARE_ENCODING_DATAPATH,
+    /** The encoding of AVDTP media is done by HW and there is control only */
+    A2DP_HARDWARE_OFFLOAD_DATAPATH,
+    /** Used when encoded by Bluetooth Stack and streaming to Hearing Aid */
+    HEARING_AID_SOFTWARE_ENCODING_DATAPATH,
+};
+
+enum CodecType : uint32_t {
+    UNKNOWN = 0x00,
+    SBC = 0x01,
+    AAC = 0x02,
+    APTX = 0x04,
+    APTX_HD = 0x08,
+    LDAC = 0x10,
+};
+
+enum SampleRate : uint32_t {
+    RATE_UNKNOWN = 0x00,
+    RATE_44100 = 0x01,
+    RATE_48000 = 0x02,
+    RATE_88200 = 0x04,
+    RATE_96000 = 0x08,
+    RATE_176400 = 0x10,
+    RATE_192000 = 0x20,
+    RATE_16000 = 0x40,
+    RATE_24000 = 0x80,
+};
+
+enum BitsPerSample : uint8_t {
+    BITS_UNKNOWN = 0x00,
+    BITS_16 = 0x01,
+    BITS_24 = 0x02,
+    BITS_32 = 0x04,
+};
+
+enum ChannelMode : uint8_t {
+    UNKNOWN = 0x00,
+    MONO = 0x01,
+    STEREO = 0x02,
+};
+
+enum SbcChannelMode : uint8_t {
+    /** Channel Mode: 4 bits */
+    UNKNOWN = 0x00,
+    JOINT_STEREO = 0x01,
+    STEREO = 0x02,
+    DUAL = 0x04,
+    MONO = 0x08,
+};
+
+enum AacObjectType : uint8_t {
+    /** MPEG-2 Low Complexity. Support is Mandatory. */
+    MPEG2_LC = 0x80,
+    /** MPEG-4 Low Complexity. Support is Optional. */
+    MPEG4_LC = 0x40,
+    /** MPEG-4 Long Term Prediction. Support is Optional. */
+    MPEG4_LTP = 0x20,
+    /** MPEG-4 Scalable. Support is Optional. */
+    MPEG4_SCALABLE = 0x10,
+};
+
+enum LdacChannelMode : uint8_t {
+    /** Channel Mode: 3 bits */
+    UNKNOWN = 0x00,
+    STEREO = 0x01,
+    DUAL = 0x02,
+    MONO = 0x04,
+};
+
+struct CodecConfiguration {
+    /** Audio PCM data configuration */
+    struct PcmDataConfiguration {
+        /** Sampling rate for encoder */
+        SampleRate sampleRate;
+        /** Bits per sample for encoder */
+        BitsPerSample bitsPerSample;
+        /** Channel mode for encoder */
+        ChannelMode channelMode;
+    } pcmDataConfiguration;
+
+    /** Encoded audio data codec configuration. It is used only if the
+     * HAL is responsible for encoding the PCM audio data. */
+    struct EncodedDataConfiguration {
+        /** Bluetooth A2DP codec */
+        CodecType codecType;
+        /**
+         * The encoded audio bitrate in bits / second.
+         * 0x00000000 - The audio bitrate is not specified / unused
+         * 0x00000001 - 0x00FFFFFF - Encoded audio bitrate in bits/second
+         * 0x01000000 - 0xFFFFFFFF - Reserved
+         */
+        uint32_t encodedAudioBitrate;
+        /** Peer MTU (in octets) */
+        uint16_t peerMtu;
+        /** Content protection by SCMS-T */
+        bool isScmstEnabled;
+        safe_union CodecSpecific {
+            /**
+             * SBC Codec specific information
+             * Refer to SBC Codec specific information elements in A2DP v1.3
+             * Profile Specification.
+             */
+            struct SbcData {
+                /** Reserved: 4 bits | Channel Mode: 4 bits */
+                SbcChannelMode channelMode;
+                /** Block length: 4 bits | Subbands: 2 bits | Allocation Method: 2 bits */
+                uint8_t codecParameters;
+                /** Minimum bitpool value */
+                uint8_t minBitpool;
+                /** Maximum bitpool value */
+                uint8_t maxBitpool;
+            } sbcData;
+            struct AacData {
+                /** AAC Object Type */
+                AacObjectType aacObjectType;
+                /** True if Variable Bit Rate is enabled */
+                bool variableBitRateEnabled;
+            } aacData;
+            struct LdacData {
+                /** Reserved: 5 bits | Channel Mode: 3 bits */
+                LdacChannelMode channelMode;
+                /**
+                 * LDAC bitrate index value:
+                 * 0x00 - High
+                 * 0x01 - Mid
+                 * 0x02 - Low
+                 * 0x7F - ABR (Adaptive Bit Rate)
+                 */
+                uint8_t bitrateIndex;
+            } ldacData;
+        } codecSpecific;
+    } encodedDataConfiguration;
+};
diff --git a/camera/common/1.0/default/VendorTagDescriptor.cpp b/camera/common/1.0/default/VendorTagDescriptor.cpp
index 052bf5b..d2bee85 100644
--- a/camera/common/1.0/default/VendorTagDescriptor.cpp
+++ b/camera/common/1.0/default/VendorTagDescriptor.cpp
@@ -176,6 +176,93 @@
 
 }
 
+int VendorTagDescriptorCache::getTagCount(metadata_vendor_id_t id) const {
+    int ret = 0;
+    auto desc = mVendorMap.find(id);
+    if (desc != mVendorMap.end()) {
+        ret = desc->second->getTagCount();
+    } else {
+        ALOGE("%s: Vendor descriptor id is missing!", __func__);
+    }
+
+    return ret;
+}
+
+void VendorTagDescriptorCache::getTagArray(uint32_t* tagArray, metadata_vendor_id_t id) const {
+    auto desc = mVendorMap.find(id);
+    if (desc != mVendorMap.end()) {
+        desc->second->getTagArray(tagArray);
+    } else {
+        ALOGE("%s: Vendor descriptor id is missing!", __func__);
+    }
+}
+
+const char* VendorTagDescriptorCache::getSectionName(uint32_t tag, metadata_vendor_id_t id) const {
+    const char* ret = nullptr;
+    auto desc = mVendorMap.find(id);
+    if (desc != mVendorMap.end()) {
+        ret = desc->second->getSectionName(tag);
+    } else {
+        ALOGE("%s: Vendor descriptor id is missing!", __func__);
+    }
+
+    return ret;
+}
+
+const char* VendorTagDescriptorCache::getTagName(uint32_t tag, metadata_vendor_id_t id) const {
+    const char* ret = nullptr;
+    auto desc = mVendorMap.find(id);
+    if (desc != mVendorMap.end()) {
+        ret = desc->second->getTagName(tag);
+    } else {
+        ALOGE("%s: Vendor descriptor id is missing!", __func__);
+    }
+
+    return ret;
+}
+
+int VendorTagDescriptorCache::getTagType(uint32_t tag, metadata_vendor_id_t id) const {
+    int ret = 0;
+    auto desc = mVendorMap.find(id);
+    if (desc != mVendorMap.end()) {
+        ret = desc->second->getTagType(tag);
+    } else {
+        ALOGE("%s: Vendor descriptor id is missing!", __func__);
+    }
+
+    return ret;
+}
+
+void VendorTagDescriptorCache::dump(int fd, int verbosity, int indentation) const {
+    for (const auto& desc : mVendorMap) {
+        desc.second->dump(fd, verbosity, indentation);
+    }
+}
+
+int32_t VendorTagDescriptorCache::addVendorDescriptor(
+    metadata_vendor_id_t id, sp<hardware::camera::common::V1_0::helper::VendorTagDescriptor> desc) {
+    auto entry = mVendorMap.find(id);
+    if (entry != mVendorMap.end()) {
+        ALOGE("%s: Vendor descriptor with same id already present!", __func__);
+        return BAD_VALUE;
+    }
+
+    mVendorMap.emplace(id, desc);
+    return NO_ERROR;
+}
+
+int32_t VendorTagDescriptorCache::getVendorTagDescriptor(
+    metadata_vendor_id_t id,
+    sp<hardware::camera::common::V1_0::helper::VendorTagDescriptor>* desc /*out*/) {
+    auto entry = mVendorMap.find(id);
+    if (entry == mVendorMap.end()) {
+        return NAME_NOT_FOUND;
+    }
+
+    *desc = entry->second;
+
+    return NO_ERROR;
+}
 } // namespace params
 } // namespace camera2
 
@@ -192,10 +279,17 @@
 static const char* vendor_tag_descriptor_get_tag_name(const vendor_tag_ops_t* v, uint32_t tag);
 static int vendor_tag_descriptor_get_tag_type(const vendor_tag_ops_t* v, uint32_t tag);
 
+static int vendor_tag_descriptor_cache_get_tag_count(metadata_vendor_id_t id);
+static void vendor_tag_descriptor_cache_get_all_tags(uint32_t* tagArray, metadata_vendor_id_t id);
+static const char* vendor_tag_descriptor_cache_get_section_name(uint32_t tag,
+                                                                metadata_vendor_id_t id);
+static const char* vendor_tag_descriptor_cache_get_tag_name(uint32_t tag, metadata_vendor_id_t id);
+static int vendor_tag_descriptor_cache_get_tag_type(uint32_t tag, metadata_vendor_id_t id);
 } /* extern "C" */
 
 static Mutex sLock;
 static sp<VendorTagDescriptor> sGlobalVendorTagDescriptor;
+static sp<VendorTagDescriptorCache> sGlobalVendorTagDescriptorCache;
 
 status_t VendorTagDescriptor::createDescriptorFromOps(const vendor_tag_ops_t* vOps,
             /*out*/
@@ -310,6 +404,39 @@
     return sGlobalVendorTagDescriptor;
 }
 
+status_t VendorTagDescriptorCache::setAsGlobalVendorTagCache(
+    const sp<VendorTagDescriptorCache>& cache) {
+    status_t res = OK;
+    Mutex::Autolock al(sLock);
+    sGlobalVendorTagDescriptorCache = cache;
+
+    struct vendor_tag_cache_ops* opsPtr = NULL;
+    if (cache != NULL) {
+        opsPtr = &(cache->mVendorCacheOps);
+        opsPtr->get_tag_count = vendor_tag_descriptor_cache_get_tag_count;
+        opsPtr->get_all_tags = vendor_tag_descriptor_cache_get_all_tags;
+        opsPtr->get_section_name = vendor_tag_descriptor_cache_get_section_name;
+        opsPtr->get_tag_name = vendor_tag_descriptor_cache_get_tag_name;
+        opsPtr->get_tag_type = vendor_tag_descriptor_cache_get_tag_type;
+    }
+    if ((res = set_camera_metadata_vendor_cache_ops(opsPtr)) != OK) {
+        ALOGE("%s: Could not set vendor tag cache, received error %s (%d).", __FUNCTION__,
+              strerror(-res), res);
+    }
+    return res;
+}
+
+void VendorTagDescriptorCache::clearGlobalVendorTagCache() {
+    Mutex::Autolock al(sLock);
+    set_camera_metadata_vendor_cache_ops(NULL);
+    sGlobalVendorTagDescriptorCache.clear();
+}
+
+sp<VendorTagDescriptorCache> VendorTagDescriptorCache::getGlobalVendorTagCache() {
+    Mutex::Autolock al(sLock);
+    return sGlobalVendorTagDescriptorCache;
+}
+
 extern "C" {
 
 int vendor_tag_descriptor_get_tag_count(const vendor_tag_ops_t* /*v*/) {
@@ -357,6 +484,50 @@
     return sGlobalVendorTagDescriptor->getTagType(tag);
 }
 
+int vendor_tag_descriptor_cache_get_tag_count(metadata_vendor_id_t id) {
+    Mutex::Autolock al(sLock);
+    if (sGlobalVendorTagDescriptorCache == NULL) {
+        ALOGE("%s: Vendor tag descriptor cache not initialized.", __FUNCTION__);
+        return VENDOR_TAG_COUNT_ERR;
+    }
+    return sGlobalVendorTagDescriptorCache->getTagCount(id);
+}
+
+void vendor_tag_descriptor_cache_get_all_tags(uint32_t* tagArray, metadata_vendor_id_t id) {
+    Mutex::Autolock al(sLock);
+    if (sGlobalVendorTagDescriptorCache == NULL) {
+        ALOGE("%s: Vendor tag descriptor cache not initialized.", __FUNCTION__);
+    }
+    sGlobalVendorTagDescriptorCache->getTagArray(tagArray, id);
+}
+
+const char* vendor_tag_descriptor_cache_get_section_name(uint32_t tag, metadata_vendor_id_t id) {
+    Mutex::Autolock al(sLock);
+    if (sGlobalVendorTagDescriptorCache == NULL) {
+        ALOGE("%s: Vendor tag descriptor cache not initialized.", __FUNCTION__);
+        return VENDOR_SECTION_NAME_ERR;
+    }
+    return sGlobalVendorTagDescriptorCache->getSectionName(tag, id);
+}
+
+const char* vendor_tag_descriptor_cache_get_tag_name(uint32_t tag, metadata_vendor_id_t id) {
+    Mutex::Autolock al(sLock);
+    if (sGlobalVendorTagDescriptorCache == NULL) {
+        ALOGE("%s: Vendor tag descriptor cache not initialized.", __FUNCTION__);
+        return VENDOR_TAG_NAME_ERR;
+    }
+    return sGlobalVendorTagDescriptorCache->getTagName(tag, id);
+}
+
+int vendor_tag_descriptor_cache_get_tag_type(uint32_t tag, metadata_vendor_id_t id) {
+    Mutex::Autolock al(sLock);
+    if (sGlobalVendorTagDescriptorCache == NULL) {
+        ALOGE("%s: Vendor tag descriptor cache not initialized.", __FUNCTION__);
+        return VENDOR_TAG_NAME_ERR;
+    }
+    return sGlobalVendorTagDescriptorCache->getTagType(tag, id);
+}
+
 } /* extern "C" */
 
 } // namespace helper
diff --git a/camera/common/1.0/default/include/VendorTagDescriptor.h b/camera/common/1.0/default/include/VendorTagDescriptor.h
index a040540..0f54db5 100644
--- a/camera/common/1.0/default/include/VendorTagDescriptor.h
+++ b/camera/common/1.0/default/include/VendorTagDescriptor.h
@@ -157,6 +157,81 @@
 
 };
 
+} /* namespace helper */
+} /* namespace V1_0 */
+} /* namespace common */
+} /* namespace camera */
+
+namespace camera2 {
+namespace params {
+
+class VendorTagDescriptorCache {
+   public:
+    typedef android::hardware::camera::common::V1_0::helper::VendorTagDescriptor
+        VendorTagDescriptor;
+    VendorTagDescriptorCache(){};
+    int32_t addVendorDescriptor(metadata_vendor_id_t id, sp<VendorTagDescriptor> desc);
+
+    int32_t getVendorTagDescriptor(metadata_vendor_id_t id, sp<VendorTagDescriptor>* desc /*out*/);
+
+    // Returns the number of vendor tags defined.
+    int getTagCount(metadata_vendor_id_t id) const;
+
+    // Returns an array containing the id's of vendor tags defined.
+    void getTagArray(uint32_t* tagArray, metadata_vendor_id_t id) const;
+
+    // Returns the section name string for a given vendor tag id.
+    const char* getSectionName(uint32_t tag, metadata_vendor_id_t id) const;
+
+    // Returns the tag name string for a given vendor tag id.
+    const char* getTagName(uint32_t tag, metadata_vendor_id_t id) const;
+
+    // Returns the tag type for a given vendor tag id.
+    int getTagType(uint32_t tag, metadata_vendor_id_t id) const;
+
+    /**
+     * Dump the currently configured vendor tags to a file descriptor.
+     */
+    void dump(int fd, int verbosity, int indentation) const;
+
+   protected:
+    std::unordered_map<metadata_vendor_id_t, sp<VendorTagDescriptor>> mVendorMap;
+    struct vendor_tag_cache_ops mVendorCacheOps;
+};
+
+} /* namespace params */
+} /* namespace camera2 */
+
+namespace camera {
+namespace common {
+namespace V1_0 {
+namespace helper {
+
+class VendorTagDescriptorCache
+    : public ::android::hardware::camera2::params::VendorTagDescriptorCache,
+      public LightRefBase<VendorTagDescriptorCache> {
+   public:
+    /**
+     * Sets the global vendor tag descriptor cache to use for this process.
+     * Camera metadata operations that access vendor tags will use the
+     * vendor tag definitions set this way.
+     *
+     * Returns OK on success, or a negative error code.
+     */
+    static status_t setAsGlobalVendorTagCache(const sp<VendorTagDescriptorCache>& cache);
+
+    /**
+     * Returns the global vendor tag cache used by this process.
+     * This will contain NULL if no vendor tags are defined.
+     */
+    static sp<VendorTagDescriptorCache> getGlobalVendorTagCache();
+
+    /**
+     * Clears the global vendor tag cache used by this process.
+     */
+    static void clearGlobalVendorTagCache();
+};
+
 } // namespace helper
 } // namespace V1_0
 } // namespace common
diff --git a/camera/device/3.4/types.hal b/camera/device/3.4/types.hal
index bf2b3fc..85b3f7d 100644
--- a/camera/device/3.4/types.hal
+++ b/camera/device/3.4/types.hal
@@ -164,6 +164,9 @@
      * If non-zero, read settings from request queue instead
      * (see ICameraDeviceSession.getCaptureRequestMetadataQueue).
      * If zero, read settings from .settings field.
+     *
+     * The v3_2 settings metadata is read first from the FMQ, followed by
+     * the physical cameras' settings metadata starting from index 0.
      */
     uint64_t fmqSettingsSize;
 
@@ -205,8 +208,70 @@
  * structure asynchronously to the framework, using the processCaptureResult()
  * callback.
  *
- * Identical to @3.2::CaptureRequest, except that it contains @3.4::physCamSettings vector.
+ * Identical to @3.2::CaptureRequest, except that it contains
+ * @3.4::physCamSettings vector.
  *
+ * With 3.4 CaptureRequest, there can be multiple sources of metadata settings.
+ * The @3.2::CaptureRequest v3_2 and each of the PhysicalCameraSetting in
+ * physicalCameraSettings can contain settings, and each buffer may have
+ * metadata settings from a different source.
+ *
+ * For both @3.2::CaptureRequest and PhysicalCameraSetting, the settings can be
+ * passed from framework to HAL using either hwbinder or FMQ; both of the
+ * structs have the fields fmqSettingsSize and settings to pass the metadata.
+ * When metadata settings are passed using hwbinder, fmqSettingsSize == 0 and
+ * settings field contains the metadata for the HAL to read. When metadata
+ * settings comes from FMQ, fmqSettingsSize > 0 and HAL reads metadata from FMQ.
+ * For the purposes of selecting which settings to use, it does not matter
+ * whether it comes from hwbinder or FMQ. When the below specifications say that
+ * v3_2 has settings or a PhysicalCameraSetting has settings, it could refer to
+ * either hwbinder or FMQ, whichever is specified in the struct.
+ *
+ * Below is the logic that the HAL must follow for applying the metadata
+ * settings when it receives a CaptureRequest request in
+ * processCaptureRequest_3_4. Note that HAL must be capable of storing both the
+ * request.v3_2 settings and the PhysicalCameraSetting settings for each
+ * physical device.
+ * - Case 1 - request.v3_2 has settings, request.physicalCameraSettings vector
+ *   is empty:
+ *   - Store the request.v3_2 settings, overwriting the previously stored
+ *     request.v3_2 settings and clearing all previously stored physical device
+ *     settings.
+ *   - Apply the settings from the request.v3_2 to all buffers.
+ * - Case 2 - request.v3_2 has settings, request.physicalCameraSettings vector
+ *   is not empty:
+ *   - Store the request.v3_2 settings, overwriting the previously stored
+ *     request.v3_2 settings.
+ *   - Each PhysicalCameraSetting in request.physicalCameraSettings must have
+ *     settings; if not, return error.
+ *   - For each PhysicalCameraSetting in request.physicalCameraSettings, store
+ *     the settings, overwriting the previously stored settings for this
+ *     physical camera; apply these settings to the buffers belonging to the
+ *     stream for this device.
+ *   - If there are any stored physical camera settings which do not correspond
+ *     to one of the PhysicalCameraSetting in this request, clear them.
+ *   - Apply the request.v3_2 settings to all buffers belonging to streams not
+ *     covered by one of the PhysicalCameraSetting in this request.
+ * - Case 3 - request.v3_2 does not have settings,
+ *   request.physicalCameraSettings vector is empty:
+ *   - Clear all previously stored physical device settings.
+ *   - Apply the stored request.v3_2 settings to all buffers. If there is no
+ *     stored request.v3_2 settings, return error.
+ * - Case 4 - request.v3_2 does not have settings,
+ *   request.physicalCameraSettings vector is not empty:
+ *   - If request.physicalCameraSettings does not have the same set of physical
+ *     cameras as the stored physical camera settings, return error.
+ *   - Each PhysicalCameraSetting in request.physicalCameraSettings must not
+ *     have settings; if any do have settings, return error.
+ *   - For each PhysicalCameraSetting in request.physicalCameraSettings, apply
+ *     the previously stored settings for this physical camera to the buffers
+ *     belonging to the stream for this device.
+ *   - Apply the stored request.v3_2 settings to all buffers belonging to
+ *     streams not covered by one of the PhysicalCameraSetting in this request.
+ *     If there is no stored request.v3_2 settings, return error.
+ *
+ * For the first request received by the HAL, only Case 1 and Case 2 are
+ * allowed.
  */
 struct CaptureRequest {
     /**
@@ -238,6 +303,9 @@
      * If non-zero, read metadata from result metadata queue instead
      * (see ICameraDeviceSession.getCaptureResultMetadataQueue).
      * If zero, read metadata from .metadata field.
+     *
+     * The v3_2 CaptureResult metadata is read first from the FMQ, followed by
+     * the physical cameras' metadata starting from index 0.
      */
     uint64_t fmqMetadataSize;
 
@@ -251,9 +319,6 @@
     /**
      * If fmqMetadataSize is zero, the metadata buffer contains the metadata
      * for the physical device with physicalCameraId.
-     *
-     * The v3_2 CaptureResult metadata is read first from the FMQ, followed by
-     * the physical cameras' metadata starting from index 0.
      */
     CameraMetadata metadata;
 };
diff --git a/camera/device/3.5/ICameraDevice.hal b/camera/device/3.5/ICameraDevice.hal
index d9f2837..492105c 100644
--- a/camera/device/3.5/ICameraDevice.hal
+++ b/camera/device/3.5/ICameraDevice.hal
@@ -84,6 +84,9 @@
      *
      * The streamList must contain at least one output-capable stream, and may
      * not contain more than one input-capable stream.
+     * In contrast to regular stream configuration the framework does not create
+     * or initialize any actual streams. This means that Hal must not use or
+     * consider the stream "id" value.
      *
      * ------------------------------------------------------------------------
      *
diff --git a/camera/provider/2.4/vts/functional/VtsHalCameraProviderV2_4TargetTest.cpp b/camera/provider/2.4/vts/functional/VtsHalCameraProviderV2_4TargetTest.cpp
index e376551..60db5df 100644
--- a/camera/provider/2.4/vts/functional/VtsHalCameraProviderV2_4TargetTest.cpp
+++ b/camera/provider/2.4/vts/functional/VtsHalCameraProviderV2_4TargetTest.cpp
@@ -715,7 +715,8 @@
             StreamConfigurationMode configMode,
             ::android::hardware::camera::device::V3_2::StreamConfiguration *config3_2,
             ::android::hardware::camera::device::V3_4::StreamConfiguration *config3_4,
-            ::android::hardware::camera::device::V3_5::StreamConfiguration *config3_5);
+            ::android::hardware::camera::device::V3_5::StreamConfiguration *config3_5,
+            uint32_t jpegBufferSize = 0);
 
     void configurePreviewStreams3_4(const std::string &name, int32_t deviceVersion,
             sp<ICameraProvider> provider,
@@ -766,6 +767,8 @@
     static Status getAvailableOutputStreams(camera_metadata_t *staticMeta,
             std::vector<AvailableStream> &outputStreams,
             const AvailableStream *threshold = nullptr);
+    static Status getJpegBufferSize(camera_metadata_t *staticMeta,
+            uint32_t* outBufSize);
     static Status isConstrainedModeAvailable(camera_metadata_t *staticMeta);
     static Status isLogicalMultiCamera(const camera_metadata_t *staticMeta);
     static Status getPhysicalCameraIds(const camera_metadata_t *staticMeta,
@@ -2786,6 +2789,10 @@
         ASSERT_EQ(Status::OK, getAvailableOutputStreams(staticMeta, outputStreams));
         ASSERT_NE(0u, outputStreams.size());
 
+        uint32_t jpegBufferSize = 0;
+        ASSERT_EQ(Status::OK, getJpegBufferSize(staticMeta, &jpegBufferSize));
+        ASSERT_NE(0u, jpegBufferSize);
+
         int32_t streamId = 0;
         uint32_t streamConfigCounter = 0;
         for (auto& it : outputStreams) {
@@ -2804,7 +2811,7 @@
             ::android::hardware::camera::device::V3_4::StreamConfiguration config3_4;
             ::android::hardware::camera::device::V3_2::StreamConfiguration config3_2;
             createStreamConfiguration(streams3_2, StreamConfigurationMode::NORMAL_MODE,
-                                      &config3_2, &config3_4, &config3_5);
+                                      &config3_2, &config3_4, &config3_5, jpegBufferSize);
             if (session3_5 != nullptr) {
                 verifyStreamCombination(cameraDevice3_5, config3_4,
                         /*expectedStatus*/ true);
@@ -2879,6 +2886,10 @@
         ASSERT_EQ(Status::OK, getAvailableOutputStreams(staticMeta, outputStreams));
         ASSERT_NE(0u, outputStreams.size());
 
+        uint32_t jpegBufferSize = 0;
+        ASSERT_EQ(Status::OK, getJpegBufferSize(staticMeta, &jpegBufferSize));
+        ASSERT_NE(0u, jpegBufferSize);
+
         int32_t streamId = 0;
         V3_2::Stream stream3_2 = {streamId++,
                          StreamType::OUTPUT,
@@ -2894,7 +2905,7 @@
         ::android::hardware::camera::device::V3_4::StreamConfiguration config3_4;
         ::android::hardware::camera::device::V3_2::StreamConfiguration config3_2;
         createStreamConfiguration(streams, StreamConfigurationMode::NORMAL_MODE,
-                                  &config3_2, &config3_4, &config3_5);
+                                  &config3_2, &config3_4, &config3_5, jpegBufferSize);
         if (session3_5 != nullptr) {
             verifyStreamCombination(cameraDevice3_5, config3_4, /*expectedStatus*/ false);
             config3_5.streamConfigCounter = streamConfigCounter++;
@@ -2934,7 +2945,7 @@
                   StreamRotation::ROTATION_0};
         streams[0] = stream3_2;
         createStreamConfiguration(streams, StreamConfigurationMode::NORMAL_MODE,
-                &config3_2, &config3_4, &config3_5);
+                &config3_2, &config3_4, &config3_5, jpegBufferSize);
         if (session3_5 != nullptr) {
             config3_5.streamConfigCounter = streamConfigCounter++;
             ret = session3_5->configureStreams_3_5(config3_5, [](Status s,
@@ -2970,7 +2981,7 @@
                       StreamRotation::ROTATION_0};
             streams[0] = stream3_2;
             createStreamConfiguration(streams, StreamConfigurationMode::NORMAL_MODE,
-                    &config3_2, &config3_4, &config3_5);
+                    &config3_2, &config3_4, &config3_5, jpegBufferSize);
             if (session3_5 != nullptr) {
                 config3_5.streamConfigCounter = streamConfigCounter++;
                 ret = session3_5->configureStreams_3_5(config3_5,
@@ -3005,7 +3016,7 @@
                       static_cast<StreamRotation>(UINT32_MAX)};
             streams[0] = stream3_2;
             createStreamConfiguration(streams, StreamConfigurationMode::NORMAL_MODE,
-                    &config3_2, &config3_4, &config3_5);
+                    &config3_2, &config3_4, &config3_5, jpegBufferSize);
             if (session3_5 != nullptr) {
                 config3_5.streamConfigCounter = streamConfigCounter++;
                 ret = session3_5->configureStreams_3_5(config3_5,
@@ -3093,6 +3104,10 @@
             }
         }
 
+        uint32_t jpegBufferSize = 0;
+        ASSERT_EQ(Status::OK, getJpegBufferSize(staticMeta, &jpegBufferSize));
+        ASSERT_NE(0u, jpegBufferSize);
+
         int32_t streamId = 0;
         bool hasPrivToY8 = false, hasY8ToY8 = false, hasY8ToBlob = false;
         uint32_t streamConfigCounter = 0;
@@ -3150,7 +3165,7 @@
                 ::android::hardware::camera::device::V3_4::StreamConfiguration config3_4;
                 ::android::hardware::camera::device::V3_2::StreamConfiguration config3_2;
                 createStreamConfiguration(streams, StreamConfigurationMode::NORMAL_MODE,
-                                          &config3_2, &config3_4, &config3_5);
+                                          &config3_2, &config3_4, &config3_5, jpegBufferSize);
                 if (session3_5 != nullptr) {
                     verifyStreamCombination(cameraDevice3_5, config3_4,
                             /*expectedStatus*/ true);
@@ -3199,7 +3214,7 @@
     }
 }
 
-// Check wehether session parameters are supported. If Hal support for them
+// Check whether session parameters are supported. If Hal support for them
 // exist, then try to configure a preview stream using them.
 TEST_F(CameraHidlTest, configureStreamsWithSessionParameters) {
     hidl_vec<hidl_string> cameraDeviceNames = getCameraDeviceNames(mProvider);
@@ -3266,6 +3281,7 @@
                                 GRALLOC1_CONSUMER_USAGE_HWCOMPOSER,
                                 0,
                                 StreamRotation::ROTATION_0};
+        previewStream.bufferSize = 0;
         ::android::hardware::hidl_vec<V3_4::Stream> streams = {previewStream};
         ::android::hardware::camera::device::V3_4::StreamConfiguration config;
         ::android::hardware::camera::device::V3_5::StreamConfiguration config3_5;
@@ -3344,6 +3360,10 @@
                 &previewThreshold));
         ASSERT_NE(0u, outputPreviewStreams.size());
 
+        uint32_t jpegBufferSize = 0;
+        ASSERT_EQ(Status::OK, getJpegBufferSize(staticMeta, &jpegBufferSize));
+        ASSERT_NE(0u, jpegBufferSize);
+
         int32_t streamId = 0;
         uint32_t streamConfigCounter = 0;
         for (auto& blobIter : outputBlobStreams) {
@@ -3370,7 +3390,7 @@
                 ::android::hardware::camera::device::V3_4::StreamConfiguration config3_4;
                 ::android::hardware::camera::device::V3_2::StreamConfiguration config3_2;
                 createStreamConfiguration(streams, StreamConfigurationMode::NORMAL_MODE,
-                                          &config3_2, &config3_4, &config3_5);
+                                          &config3_2, &config3_4, &config3_5, jpegBufferSize);
                 if (session3_5 != nullptr) {
                     verifyStreamCombination(cameraDevice3_5, config3_4,
                             /*expectedStatus*/ true);
@@ -3661,6 +3681,10 @@
                           &videoThreshold));
         ASSERT_NE(0u, outputVideoStreams.size());
 
+        uint32_t jpegBufferSize = 0;
+        ASSERT_EQ(Status::OK, getJpegBufferSize(staticMeta, &jpegBufferSize));
+        ASSERT_NE(0u, jpegBufferSize);
+
         int32_t streamId = 0;
         uint32_t streamConfigCounter = 0;
         for (auto& blobIter : outputBlobStreams) {
@@ -3686,7 +3710,7 @@
                 ::android::hardware::camera::device::V3_4::StreamConfiguration config3_4;
                 ::android::hardware::camera::device::V3_2::StreamConfiguration config3_2;
                 createStreamConfiguration(streams, StreamConfigurationMode::NORMAL_MODE,
-                                          &config3_2, &config3_4, &config3_5);
+                                          &config3_2, &config3_4, &config3_5, jpegBufferSize);
                 if (session3_5 != nullptr) {
                     verifyStreamCombination(cameraDevice3_5, config3_4,
                             /*expectedStatus*/ true);
@@ -4660,6 +4684,23 @@
     return Status::OK;
 }
 
+// Get max jpeg buffer size in android.jpeg.maxSize
+Status CameraHidlTest::getJpegBufferSize(camera_metadata_t *staticMeta, uint32_t* outBufSize) {
+    if (nullptr == staticMeta || nullptr == outBufSize) {
+        return Status::ILLEGAL_ARGUMENT;
+    }
+
+    camera_metadata_ro_entry entry;
+    int rc = find_camera_metadata_ro_entry(staticMeta,
+            ANDROID_JPEG_MAX_SIZE, &entry);
+    if ((0 != rc) || (1 != entry.count)) {
+        return Status::ILLEGAL_ARGUMENT;
+    }
+
+    *outBufSize = static_cast<uint32_t>(entry.data.i32[0]);
+    return Status::OK;
+}
+
 // Check if the camera device has logical multi-camera capability.
 Status CameraHidlTest::isLogicalMultiCamera(const camera_metadata_t *staticMeta) {
     Status ret = Status::METHOD_NOT_SUPPORTED;
@@ -4946,7 +4987,8 @@
         StreamConfigurationMode configMode,
         ::android::hardware::camera::device::V3_2::StreamConfiguration *config3_2 /*out*/,
         ::android::hardware::camera::device::V3_4::StreamConfiguration *config3_4 /*out*/,
-        ::android::hardware::camera::device::V3_5::StreamConfiguration *config3_5 /*out*/) {
+        ::android::hardware::camera::device::V3_5::StreamConfiguration *config3_5 /*out*/,
+        uint32_t jpegBufferSize) {
     ASSERT_NE(nullptr, config3_2);
     ASSERT_NE(nullptr, config3_4);
     ASSERT_NE(nullptr, config3_5);
@@ -4956,6 +4998,11 @@
     for (auto& stream3_2 : streams3_2) {
         V3_4::Stream stream;
         stream.v3_2 = stream3_2;
+        stream.bufferSize = 0;
+        if (stream3_2.format == PixelFormat::BLOB &&
+                stream3_2.dataSpace == static_cast<V3_2::DataspaceFlags>(Dataspace::V0_JFIF)) {
+            stream.bufferSize = jpegBufferSize;
+        }
         streams3_4[idx++] = stream;
     }
     // Caller is responsible to fill in non-zero config3_5->streamConfigCounter after this returns
@@ -5191,6 +5238,11 @@
     outputPreviewStreams.clear();
     auto rc = getAvailableOutputStreams(staticMeta,
             outputPreviewStreams, previewThreshold);
+
+    uint32_t jpegBufferSize = 0;
+    ASSERT_EQ(Status::OK, getJpegBufferSize(staticMeta, &jpegBufferSize));
+    ASSERT_NE(0u, jpegBufferSize);
+
     free_camera_metadata(staticMeta);
     ASSERT_EQ(Status::OK, rc);
     ASSERT_FALSE(outputPreviewStreams.empty());
@@ -5205,7 +5257,7 @@
     ::android::hardware::camera::device::V3_4::StreamConfiguration config3_4;
     ::android::hardware::camera::device::V3_5::StreamConfiguration config3_5;
     createStreamConfiguration(streams3_2, StreamConfigurationMode::NORMAL_MODE,
-                              &config3_2, &config3_4, &config3_5);
+                              &config3_2, &config3_4, &config3_5, jpegBufferSize);
     if (session3_5 != nullptr) {
         RequestTemplate reqTemplate = RequestTemplate::PREVIEW;
         ret = session3_5->constructDefaultRequestSettings(reqTemplate,
diff --git a/cas/1.0/default/Android.bp b/cas/1.0/default/Android.bp
index debb3e5..aa080f4 100644
--- a/cas/1.0/default/Android.bp
+++ b/cas/1.0/default/Android.bp
@@ -23,10 +23,10 @@
       "libhidlmemory",
       "libhidltransport",
       "liblog",
+      "libstagefright_foundation",
       "libutils",
     ],
     header_libs: [
-      "libstagefright_foundation_headers",
       "media_plugin_headers",
     ],
 }
diff --git a/cas/1.0/default/DescramblerImpl.cpp b/cas/1.0/default/DescramblerImpl.cpp
index 6d5e2d5..9b09751 100644
--- a/cas/1.0/default/DescramblerImpl.cpp
+++ b/cas/1.0/default/DescramblerImpl.cpp
@@ -20,6 +20,7 @@
 #include <hidlmemory/mapping.h>
 #include <media/cas/DescramblerAPI.h>
 #include <media/hardware/CryptoAPI.h>
+#include <media/stagefright/foundation/AString.h>
 #include <media/stagefright/foundation/AUtils.h>
 #include <utils/Log.h>
 
@@ -177,6 +178,7 @@
     // Casting hidl SubSample to DescramblerPlugin::SubSample, but need
     // to ensure structs are actually idential
 
+    AString detailedError;
     int32_t result = holder->descramble(
             dstBuffer.type != BufferType::SHARED_MEMORY,
             (DescramblerPlugin::ScramblingControl)scramblingControl,
@@ -186,10 +188,10 @@
             srcOffset,
             dstPtr,
             dstOffset,
-            NULL);
+            &detailedError);
 
     holder.reset();
-    _hidl_cb(toStatus(result >= 0 ? OK : result), result, NULL);
+    _hidl_cb(toStatus(result >= 0 ? OK : result), result, detailedError.c_str());
     return Void();
 }
 
diff --git a/compatibility_matrices/compatibility_matrix.current.xml b/compatibility_matrices/compatibility_matrix.current.xml
index 42ac921..e1c5bac 100644
--- a/compatibility_matrices/compatibility_matrix.current.xml
+++ b/compatibility_matrices/compatibility_matrix.current.xml
@@ -9,7 +9,7 @@
     </hal>
     <hal format="hidl" optional="false">
         <name>android.hardware.audio</name>
-        <version>4.0</version>
+        <version>5.0</version>
         <interface>
             <name>IDevicesFactory</name>
             <instance>default</instance>
@@ -17,7 +17,7 @@
     </hal>
     <hal format="hidl" optional="false">
         <name>android.hardware.audio.effect</name>
-        <version>4.0</version>
+        <version>5.0</version>
         <interface>
             <name>IEffectsFactory</name>
             <instance>default</instance>
@@ -88,6 +88,14 @@
         </interface>
     </hal>
     <hal format="hidl" optional="true">
+        <name>android.hardware.bluetooth.audio</name>
+        <version>2.0</version>
+        <interface>
+            <name>IBluetoothAudioProvidersFactory</name>
+            <instance>default</instance>
+        </interface>
+    </hal>
+    <hal format="hidl" optional="true">
         <name>android.hardware.boot</name>
         <version>1.0</version>
         <interface>
@@ -195,6 +203,7 @@
     <hal format="hidl" optional="false">
         <name>android.hardware.graphics.allocator</name>
         <version>2.0</version>
+        <version>3.0</version>
         <interface>
             <name>IAllocator</name>
             <instance>default</instance>
@@ -210,7 +219,8 @@
     </hal>
     <hal format="hidl" optional="false">
         <name>android.hardware.graphics.mapper</name>
-        <version>2.0</version>
+        <version>2.0-1</version>
+        <version>3.0</version>
         <interface>
             <name>IMapper</name>
             <instance>default</instance>
@@ -335,7 +345,7 @@
     </hal>
     <hal format="hidl" optional="true">
         <name>android.hardware.radio</name>
-        <version>1.0-2</version>
+        <version>1.4</version>
         <interface>
             <name>IRadio</name>
             <instance>slot1</instance>
@@ -349,7 +359,7 @@
     </hal>
     <hal format="hidl" optional="true">
         <name>android.hardware.radio.config</name>
-        <version>1.0</version>
+        <version>1.2</version>
         <interface>
             <name>IRadioConfig</name>
             <instance>default</instance>
@@ -496,7 +506,7 @@
     </hal>
     <hal format="hidl" optional="true">
         <name>android.hardware.wifi.supplicant</name>
-        <version>1.0-1</version>
+        <version>1.0-2</version>
         <interface>
             <name>ISupplicant</name>
             <instance>default</instance>
diff --git a/configstore/1.2/Android.bp b/configstore/1.2/Android.bp
index bb4dd4a..a3976b6 100644
--- a/configstore/1.2/Android.bp
+++ b/configstore/1.2/Android.bp
@@ -7,6 +7,7 @@
         enabled: true,
     },
     srcs: [
+        "types.hal",
         "ISurfaceFlingerConfigs.hal",
     ],
     interfaces: [
@@ -17,6 +18,10 @@
         "android.hardware.graphics.common@1.2",
         "android.hidl.base@1.0",
     ],
+    types: [
+        "CieXyz",
+        "DisplayPrimaries",
+    ],
     gen_java: true,
 }
 
diff --git a/configstore/1.2/ISurfaceFlingerConfigs.hal b/configstore/1.2/ISurfaceFlingerConfigs.hal
index e91b2c7..7e5f706 100644
--- a/configstore/1.2/ISurfaceFlingerConfigs.hal
+++ b/configstore/1.2/ISurfaceFlingerConfigs.hal
@@ -69,4 +69,11 @@
     getCompositionPreference()
         generates (Dataspace dataspace, PixelFormat pixelFormat,
                    Dataspace wcgDataspace, PixelFormat wcgPixelFormat);
+
+    /**
+     * Returns the native panel primary data. The data includes red, green,
+     * blue and white. The primary format is CIE 1931 XYZ color space. If
+     * unspecified, the primaries is sRGB gamut by default.
+     */
+    getDisplayNativePrimaries() generates (DisplayPrimaries primaries);
 };
diff --git a/configstore/1.2/default/SurfaceFlingerConfigs.cpp b/configstore/1.2/default/SurfaceFlingerConfigs.cpp
index c2cf374..d38b402 100644
--- a/configstore/1.2/default/SurfaceFlingerConfigs.cpp
+++ b/configstore/1.2/default/SurfaceFlingerConfigs.cpp
@@ -17,6 +17,7 @@
 #include "SurfaceFlingerConfigs.h"
 
 #include <android/hardware/configstore/1.1/types.h>
+#include <android/hardware/configstore/1.2/types.h>
 #include <android/hardware/graphics/common/1.1/types.h>
 #include <log/log.h>
 
@@ -241,6 +242,85 @@
     return Void();
 }
 
+Return<void> SurfaceFlingerConfigs::getDisplayNativePrimaries(getDisplayNativePrimaries_cb _hidl_cb) {
+    DisplayPrimaries primaries;
+    // The default XYZ is sRGB gamut in CIE1931 color space
+#ifdef TARGET_DISPLAY_PRIMARY_RED_X
+    primaries.red.X = TARGET_DISPLAY_PRIMARY_RED_X;
+#else
+    primaries.red.X = 0.4123;
+#endif
+
+#ifdef TARGET_DISPLAY_PRIMARY_RED_Y
+    primaries.red.Y = TARGET_DISPLAY_PRIMARY_RED_Y;
+#else
+    primaries.red.Y = 0.2126;
+#endif
+
+#ifdef TARGET_DISPLAY_PRIMARY_RED_Z
+    primaries.red.Z = TARGET_DISPLAY_PRIMARY_RED_Z;
+#else
+    primaries.red.Z = 0.0193;
+#endif
+
+#ifdef TARGET_DISPLAY_PRIMARY_GREEN_X
+    primaries.green.X = TARGET_DISPLAY_PRIMARY_GREEN_X;
+#else
+    primaries.green.X = 0.3576;
+#endif
+
+#ifdef TARGET_DISPLAY_PRIMARY_GREEN_Y
+    primaries.green.Y = TARGET_DISPLAY_PRIMARY_GREEN_Y;
+#else
+    primaries.green.Y = 0.7152;
+#endif
+
+#ifdef TARGET_DISPLAY_PRIMARY_GREEN_Z
+    primaries.green.Z = TARGET_DISPLAY_PRIMARY_GREEN_Z;
+#else
+    primaries.green.Z = 0.1192;
+#endif
+
+#ifdef TARGET_DISPLAY_PRIMARY_BLUE_X
+    primaries.blue.X = TARGET_DISPLAY_PRIMARY_BLUE_X;
+#else
+    primaries.blue.X = 0.1805;
+#endif
+
+#ifdef TARGET_DISPLAY_PRIMARY_BLUE_Y
+    primaries.blue.Y = TARGET_DISPLAY_PRIMARY_BLUE_Y;
+#else
+    primaries.blue.Y = 0.0722;
+#endif
+
+#ifdef TARGET_DISPLAY_PRIMARY_BLUE_Z
+    primaries.blue.Z = TARGET_DISPLAY_PRIMARY_BLUE_Z;
+#else
+    primaries.blue.Z = 0.9506;
+#endif
+
+#ifdef TARGET_DISPLAY_PRIMARY_WHITE_X
+    primaries.white.X = TARGET_DISPLAY_PRIMARY_WHITE_X;
+#else
+    primaries.white.X = 0.9505;
+#endif
+
+#ifdef TARGET_DISPLAY_PRIMARY_WHITE_Y
+    primaries.white.Y = TARGET_DISPLAY_PRIMARY_WHITE_Y;
+#else
+    primaries.white.Y = 1.0000;
+#endif
+
+#ifdef TARGET_DISPLAY_PRIMARY_WHITE_Z
+    primaries.white.Z = TARGET_DISPLAY_PRIMARY_WHITE_Z;
+#else
+    primaries.white.Z = 1.0891;
+#endif
+
+    _hidl_cb(primaries);
+    return Void();
+}
+
 }  // namespace implementation
 }  // namespace V1_2
 }  // namespace configstore
diff --git a/configstore/1.2/default/SurfaceFlingerConfigs.h b/configstore/1.2/default/SurfaceFlingerConfigs.h
index 7dd8f6d..54a6e62 100644
--- a/configstore/1.2/default/SurfaceFlingerConfigs.h
+++ b/configstore/1.2/default/SurfaceFlingerConfigs.h
@@ -53,6 +53,7 @@
     // ::android::hardware::configstore::V1_2::ISurfaceFlingerConfigs follow implementation.
     Return<void> useColorManagement(useColorManagement_cb _hidl_cb) override;
     Return<void> getCompositionPreference(getCompositionPreference_cb _hidl_cb) override;
+    Return<void> getDisplayNativePrimaries(getDisplayNativePrimaries_cb _hidl_cb) override;
 };
 
 }  // namespace implementation
diff --git a/configstore/1.2/default/surfaceflinger.mk b/configstore/1.2/default/surfaceflinger.mk
index dab6aa55..9a67256 100644
--- a/configstore/1.2/default/surfaceflinger.mk
+++ b/configstore/1.2/default/surfaceflinger.mk
@@ -74,3 +74,51 @@
 ifneq ($(SF_WCG_COMPOSITION_PIXEL_FORMAT),)
     LOCAL_CFLAGS += -DWCG_COMPOSITION_PIXEL_FORMAT=$(SF_WCG_COMPOSITION_PIXEL_FORMAT)
 endif
+
+ifneq ($(TARGET_DISPLAY_PRIMARY_RED_X),)
+    LOCAL_CFLAGS += -DTARGET_DISPLAY_PRIMARY_RED_X=$(TARGET_DISPLAY_PRIMARY_RED_X)
+endif
+
+ifneq ($(TARGET_DISPLAY_PRIMARY_RED_Y),)
+    LOCAL_CFLAGS += -DTARGET_DISPLAY_PRIMARY_RED_Y=$(TARGET_DISPLAY_PRIMARY_RED_Y)
+endif
+
+ifneq ($(TARGET_DISPLAY_PRIMARY_RED_Z),)
+    LOCAL_CFLAGS += -DTARGET_DISPLAY_PRIMARY_RED_Z=$(TARGET_DISPLAY_PRIMARY_RED_Z)
+endif
+
+ifneq ($(TARGET_DISPLAY_PRIMARY_GREEN_X),)
+    LOCAL_CFLAGS += -DTARGET_DISPLAY_PRIMARY_GREEN_X=$(TARGET_DISPLAY_PRIMARY_GREEN_X)
+endif
+
+ifneq ($(TARGET_DISPLAY_PRIMARY_GREEN_Y),)
+    LOCAL_CFLAGS += -DTARGET_DISPLAY_PRIMARY_GREEN_Y=$(TARGET_DISPLAY_PRIMARY_GREEN_Y)
+endif
+
+ifneq ($(TARGET_DISPLAY_PRIMARY_GREEN_Z),)
+    LOCAL_CFLAGS += -DTARGET_DISPLAY_PRIMARY_GREEN_Z=$(TARGET_DISPLAY_PRIMARY_GREEN_Z)
+endif
+
+ifneq ($(TARGET_DISPLAY_PRIMARY_BLUE_X),)
+    LOCAL_CFLAGS += -DTARGET_DISPLAY_PRIMARY_BLUE_X=$(TARGET_DISPLAY_PRIMARY_BLUE_X)
+endif
+
+ifneq ($(TARGET_DISPLAY_PRIMARY_BLUE_Y),)
+    LOCAL_CFLAGS += -DTARGET_DISPLAY_PRIMARY_BLUE_Y=$(TARGET_DISPLAY_PRIMARY_BLUE_Y)
+endif
+
+ifneq ($(TARGET_DISPLAY_PRIMARY_BLUE_Z),)
+    LOCAL_CFLAGS += -DTARGET_DISPLAY_PRIMARY_BLUE_Z=$(TARGET_DISPLAY_PRIMARY_BLUE_Z)
+endif
+
+ifneq ($(TARGET_DISPLAY_PRIMARY_WHITE_X),)
+    LOCAL_CFLAGS += -DTARGET_DISPLAY_PRIMARY_WHITE_X=$(TARGET_DISPLAY_PRIMARY_WHITE_X)
+endif
+
+ifneq ($(TARGET_DISPLAY_PRIMARY_WHITE_Y),)
+    LOCAL_CFLAGS += -DTARGET_DISPLAY_PRIMARY_WHITE_Y=$(TARGET_DISPLAY_PRIMARY_WHITE_Y)
+endif
+
+ifneq ($(TARGET_DISPLAY_PRIMARY_WHITE_Z),)
+    LOCAL_CFLAGS += -DTARGET_DISPLAY_PRIMARY_WHITE_Z=$(TARGET_DISPLAY_PRIMARY_WHITE_Z)
+endif
diff --git a/configstore/1.2/types.hal b/configstore/1.2/types.hal
new file mode 100644
index 0000000..5b2c9a6
--- /dev/null
+++ b/configstore/1.2/types.hal
@@ -0,0 +1,28 @@
+/*
+ * Copyright (C) 2019 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package android.hardware.configstore@1.2;
+
+struct CieXyz {
+    float X;
+    float Y;
+    float Z;
+};
+struct DisplayPrimaries {
+    CieXyz red;
+    CieXyz green;
+    CieXyz blue;
+    CieXyz white;
+};
diff --git a/configstore/1.2/vts/functional/VtsHalConfigstoreV1_2TargetTest.cpp b/configstore/1.2/vts/functional/VtsHalConfigstoreV1_2TargetTest.cpp
index dc5fec5..881b591 100644
--- a/configstore/1.2/vts/functional/VtsHalConfigstoreV1_2TargetTest.cpp
+++ b/configstore/1.2/vts/functional/VtsHalConfigstoreV1_2TargetTest.cpp
@@ -21,6 +21,7 @@
 #include <android-base/logging.h>
 #include <android/hardware/configstore/1.0/types.h>
 #include <android/hardware/configstore/1.2/ISurfaceFlingerConfigs.h>
+#include <android/hardware/configstore/1.2/types.h>
 #include <unistd.h>
 
 using ::android::sp;
@@ -31,6 +32,7 @@
 using ::android::hardware::configstore::V1_0::OptionalInt64;
 using ::android::hardware::configstore::V1_0::OptionalUInt64;
 using ::android::hardware::configstore::V1_2::ISurfaceFlingerConfigs;
+using ::android::hardware::configstore::V1_2::DisplayPrimaries;
 using ::android::hardware::graphics::common::V1_1::PixelFormat;
 using ::android::hardware::graphics::common::V1_2::Dataspace;
 
@@ -125,6 +127,43 @@
     }
 }
 
+TEST_F(ConfigstoreHidlTest, TestGetDisplayNativePrimaries) {
+    DisplayPrimaries primaries;
+
+    Return<void> status = sfConfigs->getDisplayNativePrimaries(
+        [&](DisplayPrimaries tmpPrimaries) {
+            primaries.red = tmpPrimaries.red;
+            primaries.green = tmpPrimaries.green;
+            primaries.blue = tmpPrimaries.blue;
+            primaries.white = tmpPrimaries.white;
+        });
+    EXPECT_OK(status);
+
+    // Display primaries should be greater than or equal to zero.
+    // Or it returns defualt value if there is no definition.
+    // RED
+    EXPECT_GE(primaries.red.X, 0.0);
+    EXPECT_GE(primaries.red.Y, 0.0);
+    EXPECT_GE(primaries.red.Z, 0.0);
+
+    // GREEN
+    EXPECT_GE(primaries.green.X, 0.0);
+    EXPECT_GE(primaries.green.Y, 0.0);
+    EXPECT_GE(primaries.green.Z, 0.0);
+
+
+    // BLUE
+    EXPECT_GE(primaries.blue.X, 0.0);
+    EXPECT_GE(primaries.blue.Y, 0.0);
+    EXPECT_GE(primaries.blue.Z, 0.0);
+
+
+    // WHITE
+    EXPECT_GE(primaries.white.X, 0.0);
+    EXPECT_GE(primaries.white.Y, 0.0);
+    EXPECT_GE(primaries.white.Z, 0.0);
+}
+
 int main(int argc, char** argv) {
     ::testing::AddGlobalTestEnvironment(ConfigstoreHidlEnvironment::Instance());
     ::testing::InitGoogleTest(&argc, argv);
diff --git a/current.txt b/current.txt
index c063f3e..3b87306 100644
--- a/current.txt
+++ b/current.txt
@@ -388,6 +388,7 @@
 2a55e224aa9bc62c0387cd85ad3c97e33f0c33a4e1489cbae86b2523e6f9df35 android.hardware.camera.device@3.2::ICameraDevice
 8caf9104dc6885852c0b117d853dd93f6d4b61a0a365138295eb8bcd41b36423 android.hardware.camera.device@3.2::ICameraDeviceSession
 684702a60deef03a1e8093961dc0a18c555c857ad5a77ba7340b0635ae01eb70 android.hardware.camera.device@3.4::ICameraDeviceSession
+f8a19622cb0cc890913b1ef3e32b675ffb26089a09e02fef4056ebad324d2b5d android.hardware.camera.device@3.4::types
 291638a1b6d4e63283e9e722ab5049d9351717ffa2b66162124f84d1aa7c2835 android.hardware.camera.metadata@3.2::types
 8a075cf3a17fe99c6d23415a3e9a65612f1fee73ee052a3a8a0ca5b8877395a4 android.hardware.camera.metadata@3.3::types
 da33234403ff5d60f3473711917b9948e6484a4260b5247acdafb111193a9de2 android.hardware.configstore@1.0::ISurfaceFlingerConfigs
@@ -395,7 +396,7 @@
 d702fb01dc2a0733aa820b7eb65435ee3334f75632ef880bafd2fb8803a20a58 android.hardware.gnss@1.0::IGnssMeasurementCallback
 b7ecf29927055ec422ec44bf776223f07d79ad9f92ccf9becf167e62c2607e7a android.hardware.keymaster@4.0::IKeymasterDevice
 574e8f1499436fb4075894dcae0b36682427956ecb114f17f1fe22d116a83c6b android.hardware.neuralnetworks@1.0::IPreparedModel
-1fb32361286b938d48a55c2539c846732afce0b99fe08590f556643125bc13d3 android.hardware.neuralnetworks@1.0::types
+417ab60fe1ef786778047e4486f3d868ebce570d91addd8fe4251515213072de android.hardware.neuralnetworks@1.0::types
 e22e8135d061d0e9c4c1a70c25c19fdba10f4d3cda9795ef25b6392fc520317c android.hardware.neuralnetworks@1.1::types
 1d4a5776614c08b5d794a5ec5ab04697260cbd4b3441d5935cd53ee71d19da02 android.hardware.radio@1.0::IRadioResponse
 271187e261b30c01a33011aea257c07a2d2f05b72943ebee89e973e997849973 android.hardware.radio@1.0::types
diff --git a/drm/1.2/Android.bp b/drm/1.2/Android.bp
index 66a1bd8..fa2962a 100644
--- a/drm/1.2/Android.bp
+++ b/drm/1.2/Android.bp
@@ -9,8 +9,10 @@
     srcs: [
         "types.hal",
         "ICryptoFactory.hal",
+        "ICryptoPlugin.hal",
         "IDrmFactory.hal",
         "IDrmPlugin.hal",
+        "IDrmPluginListener.hal",
     ],
     interfaces: [
         "android.hardware.drm@1.0",
@@ -18,8 +20,8 @@
         "android.hidl.base@1.0",
     ],
     types: [
-        "KeySetId",
         "OfflineLicenseState",
+        "Status",
     ],
     gen_java: false,
 }
diff --git a/drm/1.2/ICryptoPlugin.hal b/drm/1.2/ICryptoPlugin.hal
new file mode 100644
index 0000000..0700676
--- /dev/null
+++ b/drm/1.2/ICryptoPlugin.hal
@@ -0,0 +1,84 @@
+/**
+ * Copyright (C) 2018 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package android.hardware.drm@1.2;
+
+import @1.0::DestinationBuffer;
+import @1.0::ICryptoPlugin;
+import @1.0::Mode;
+import @1.0::Pattern;
+import @1.0::SessionId;
+import @1.0::SharedBuffer;
+import @1.0::SubSample;
+
+/**
+ * ICryptoPlugin is the HAL for vendor-provided crypto plugins.
+ * It allows crypto sessions to be opened and operated on, to
+ * load crypto keys for a codec to decrypt protected video content.
+ */
+interface ICryptoPlugin extends @1.0::ICryptoPlugin {
+
+    /**
+     * Decrypt an array of subsamples from the source memory buffer to the
+     * destination memory buffer.
+     *
+     * decrypt_1_2() only differs from decrypt() in that additional status
+     * codes must be returned.
+     *
+     * @param secure a flag to indicate if a secure decoder is being used. This
+     *     enables the plugin to configure buffer modes to work consistently with
+     *     a secure decoder.
+     * @param the keyId for the key that is used to do the the decryption. The
+     *     keyId refers to a key in the associated MediaDrm instance.
+     * @param iv the initialization vector to use
+     * @param mode the crypto mode to use
+     * @param pattern the crypto pattern to use
+     * @param subSamples a vector of subsamples indicating the number
+     *     of clear and encrypted bytes to process. This allows the decrypt
+     *     call to operate on a range of subsamples in a single call
+     * @param source the input buffer for the decryption
+     * @param offset the offset of the first byte of encrypted data from
+     *     the base of the source buffer
+     * @param destination the output buffer for the decryption
+     * @return status the status of the call. The status must be OK or one
+     *     of the following errors:
+     *     ERROR_DRM_NO_LICENSE if no license keys have been loaded
+     *     ERROR_DRM_LICENSE_EXPIRED if the license keys have expired
+     *     ERROR_DRM_RESOURCE_BUSY if the resources required to perform
+     *         the decryption are not available
+     *     ERROR_DRM_INSUFFICIENT_OUTPUT_PROTECTION if required output
+     *         protections are not active
+     *     ERROR_DRM_INSUFFICIENT_SECURITY if the security level of the
+     *         device is not sufficient to meet the requirements in
+     *         the license policy
+     *     ERROR_DRM_FRAME_TOO_LARGE if the frame being decrypted into
+     *         the secure output buffer exceeds the size of the buffer
+     *     ERROR_DRM_SESSION_NOT_OPENED if the decrypt session is not
+     *         opened
+     *     ERROR_DRM_DECRYPT if the decrypt operation fails
+     *     ERROR_DRM_INVALID_STATE if the device is in a state where it
+     *         is not able to perform decryption
+     *     ERROR_DRM_CANNOT_HANDLE in other failure cases.
+     *
+     * @return bytesWritten the number of bytes output from the decryption
+     * @return detailedError if the error is a vendor-specific error, the
+     *     vendor's crypto HAL may provide a detailed error string to help
+     *     describe the error.
+     */
+    decrypt_1_2(bool secure, uint8_t[16] keyId, uint8_t[16] iv, Mode mode,
+        Pattern pattern, vec<SubSample> subSamples,
+            SharedBuffer source, uint64_t offset, DestinationBuffer destination)
+        generates(Status status, uint32_t bytesWritten, string detailedError);
+};
diff --git a/drm/1.2/IDrmPlugin.hal b/drm/1.2/IDrmPlugin.hal
index 88338d6..88ace0b 100644
--- a/drm/1.2/IDrmPlugin.hal
+++ b/drm/1.2/IDrmPlugin.hal
@@ -15,13 +15,19 @@
  */
 package android.hardware.drm@1.2;
 
-import @1.1::IDrmPlugin;
+import @1.0::KeyedVector;
+import @1.0::KeyType;
+import @1.0::SessionId;
 import @1.0::Status;
+import @1.1::IDrmPlugin;
+import @1.1::KeyRequestType;
+import @1.2::IDrmPluginListener;
 
 /**
- * IDrmPlugin is used to interact with a specific drm plugin that was created by
- * IDrm::createPlugin. A drm plugin provides methods for obtaining drm keys that
- * may be used by a codec to decrypt protected video content.
+ * IDrmPlugin is used to interact with a specific drm plugin that was
+ * created by IDrm::createPlugin. A drm plugin provides methods for
+ * obtaining drm keys to be used by a codec to decrypt protected video
+ * content.
  */
 interface IDrmPlugin extends @1.1::IDrmPlugin {
 
@@ -32,24 +38,25 @@
      * request/response exchange when the key request KeyType is
      * OFFLINE. Normally each app is responsible for keeping track of
      * the KeySetIds it has created. In some situations however, it
-     * may be necessary to request the list of stored offline license
+     * will be necessary to request the list of stored offline license
      * KeySetIds. If an app loses the KeySetId for any stored licenses
      * that it created, for example, it must be able to recover the
-     * stored KeySetIds so those licenses can be removed when they
+     * stored KeySetIds so those licenses will be removed when they
      * expire or when the app is uninstalled.
      * <p>
      * This method returns a list of the KeySetIds for all offline
-     * licenses. The offline license KeySetId may be used to query
+     * licenses. The offline license KeySetId allows an app to query
      * the status of an offline license or remove it.
      *
-     * @return status the status of the call. May be OK or
+     * @return status the status of the call. Must be OK or
      *     ERROR_DRM_INVALID_STATE if the HAL is in a state where the
      *     KeySetIds can't be returned.
      * @return a list of offline license keySetIds. If there are no offline
      *     licenses, the list must be empty and OK must be returned as the
      *     status.
      */
-    getOfflineLicenseKeySetIds() generates (Status status, vec<KeySetId> keySetIds);
+    getOfflineLicenseKeySetIds() generates (@1.0::Status status,
+            vec<KeySetId> keySetIds);
 
     /**
      * Normally offline licenses are released using a key
@@ -59,20 +66,20 @@
      * removed and then adjust the count of offline licenses allocated
      * to the device.
      * <p>
-     * In some exceptional situations it may be necessary to directly
-     * remove offline licenses without notifying the server, which may
-     * be performed using this method.
+     * In some exceptional situations it will be necessary to directly
+     * remove offline licenses without notifying the server, which is
+     * performed by this method.
      *
      * @param keySetId the id of the offline license to remove
-     * @return status the status of the call. May be one of OK on
+     * @return status the status of the call. Must be one of OK on
      *     success, BAD_VALUE if the license is not found or
      *     ERROR_DRM_INVALID_STATE if the HAL is in a state where the
      *     KeySetIds can't be returned.
      */
-    removeOfflineLicense(KeySetId keySetId) generates (Status status);
+    removeOfflineLicense(KeySetId keySetId) generates (@1.0::Status status);
 
     /**
-     * Request the state of an offline license. An offline license may
+     * Request the state of an offline license. An offline license must
      * be usable or inactive. The keys in a usable offline license are
      * available for decryption. When the offline license state is
      * inactive, the keys have been marked for release using
@@ -81,7 +88,7 @@
      * usable for decryption.
      *
      * @param keySetId the id of the offline license
-     * @return status the status of the call. May be one of OK on
+     * @return status the status of the call. Must be one of OK on
      *     success, BAD_VALUE if the license is not found or
      *     ERROR_DRM_INVALID_STATE if the HAL is in a state where the
      *     offline license state can't be queried.
@@ -89,6 +96,100 @@
      *     If the return status is not OK then state must be set to
      *     UNKNOWN.
      */
-    getOfflineLicenseState(KeySetId keySetId) generates (Status status,
-            OfflineLicenseState state);
+    getOfflineLicenseState(KeySetId keySetId) generates (
+            @1.0::Status status, OfflineLicenseState state);
+
+    /**
+     * A key request/response exchange occurs between the app and a License
+     * Server to obtain the keys required to decrypt the content.
+     * getKeyRequest_1_2() is used to obtain an opaque key request blob that is
+     * delivered to the license server.
+     *
+     * getKeyRequest_1_2() only differs from getKeyRequest_1_1() in that
+     *     additional status codes must be returned.
+     *
+     * @param scope either a sessionId or a keySetId, depending on the
+     *     specified keyType. When the keyType is OFFLINE or STREAMING, scope
+     *     must be set to the sessionId the keys will be provided to. When the
+     *     keyType is RELEASE, scope must be set to the keySetId of the keys
+     *     being released.
+     * @param initData container-specific data, its meaning is interpreted
+     *     based on the mime type provided in the mimeType parameter. It could
+     *     contain, for example, the content ID, key ID or other data obtained
+     *     from the content metadata that is required to generate the key
+     *     request. initData must be empty when keyType is RELEASE.
+     * @param mimeType identifies the mime type of the content
+     * @param keyType specifies if the keys are to be used for streaming,
+     *     offline or a release
+     * @param optionalParameters included in the key request message to
+     *     allow a client application to provide additional message parameters
+     *     to the server.
+     * @return status the status of the call. The status must be OK or one of
+     *     the following errors: ERROR_DRM_SESSION_NOT_OPENED if the session is
+     *     not opened, ERROR_DRM_NOT_PROVISIONED if the device requires
+     *     provisioning before it is able to generate a key request,
+     *     ERROR_DRM_RESOURCE_CONTENTION if client applications using the hal
+     *     are temporarily exceeding the available crypto resources such that a
+     *     retry of the operation is likely to succeed, ERROR_DRM_CANNOT_HANDLE
+     *     if getKeyRequest is not supported at the time of the call, BAD_VALUE
+     *     if any parameters are invalid or ERROR_DRM_INVALID_STATE if the HAL
+     *     is in a state where a key request cannot be generated.
+     * @return request if successful, the opaque key request blob is returned
+     * @return requestType indicates type information about the returned
+     *      request. The type must be one of INITIAL, RENEWAL, RELEASE, NONE or
+     *      UPDATE. An INITIAL request is the first key request for a
+     *      license. RENEWAL is a subsequent key request used to refresh the
+     *      keys in a license. RELEASE corresponds to a keyType of RELEASE,
+     *      which indicates keys are being released. NONE indicates that no
+     *      request is needed because the keys are already loaded. UPDATE
+     *      indicates that the keys need to be refetched after the initial
+     *      license request.
+     * @return defaultUrl the URL that the request may be sent to, if
+     *      provided by the drm HAL. The app can choose to override this URL.
+     */
+    getKeyRequest_1_2(vec<uint8_t> scope, vec<uint8_t> initData,
+            string mimeType, KeyType keyType, KeyedVector optionalParameters)
+        generates (Status status, vec<uint8_t> request,
+                KeyRequestType requestType, string defaultUrl);
+
+    /**
+     * A provision request/response exchange occurs between the app and a
+     * provisioning server to retrieve a device certificate. getProvisionRequest
+     * is used to obtain an opaque provisioning request blob that is delivered
+     * to the provisioning server.
+     *
+     * getProvisionRequest_1_2() only differs from getProvisionRequest_1_0() in
+     *     that additional status codes must be returned.
+     *
+     * @param certificateType the type of certificate requested, e.g. "X.509"
+     * @param certificateAuthority identifies the certificate authority. A
+     *     certificate authority (CA) is an entity which issues digital
+     *     certificates for use by other parties. It is an example of a trusted
+     *     third party.
+     * @return status the status of the call. The status must be OK or one of
+     *     the following errors: ERROR_DRM_RESOURCE_CONTENTION if client
+     *     applications using the hal are temporarily exceeding the available
+     *     crypto resources such that a retry of the operation is likely to
+     *     succeed, ERROR_DRM_CANNOT_HANDLE if the drm scheme does not require
+     *     provisioning or ERROR_DRM_INVALID_STATE if the HAL is in a state
+     *     where the provision request cannot be generated.
+     * @return request if successful the opaque certificate request blob
+     *     is returned
+     * @return defaultUrl URL that the provisioning request may be
+     *     sent to, if known by the HAL implementation. An app can choose to
+     *     override this URL. If the HAL implementation does not provide a
+     *     defaultUrl, the returned string must be empty.
+     */
+    getProvisionRequest_1_2(string certificateType, string certificateAuthority)
+        generates (Status status, vec<uint8_t> request, string defaultUrl);
+
+    /**
+     * Send a session lost state event to the listener. This event
+     * indicates that a session's state has become invalid because the
+     * device crypto hardware is incapable of retaining crypto session
+     * state across suspend and resume cycles.
+     *
+     * @param sessionId identifies the session the event originated from
+     */
+    sendSessionLostState(SessionId sessionId);
 };
diff --git a/drm/1.2/IDrmPluginListener.hal b/drm/1.2/IDrmPluginListener.hal
new file mode 100644
index 0000000..a6bd6c9
--- /dev/null
+++ b/drm/1.2/IDrmPluginListener.hal
@@ -0,0 +1,39 @@
+/*
+ * Copyright (C) 2018 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.hardware.drm@1.2;
+
+import @1.0::IDrmPluginListener;
+import @1.0::SessionId;
+
+/**
+ * IDrmPluginListener is a listener interface for Drm events sent from an
+ * IDrmPlugin instance.
+ */
+interface IDrmPluginListener extends @1.0::IDrmPluginListener {
+    /**
+     * Some device crypto hardware is incapable of retaining crypto
+     * session state across suspend and resume cycles. A
+     * SessionLostState event must be signaled when a session has
+     * become invalid for this reason. This event must not be used to
+     * indicate a failure in the crypto system. Closing the session
+     * and opening a new one must allow the application to resume
+     * normal use of the drm hal module.
+     *
+     * @param sessionId identifies the session that has been invalidated
+     */
+     oneway sendSessionLostState(SessionId sessionId);
+};
diff --git a/drm/1.2/types.hal b/drm/1.2/types.hal
index 8770c79..6e1acde 100644
--- a/drm/1.2/types.hal
+++ b/drm/1.2/types.hal
@@ -16,6 +16,8 @@
 
 package android.hardware.drm@1.2;
 
+import @1.0::Status;
+
 enum OfflineLicenseState : uint32_t {
     /**
      * Offline license state is unknown
@@ -23,7 +25,7 @@
     UNKNOWN,
 
     /**
-     * Offline license state is usable, the keys may be used for decryption.
+     * Offline license state is usable, the keys are usable for decryption.
      */
     USABLE,
 
@@ -35,6 +37,40 @@
     INACTIVE
 };
 
+enum Status : @1.0::Status {
+    /**
+     * The drm HAL module must return ERROR_DRM_INSUFFICIENT_SECURITY
+     * from the crypto plugin decrypt method when the security level
+     * of the device is not sufficient to meet the requirements in the
+     * license policy.
+     */
+    ERROR_DRM_INSUFFICIENT_SECURITY,
+
+    /**
+     * The drm HAL module must return ERROR_FRAME_TOO_LARGE from the
+     * decrypt method when the frame being decrypted into the secure
+     * output buffer exceeds the size of the buffer.
+     */
+    ERROR_DRM_FRAME_TOO_LARGE,
+
+    /**
+     * This error must be returned from any session method when an
+     * attempt is made to use the session after the crypto hardware
+     * state has been invalidated. Some devices are not able to
+     * retain crypto session state across device suspend/resume which
+     * results in invalid session state.
+     */
+    ERROR_DRM_SESSION_LOST_STATE,
+
+     /**
+      * The drm HAL module must return this error if client
+      * applications using the hal are temporarily exceeding the
+      * capacity of available crypto resources such that a retry of
+      * the operation is likely to succeed.
+      */
+    ERROR_DRM_RESOURCE_CONTENTION,
+};
+
 /**
  * KeySetId is an identifier that references a set of keys in an
  * offline license. The keySetId is created by the HAL implementation
diff --git a/gnss/2.0/Android.bp b/gnss/2.0/Android.bp
index 9b6b076..9b04be0 100644
--- a/gnss/2.0/Android.bp
+++ b/gnss/2.0/Android.bp
@@ -19,6 +19,7 @@
     ],
     interfaces: [
         "android.hardware.gnss.measurement_corrections@1.0",
+        "android.hardware.gnss.visibility_control@1.0",
         "android.hardware.gnss@1.0",
         "android.hardware.gnss@1.1",
         "android.hidl.base@1.0",
diff --git a/gnss/2.0/IGnss.hal b/gnss/2.0/IGnss.hal
index e1acd6d..1f1858e 100644
--- a/gnss/2.0/IGnss.hal
+++ b/gnss/2.0/IGnss.hal
@@ -17,6 +17,7 @@
 package android.hardware.gnss@2.0;
 
 import android.hardware.gnss.measurement_corrections@1.0::IMeasurementCorrections;
+import android.hardware.gnss.visibility_control@1.0::IGnssVisibilityControl;
 import @1.1::IGnss;
 
 import IGnssCallback;
@@ -25,7 +26,15 @@
 import IAGnss;
 import IAGnssRil;
 
-/** Represents the standard GNSS (Global Navigation Satellite System) interface. */
+/**
+ * Represents the standard GNSS (Global Navigation Satellite System) interface.
+ *
+ * Due to the introduction of new GNSS HAL package android.hardware.gnss.visibility_control@1.0
+ * the interface @1.0::IGnssNi.hal and @1.0::IGnssNiCallback.hal are deprecated in this version
+ * and are not supported by the framework. The GNSS HAL implementation of this interface
+ * must return nullptr for the following @1.0::IGnss method.
+ *      getExtensionGnssNi() generates (IGnssNi gnssNiIface);
+ */
 interface IGnss extends @1.1::IGnss {
     /**
      * Opens the interface and provides the callback routines to the implementation of this
@@ -76,6 +85,13 @@
      *
      * @return measurementCorrectionsIface Handle to the IMeasurementCorrections interface.
      */
-     getExtensionMeasurementCorrections()
+    getExtensionMeasurementCorrections()
             generates (IMeasurementCorrections measurementCorrectionsIface);
-};
+
+    /**
+     * This method returns the IGnssVisibilityControl interface.
+     *
+     * @return visibilityControlIface Handle to the IGnssVisibilityControl interface.
+     */
+    getExtensionVisibilityControl() generates (IGnssVisibilityControl visibilityControlIface);
+};
\ No newline at end of file
diff --git a/gnss/2.0/default/Android.bp b/gnss/2.0/default/Android.bp
index 92d5c1f..985aa2b 100644
--- a/gnss/2.0/default/Android.bp
+++ b/gnss/2.0/default/Android.bp
@@ -26,6 +26,7 @@
         "AGnssRil.cpp",
         "Gnss.cpp",
         "GnssMeasurement.cpp",
+        "GnssVisibilityControl.cpp",
         "service.cpp"
     ],
     shared_libs: [
@@ -35,6 +36,7 @@
         "liblog",
         "android.hardware.gnss@2.0",
         "android.hardware.gnss.measurement_corrections@1.0",
+        "android.hardware.gnss.visibility_control@1.0",
         "android.hardware.gnss@1.0",
         "android.hardware.gnss@1.1",
     ],
diff --git a/gnss/2.0/default/Gnss.cpp b/gnss/2.0/default/Gnss.cpp
index 5c752d5..217f0f3 100644
--- a/gnss/2.0/default/Gnss.cpp
+++ b/gnss/2.0/default/Gnss.cpp
@@ -22,8 +22,10 @@
 #include "AGnssRil.h"
 #include "GnssConfiguration.h"
 #include "GnssMeasurement.h"
+#include "GnssVisibilityControl.h"
 
 using ::android::hardware::Status;
+using ::android::hardware::gnss::visibility_control::V1_0::implementation::GnssVisibilityControl;
 
 namespace android {
 namespace hardware {
@@ -93,8 +95,8 @@
 }
 
 Return<sp<V1_0::IGnssNi>> Gnss::getExtensionGnssNi() {
-    // TODO implement
-    return sp<V1_0::IGnssNi>{};
+    // The IGnssNi.hal interface is deprecated in 2.0.
+    return nullptr;
 }
 
 Return<sp<V1_0::IGnssMeasurement>> Gnss::getExtensionGnssMeasurement() {
@@ -205,6 +207,11 @@
     return sp<measurement_corrections::V1_0::IMeasurementCorrections>{};
 }
 
+Return<sp<visibility_control::V1_0::IGnssVisibilityControl>> Gnss::getExtensionVisibilityControl() {
+    ALOGD("Gnss::getExtensionVisibilityControl");
+    return new GnssVisibilityControl();
+}
+
 Return<bool> Gnss::setCallback_2_0(const sp<V2_0::IGnssCallback>& callback) {
     ALOGD("Gnss::setCallback_2_0");
     if (callback == nullptr) {
diff --git a/gnss/2.0/default/Gnss.h b/gnss/2.0/default/Gnss.h
index e86158f..890b026 100644
--- a/gnss/2.0/default/Gnss.h
+++ b/gnss/2.0/default/Gnss.h
@@ -79,6 +79,8 @@
     Return<bool> setCallback_2_0(const sp<V2_0::IGnssCallback>& callback) override;
     Return<sp<measurement_corrections::V1_0::IMeasurementCorrections>>
     getExtensionMeasurementCorrections() override;
+    Return<sp<visibility_control::V1_0::IGnssVisibilityControl>> getExtensionVisibilityControl()
+            override;
 
    private:
     static sp<V2_0::IGnssCallback> sGnssCallback_2_0;
diff --git a/gnss/2.0/default/GnssVisibilityControl.cpp b/gnss/2.0/default/GnssVisibilityControl.cpp
new file mode 100644
index 0000000..99b8e34
--- /dev/null
+++ b/gnss/2.0/default/GnssVisibilityControl.cpp
@@ -0,0 +1,57 @@
+/*
+ * Copyright (C) 2019 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#define LOG_TAG "GnssVisibilityControl"
+
+#include "GnssVisibilityControl.h"
+#include <log/log.h>
+
+namespace android {
+namespace hardware {
+namespace gnss {
+namespace visibility_control {
+namespace V1_0 {
+namespace implementation {
+
+// Methods from ::android::hardware::gnss::visibility_control::V1_0::IGnssVisibilityControl follow.
+Return<bool> GnssVisibilityControl::enableNfwLocationAccess(
+        const hidl_vec<hidl_string>& proxyApps) {
+    std::string os;
+    bool first = true;
+    for (const auto& proxyApp : proxyApps) {
+        if (first) {
+            first = false;
+        } else {
+            os += " ";
+        }
+
+        os += proxyApp;
+    }
+
+    ALOGD("enableNfwLocationAccess proxyApps: %s", os.c_str());
+    return true;
+}
+
+Return<bool> GnssVisibilityControl::setCallback(const sp<V1_0::IGnssVisibilityControlCallback>&) {
+    return true;
+}
+
+}  // namespace implementation
+}  // namespace V1_0
+}  // namespace visibility_control
+}  // namespace gnss
+}  // namespace hardware
+}  // namespace android
diff --git a/gnss/2.0/default/GnssVisibilityControl.h b/gnss/2.0/default/GnssVisibilityControl.h
new file mode 100644
index 0000000..45febff
--- /dev/null
+++ b/gnss/2.0/default/GnssVisibilityControl.h
@@ -0,0 +1,53 @@
+/*
+ * Copyright (C) 2019 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef ANDROID_HARDWARE_GNSS_VISIBILITY_CONTROL_V1_0_GNSSVISIBILITYCONTROL_H
+#define ANDROID_HARDWARE_GNSS_VISIBILITY_CONTROL_V1_0_GNSSVISIBILITYCONTROL_H
+
+#include <android/hardware/gnss/visibility_control/1.0/IGnssVisibilityControl.h>
+#include <hidl/MQDescriptor.h>
+#include <hidl/Status.h>
+
+namespace android {
+namespace hardware {
+namespace gnss {
+namespace visibility_control {
+namespace V1_0 {
+namespace implementation {
+
+using ::android::sp;
+using ::android::hardware::hidl_array;
+using ::android::hardware::hidl_memory;
+using ::android::hardware::hidl_string;
+using ::android::hardware::hidl_vec;
+using ::android::hardware::Return;
+using ::android::hardware::Void;
+
+struct GnssVisibilityControl : public IGnssVisibilityControl {
+    // Methods from ::android::hardware::gnss::visibility_control::V1_0::IGnssVisibilityControl
+    // follow.
+    Return<bool> enableNfwLocationAccess(const hidl_vec<hidl_string>& proxyApps) override;
+    Return<bool> setCallback(const sp<V1_0::IGnssVisibilityControlCallback>& callback) override;
+};
+
+}  // namespace implementation
+}  // namespace V1_0
+}  // namespace visibility_control
+}  // namespace gnss
+}  // namespace hardware
+}  // namespace android
+
+#endif  // ANDROID_HARDWARE_GNSS_VISIBILITY_CONTROL_V1_0_GNSSVISIBILITYCONTROL_H
\ No newline at end of file
diff --git a/gnss/2.0/vts/functional/Android.bp b/gnss/2.0/vts/functional/Android.bp
index 894716d..684b381 100644
--- a/gnss/2.0/vts/functional/Android.bp
+++ b/gnss/2.0/vts/functional/Android.bp
@@ -24,6 +24,7 @@
     ],
     static_libs: [
         "android.hardware.gnss.measurement_corrections@1.0",
+        "android.hardware.gnss.visibility_control@1.0",
         "android.hardware.gnss@1.0",
         "android.hardware.gnss@1.1",
         "android.hardware.gnss@2.0",
diff --git a/gnss/2.0/vts/functional/gnss_hal_test_cases.cpp b/gnss/2.0/vts/functional/gnss_hal_test_cases.cpp
index cef06a2..552cf1b 100644
--- a/gnss/2.0/vts/functional/gnss_hal_test_cases.cpp
+++ b/gnss/2.0/vts/functional/gnss_hal_test_cases.cpp
@@ -19,6 +19,7 @@
 #include <VtsHalHidlTargetTestBase.h>
 #include <gnss_hal_test.h>
 
+using android::hardware::hidl_string;
 using android::hardware::hidl_vec;
 
 using IGnssConfiguration_2_0 = android::hardware::gnss::V2_0::IGnssConfiguration;
@@ -30,6 +31,8 @@
 using IAGnss_2_0 = android::hardware::gnss::V2_0::IAGnss;
 using IAGnss_1_0 = android::hardware::gnss::V1_0::IAGnss;
 using IAGnssCallback_2_0 = android::hardware::gnss::V2_0::IAGnssCallback;
+using android::hardware::gnss::V1_0::IGnssNi;
+using android::hardware::gnss::visibility_control::V1_0::IGnssVisibilityControl;
 
 /*
  * SetupTeardownCreateCleanup:
@@ -117,7 +120,7 @@
  * The GNSS HAL 2.0 implementation must support @2.0::IAGnssRil interface due to the deprecation
  * of framework network API methods needed to support the @1.0::IAGnssRil interface.
  *
- * TODO (b/121287858): Enforce gnss@2.0 HAL package is supported on devices launced with Q or later.
+ * TODO (b/121287858): Enforce gnss@2.0 HAL package is supported on devices launched with Q or later
  */
 TEST_F(GnssHalTest, TestAGnssRilExtension) {
     auto agnssRil = gnss_hal_->getExtensionAGnssRil_2_0();
@@ -199,7 +202,7 @@
  * The GNSS HAL 2.0 implementation must support @2.0::IAGnss interface due to the deprecation
  * of framework network API methods needed to support the @1.0::IAGnss interface.
  *
- * TODO (b/121287858): Enforce gnss@2.0 HAL package is supported on devices launced with Q or later.
+ * TODO (b/121287858): Enforce gnss@2.0 HAL package is supported on devices launched with Q or later
  */
 TEST_F(GnssHalTest, TestAGnssExtension) {
     // Verify IAGnss 2.0 is supported.
@@ -218,10 +221,45 @@
  * TestAGnssExtension_1_0_Deprecation:
  * Gets the @1.0::IAGnss extension and verifies that it is a nullptr.
  *
- * TODO (b/121287858): Enforce gnss@2.0 HAL package is supported on devices launced with Q or later.
+ * TODO (b/121287858): Enforce gnss@2.0 HAL package is supported on devices launched with Q or later
  */
 TEST_F(GnssHalTest, TestAGnssExtension_1_0_Deprecation) {
     // Verify IAGnss 1.0 is not supported.
     auto agnss_1_0 = gnss_hal_->getExtensionAGnss();
     ASSERT_TRUE(!agnss_1_0.isOk() || ((sp<IAGnss_1_0>)agnss_1_0) == nullptr);
 }
+
+/*
+ * TestGnssNiExtension_Deprecation:
+ * Gets the @1.0::IGnssNi extension and verifies that it is a nullptr.
+ *
+ * TODO (b/121287858): Enforce gnss@2.0 HAL package is supported on devices launched with Q or later
+ */
+TEST_F(GnssHalTest, TestGnssNiExtension_Deprecation) {
+    // Verify IGnssNi 1.0 is not supported.
+    auto gnssNi = gnss_hal_->getExtensionGnssNi();
+    ASSERT_TRUE(!gnssNi.isOk() || ((sp<IGnssNi>)gnssNi) == nullptr);
+}
+
+/*
+ * TestGnssVisibilityControlExtension:
+ * Gets the GnssVisibilityControlExtension and verifies that it supports the
+ * gnss.visibility_control@1.0::IGnssVisibilityControl interface by invoking a method.
+ *
+ * The GNSS HAL 2.0 implementation must support gnss.visibility_control@1.0::IGnssVisibilityControl.
+ *
+ * TODO (b/121287858): Enforce gnss@2.0 HAL package is supported on devices launched with Q or later
+ */
+TEST_F(GnssHalTest, TestGnssVisibilityControlExtension) {
+    // Verify IGnssVisibilityControl is supported.
+    auto gnssVisibilityControl = gnss_hal_->getExtensionVisibilityControl();
+    ASSERT_TRUE(gnssVisibilityControl.isOk());
+    sp<IGnssVisibilityControl> iGnssVisibilityControl = gnssVisibilityControl;
+    ASSERT_NE(iGnssVisibilityControl, nullptr);
+
+    // Set non-framework proxy apps.
+    hidl_vec<hidl_string> proxyApps{"ims.example.com", "mdt.example.com"};
+    auto result = iGnssVisibilityControl->enableNfwLocationAccess(proxyApps);
+    ASSERT_TRUE(result.isOk());
+    EXPECT_TRUE(result);
+}
diff --git a/gnss/visibility_control/1.0/Android.bp b/gnss/visibility_control/1.0/Android.bp
new file mode 100644
index 0000000..40a28c9
--- /dev/null
+++ b/gnss/visibility_control/1.0/Android.bp
@@ -0,0 +1,18 @@
+// This file is autogenerated by hidl-gen -Landroidbp.
+
+hidl_interface {
+    name: "android.hardware.gnss.visibility_control@1.0",
+    root: "android.hardware",
+    vndk: {
+        enabled: true,
+    },
+    srcs: [
+        "IGnssVisibilityControl.hal",
+        "IGnssVisibilityControlCallback.hal",
+    ],
+    interfaces: [
+        "android.hidl.base@1.0",
+    ],
+    gen_java: true,
+}
+
diff --git a/gnss/visibility_control/1.0/IGnssVisibilityControl.hal b/gnss/visibility_control/1.0/IGnssVisibilityControl.hal
new file mode 100644
index 0000000..9148127
--- /dev/null
+++ b/gnss/visibility_control/1.0/IGnssVisibilityControl.hal
@@ -0,0 +1,83 @@
+/*
+ * Copyright (C) 2018 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.hardware.gnss.visibility_control@1.0;
+
+import IGnssVisibilityControlCallback;
+
+/**
+ * Represents the GNSS location reporting permissions and notification interface.
+ *
+ * This interface is used to tell the GNSS HAL implementation whether the framework user has
+ * granted permission to the GNSS HAL implementation to provide GNSS location information for
+ * non-framework (NFW), non-user initiated emergency use cases, and to notify the framework user
+ * of these GNSS location information deliveries.
+ *
+ * For user initiated emergency cases (and for the configured extended emergency session duration),
+ * the GNSS HAL implementation must serve the emergency location supporting network initiated
+ * location requests immediately irrespective of this permission settings.
+ *
+ * There is no separate need for the GNSS HAL implementation to monitor the global device location
+ * on/off setting. Permission to use GNSS for non-framework use cases is expressly controlled
+ * by the method enableNfwLocationAccess(). The framework monitors the location permission settings
+ * of the configured proxy applications(s), and device location settings, and calls the method
+ * enableNfwLocationAccess() whenever the user control proxy applications have, or do not have,
+ * location permission. The proxy applications are used to provide user visibility and control of
+ * location access by the non-framework on/off device entities they are representing.
+ *
+ * For device user visibility, the GNSS HAL implementation must call the method
+ * IGnssVisibilityControlCallback.nfwNotifyCb() whenever location request is rejected or
+ * location information is provided to non-framework entities (on or off device). This includes
+ * the network initiated location requests for user-initiated emergency use cases as well.
+ *
+ * The HAL implementations that support this interface must not report GNSS location, measurement,
+ * status, or other information that can be used to derive user location to any entity when not
+ * expressly authorized by this HAL. This includes all endpoints for location information
+ * off the device, including carriers, vendors, OEM and others directly or indirectly.
+ */
+interface IGnssVisibilityControl {
+    /**
+     * Enables/disables non-framework entity location access permission in the GNSS HAL.
+     *
+     * The framework will call this method to update GNSS HAL implementation every time the
+     * framework user, through the given proxy application(s) and/or device location settings,
+     * explicitly grants/revokes the location access permission for non-framework, non-user
+     * initiated emergency use cases.
+     *
+     * Whenever the user location information is delivered to non-framework entities, the HAL
+     * implementation must call the method IGnssVisibilityControlCallback.nfwNotifyCb() to notify
+     * the framework for user visibility.
+     *
+     * @param proxyApps Full list of package names of proxy Android applications representing
+     * the non-framework location access entities (on/off the device) for which the framework
+     * user has granted non-framework location access permission. The GNSS HAL implementation
+     * must provide location information only to non-framework entities represented by these
+     * proxy applications.
+     *
+     * The package name of the proxy Android application follows the standard Java language
+     * package naming format. For example, com.example.myapp.
+     *
+     * @return success True if the operation was successful.
+     */
+    enableNfwLocationAccess(vec<string> proxyApps) generates (bool success);
+
+    /**
+     * Registers the callback for HAL implementation to use.
+     *
+     * @param callback Handle to IGnssVisibilityControlCallback interface.
+     */
+    setCallback(IGnssVisibilityControlCallback callback) generates (bool success);
+};
\ No newline at end of file
diff --git a/gnss/visibility_control/1.0/IGnssVisibilityControlCallback.hal b/gnss/visibility_control/1.0/IGnssVisibilityControlCallback.hal
new file mode 100644
index 0000000..5a582c2
--- /dev/null
+++ b/gnss/visibility_control/1.0/IGnssVisibilityControlCallback.hal
@@ -0,0 +1,160 @@
+/*
+ * Copyright (C) 2018 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.hardware.gnss.visibility_control@1.0;
+
+/**
+ * GNSS location reporting permissions and notification callback interface.
+ */
+interface IGnssVisibilityControlCallback {
+    /**
+     * Protocol stack that is requesting the non-framework location information.
+     */
+    enum NfwProtocolStack : uint8_t {
+        /** Cellular control plane requests */
+        CTRL_PLANE                      = 0,
+        /** All types of SUPL requests */
+        SUPL                            = 1,
+
+        /** All types of requests from IMS */
+        IMS                             = 10,
+        /** All types of requests from SIM */
+        SIM                             = 11,
+
+        /** Requests from other protocol stacks */
+        OTHER_PROTOCOL_STACK            = 100
+    };
+
+    /*
+     * Entity that is requesting/receiving the location information.
+     */
+    enum NfwRequestor : uint8_t {
+        /** Wireless service provider */
+        CARRIER                         = 0,
+
+        /** Device manufacturer */
+        OEM                             = 10,
+        /** Modem chipset vendor */
+        MODEM_CHIPSET_VENDOR            = 11,
+        /** GNSS chipset vendor */
+        GNSS_CHIPSET_VENDOR             = 12,
+        /** Other chipset vendor */
+        OTHER_CHIPSET_VENDOR            = 13,
+
+        /** Automobile client */
+        AUTOMOBILE_CLIENT               = 20,
+
+        /** Other sources */
+        OTHER_REQUESTOR                 = 100
+     };
+
+    /**
+     * GNSS response type for non-framework location requests.
+     */
+    enum NfwResponseType : uint8_t {
+        /** Request rejected because framework has not given permission for this use case */
+        REJECTED                        = 0,
+
+        /** Request accepted but could not provide location because of a failure */
+        ACCEPTED_NO_LOCATION_PROVIDED   = 1,
+
+        /** Request accepted and location provided */
+        ACCEPTED_LOCATION_PROVIDED      = 2,
+     };
+
+    /**
+     * Represents a non-framework location information request/response notification.
+     */
+    struct NfwNotification {
+        /**
+         * Package name of the Android proxy application representing the non-framework
+         * entity that requested location. Set to empty string if unknown.
+         */
+        string proxyAppPackageName;
+
+        /** Protocol stack that initiated the non-framework location request. */
+        NfwProtocolStack protocolStack;
+
+        /**
+         * Name of the protocol stack if protocolStack field is set to OTHER_PROTOCOL_STACK.
+         * Otherwise, set to empty string.
+         *
+         * This field is opaque to the framework and used for logging purposes.
+         */
+        string otherProtocolStackName;
+
+        /** Source initiating/receiving the location information. */
+        NfwRequestor requestor;
+
+        /**
+         * Identity of the endpoint receiving the location information. For example, carrier
+         * name, OEM name, SUPL SLP/E-SLP FQDN, chipset vendor name, etc.
+         *
+         * This field is opaque to the framework and used for logging purposes.
+         */
+        string requestorId;
+
+        /** Indicates whether location information was provided for this request. */
+        NfwResponseType responseType;
+
+        /** Is the device in user initiated emergency session. */
+        bool inEmergencyMode;
+
+        /** Is cached location provided */
+        bool isCachedLocation;
+    };
+
+    /**
+     * Callback to report a non-framework delivered location.
+     *
+     * The GNSS HAL implementation must call this method to notify the framework whenever
+     * a non-framework location request is made to the GNSS HAL.
+     *
+     * Non-framework entities like low power sensor hubs that request location from GNSS and
+     * only pass location information through Android framework controls are exempt from this
+     * power-spending reporting. However, low power sensor hubs or other chipsets which may send
+     * the location information to anywhere other than Android framework (which provides user
+     * visibility and control), must report location information use through this API whenever
+     * location information (or events driven by that location such as "home" location detection)
+     * leaves the domain of that low power chipset.
+     *
+     * To avoid overly spamming the framework, high speed location reporting of the exact same
+     * type may be throttled to report location at a lower rate than the actual report rate, as
+     * long as the location is reported with a latency of no more than the larger of 5 seconds,
+     * or the next the Android processor awake time. For example, if an Automotive client is
+     * getting location information from the GNSS location system at 20Hz, this method may be
+     * called at 1Hz. As another example, if a low power processor is getting location from the
+     * GNSS chipset, and the Android processor is asleep, the notification to the Android HAL may
+     * be delayed until the next wake of the Android processor.
+     *
+     * @param notification Non-framework delivered location request/response description.
+     */
+    nfwNotifyCb(NfwNotification notification);
+
+    /**
+     * Tells if the device is currently in an emergency session.
+     *
+     * Emergency session is defined as the device being actively in a user initiated emergency
+     * call or in post emergency call extension time period.
+     *
+     * If the GNSS HAL implementation cannot determine if the device is in emergency session
+     * mode, it must call this method to confirm that the device is in emergency session before
+     * serving network initiated emergency SUPL and Control Plane location requests.
+     *
+     * @return success True if the framework determines that the device is in emergency session.
+     */
+    isInEmergencySession() generates (bool success);
+};
\ No newline at end of file
diff --git a/graphics/allocator/2.0/default/OWNERS b/graphics/allocator/2.0/default/OWNERS
index 3aa5fa1..273cb4c 100644
--- a/graphics/allocator/2.0/default/OWNERS
+++ b/graphics/allocator/2.0/default/OWNERS
@@ -1,4 +1,4 @@
 # Graphics team
 jessehall@google.com
-olv@google.com
+marissaw@google.com
 stoza@google.com
diff --git a/graphics/allocator/2.0/utils/OWNERS b/graphics/allocator/2.0/utils/OWNERS
index 3aa5fa1..273cb4c 100644
--- a/graphics/allocator/2.0/utils/OWNERS
+++ b/graphics/allocator/2.0/utils/OWNERS
@@ -1,4 +1,4 @@
 # Graphics team
 jessehall@google.com
-olv@google.com
+marissaw@google.com
 stoza@google.com
diff --git a/graphics/allocator/3.0/Android.bp b/graphics/allocator/3.0/Android.bp
new file mode 100644
index 0000000..fa3e2ce
--- /dev/null
+++ b/graphics/allocator/3.0/Android.bp
@@ -0,0 +1,21 @@
+// This file is autogenerated by hidl-gen -Landroidbp.
+
+hidl_interface {
+    name: "android.hardware.graphics.allocator@3.0",
+    root: "android.hardware",
+    vndk: {
+        enabled: true,
+    },
+    srcs: [
+        "IAllocator.hal",
+    ],
+    interfaces: [
+        "android.hardware.graphics.common@1.0",
+        "android.hardware.graphics.common@1.1",
+        "android.hardware.graphics.common@1.2",
+        "android.hardware.graphics.mapper@3.0",
+        "android.hidl.base@1.0",
+    ],
+    gen_java: false,
+}
+
diff --git a/graphics/allocator/3.0/IAllocator.hal b/graphics/allocator/3.0/IAllocator.hal
new file mode 100644
index 0000000..3651e91
--- /dev/null
+++ b/graphics/allocator/3.0/IAllocator.hal
@@ -0,0 +1,52 @@
+/*
+ * Copyright 2019 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.hardware.graphics.allocator@3.0;
+
+import android.hardware.graphics.mapper@3.0;
+
+interface IAllocator {
+    /**
+     * Retrieves implementation-defined debug information, which will be
+     * displayed during, for example, `dumpsys SurfaceFlinger`.
+     *
+     * @return debugInfo is a string of debug information.
+     */
+    dumpDebugInfo() generates (string debugInfo);
+
+    /**
+     * Allocates buffers with the properties specified by the descriptor.
+     *
+     * @param descriptor Properties of the buffers to allocate. This must be
+     *     obtained from IMapper::createDescriptor().
+     * @param count The number of buffers to allocate.
+     * @return error Error status of the call, which may be
+     *     - `NONE` upon success.
+     *     - `BAD_DESCRIPTOR` if the descriptor is invalid.
+     *     - `NO_RESOURCES` if the allocation cannot be fulfilled at this time.
+     *     - `UNSUPPORTED` if any of the properties encoded in the descriptor
+     *       are not supported.
+     * @return stride The number of pixels between two consecutive rows of
+     *     an allocated buffer, when the concept of consecutive rows is defined.
+     *     Otherwise, it has no meaning.
+     * @return buffers Array of raw handles to the allocated buffers.
+     */
+    allocate(BufferDescriptor descriptor, uint32_t count)
+        generates (Error error,
+                   uint32_t stride,
+                   vec<handle> buffers);
+};
+
diff --git a/graphics/composer/2.1/default/Android.bp b/graphics/composer/2.1/default/Android.bp
index 2de1e3c..63accff 100644
--- a/graphics/composer/2.1/default/Android.bp
+++ b/graphics/composer/2.1/default/Android.bp
@@ -10,6 +10,7 @@
     shared_libs: [
         "android.hardware.graphics.composer@2.1",
         "android.hardware.graphics.mapper@2.0",
+        "android.hardware.graphics.mapper@3.0",
         "libbase",
         "libcutils",
         "libfmq",
diff --git a/graphics/composer/2.1/default/OWNERS b/graphics/composer/2.1/default/OWNERS
index 4714be2..db8fb80 100644
--- a/graphics/composer/2.1/default/OWNERS
+++ b/graphics/composer/2.1/default/OWNERS
@@ -1,5 +1,6 @@
 # Graphics team
 courtneygo@google.com
 jessehall@google.com
-olv@google.com
+lpy@google.com
 stoza@google.com
+vhau@google.com
diff --git a/graphics/composer/2.1/utils/OWNERS b/graphics/composer/2.1/utils/OWNERS
index d515a23..5acc631 100644
--- a/graphics/composer/2.1/utils/OWNERS
+++ b/graphics/composer/2.1/utils/OWNERS
@@ -1,4 +1,5 @@
 courtneygo@google.com
 jessehall@google.com
-olv@google.com
+lpy@google.com
 stoza@google.com
+vhau@google.com
diff --git a/graphics/composer/2.1/utils/hal/Android.bp b/graphics/composer/2.1/utils/hal/Android.bp
index f24e768..7a501fc 100644
--- a/graphics/composer/2.1/utils/hal/Android.bp
+++ b/graphics/composer/2.1/utils/hal/Android.bp
@@ -20,11 +20,13 @@
     shared_libs: [
         "android.hardware.graphics.composer@2.1",
         "android.hardware.graphics.mapper@2.0",
+        "android.hardware.graphics.mapper@3.0",
         "libhardware", // TODO remove hwcomposer2.h dependency
     ],
     export_shared_lib_headers: [
         "android.hardware.graphics.composer@2.1",
         "android.hardware.graphics.mapper@2.0",
+        "android.hardware.graphics.mapper@3.0",
         "libhardware",
     ],
     header_libs: [
diff --git a/graphics/composer/2.1/utils/hal/include/composer-hal/2.1/ComposerResources.h b/graphics/composer/2.1/utils/hal/include/composer-hal/2.1/ComposerResources.h
index f249f1a..3a73f84 100644
--- a/graphics/composer/2.1/utils/hal/include/composer-hal/2.1/ComposerResources.h
+++ b/graphics/composer/2.1/utils/hal/include/composer-hal/2.1/ComposerResources.h
@@ -26,6 +26,7 @@
 #include <vector>
 
 #include <android/hardware/graphics/mapper/2.0/IMapper.h>
+#include <android/hardware/graphics/mapper/3.0/IMapper.h>
 #include <log/log.h>
 
 namespace android {
@@ -39,9 +40,16 @@
 class ComposerHandleImporter {
    public:
     bool init() {
-        mMapper = mapper::V2_0::IMapper::getService();
-        ALOGE_IF(!mMapper, "failed to get mapper service");
-        return mMapper != nullptr;
+        mMapper3 = mapper::V3_0::IMapper::getService();
+        if (mMapper3) {
+            return true;
+        }
+        ALOGW_IF(!mMapper3, "failed to get mapper 3.0 service");
+
+        mMapper2 = mapper::V2_0::IMapper::getService();
+        ALOGE_IF(!mMapper2, "failed to get mapper 2.0 service");
+
+        return mMapper2 != nullptr;
     }
 
     Error importBuffer(const native_handle_t* rawHandle, const native_handle_t** outBufferHandle) {
@@ -50,14 +58,28 @@
             return Error::NONE;
         }
 
-        mapper::V2_0::Error error;
         const native_handle_t* bufferHandle;
-        mMapper->importBuffer(rawHandle, [&](const auto& tmpError, const auto& tmpBufferHandle) {
-            error = tmpError;
-            bufferHandle = static_cast<const native_handle_t*>(tmpBufferHandle);
-        });
-        if (error != mapper::V2_0::Error::NONE) {
-            return Error::NO_RESOURCES;
+        if (mMapper2) {
+            mapper::V2_0::Error error;
+            mMapper2->importBuffer(
+                rawHandle, [&](const auto& tmpError, const auto& tmpBufferHandle) {
+                    error = tmpError;
+                    bufferHandle = static_cast<const native_handle_t*>(tmpBufferHandle);
+                });
+            if (error != mapper::V2_0::Error::NONE) {
+                return Error::NO_RESOURCES;
+            }
+        }
+        if (mMapper3) {
+            mapper::V3_0::Error error;
+            mMapper3->importBuffer(
+                rawHandle, [&](const auto& tmpError, const auto& tmpBufferHandle) {
+                    error = tmpError;
+                    bufferHandle = static_cast<const native_handle_t*>(tmpBufferHandle);
+                });
+            if (error != mapper::V3_0::Error::NONE) {
+                return Error::NO_RESOURCES;
+            }
         }
 
         *outBufferHandle = bufferHandle;
@@ -66,7 +88,13 @@
 
     void freeBuffer(const native_handle_t* bufferHandle) {
         if (bufferHandle) {
-            mMapper->freeBuffer(static_cast<void*>(const_cast<native_handle_t*>(bufferHandle)));
+            if (mMapper2) {
+                mMapper2->freeBuffer(
+                    static_cast<void*>(const_cast<native_handle_t*>(bufferHandle)));
+            } else if (mMapper3) {
+                mMapper3->freeBuffer(
+                    static_cast<void*>(const_cast<native_handle_t*>(bufferHandle)));
+            }
         }
     }
 
@@ -91,7 +119,8 @@
     }
 
    private:
-    sp<mapper::V2_0::IMapper> mMapper;
+    sp<mapper::V2_0::IMapper> mMapper2;
+    sp<mapper::V3_0::IMapper> mMapper3;
 };
 
 class ComposerHandleCache {
diff --git a/graphics/composer/2.1/utils/hwc2on1adapter/HWC2On1Adapter.cpp b/graphics/composer/2.1/utils/hwc2on1adapter/HWC2On1Adapter.cpp
index 366d641..3d138f7 100644
--- a/graphics/composer/2.1/utils/hwc2on1adapter/HWC2On1Adapter.cpp
+++ b/graphics/composer/2.1/utils/hwc2on1adapter/HWC2On1Adapter.cpp
@@ -1921,8 +1921,8 @@
     mHwc1Id(0),
     mHasUnsupportedPlaneAlpha(false) {}
 
-bool HWC2On1Adapter::SortLayersByZ::operator()(
-        const std::shared_ptr<Layer>& lhs, const std::shared_ptr<Layer>& rhs) {
+bool HWC2On1Adapter::SortLayersByZ::operator()(const std::shared_ptr<Layer>& lhs,
+                                               const std::shared_ptr<Layer>& rhs) const {
     return lhs->getZ() < rhs->getZ();
 }
 
diff --git a/graphics/composer/2.1/utils/hwc2on1adapter/include/hwc2on1adapter/HWC2On1Adapter.h b/graphics/composer/2.1/utils/hwc2on1adapter/include/hwc2on1adapter/HWC2On1Adapter.h
index 3badfce..da771dc 100644
--- a/graphics/composer/2.1/utils/hwc2on1adapter/include/hwc2on1adapter/HWC2On1Adapter.h
+++ b/graphics/composer/2.1/utils/hwc2on1adapter/include/hwc2on1adapter/HWC2On1Adapter.h
@@ -130,8 +130,8 @@
 
     class SortLayersByZ {
         public:
-            bool operator()(const std::shared_ptr<Layer>& lhs,
-                    const std::shared_ptr<Layer>& rhs);
+         bool operator()(const std::shared_ptr<Layer>& lhs,
+                         const std::shared_ptr<Layer>& rhs) const;
     };
 
     // The semantics of the fences returned by the device differ between
diff --git a/graphics/composer/2.1/vts/OWNERS b/graphics/composer/2.1/vts/OWNERS
index ef69d7c..0b42d2e 100644
--- a/graphics/composer/2.1/vts/OWNERS
+++ b/graphics/composer/2.1/vts/OWNERS
@@ -1,6 +1,7 @@
 # Graphics team
-olv@google.com
+lpy@google.com
+vhau@google.com
 
 # VTS team
 yim@google.com
-zhuoyao@google.com
\ No newline at end of file
+zhuoyao@google.com
diff --git a/graphics/composer/2.2/default/Android.mk b/graphics/composer/2.2/default/Android.mk
index 2f80f0c..7dedf61 100644
--- a/graphics/composer/2.2/default/Android.mk
+++ b/graphics/composer/2.2/default/Android.mk
@@ -12,6 +12,7 @@
         android.hardware.graphics.composer@2.1 \
         android.hardware.graphics.composer@2.2 \
         android.hardware.graphics.mapper@2.0 \
+        android.hardware.graphics.mapper@3.0 \
         libbase \
         libbinder \
         libcutils \
diff --git a/graphics/composer/2.2/default/OWNERS b/graphics/composer/2.2/default/OWNERS
index 4714be2..db8fb80 100644
--- a/graphics/composer/2.2/default/OWNERS
+++ b/graphics/composer/2.2/default/OWNERS
@@ -1,5 +1,6 @@
 # Graphics team
 courtneygo@google.com
 jessehall@google.com
-olv@google.com
+lpy@google.com
 stoza@google.com
+vhau@google.com
diff --git a/graphics/composer/2.2/utils/OWNERS b/graphics/composer/2.2/utils/OWNERS
index 1beb074..a17a50c 100644
--- a/graphics/composer/2.2/utils/OWNERS
+++ b/graphics/composer/2.2/utils/OWNERS
@@ -1,7 +1,8 @@
 # Graphics team
 courtneygo@google.com
-olv@google.com
+lpy@google.com
 stoza@google.com
+vhau@google.com
 
 # VTS team
 yim@google.com
diff --git a/graphics/composer/2.2/vts/functional/OWNERS b/graphics/composer/2.2/vts/functional/OWNERS
index 1beb074..a17a50c 100644
--- a/graphics/composer/2.2/vts/functional/OWNERS
+++ b/graphics/composer/2.2/vts/functional/OWNERS
@@ -1,7 +1,8 @@
 # Graphics team
 courtneygo@google.com
-olv@google.com
+lpy@google.com
 stoza@google.com
+vhau@google.com
 
 # VTS team
 yim@google.com
diff --git a/graphics/composer/2.3/default/Android.bp b/graphics/composer/2.3/default/Android.bp
index ad49ec3..07afd6c 100644
--- a/graphics/composer/2.3/default/Android.bp
+++ b/graphics/composer/2.3/default/Android.bp
@@ -29,6 +29,7 @@
         "android.hardware.graphics.composer@2.2",
         "android.hardware.graphics.composer@2.3",
         "android.hardware.graphics.mapper@2.0",
+        "android.hardware.graphics.mapper@3.0",
         "libbase",
         "libbinder",
         "libcutils",
diff --git a/graphics/composer/2.3/default/OWNERS b/graphics/composer/2.3/default/OWNERS
index 3aa5fa1..820ebe6 100644
--- a/graphics/composer/2.3/default/OWNERS
+++ b/graphics/composer/2.3/default/OWNERS
@@ -1,4 +1,5 @@
 # Graphics team
 jessehall@google.com
-olv@google.com
+lpy@google.com
 stoza@google.com
+vhau@google.com
diff --git a/graphics/mapper/2.0/default/OWNERS b/graphics/mapper/2.0/default/OWNERS
index 3aa5fa1..273cb4c 100644
--- a/graphics/mapper/2.0/default/OWNERS
+++ b/graphics/mapper/2.0/default/OWNERS
@@ -1,4 +1,4 @@
 # Graphics team
 jessehall@google.com
-olv@google.com
+marissaw@google.com
 stoza@google.com
diff --git a/graphics/mapper/2.0/utils/OWNERS b/graphics/mapper/2.0/utils/OWNERS
index 3aa5fa1..273cb4c 100644
--- a/graphics/mapper/2.0/utils/OWNERS
+++ b/graphics/mapper/2.0/utils/OWNERS
@@ -1,4 +1,4 @@
 # Graphics team
 jessehall@google.com
-olv@google.com
+marissaw@google.com
 stoza@google.com
diff --git a/graphics/mapper/2.0/vts/OWNERS b/graphics/mapper/2.0/vts/OWNERS
index ef69d7c..8e86f64 100644
--- a/graphics/mapper/2.0/vts/OWNERS
+++ b/graphics/mapper/2.0/vts/OWNERS
@@ -1,6 +1,6 @@
 # Graphics team
-olv@google.com
+marissaw@google.com
 
 # VTS team
 yim@google.com
-zhuoyao@google.com
\ No newline at end of file
+zhuoyao@google.com
diff --git a/graphics/mapper/2.1/default/OWNERS b/graphics/mapper/2.1/default/OWNERS
index 3aa5fa1..273cb4c 100644
--- a/graphics/mapper/2.1/default/OWNERS
+++ b/graphics/mapper/2.1/default/OWNERS
@@ -1,4 +1,4 @@
 # Graphics team
 jessehall@google.com
-olv@google.com
+marissaw@google.com
 stoza@google.com
diff --git a/graphics/mapper/2.1/utils/OWNERS b/graphics/mapper/2.1/utils/OWNERS
index 3aa5fa1..273cb4c 100644
--- a/graphics/mapper/2.1/utils/OWNERS
+++ b/graphics/mapper/2.1/utils/OWNERS
@@ -1,4 +1,4 @@
 # Graphics team
 jessehall@google.com
-olv@google.com
+marissaw@google.com
 stoza@google.com
diff --git a/graphics/mapper/2.1/vts/OWNERS b/graphics/mapper/2.1/vts/OWNERS
index ef69d7c..8e86f64 100644
--- a/graphics/mapper/2.1/vts/OWNERS
+++ b/graphics/mapper/2.1/vts/OWNERS
@@ -1,6 +1,6 @@
 # Graphics team
-olv@google.com
+marissaw@google.com
 
 # VTS team
 yim@google.com
-zhuoyao@google.com
\ No newline at end of file
+zhuoyao@google.com
diff --git a/graphics/mapper/3.0/Android.bp b/graphics/mapper/3.0/Android.bp
new file mode 100644
index 0000000..b2f0aa6
--- /dev/null
+++ b/graphics/mapper/3.0/Android.bp
@@ -0,0 +1,26 @@
+// This file is autogenerated by hidl-gen -Landroidbp.
+
+hidl_interface {
+    name: "android.hardware.graphics.mapper@3.0",
+    root: "android.hardware",
+    vndk: {
+        enabled: true,
+        support_system_process: true,
+    },
+    srcs: [
+        "types.hal",
+        "IMapper.hal",
+    ],
+    interfaces: [
+        "android.hardware.graphics.common@1.0",
+        "android.hardware.graphics.common@1.1",
+        "android.hardware.graphics.common@1.2",
+        "android.hidl.base@1.0",
+    ],
+    types: [
+        "Error",
+        "YCbCrLayout",
+    ],
+    gen_java: false,
+}
+
diff --git a/graphics/mapper/3.0/IMapper.hal b/graphics/mapper/3.0/IMapper.hal
new file mode 100644
index 0000000..e399045
--- /dev/null
+++ b/graphics/mapper/3.0/IMapper.hal
@@ -0,0 +1,276 @@
+/*
+ * Copyright 2019 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.hardware.graphics.mapper@3.0;
+
+import android.hardware.graphics.common@1.1::BufferUsage;
+import android.hardware.graphics.common@1.1::PixelFormat;
+import android.hardware.graphics.common@1.2::Rect;
+
+interface IMapper {
+    struct BufferDescriptorInfo {
+        /**
+         * The width specifies how many columns of pixels must be in the
+         * allocated buffer, but does not necessarily represent the offset in
+         * columns between the same column in adjacent rows. The rows may be
+         * padded.
+         */
+        uint32_t width;
+
+       /**
+        * The height specifies how many rows of pixels must be in the
+        * allocated buffer.
+        */
+        uint32_t height;
+
+       /**
+        * The number of image layers that must be in the allocated buffer.
+        */
+        uint32_t layerCount;
+
+        /** Buffer pixel format. */
+        PixelFormat format;
+
+        /**
+         * Buffer usage mask; valid flags can be found in the definition of
+         * BufferUsage.
+         */
+        bitfield<BufferUsage> usage;
+    };
+
+    struct Rect {
+        int32_t left;
+        int32_t top;
+        int32_t width;
+        int32_t height;
+    };
+
+    /**
+     * Creates a buffer descriptor. The descriptor can be used with IAllocator
+     * to allocate buffers.
+     *
+     * Since the buffer descriptor fully describes a buffer, any device
+     * dependent or device independent checks must be performed here whenever
+     * possible. Specifically, when layered buffers are not supported, this
+     * function must return `UNSUPPORTED` if `description.layers` is great than
+     * 1.
+     *
+     * @param description Attributes of the descriptor.
+     * @return error Error status of the call, which may be
+     *     - `NONE` upon success.
+     *     - `BAD_VALUE` if any of the specified attributes are invalid or
+     *       inconsistent.
+     *     - `NO_RESOURCES` if the creation cannot be fullfilled due to
+     *       unavailability of resources.
+     *     - `UNSUPPORTED` when any of the specified attributes are not
+     *       supported.
+     * @return descriptor Newly created buffer descriptor.
+     */
+    createDescriptor(BufferDescriptorInfo description)
+            generates (Error error,
+                       BufferDescriptor descriptor);
+
+    /**
+     * Imports a raw buffer handle to create an imported buffer handle for use
+     * with the rest of the mapper or with other in-process libraries.
+     *
+     * A buffer handle is considered raw when it is cloned (e.g., with
+     * `native_handle_clone()`) from another buffer handle locally, or when it
+     * is received from another HAL server/client or another process. A raw
+     * buffer handle must not be used to access the underlying graphic
+     * buffer. It must be imported to create an imported handle first.
+     *
+     * This function must at least validate the raw handle before creating the
+     * imported handle. It must also support importing the same raw handle
+     * multiple times to create multiple imported handles. The imported handle
+     * must be considered valid everywhere in the process, including in
+     * another instance of the mapper.
+     *
+     * Because of passthrough HALs, a raw buffer handle received from a HAL
+     * may actually have been imported in the process. importBuffer() must treat
+     * such a handle as if it is raw and must not return `BAD_BUFFER`. The
+     * returned handle is independent from the input handle as usual, and
+     * freeBuffer() must be called on it when it is no longer needed.
+     *
+     * @param rawHandle Raw buffer handle to import.
+     * @return error Error status of the call, which may be
+     *     - `NONE` upon success.
+     *     - `BAD_BUFFER` if the raw handle is invalid.
+     *     - `NO_RESOURCES` if the raw handle cannot be imported due to
+     *       unavailability of resources.
+     * @return buffer Imported buffer handle that has the type
+     *     `buffer_handle_t` which is a handle type.
+     */
+    importBuffer(handle rawHandle) generates (Error error, pointer buffer);
+
+    /**
+     * Frees a buffer handle. Buffer handles returned by importBuffer() must be
+     * freed with this function when no longer needed.
+     *
+     * This function must free up all resources allocated by importBuffer() for
+     * the imported handle. For example, if the imported handle was created
+     * with `native_handle_create()`, this function must call
+     * `native_handle_close()` and `native_handle_delete()`.
+     *
+     * @param buffer Imported buffer handle.
+     * @return error Error status of the call, which may be
+     *     - `NONE` upon success.
+     *     - `BAD_BUFFER` if the buffer is invalid.
+     */
+    freeBuffer(pointer buffer) generates (Error error);
+
+    /**
+     * Validates that the buffer can be safely accessed by a caller who assumes
+     * the specified @p description and @p stride. This must at least validate
+     * that the buffer size is large enough. Validating the buffer against
+     * individual buffer attributes is optional.
+     *
+     * @param buffer Buffer to validate against.
+     * @param description Attributes of the buffer.
+     * @param stride Stride returned by IAllocator::allocate().
+     * @return error Error status of the call, which may be
+     *     - `NONE` upon success.
+     *     - `BAD_BUFFER` if the buffer is invalid.
+     *     - `BAD_VALUE` if the buffer cannot be safely accessed.
+     */
+    validateBufferSize(pointer buffer,
+                       BufferDescriptorInfo description,
+                       uint32_t stride)
+            generates (Error error);
+
+    /**
+     * Calculates the transport size of a buffer. An imported buffer handle is a
+     * raw buffer handle with the process-local runtime data appended. This
+     * function, for example, allows a caller to omit the process-local runtime
+     * data at the tail when serializing the imported buffer handle.
+     *
+     * Note that a client might or might not omit the process-local runtime data
+     * when sending an imported buffer handle. The mapper must support both
+     * cases on the receiving end.
+     *
+     * @param buffer Buffer to get the transport size from.
+     * @return error Error status of the call, which may be
+     *     - `NONE` upon success.
+     *     - `BAD_BUFFER` if the buffer is invalid.
+     * @return numFds The number of file descriptors needed for transport.
+     * @return numInts The number of integers needed for transport.
+     */
+    getTransportSize(pointer buffer)
+            generates (Error error,
+                       uint32_t numFds,
+                       uint32_t numInts);
+
+    /**
+     * Locks the given buffer for the specified CPU usage.
+     *
+     * Locking the same buffer simultaneously from multiple threads is
+     * permitted, but if any of the threads attempt to lock the buffer for
+     * writing, the behavior is undefined, except that it must not cause
+     * process termination or block the client indefinitely. Leaving the
+     * buffer content in an indeterminate state or returning an error are both
+     * acceptable.
+     *
+     * The client must not modify the content of the buffer outside of
+     * @p accessRegion, and the device need not guarantee that content outside
+     * of @p accessRegion is valid for reading. The result of reading or writing
+     * outside of @p accessRegion is undefined, except that it must not cause
+     * process termination.
+     *
+     * On success, @p data must be filled with a pointer to the locked buffer
+     * memory. This address will represent the top-left corner of the entire
+     * buffer, even if @p accessRegion does not begin at the top-left corner.
+     *
+     * @param buffer Buffer to lock.
+     * @param cpuUsage CPU usage flags to request. See +ndk
+     *     libnativewindow#AHardwareBuffer_UsageFlags for possible values.
+     * @param accessRegion Portion of the buffer that the client intends to
+     *     access.
+     * @param acquireFence Handle containing a file descriptor referring to a
+     *     sync fence object, which will be signaled when it is safe for the
+     *     mapper to lock the buffer. @p acquireFence may be an empty fence if
+     *     it is already safe to lock.
+     * @return error Error status of the call, which may be
+     *     - `NONE` upon success.
+     *     - `BAD_BUFFER` if the buffer is invalid or is incompatible with this
+     *       function.
+     *     - `BAD_VALUE` if @p cpuUsage is 0, contains non-CPU usage flags, or
+     *       is incompatible with the buffer.
+     *     - `NO_RESOURCES` if the buffer cannot be locked at this time. Note
+     *       that locking may succeed at a later time.
+     * @return data CPU-accessible pointer to the buffer data.
+     */
+    lock(pointer buffer,
+         uint64_t cpuUsage,
+         Rect accessRegion,
+         handle acquireFence)
+            generates (Error error,
+                       pointer data);
+
+    /**
+     * Locks a YCbCr buffer for the specified CPU usage.
+     *
+     * This is largely the same as lock(), except that instead of returning a
+     * pointer directly to the buffer data, it returns a `YCbCrLayout` struct
+     * describing how to access the data planes.
+     *
+     * This function must work on buffers with
+     * `AHARDWAREBUFFER_FORMAT_Y8Cb8Cr8_*` if supported by the device, as well
+     * as with any other formats requested by multimedia codecs when they are
+     * configured with a flexible-YUV-compatible color format.
+     *
+     * @param buffer Buffer to lock.
+     * @param cpuUsage CPU usage flags to request. See +ndk
+     *     libnativewindow#AHardwareBuffer_UsageFlags for possible values.
+     * @param accessRegion Portion of the buffer that the client intends to
+     *     access.
+     * @param acquireFence Handle containing a file descriptor referring to a
+     *     sync fence object, which will be signaled when it is safe for the
+     *     mapper to lock the buffer. @p acquireFence may be empty if it is
+     *     already safe to lock.
+     * @return error Error status of the call, which may be
+     *     - `NONE` upon success.
+     *     - `BAD_BUFFER` if the buffer is invalid or is incompatible with this
+     *       function.
+     *     - `BAD_VALUE` if @p cpuUsage is 0, contains non-CPU usage flags, or
+     *       is incompatible with the buffer.
+     *     - `NO_RESOURCES` if the buffer cannot be locked at this time. Note
+     *       that locking may succeed at a later time.
+     * @return layout Data layout of the locked buffer.
+     */
+    lockYCbCr(pointer buffer,
+              uint64_t cpuUsage,
+              Rect accessRegion,
+              handle acquireFence)
+            generates (Error error,
+                       YCbCrLayout layout);
+
+    /**
+     * Unlocks a buffer to indicate all CPU accesses to the buffer have
+     * completed.
+     *
+     * @param buffer Buffer to unlock.
+     * @return error Error status of the call, which may be
+     *     - `NONE` upon success.
+     *     - `BAD_BUFFER` if the buffer is invalid or not locked.
+     * @return releaseFence Handle containing a file descriptor referring to a
+     *     sync fence object. The sync fence object will be signaled when the
+     *     mapper has completed any pending work. @p releaseFence may be an
+     *     empty fence.
+     */
+    unlock(pointer buffer) generates (Error error, handle releaseFence);
+
+};
+
diff --git a/graphics/mapper/3.0/types.hal b/graphics/mapper/3.0/types.hal
new file mode 100644
index 0000000..f94abd3
--- /dev/null
+++ b/graphics/mapper/3.0/types.hal
@@ -0,0 +1,84 @@
+/*
+ * Copyright 2019 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.hardware.graphics.mapper@3.0;
+
+/**
+ * Error values that may be returned by a method of IAllocator or IMapper.
+ */
+enum Error : int32_t {
+    /**
+     * No error.
+     */
+    NONE            = 0,
+    /**
+     * Invalid BufferDescriptor.
+     */
+    BAD_DESCRIPTOR  = 1,
+    /**
+     * Invalid buffer handle.
+     */
+    BAD_BUFFER      = 2,
+    /**
+     * Invalid HardwareBufferDescription.
+     */
+    BAD_VALUE       = 3,
+    /**
+     * Resource unavailable.
+     */
+    NO_RESOURCES    = 5,
+    /**
+     * Permanent failure.
+     */
+    UNSUPPORTED     = 7,
+};
+
+/**
+ * A buffer descriptor is an implementation-defined opaque data returned by
+ * createDescriptor(). It describes the properties of a buffer and is consumed
+ * by the allocator.
+ */
+typedef vec<uint32_t> BufferDescriptor;
+
+/**
+ * Structure for describing YCbCr formats for consumption by applications.
+ * This is used with PixelFormat::YCBCR_*_888.
+ *
+ * Buffer chroma subsampling is defined in the format.
+ * e.g. PixelFormat::YCBCR_420_888 has subsampling 4:2:0.
+ *
+ * Buffers must have a 8 bit depth.
+ *
+ * y, cb, and cr point to the first byte of their respective planes.
+ *
+ * Stride describes the distance in bytes from the first value of one row of
+ * the image to the first value of the next row. It includes the width of the
+ * image plus padding.
+ * yStride is the stride of the luma plane.
+ * cStride is the stride of the chroma planes.
+ *
+ * chromaStep is the distance in bytes from one chroma pixel value to the
+ * next. This is 2 bytes for semiplanar (because chroma values are interleaved
+ * and each chroma value is one byte) and 1 for planar.
+ */
+struct YCbCrLayout {
+    pointer y;
+    pointer cb;
+    pointer cr;
+    uint32_t yStride;
+    uint32_t cStride;
+    uint32_t chromaStep;
+};
diff --git a/graphics/mapper/3.0/utils/OWNERS b/graphics/mapper/3.0/utils/OWNERS
new file mode 100644
index 0000000..96f6d51
--- /dev/null
+++ b/graphics/mapper/3.0/utils/OWNERS
@@ -0,0 +1,3 @@
+# Graphics team
+marissaw@google.com
+stoza@google.com
diff --git a/graphics/mapper/3.0/utils/vts/Android.bp b/graphics/mapper/3.0/utils/vts/Android.bp
new file mode 100644
index 0000000..c3d480a
--- /dev/null
+++ b/graphics/mapper/3.0/utils/vts/Android.bp
@@ -0,0 +1,34 @@
+//
+// Copyright (C) 2019 The Android Open Source Project
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+//      http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//
+
+cc_library_static {
+    name: "android.hardware.graphics.mapper@3.0-vts",
+    defaults: ["VtsHalTargetTestDefaults"],
+    srcs: ["MapperVts.cpp"],
+    cflags: [
+        "-O0",
+        "-g",
+    ],
+    static_libs: [
+        "android.hardware.graphics.allocator@3.0",
+        "android.hardware.graphics.mapper@3.0",
+    ],
+    export_static_lib_headers: [
+        "android.hardware.graphics.allocator@3.0",
+        "android.hardware.graphics.mapper@3.0",
+    ],
+    export_include_dirs: ["include"],
+}
diff --git a/graphics/mapper/3.0/utils/vts/MapperVts.cpp b/graphics/mapper/3.0/utils/vts/MapperVts.cpp
new file mode 100644
index 0000000..8428403
--- /dev/null
+++ b/graphics/mapper/3.0/utils/vts/MapperVts.cpp
@@ -0,0 +1,272 @@
+/*
+ * Copyright 2018 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include <mapper-vts/3.0/MapperVts.h>
+
+#include <VtsHalHidlTargetTestBase.h>
+
+namespace android {
+namespace hardware {
+namespace graphics {
+namespace mapper {
+namespace V3_0 {
+namespace vts {
+
+Gralloc::Gralloc(const std::string& allocatorServiceName, const std::string& mapperServiceName) {
+    init(allocatorServiceName, mapperServiceName);
+}
+
+void Gralloc::init(const std::string& allocatorServiceName, const std::string& mapperServiceName) {
+    mAllocator = ::testing::VtsHalHidlTargetTestBase::getService<IAllocator>(allocatorServiceName);
+    ASSERT_NE(nullptr, mAllocator.get()) << "failed to get allocator service";
+
+    mMapper = ::testing::VtsHalHidlTargetTestBase::getService<IMapper>(mapperServiceName);
+    ASSERT_NE(nullptr, mMapper.get()) << "failed to get mapper service";
+    ASSERT_FALSE(mMapper->isRemote()) << "mapper is not in passthrough mode";
+}
+
+Gralloc::~Gralloc() {
+    for (auto bufferHandle : mClonedBuffers) {
+        auto buffer = const_cast<native_handle_t*>(bufferHandle);
+        native_handle_close(buffer);
+        native_handle_delete(buffer);
+    }
+    mClonedBuffers.clear();
+
+    for (auto bufferHandle : mImportedBuffers) {
+        auto buffer = const_cast<native_handle_t*>(bufferHandle);
+        EXPECT_EQ(Error::NONE, mMapper->freeBuffer(buffer)) << "failed to free buffer " << buffer;
+    }
+    mImportedBuffers.clear();
+}
+
+sp<IAllocator> Gralloc::getAllocator() const {
+    return mAllocator;
+}
+
+std::string Gralloc::dumpDebugInfo() {
+    std::string debugInfo;
+    mAllocator->dumpDebugInfo([&](const auto& tmpDebugInfo) { debugInfo = tmpDebugInfo.c_str(); });
+
+    return debugInfo;
+}
+
+const native_handle_t* Gralloc::cloneBuffer(const hidl_handle& rawHandle) {
+    const native_handle_t* bufferHandle = native_handle_clone(rawHandle.getNativeHandle());
+    EXPECT_NE(nullptr, bufferHandle);
+
+    if (bufferHandle) {
+        mClonedBuffers.insert(bufferHandle);
+    }
+
+    return bufferHandle;
+}
+
+std::vector<const native_handle_t*> Gralloc::allocate(const BufferDescriptor& descriptor,
+                                                      uint32_t count, bool import,
+                                                      uint32_t* outStride) {
+    std::vector<const native_handle_t*> bufferHandles;
+    bufferHandles.reserve(count);
+    mAllocator->allocate(
+        descriptor, count,
+        [&](const auto& tmpError, const auto& tmpStride, const auto& tmpBuffers) {
+            ASSERT_EQ(Error::NONE, tmpError) << "failed to allocate buffers";
+            ASSERT_EQ(count, tmpBuffers.size()) << "invalid buffer array";
+
+            for (uint32_t i = 0; i < count; i++) {
+                if (import) {
+                    ASSERT_NO_FATAL_FAILURE(bufferHandles.push_back(importBuffer(tmpBuffers[i])));
+                } else {
+                    ASSERT_NO_FATAL_FAILURE(bufferHandles.push_back(cloneBuffer(tmpBuffers[i])));
+                }
+            }
+
+            if (outStride) {
+                *outStride = tmpStride;
+            }
+        });
+
+    if (::testing::Test::HasFatalFailure()) {
+        bufferHandles.clear();
+    }
+
+    return bufferHandles;
+}
+
+const native_handle_t* Gralloc::allocate(const IMapper::BufferDescriptorInfo& descriptorInfo,
+                                         bool import, uint32_t* outStride) {
+    BufferDescriptor descriptor = createDescriptor(descriptorInfo);
+    if (::testing::Test::HasFatalFailure()) {
+        return nullptr;
+    }
+
+    auto buffers = allocate(descriptor, 1, import, outStride);
+    if (::testing::Test::HasFatalFailure()) {
+        return nullptr;
+    }
+
+    return buffers[0];
+}
+
+sp<IMapper> Gralloc::getMapper() const {
+    return mMapper;
+}
+
+BufferDescriptor Gralloc::createDescriptor(const IMapper::BufferDescriptorInfo& descriptorInfo) {
+    BufferDescriptor descriptor;
+    mMapper->createDescriptor(descriptorInfo, [&](const auto& tmpError, const auto& tmpDescriptor) {
+        ASSERT_EQ(Error::NONE, tmpError) << "failed to create descriptor";
+        descriptor = tmpDescriptor;
+    });
+
+    return descriptor;
+}
+
+const native_handle_t* Gralloc::importBuffer(const hidl_handle& rawHandle) {
+    const native_handle_t* bufferHandle = nullptr;
+    mMapper->importBuffer(rawHandle, [&](const auto& tmpError, const auto& tmpBuffer) {
+        ASSERT_EQ(Error::NONE, tmpError)
+            << "failed to import buffer %p" << rawHandle.getNativeHandle();
+        bufferHandle = static_cast<const native_handle_t*>(tmpBuffer);
+    });
+
+    if (bufferHandle) {
+        mImportedBuffers.insert(bufferHandle);
+    }
+
+    return bufferHandle;
+}
+
+void Gralloc::freeBuffer(const native_handle_t* bufferHandle) {
+    auto buffer = const_cast<native_handle_t*>(bufferHandle);
+
+    if (mImportedBuffers.erase(bufferHandle)) {
+        Error error = mMapper->freeBuffer(buffer);
+        ASSERT_EQ(Error::NONE, error) << "failed to free buffer " << buffer;
+    } else {
+        mClonedBuffers.erase(bufferHandle);
+        native_handle_close(buffer);
+        native_handle_delete(buffer);
+    }
+}
+
+void* Gralloc::lock(const native_handle_t* bufferHandle, uint64_t cpuUsage,
+                    const IMapper::Rect& accessRegion, int acquireFence) {
+    auto buffer = const_cast<native_handle_t*>(bufferHandle);
+
+    NATIVE_HANDLE_DECLARE_STORAGE(acquireFenceStorage, 1, 0);
+    hidl_handle acquireFenceHandle;
+    if (acquireFence >= 0) {
+        auto h = native_handle_init(acquireFenceStorage, 1, 0);
+        h->data[0] = acquireFence;
+        acquireFenceHandle = h;
+    }
+
+    void* data = nullptr;
+    mMapper->lock(buffer, cpuUsage, accessRegion, acquireFenceHandle,
+                  [&](const auto& tmpError, const auto& tmpData) {
+                      ASSERT_EQ(Error::NONE, tmpError) << "failed to lock buffer " << buffer;
+                      data = tmpData;
+                  });
+
+    if (acquireFence >= 0) {
+        close(acquireFence);
+    }
+
+    return data;
+}
+
+YCbCrLayout Gralloc::lockYCbCr(const native_handle_t* bufferHandle, uint64_t cpuUsage,
+                               const IMapper::Rect& accessRegion, int acquireFence) {
+    auto buffer = const_cast<native_handle_t*>(bufferHandle);
+
+    NATIVE_HANDLE_DECLARE_STORAGE(acquireFenceStorage, 1, 0);
+    hidl_handle acquireFenceHandle;
+    if (acquireFence >= 0) {
+        auto h = native_handle_init(acquireFenceStorage, 1, 0);
+        h->data[0] = acquireFence;
+        acquireFenceHandle = h;
+    }
+
+    YCbCrLayout layout = {};
+    mMapper->lockYCbCr(buffer, cpuUsage, accessRegion, acquireFenceHandle,
+                       [&](const auto& tmpError, const auto& tmpLayout) {
+                           ASSERT_EQ(Error::NONE, tmpError)
+                               << "failed to lockYCbCr buffer " << buffer;
+                           layout = tmpLayout;
+                       });
+
+    if (acquireFence >= 0) {
+        close(acquireFence);
+    }
+
+    return layout;
+}
+
+int Gralloc::unlock(const native_handle_t* bufferHandle) {
+    auto buffer = const_cast<native_handle_t*>(bufferHandle);
+
+    int releaseFence = -1;
+    mMapper->unlock(buffer, [&](const auto& tmpError, const auto& tmpReleaseFence) {
+        ASSERT_EQ(Error::NONE, tmpError) << "failed to unlock buffer " << buffer;
+
+        auto fenceHandle = tmpReleaseFence.getNativeHandle();
+        if (fenceHandle) {
+            ASSERT_EQ(0, fenceHandle->numInts) << "invalid fence handle " << fenceHandle;
+            if (fenceHandle->numFds == 1) {
+                releaseFence = dup(fenceHandle->data[0]);
+                ASSERT_LT(0, releaseFence) << "failed to dup fence fd";
+            } else {
+                ASSERT_EQ(0, fenceHandle->numFds) << " invalid fence handle " << fenceHandle;
+            }
+        }
+    });
+
+    return releaseFence;
+}
+
+bool Gralloc::validateBufferSize(const native_handle_t* bufferHandle,
+                                 const IMapper::BufferDescriptorInfo& descriptorInfo,
+                                 uint32_t stride) {
+    auto buffer = const_cast<native_handle_t*>(bufferHandle);
+
+    Error error = mMapper->validateBufferSize(buffer, descriptorInfo, stride);
+    return error == Error::NONE;
+}
+
+void Gralloc::getTransportSize(const native_handle_t* bufferHandle, uint32_t* outNumFds,
+                               uint32_t* outNumInts) {
+    auto buffer = const_cast<native_handle_t*>(bufferHandle);
+
+    *outNumFds = 0;
+    *outNumInts = 0;
+    mMapper->getTransportSize(
+        buffer, [&](const auto& tmpError, const auto& tmpNumFds, const auto& tmpNumInts) {
+            ASSERT_EQ(Error::NONE, tmpError) << "failed to get transport size";
+            ASSERT_GE(bufferHandle->numFds, int(tmpNumFds)) << "invalid numFds " << tmpNumFds;
+            ASSERT_GE(bufferHandle->numInts, int(tmpNumInts)) << "invalid numInts " << tmpNumInts;
+
+            *outNumFds = tmpNumFds;
+            *outNumInts = tmpNumInts;
+        });
+}
+
+}  // namespace vts
+}  // namespace V3_0
+}  // namespace mapper
+}  // namespace graphics
+}  // namespace hardware
+}  // namespace android
diff --git a/graphics/mapper/3.0/utils/vts/include/mapper-vts/3.0/MapperVts.h b/graphics/mapper/3.0/utils/vts/include/mapper-vts/3.0/MapperVts.h
new file mode 100644
index 0000000..c94961c
--- /dev/null
+++ b/graphics/mapper/3.0/utils/vts/include/mapper-vts/3.0/MapperVts.h
@@ -0,0 +1,99 @@
+/*
+ * Copyright 2019 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#pragma once
+
+#include <string>
+#include <unordered_set>
+#include <vector>
+
+#include <android/hardware/graphics/allocator/3.0/IAllocator.h>
+#include <android/hardware/graphics/mapper/3.0/IMapper.h>
+#include <utils/StrongPointer.h>
+
+namespace android {
+namespace hardware {
+namespace graphics {
+namespace mapper {
+namespace V3_0 {
+namespace vts {
+
+using android::hardware::graphics::allocator::V3_0::IAllocator;
+
+// A wrapper to IAllocator and IMapper.
+class Gralloc {
+   public:
+    Gralloc(const std::string& allocatorServiceName = "default",
+            const std::string& mapperServiceName = "default");
+    ~Gralloc();
+
+    // IAllocator methods
+
+    sp<IAllocator> getAllocator() const;
+
+    std::string dumpDebugInfo();
+
+    // When import is false, this simply calls IAllocator::allocate. When import
+    // is true, the returned buffers are also imported into the mapper.
+    //
+    // Either case, the returned buffers must be freed with freeBuffer.
+    std::vector<const native_handle_t*> allocate(const BufferDescriptor& descriptor, uint32_t count,
+                                                 bool import = true, uint32_t* outStride = nullptr);
+    const native_handle_t* allocate(const IMapper::BufferDescriptorInfo& descriptorInfo,
+                                    bool import = true, uint32_t* outStride = nullptr);
+
+    // IMapper methods
+
+    sp<IMapper> getMapper() const;
+
+    BufferDescriptor createDescriptor(const IMapper::BufferDescriptorInfo& descriptorInfo);
+
+    const native_handle_t* importBuffer(const hidl_handle& rawHandle);
+    void freeBuffer(const native_handle_t* bufferHandle);
+
+    // We use fd instead of hidl_handle in these functions to pass fences
+    // in and out of the mapper.  The ownership of the fd is always transferred
+    // with each of these functions.
+    void* lock(const native_handle_t* bufferHandle, uint64_t cpuUsage,
+               const IMapper::Rect& accessRegion, int acquireFence);
+    YCbCrLayout lockYCbCr(const native_handle_t* bufferHandle, uint64_t cpuUsage,
+                          const IMapper::Rect& accessRegion, int acquireFence);
+    int unlock(const native_handle_t* bufferHandle);
+
+    bool validateBufferSize(const native_handle_t* bufferHandle,
+                            const IMapper::BufferDescriptorInfo& descriptorInfo, uint32_t stride);
+    void getTransportSize(const native_handle_t* bufferHandle, uint32_t* outNumFds,
+                          uint32_t* outNumInts);
+
+   private:
+    void init(const std::string& allocatorServiceName, const std::string& mapperServiceName);
+    const native_handle_t* cloneBuffer(const hidl_handle& rawHandle);
+
+    sp<IAllocator> mAllocator;
+    sp<IMapper> mMapper;
+
+    // Keep track of all cloned and imported handles.  When a test fails with
+    // ASSERT_*, the destructor will free the handles for the test.
+    std::unordered_set<const native_handle_t*> mClonedBuffers;
+    std::unordered_set<const native_handle_t*> mImportedBuffers;
+};
+
+}  // namespace vts
+}  // namespace V3_0
+}  // namespace mapper
+}  // namespace graphics
+}  // namespace hardware
+}  // namespace android
diff --git a/graphics/mapper/3.0/vts/OWNERS b/graphics/mapper/3.0/vts/OWNERS
new file mode 100644
index 0000000..96f6d51
--- /dev/null
+++ b/graphics/mapper/3.0/vts/OWNERS
@@ -0,0 +1,3 @@
+# Graphics team
+marissaw@google.com
+stoza@google.com
diff --git a/graphics/mapper/3.0/vts/functional/Android.bp b/graphics/mapper/3.0/vts/functional/Android.bp
new file mode 100644
index 0000000..77075a5
--- /dev/null
+++ b/graphics/mapper/3.0/vts/functional/Android.bp
@@ -0,0 +1,30 @@
+//
+// Copyright 2018 The Android Open Source Project
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+//      http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//
+
+cc_test {
+    name: "VtsHalGraphicsMapperV3_0TargetTest",
+    defaults: ["VtsHalTargetTestDefaults"],
+    srcs: ["VtsHalGraphicsMapperV3_0TargetTest.cpp"],
+    static_libs: [
+        "android.hardware.graphics.allocator@3.0",
+        "android.hardware.graphics.common@1.0",
+        "android.hardware.graphics.common@1.1",
+        "android.hardware.graphics.common@1.2",
+        "android.hardware.graphics.mapper@3.0",
+        "android.hardware.graphics.mapper@3.0-vts",
+    ],
+    test_suites: ["general-tests"],
+}
diff --git a/graphics/mapper/3.0/vts/functional/VtsHalGraphicsMapperV3_0TargetTest.cpp b/graphics/mapper/3.0/vts/functional/VtsHalGraphicsMapperV3_0TargetTest.cpp
new file mode 100644
index 0000000..430a526
--- /dev/null
+++ b/graphics/mapper/3.0/vts/functional/VtsHalGraphicsMapperV3_0TargetTest.cpp
@@ -0,0 +1,445 @@
+/*
+ * Copyright 2018 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#define LOG_TAG "VtsHalGraphicsMapperV3_0TargetTest"
+
+#include <chrono>
+#include <thread>
+#include <vector>
+
+#include <VtsHalHidlTargetTestBase.h>
+#include <android-base/logging.h>
+#include <mapper-vts/3.0/MapperVts.h>
+
+namespace android {
+namespace hardware {
+namespace graphics {
+namespace mapper {
+namespace V3_0 {
+namespace vts {
+namespace {
+
+using android::hardware::graphics::common::V1_0::BufferUsage;
+using android::hardware::graphics::common::V1_1::PixelFormat;
+
+// Test environment for graphics.mapper.
+class GraphicsMapperHidlEnvironment : public ::testing::VtsHalHidlTargetTestEnvBase {
+   public:
+    // get the test environment singleton
+    static GraphicsMapperHidlEnvironment* Instance() {
+        static GraphicsMapperHidlEnvironment* instance = new GraphicsMapperHidlEnvironment;
+        return instance;
+    }
+
+    virtual void registerTestServices() override {
+        registerTestService<IAllocator>();
+        registerTestService<IMapper>();
+    }
+};
+
+class GraphicsMapperHidlTest : public ::testing::VtsHalHidlTargetTestBase {
+   protected:
+    void SetUp() override {
+        ASSERT_NO_FATAL_FAILURE(
+            mGralloc = std::make_unique<Gralloc>(
+                GraphicsMapperHidlEnvironment::Instance()->getServiceName<IAllocator>(),
+                GraphicsMapperHidlEnvironment::Instance()->getServiceName<IMapper>()));
+
+        mDummyDescriptorInfo.width = 64;
+        mDummyDescriptorInfo.height = 64;
+        mDummyDescriptorInfo.layerCount = 1;
+        mDummyDescriptorInfo.format = PixelFormat::RGBA_8888;
+        mDummyDescriptorInfo.usage =
+            static_cast<uint64_t>(BufferUsage::CPU_WRITE_OFTEN | BufferUsage::CPU_READ_OFTEN);
+    }
+
+    void TearDown() override {}
+
+    std::unique_ptr<Gralloc> mGralloc;
+    IMapper::BufferDescriptorInfo mDummyDescriptorInfo{};
+};
+
+/**
+ * Test IAllocator::dumpDebugInfo by calling it.
+ */
+TEST_F(GraphicsMapperHidlTest, AllocatorDumpDebugInfo) {
+    mGralloc->dumpDebugInfo();
+}
+
+/**
+ * Test IAllocator::allocate with valid buffer descriptors.
+ */
+TEST_F(GraphicsMapperHidlTest, AllocatorAllocate) {
+    BufferDescriptor descriptor;
+    ASSERT_NO_FATAL_FAILURE(descriptor = mGralloc->createDescriptor(mDummyDescriptorInfo));
+
+    for (uint32_t count = 0; count < 5; count++) {
+        std::vector<const native_handle_t*> bufferHandles;
+        uint32_t stride;
+        ASSERT_NO_FATAL_FAILURE(bufferHandles =
+                                    mGralloc->allocate(descriptor, count, false, &stride));
+
+        if (count >= 1) {
+            EXPECT_LE(mDummyDescriptorInfo.width, stride) << "invalid buffer stride";
+        }
+
+        for (auto bufferHandle : bufferHandles) {
+            mGralloc->freeBuffer(bufferHandle);
+        }
+    }
+}
+
+/**
+ * Test IAllocator::allocate with invalid buffer descriptors.
+ */
+TEST_F(GraphicsMapperHidlTest, AllocatorAllocateNegative) {
+    // this assumes any valid descriptor is non-empty
+    BufferDescriptor descriptor;
+    mGralloc->getAllocator()->allocate(descriptor, 1,
+                                       [&](const auto& tmpError, const auto&, const auto&) {
+                                           EXPECT_EQ(Error::BAD_DESCRIPTOR, tmpError);
+                                       });
+}
+
+/**
+ * Test IAllocator::allocate does not leak.
+ */
+TEST_F(GraphicsMapperHidlTest, AllocatorAllocateNoLeak) {
+    auto info = mDummyDescriptorInfo;
+    info.width = 1024;
+    info.height = 1024;
+
+    for (int i = 0; i < 2048; i++) {
+        auto bufferHandle = mGralloc->allocate(info, false);
+        mGralloc->freeBuffer(bufferHandle);
+    }
+}
+
+/**
+ * Test that IAllocator::allocate is thread-safe.
+ */
+TEST_F(GraphicsMapperHidlTest, AllocatorAllocateThreaded) {
+    BufferDescriptor descriptor;
+    ASSERT_NO_FATAL_FAILURE(descriptor = mGralloc->createDescriptor(mDummyDescriptorInfo));
+
+    std::atomic<bool> timeUp(false);
+    std::atomic<uint64_t> allocationCount(0);
+    auto threadLoop = [&]() {
+        while (!timeUp) {
+            mGralloc->getAllocator()->allocate(
+                descriptor, 1, [&](const auto&, const auto&, const auto&) { allocationCount++; });
+        }
+    };
+
+    std::vector<std::thread> threads;
+    for (int i = 0; i < 8; i++) {
+        threads.push_back(std::thread(threadLoop));
+    }
+
+    std::this_thread::sleep_for(std::chrono::seconds(3));
+    timeUp = true;
+    LOG(VERBOSE) << "Made " << allocationCount << " threaded allocations";
+
+    for (auto& thread : threads) {
+        thread.join();
+    }
+}
+
+/**
+ * Test IMapper::createDescriptor with valid descriptor info.
+ */
+TEST_F(GraphicsMapperHidlTest, CreateDescriptorBasic) {
+    ASSERT_NO_FATAL_FAILURE(mGralloc->createDescriptor(mDummyDescriptorInfo));
+}
+
+/**
+ * Test IMapper::createDescriptor with invalid descriptor info.
+ */
+TEST_F(GraphicsMapperHidlTest, CreateDescriptorNegative) {
+    auto info = mDummyDescriptorInfo;
+    info.width = 0;
+    mGralloc->getMapper()->createDescriptor(info, [&](const auto& tmpError, const auto&) {
+        EXPECT_EQ(Error::BAD_VALUE, tmpError) << "createDescriptor did not fail with BAD_VALUE";
+    });
+}
+
+/**
+ * Test IMapper::importBuffer and IMapper::freeBuffer with allocated buffers.
+ */
+TEST_F(GraphicsMapperHidlTest, ImportFreeBufferBasic) {
+    const native_handle_t* bufferHandle;
+    ASSERT_NO_FATAL_FAILURE(bufferHandle = mGralloc->allocate(mDummyDescriptorInfo, true));
+    ASSERT_NO_FATAL_FAILURE(mGralloc->freeBuffer(bufferHandle));
+}
+
+/**
+ * Test IMapper::importBuffer and IMapper::freeBuffer with cloned buffers.
+ */
+TEST_F(GraphicsMapperHidlTest, ImportFreeBufferClone) {
+    const native_handle_t* clonedBufferHandle;
+    ASSERT_NO_FATAL_FAILURE(clonedBufferHandle = mGralloc->allocate(mDummyDescriptorInfo, false));
+
+    // A cloned handle is a raw handle. Check that we can import it multiple
+    // times.
+    const native_handle_t* importedBufferHandles[2];
+    ASSERT_NO_FATAL_FAILURE(importedBufferHandles[0] = mGralloc->importBuffer(clonedBufferHandle));
+    ASSERT_NO_FATAL_FAILURE(importedBufferHandles[1] = mGralloc->importBuffer(clonedBufferHandle));
+    ASSERT_NO_FATAL_FAILURE(mGralloc->freeBuffer(importedBufferHandles[0]));
+    ASSERT_NO_FATAL_FAILURE(mGralloc->freeBuffer(importedBufferHandles[1]));
+
+    ASSERT_NO_FATAL_FAILURE(mGralloc->freeBuffer(clonedBufferHandle));
+}
+
+/**
+ * Test IMapper::importBuffer and IMapper::freeBuffer cross mapper instances.
+ */
+TEST_F(GraphicsMapperHidlTest, ImportFreeBufferSingleton) {
+    const native_handle_t* rawHandle;
+    ASSERT_NO_FATAL_FAILURE(rawHandle = mGralloc->allocate(mDummyDescriptorInfo, false));
+
+    native_handle_t* importedHandle = nullptr;
+    mGralloc->getMapper()->importBuffer(rawHandle, [&](const auto& tmpError, const auto& buffer) {
+        ASSERT_EQ(Error::NONE, tmpError);
+        importedHandle = static_cast<native_handle_t*>(buffer);
+    });
+
+    // free the imported handle with another mapper
+    std::unique_ptr<Gralloc> anotherGralloc;
+    ASSERT_NO_FATAL_FAILURE(
+        anotherGralloc = std::make_unique<Gralloc>(
+            GraphicsMapperHidlEnvironment::Instance()->getServiceName<IAllocator>(),
+            GraphicsMapperHidlEnvironment::Instance()->getServiceName<IMapper>()));
+    Error error = mGralloc->getMapper()->freeBuffer(importedHandle);
+    ASSERT_EQ(Error::NONE, error);
+
+    ASSERT_NO_FATAL_FAILURE(mGralloc->freeBuffer(rawHandle));
+}
+
+/**
+ * Test IMapper::importBuffer and IMapper::freeBuffer do not leak.
+ */
+TEST_F(GraphicsMapperHidlTest, ImportFreeBufferNoLeak) {
+    auto info = mDummyDescriptorInfo;
+    info.width = 1024;
+    info.height = 1024;
+
+    for (int i = 0; i < 2048; i++) {
+        auto bufferHandle = mGralloc->allocate(info, true);
+        mGralloc->freeBuffer(bufferHandle);
+    }
+}
+
+/**
+ * Test IMapper::importBuffer with invalid buffers.
+ */
+TEST_F(GraphicsMapperHidlTest, ImportBufferNegative) {
+    native_handle_t* invalidHandle = nullptr;
+    mGralloc->getMapper()->importBuffer(invalidHandle, [&](const auto& tmpError, const auto&) {
+        EXPECT_EQ(Error::BAD_BUFFER, tmpError)
+            << "importBuffer with nullptr did not fail with BAD_BUFFER";
+    });
+
+    invalidHandle = native_handle_create(0, 0);
+    mGralloc->getMapper()->importBuffer(invalidHandle, [&](const auto& tmpError, const auto&) {
+        EXPECT_EQ(Error::BAD_BUFFER, tmpError)
+            << "importBuffer with invalid handle did not fail with BAD_BUFFER";
+    });
+    native_handle_delete(invalidHandle);
+}
+
+/**
+ * Test IMapper::freeBuffer with invalid buffers.
+ */
+TEST_F(GraphicsMapperHidlTest, FreeBufferNegative) {
+    native_handle_t* invalidHandle = nullptr;
+    Error error = mGralloc->getMapper()->freeBuffer(invalidHandle);
+    EXPECT_EQ(Error::BAD_BUFFER, error) << "freeBuffer with nullptr did not fail with BAD_BUFFER";
+
+    invalidHandle = native_handle_create(0, 0);
+    error = mGralloc->getMapper()->freeBuffer(invalidHandle);
+    EXPECT_EQ(Error::BAD_BUFFER, error)
+        << "freeBuffer with invalid handle did not fail with BAD_BUFFER";
+    native_handle_delete(invalidHandle);
+
+    const native_handle_t* clonedBufferHandle;
+    ASSERT_NO_FATAL_FAILURE(clonedBufferHandle = mGralloc->allocate(mDummyDescriptorInfo, false));
+    error = mGralloc->getMapper()->freeBuffer(invalidHandle);
+    EXPECT_EQ(Error::BAD_BUFFER, error)
+        << "freeBuffer with un-imported handle did not fail with BAD_BUFFER";
+
+    mGralloc->freeBuffer(clonedBufferHandle);
+}
+
+/**
+ * Test IMapper::lock and IMapper::unlock.
+ */
+TEST_F(GraphicsMapperHidlTest, LockUnlockBasic) {
+    const auto& info = mDummyDescriptorInfo;
+
+    const native_handle_t* bufferHandle;
+    uint32_t stride;
+    ASSERT_NO_FATAL_FAILURE(bufferHandle = mGralloc->allocate(info, true, &stride));
+
+    // lock buffer for writing
+    const IMapper::Rect region{0, 0, static_cast<int32_t>(info.width),
+                               static_cast<int32_t>(info.height)};
+    int fence = -1;
+    uint8_t* data;
+    ASSERT_NO_FATAL_FAILURE(
+        data = static_cast<uint8_t*>(mGralloc->lock(bufferHandle, info.usage, region, fence)));
+
+    // RGBA_8888
+    size_t strideInBytes = stride * 4;
+    size_t writeInBytes = info.width * 4;
+
+    for (uint32_t y = 0; y < info.height; y++) {
+        memset(data, y, writeInBytes);
+        data += strideInBytes;
+    }
+
+    ASSERT_NO_FATAL_FAILURE(fence = mGralloc->unlock(bufferHandle));
+
+    // lock again for reading
+    ASSERT_NO_FATAL_FAILURE(
+        data = static_cast<uint8_t*>(mGralloc->lock(bufferHandle, info.usage, region, fence)));
+    for (uint32_t y = 0; y < info.height; y++) {
+        for (size_t i = 0; i < writeInBytes; i++) {
+            EXPECT_EQ(static_cast<uint8_t>(y), data[i]);
+        }
+        data += strideInBytes;
+    }
+
+    ASSERT_NO_FATAL_FAILURE(fence = mGralloc->unlock(bufferHandle));
+    if (fence >= 0) {
+        close(fence);
+    }
+}
+
+/**
+ * Test IMapper::lockYCbCr.  This locks a YV12 buffer, and makes sure we can
+ * write to and read from it.
+ */
+TEST_F(GraphicsMapperHidlTest, LockYCbCrBasic) {
+    auto info = mDummyDescriptorInfo;
+    info.format = PixelFormat::YV12;
+
+    const native_handle_t* bufferHandle;
+    uint32_t stride;
+    ASSERT_NO_FATAL_FAILURE(bufferHandle = mGralloc->allocate(info, true, &stride));
+
+    // lock buffer for writing
+    const IMapper::Rect region{0, 0, static_cast<int32_t>(info.width),
+                               static_cast<int32_t>(info.height)};
+    int fence = -1;
+    YCbCrLayout layout;
+    ASSERT_NO_FATAL_FAILURE(layout = mGralloc->lockYCbCr(bufferHandle, info.usage, region, fence));
+
+    auto yData = static_cast<uint8_t*>(layout.y);
+    auto cbData = static_cast<uint8_t*>(layout.cb);
+    auto crData = static_cast<uint8_t*>(layout.cr);
+    for (uint32_t y = 0; y < info.height; y++) {
+        for (uint32_t x = 0; x < info.width; x++) {
+            auto val = static_cast<uint8_t>(info.height * y + x);
+
+            yData[layout.yStride * y + x] = val;
+            if (y % 2 == 0 && x % 2 == 0) {
+                cbData[layout.cStride * y / 2 + x / 2] = val;
+                crData[layout.cStride * y / 2 + x / 2] = val;
+            }
+        }
+    }
+
+    ASSERT_NO_FATAL_FAILURE(fence = mGralloc->unlock(bufferHandle));
+
+    // lock again for reading
+    ASSERT_NO_FATAL_FAILURE(layout = mGralloc->lockYCbCr(bufferHandle, info.usage, region, fence));
+
+    yData = static_cast<uint8_t*>(layout.y);
+    cbData = static_cast<uint8_t*>(layout.cb);
+    crData = static_cast<uint8_t*>(layout.cr);
+    for (uint32_t y = 0; y < info.height; y++) {
+        for (uint32_t x = 0; x < info.width; x++) {
+            auto val = static_cast<uint8_t>(info.height * y + x);
+
+            EXPECT_EQ(val, yData[layout.yStride * y + x]);
+            if (y % 2 == 0 && x % 2 == 0) {
+                EXPECT_EQ(val, cbData[layout.cStride * y / 2 + x / 2]);
+                EXPECT_EQ(val, crData[layout.cStride * y / 2 + x / 2]);
+            }
+        }
+    }
+
+    ASSERT_NO_FATAL_FAILURE(fence = mGralloc->unlock(bufferHandle));
+    if (fence >= 0) {
+        close(fence);
+    }
+}
+
+/**
+ * Test IMapper::unlock with invalid buffers.
+ */
+TEST_F(GraphicsMapperHidlTest, UnlockNegative) {
+    native_handle_t* invalidHandle = nullptr;
+    mGralloc->getMapper()->unlock(invalidHandle, [&](const auto& tmpError, const auto&) {
+        EXPECT_EQ(Error::BAD_BUFFER, tmpError)
+            << "unlock with nullptr did not fail with BAD_BUFFER";
+    });
+
+    invalidHandle = native_handle_create(0, 0);
+    mGralloc->getMapper()->unlock(invalidHandle, [&](const auto& tmpError, const auto&) {
+        EXPECT_EQ(Error::BAD_BUFFER, tmpError)
+            << "unlock with invalid handle did not fail with BAD_BUFFER";
+    });
+    native_handle_delete(invalidHandle);
+
+    ASSERT_NO_FATAL_FAILURE(invalidHandle = const_cast<native_handle_t*>(
+                                mGralloc->allocate(mDummyDescriptorInfo, false)));
+    mGralloc->getMapper()->unlock(invalidHandle, [&](const auto& tmpError, const auto&) {
+        EXPECT_EQ(Error::BAD_BUFFER, tmpError)
+            << "unlock with un-imported handle did not fail with BAD_BUFFER";
+    });
+    mGralloc->freeBuffer(invalidHandle);
+
+// disabled as it fails on many existing drivers
+#if 0
+  ASSERT_NO_FATAL_FAILURE(invalidHandle = const_cast<native_handle_t*>(
+                              mGralloc->allocate(mDummyDescriptorInfo, true)));
+  mGralloc->getMapper()->unlock(
+      invalidHandle, [&](const auto& tmpError, const auto&) {
+        EXPECT_EQ(Error::BAD_BUFFER, tmpError)
+            << "unlock with unlocked handle did not fail with BAD_BUFFER";
+      });
+  mGralloc->freeBuffer(invalidHandle);
+#endif
+}
+
+}  // namespace
+}  // namespace vts
+}  // namespace V3_0
+}  // namespace mapper
+}  // namespace graphics
+}  // namespace hardware
+}  // namespace android
+
+int main(int argc, char** argv) {
+    using android::hardware::graphics::mapper::V3_0::vts::GraphicsMapperHidlEnvironment;
+    ::testing::AddGlobalTestEnvironment(GraphicsMapperHidlEnvironment::Instance());
+    ::testing::InitGoogleTest(&argc, argv);
+    GraphicsMapperHidlEnvironment::Instance()->init(&argc, argv);
+    int status = RUN_ALL_TESTS();
+    LOG(INFO) << "Test result = " << status;
+    return status;
+}
diff --git a/neuralnetworks/1.0/types.hal b/neuralnetworks/1.0/types.hal
index 0880b2f..89af35a 100644
--- a/neuralnetworks/1.0/types.hal
+++ b/neuralnetworks/1.0/types.hal
@@ -55,10 +55,20 @@
      */
     TENSOR_QUANT8_ASYMM = 5,
 
-    /** OEM specific scalar value. */
+    /**
+     * DEPRECATED. Since NNAPI 1.2, extensions are the preferred alternative to
+     * OEM operation and data types.
+     *
+     * OEM specific scalar value.
+     */
     OEM                 = 10000,
 
-    /** A tensor of OEM specific values. */
+    /**
+     * DEPRECATED. Since NNAPI 1.2, extensions are the preferred alternative to
+     * OEM operation and data types.
+     *
+     * A tensor of OEM specific values.
+     */
     TENSOR_OEM_BYTE     = 10001,
 };
 
@@ -1448,7 +1458,8 @@
     TANH = 28,
 
     /**
-     * OEM specific operation.
+     * DEPRECATED. Since NNAPI 1.2, extensions are the preferred alternative to
+     * OEM operation and data types.
      *
      * This operation is OEM specific. It should only be used for OEM
      * applications.
diff --git a/neuralnetworks/1.0/vts/functional/Callbacks.cpp b/neuralnetworks/1.0/vts/functional/Callbacks.cpp
index a1c5a1a..03afcd0 100644
--- a/neuralnetworks/1.0/vts/functional/Callbacks.cpp
+++ b/neuralnetworks/1.0/vts/functional/Callbacks.cpp
@@ -139,8 +139,10 @@
     return Void();
 }
 
-Return<void> ExecutionCallback::notify_1_2(ErrorStatus errorStatus) {
+Return<void> ExecutionCallback::notify_1_2(ErrorStatus errorStatus,
+                                           const hidl_vec<OutputShape>& outputShapes) {
     mErrorStatus = errorStatus;
+    mOutputShapes = outputShapes;
     CallbackBase::notify();
     return Void();
 }
@@ -150,6 +152,11 @@
     return mErrorStatus;
 }
 
+const std::vector<OutputShape>& ExecutionCallback::getOutputShapes() {
+    wait();
+    return mOutputShapes;
+}
+
 }  // namespace implementation
 }  // namespace V1_2
 }  // namespace neuralnetworks
diff --git a/neuralnetworks/1.0/vts/functional/Callbacks.h b/neuralnetworks/1.0/vts/functional/Callbacks.h
index e89980d..46f29a6 100644
--- a/neuralnetworks/1.0/vts/functional/Callbacks.h
+++ b/neuralnetworks/1.0/vts/functional/Callbacks.h
@@ -275,8 +275,9 @@
      * Either IExecutionCallback::notify or IExecutionCallback::notify_1_2 must
      * be called exactly once on a given ExecutionCallback object.
      *
-     * @param status Error status returned from asynchronously preparing the
-     *               model; will be:
+     * @param status Error status returned from launching the asynchronous task
+     *               (if the launch fails) or from the asynchronous task itself
+     *               (if the launch succeeds). Must be:
      *               - NONE if the asynchronous execution was successful
      *               - DEVICE_UNAVAILABLE if driver is offline or busy
      *               - GENERAL_FAILURE if there is an unspecified error
@@ -285,27 +286,73 @@
      *               - INVALID_ARGUMENT if the input request is invalid
      */
     Return<void> notify(ErrorStatus status) override;
-    Return<void> notify_1_2(ErrorStatus status) override;
+
+    /**
+     * Similar to IExecutionCallback::notify, but for V1_2::IPreparedModel to
+     * also notify output shapes along with error status.
+     *
+     * @param status Error status returned from launching the asynchronous task
+     *               (if the launch fails) or from the asynchronous task itself
+     *               (if the launch succeeds). Must be:
+     *               - NONE if the asynchronous execution was successful
+     *               - DEVICE_UNAVAILABLE if driver is offline or busy
+     *               - GENERAL_FAILURE if the asynchronous task resulted in an
+     *                 unspecified error
+     *               - OUTPUT_INSUFFICIENT_SIZE if at least one output
+     *                 operand buffer is not large enough to store the
+     *                 corresponding output
+     *               - INVALID_ARGUMENT if one of the input arguments to
+     *                 prepareModel is invalid
+     * @param outputShapes A list of shape information of model output operands.
+     *                     The index into "outputShapes" corresponds to the index
+     *                     of the output operand in the Request outputs vector.
+     *                     outputShapes must be empty unless the status is either
+     *                     NONE or OUTPUT_INSUFFICIENT_SIZE.
+     */
+    Return<void> notify_1_2(ErrorStatus status, const hidl_vec<OutputShape>& outputShapes) override;
 
     /**
      * Retrieves the error status returned from the asynchronous task launched
-     * by IPreparedModel::execute. If IPreparedModel::execute has not finished
+     * by either IPreparedModel::execute or IPreparedModel::execute_1_2. If
+     * IPreparedModel::execute or IPreparedModel::execute_1_2 has not finished
      * asynchronously executing, this call will block until the asynchronous task
      * notifies the object.
      *
-     * @return status Error status returned from asynchronously preparing the
-     *                model; will be:
+     * @return status Error status returned from launching the asynchronous task
+     *                (if the launch fails) or from the asynchronous task itself
+     *                (if the launch succeeds). Must be:
      *                - NONE if the asynchronous execution was successful
      *                - DEVICE_UNAVAILABLE if driver is offline or busy
-     *                - GENERAL_FAILURE if there is an unspecified error
-     *                - OUTPUT_INSUFFICIENT_SIZE if provided output buffer is
-     *                  not large enough to store the resultant values
-     *                - INVALID_ARGUMENT if the input request is invalid
+     *                - GENERAL_FAILURE if the asynchronous task resulted in an
+     *                  unspecified error
+     *                - OUTPUT_INSUFFICIENT_SIZE if at least one output
+     *                  operand buffer is not large enough to store the
+     *                  corresponding output
+     *                - INVALID_ARGUMENT if one of the input arguments to
+     *                  prepareModel is invalid
      */
     ErrorStatus getStatus();
 
- private:
+    /**
+     * Retrieves the output shapes returned from the asynchronous task launched
+     * by IPreparedModel::execute_1_2. If IPreparedModel::execute_1_2 has not finished
+     * asynchronously executing, this call will block until the asynchronous task
+     * notifies the object.
+     *
+     * If the asynchronous task was launched by IPreparedModel::execute, an empty vector
+     * will be returned.
+     *
+     * @return outputShapes A list of shape information of model output operands.
+     *                      The index into "outputShapes" corresponds to the index
+     *                      of the output operand in the Request outputs vector.
+     *                      outputShapes must be empty unless the status is either
+     *                      NONE or OUTPUT_INSUFFICIENT_SIZE.
+     */
+    const std::vector<OutputShape>& getOutputShapes();
+
+   private:
     ErrorStatus mErrorStatus;
+    std::vector<OutputShape> mOutputShapes;
 };
 
 
diff --git a/neuralnetworks/1.0/vts/functional/GeneratedTestHarness.cpp b/neuralnetworks/1.0/vts/functional/GeneratedTestHarness.cpp
index 3b4eb21..b5a8607 100644
--- a/neuralnetworks/1.0/vts/functional/GeneratedTestHarness.cpp
+++ b/neuralnetworks/1.0/vts/functional/GeneratedTestHarness.cpp
@@ -89,13 +89,24 @@
                                                 sp<ExecutionCallback>& callback) {
     return preparedModel->execute_1_2(request, callback);
 }
-static Return<ErrorStatus> ExecutePreparedModel(sp<V1_0::IPreparedModel>&, const Request&) {
+static Return<ErrorStatus> ExecutePreparedModel(sp<V1_0::IPreparedModel>&, const Request&,
+                                                hidl_vec<OutputShape>*) {
     ADD_FAILURE() << "asking for synchronous execution at V1_0";
     return ErrorStatus::GENERAL_FAILURE;
 }
 static Return<ErrorStatus> ExecutePreparedModel(sp<V1_2::IPreparedModel>& preparedModel,
-                                                const Request& request) {
-    return preparedModel->executeSynchronously(request);
+                                                const Request& request,
+                                                hidl_vec<OutputShape>* outputShapes) {
+    ErrorStatus result;
+    Return<void> ret = preparedModel->executeSynchronously(
+        request, [&result, &outputShapes](ErrorStatus error, const hidl_vec<OutputShape>& shapes) {
+            result = error;
+            *outputShapes = shapes;
+        });
+    if (!ret.isOk()) {
+        return ErrorStatus::GENERAL_FAILURE;
+    }
+    return result;
 }
 enum class Synchronously { NO, YES };
 const float kDefaultAtol = 1e-5f;
@@ -197,6 +208,8 @@
         inputMemory->commit();
         outputMemory->commit();
 
+        ErrorStatus executionStatus;
+        hidl_vec<OutputShape> outputShapes;
         if (sync == Synchronously::NO) {
             SCOPED_TRACE("asynchronous");
 
@@ -211,18 +224,24 @@
 
             // retrieve execution status
             executionCallback->wait();
-            ErrorStatus executionReturnStatus = executionCallback->getStatus();
-            EXPECT_EQ(ErrorStatus::NONE, executionReturnStatus);
+            executionStatus = executionCallback->getStatus();
+            outputShapes = executionCallback->getOutputShapes();
         } else {
             SCOPED_TRACE("synchronous");
 
             // execute
-            Return<ErrorStatus> executionStatus = ExecutePreparedModel(
-                preparedModel, {.inputs = inputs_info, .outputs = outputs_info, .pools = pools});
-            ASSERT_TRUE(executionStatus.isOk());
-            EXPECT_EQ(ErrorStatus::NONE, static_cast<ErrorStatus>(executionStatus));
+            Return<ErrorStatus> executionReturnStatus = ExecutePreparedModel(
+                preparedModel, {.inputs = inputs_info, .outputs = outputs_info, .pools = pools},
+                &outputShapes);
+            ASSERT_TRUE(executionReturnStatus.isOk());
+            executionStatus = static_cast<ErrorStatus>(executionReturnStatus);
         }
 
+        ASSERT_EQ(ErrorStatus::NONE, executionStatus);
+        // TODO(xusongw): Check if the returned output shapes match with expectation once the
+        //                sample driver implementation of dynamic output shape is finished.
+        ASSERT_EQ(outputShapes.size(), 0);
+
         // validate results
         outputMemory->read();
         copy_back(&test, outputs_info, outputPtr);
diff --git a/neuralnetworks/1.2/Android.bp b/neuralnetworks/1.2/Android.bp
index 7d13104..d8762b0 100644
--- a/neuralnetworks/1.2/Android.bp
+++ b/neuralnetworks/1.2/Android.bp
@@ -27,6 +27,7 @@
         "Operation",
         "OperationType",
         "OperationTypeRange",
+        "OutputShape",
     ],
     gen_java: false,
 }
diff --git a/neuralnetworks/1.2/IExecutionCallback.hal b/neuralnetworks/1.2/IExecutionCallback.hal
index 667e0d6..47de1b6 100644
--- a/neuralnetworks/1.2/IExecutionCallback.hal
+++ b/neuralnetworks/1.2/IExecutionCallback.hal
@@ -18,6 +18,7 @@
 
 import @1.0::ErrorStatus;
 import @1.0::IExecutionCallback;
+import OutputShape;
 
 /**
  * IExecutionCallback must be used to return the error status result from an
@@ -39,10 +40,16 @@
      *               - DEVICE_UNAVAILABLE if driver is offline or busy
      *               - GENERAL_FAILURE if the asynchronous task resulted in an
      *                 unspecified error
-     *               - OUTPUT_INSUFFICIENT_SIZE if provided output buffer is
-     *                 not large enough to store the resultant values
+     *               - OUTPUT_INSUFFICIENT_SIZE if at least one output
+     *                 operand buffer is not large enough to store the
+     *                 corresponding output
      *               - INVALID_ARGUMENT if one of the input arguments to
      *                 prepareModel is invalid
+     * @param outputShapes A list of shape information of model output operands.
+     *                     The index into "outputShapes" corresponds with to index
+     *                     of the output operand in the Request outputs vector.
+     *                     outputShapes must be empty unless the status is either
+     *                     NONE or OUTPUT_INSUFFICIENT_SIZE.
      */
-    oneway notify_1_2(ErrorStatus status);
+    oneway notify_1_2(ErrorStatus status, vec<OutputShape> outputShapes);
 };
diff --git a/neuralnetworks/1.2/IPreparedModel.hal b/neuralnetworks/1.2/IPreparedModel.hal
index 4e91c67..044ca28 100644
--- a/neuralnetworks/1.2/IPreparedModel.hal
+++ b/neuralnetworks/1.2/IPreparedModel.hal
@@ -100,11 +100,17 @@
      *                - NONE if execution is performed successfully
      *                - DEVICE_UNAVAILABLE if driver is offline or busy
      *                - GENERAL_FAILURE if there is an unspecified error
-     *                - OUTPUT_INSUFFICIENT_SIZE if provided output buffer is
-     *                  not large enough to store the resultant values
+     *                - OUTPUT_INSUFFICIENT_SIZE if at least one output
+     *                  operand buffer is not large enough to store the
+     *                  corresponding output
      *                - INVALID_ARGUMENT if one of the input arguments is
      *                  invalid
+     * @return outputShapes A list of shape information of model output operands.
+     *                      The index into "outputShapes" corresponds to the index
+     *                      of the output operand in the Request outputs vector.
+     *                      outputShapes must be empty unless the status is either
+     *                      NONE or OUTPUT_INSUFFICIENT_SIZE.
      */
     executeSynchronously(Request request)
-        generates (ErrorStatus status);
+        generates (ErrorStatus status, vec<OutputShape> outputShapes);
 };
diff --git a/neuralnetworks/1.2/types.hal b/neuralnetworks/1.2/types.hal
index 40c07e7..b072793 100644
--- a/neuralnetworks/1.2/types.hal
+++ b/neuralnetworks/1.2/types.hal
@@ -150,7 +150,7 @@
     TRANSPOSE_CONV_2D = 84,
     UNIDIRECTIONAL_SEQUENCE_LSTM = 85,
     UNIDIRECTIONAL_SEQUENCE_RNN = 86,
-    ROTATED_BBOX_TRANSFORM = 87,
+    DETECTION_POSTPROCESSING = 87,
     ABS = 88,
     ROI_POOLING = 89,
     EQUAL = 90,
@@ -234,9 +234,6 @@
      *
      * For a scalar operand, dimensions.size() must be 0.
      *
-     * For a tensor operand, dimensions.size() must be at least 1;
-     * however, any of the dimensions may be unspecified.
-     *
      * A tensor operand with all dimensions specified has "fully
      * specified" dimensions. Whenever possible (i.e., whenever the
      * dimensions are known at model construction time), a tensor
@@ -255,17 +252,20 @@
      *     . The operand has lifetime CONSTANT_COPY or
      *       CONSTANT_REFERENCE.
      *
-     *     . The operand has lifetime MODEL_INPUT or MODEL_OUTPUT. Fully
+     *     . The operand has lifetime MODEL_INPUT. Fully
      *       specified dimensions must either be present in the
      *       Operand or they must be provided in the corresponding
      *       RequestArgument.
-     *       EXCEPTION: If the input or output is optional and omitted
+     *       EXCEPTION: If the input is optional and omitted
      *       (by setting the hasNoValue field of the corresponding
      *       RequestArgument to true) then it need not have fully
      *       specified dimensions.
      *
      * A tensor operand with some number of unspecified dimensions is
      * represented by setting each unspecified dimension to 0.
+     *
+     * A tensor operand with unspecified rank is represented by providing
+     * an empty dimensions vector.
      */
     vec<uint32_t> dimensions;
 
@@ -397,3 +397,18 @@
      */
     bool relaxComputationFloat32toFloat16;
 };
+
+/**
+ * Describes the shape information of an output operand after execution.
+ */
+struct OutputShape {
+    /**
+     * Dimensions of the operand.
+     */
+    vec<uint32_t> dimensions;
+
+    /**
+     * Whether the provided buffer size is sufficient for the output.
+     */
+    bool isSufficient;
+};
diff --git a/neuralnetworks/1.2/vts/functional/ValidateRequest.cpp b/neuralnetworks/1.2/vts/functional/ValidateRequest.cpp
index d80fbcf..1eaea4b 100644
--- a/neuralnetworks/1.2/vts/functional/ValidateRequest.cpp
+++ b/neuralnetworks/1.2/vts/functional/ValidateRequest.cpp
@@ -110,15 +110,20 @@
 
         executionCallback->wait();
         ErrorStatus executionReturnStatus = executionCallback->getStatus();
+        const auto& outputShapes = executionCallback->getOutputShapes();
         ASSERT_EQ(ErrorStatus::INVALID_ARGUMENT, executionReturnStatus);
+        ASSERT_EQ(outputShapes.size(), 0);
     }
 
     {
         SCOPED_TRACE(message + " [executeSynchronously]");
 
-        Return<ErrorStatus> executeStatus = preparedModel->executeSynchronously(request);
+        Return<void> executeStatus = preparedModel->executeSynchronously(
+            request, [](ErrorStatus error, const hidl_vec<OutputShape>& outputShapes) {
+                ASSERT_EQ(ErrorStatus::INVALID_ARGUMENT, error);
+                EXPECT_EQ(outputShapes.size(), 0);
+            });
         ASSERT_TRUE(executeStatus.isOk());
-        ASSERT_EQ(ErrorStatus::INVALID_ARGUMENT, static_cast<ErrorStatus>(executeStatus));
     }
 }
 
diff --git a/prebuilt_hashes/dump_hals_for_release.py b/prebuilt_hashes/dump_hals_for_release.py
index fee12ab..e9ed4c2 100755
--- a/prebuilt_hashes/dump_hals_for_release.py
+++ b/prebuilt_hashes/dump_hals_for_release.py
@@ -32,7 +32,7 @@
 
 class Constants:
     CURRENT = 'current'
-    HAL_PATH_PATTERN = r'/((?:[a-zA-Z_]+/)*)(\d+\.\d+)/([a-zA-Z_]+).hal'
+    HAL_PATH_PATTERN = r'/((?:[a-zA-Z_][a-zA-Z0-9_]*/)*)(\d+\.\d+)/([a-zA-Z_][a-zA-Z0-9_]*).hal'
     CURRENT_TXT_PATTERN = r'(?:.*/)?([0-9]+|current).txt'
 
 def trim_trailing_comments(line):
diff --git a/radio/1.4/IRadio.hal b/radio/1.4/IRadio.hal
index 3fe608f..dd69607 100644
--- a/radio/1.4/IRadio.hal
+++ b/radio/1.4/IRadio.hal
@@ -105,14 +105,14 @@
     oneway setDataProfile_1_4(int32_t serial, vec<DataProfileInfo> profiles);
 
     /**
-     * Initiate emergency voice call, with zero or more emergency service category(s) and routing
-     * information for handling the call. Android uses this request to make its emergency call
-     * instead of using @1.0::IRadio.dial if the 'address' in the 'dialInfo' field is identified
-     * as an emergency number by Android.
+     * Initiate emergency voice call, with zero or more emergency service category(s), zero or
+     * more emergency Uniform Resource Names (URN), and routing information for handling the call.
+     * Android uses this request to make its emergency call instead of using @1.0::IRadio.dial
+     * if the 'address' in the 'dialInfo' field is identified as an emergency number by Android.
      *
-     * In multi-sim senario, this radio request is sent through the IRadio service that serves
-     * the subscription the emergency number belongs to, no matter of the PUK/PIN state of the
-     * subscription and the service state.
+     * In multi-sim scenario, if the emergency number is from a specific subscription, this radio
+     * request is sent through the IRadio service that serves the subscription, no matter of the
+     * PUK/PIN state of the subscription and the service state of the radio.
      *
      * Some countries or carriers require some emergency numbers that must be handled with normal
      * call routing or emergency routing. If the 'routing' field is specified as
@@ -122,22 +122,32 @@
      * @1.4::EmergencyNumberRouting#UNKNOWN, Android does not know how to handle the call.
      *
      * If the dialed emergency number does not have a specified emergency service category, the
-     * 'categories' field is set to @1.4::EmergencyServiceCategory#UNSPECIFIED; if the underlying
-     * technology used to request emergency services does not support the emergency service
-     * category, the categories may be ignored.
+     * 'categories' field is set to @1.4::EmergencyServiceCategory#UNSPECIFIED; if the dialed
+     * emergency number does not have specified emergency Uniform Resource Names, the 'urns' field
+     * is set to an empty list. If the underlying technology used to request emergency services
+     * does not support the emergency service category or emergency uniform resource names, the
+     * field 'categories' or 'urns' may be ignored.
      *
-     * Reference: 3gpp TS 22.101, Section 10 - Emergency Calls
+     * If 'isTesting' is true, this request is for testing purpose, and must not be sent to a real
+     * emergency service; otherwise it's for a real emergency call request.
+     *
+     * Reference: 3gpp 22.101, Section 10 - Emergency Calls;
+     *            3gpp 23.167, Section 6 - Functional description;
+     *            3gpp 24.503, Section 5.1.6.8.1 - General;
+     *            RFC 5031
      *
      * @param serial Serial number of request.
      * @param dialInfo the same @1.0::Dial information used by @1.0::IRadio.dial.
      * @param categories bitfield<@1.4::EmergencyServiceCategory> the Emergency Service Category(s)
      *     of the call.
+     * @param urns the emergency Uniform Resource Names (URN)
      * @param routing @1.4::EmergencyCallRouting the emergency call routing information.
      *
      * Response function is IRadioResponse.emergencyDialResponse()
      */
     oneway emergencyDial(int32_t serial, Dial dialInfo,
-            bitfield<EmergencyServiceCategory> categories, EmergencyCallRouting routing);
+            bitfield<EmergencyServiceCategory> categories, vec<string> urns,
+            EmergencyCallRouting routing, bool isTesting);
 
     /**
      * Starts a network scan
diff --git a/radio/1.4/IRadioIndication.hal b/radio/1.4/IRadioIndication.hal
index a58d19c..58b7b70 100644
--- a/radio/1.4/IRadioIndication.hal
+++ b/radio/1.4/IRadioIndication.hal
@@ -27,22 +27,24 @@
      * Report the current list of emergency numbers
      *
      * Each emergency number (@1.4::EmergencyNumber) in the emergency number list contains a
-     * dialing number, zero or more service category(s), mobile country code, mobile network code,
-     * and source(s) that indicate where it comes from.
+     * dialing number, zero or more service category(s), zero or more emergency uniform resource
+     * names, mobile country code, mobile network code, and source(s) that indicate where it comes
+     * from.
      *
      * Radio must report all the valid emergency numbers with known mobile country code, mobile
-     * network code and emergency service categories from all available sources including network
-     * signaling, sim, modem/oem configuration, and default configuration (112 and 911 must be
-     * always available; additionally, 000, 08, 110, 999, 118 and 119 must be available when sim
-     * is not present). Radio shall not report emergency numbers that are invalid in the current
-     * locale. The reported emergency number list must not have duplicate @1.4::EmergencyNumber
-     * entries. Please refer the documentation of @1.4::EmergencyNumber to construct each
-     * emergency number to report.
+     * network code, emergency service categories, and emergency uniform resource names from all
+     * available sources including network signaling, sim, modem/oem configuration, and default
+     * configuration (112 and 911 must be always available; additionally, 000, 08, 110, 999, 118
+     * and 119 must be available when sim is not present). Radio shall not report emergency numbers
+     * that are invalid in the current locale. The reported emergency number list must not have
+     * duplicate @1.4::EmergencyNumber entries. Please refer the documentation of
+     * @1.4::EmergencyNumber to construct each emergency number to report.
      *
      * Radio must report the complete list of emergency numbers whenever the emergency numbers in
      * the list are changed or whenever the client and the radio server are connected.
      *
-     * Reference: 3gpp 22.101, Section 10 - Emergency Calls
+     * Reference: 3gpp 22.101, Section 10 - Emergency Calls;
+     *            3gpp 24.008, Section 9.2.13.4 - Emergency Number List
      *
      * @param type Type of radio indication
      * @param emergencyNumberList Current list of emergency numbers known to radio.
diff --git a/radio/1.4/types.hal b/radio/1.4/types.hal
index 2eecc7a..76e8403 100644
--- a/radio/1.4/types.hal
+++ b/radio/1.4/types.hal
@@ -40,6 +40,7 @@
 import @1.2::CellInfoWcdma;
 import @1.2::CardStatus;
 import @1.2::CellIdentity;
+import @1.2::CellConnectionStatus;
 import @1.2::DataRegStateResult;
 import @1.2::PhysicalChannelConfig;
 
@@ -53,20 +54,27 @@
 };
 
 /**
- * Emergency number contains information of number, one or more service category(s), mobile country
- * code (mcc), mobile network country (mnc) and source(s) that indicate where it comes from.
+ * Emergency number contains information of number, one or more service category(s), zero or more
+ * emergency uniform resource names, mobile country code (mcc), mobile network country (mnc) and
+ * source(s) that indicate where it comes from.
  *
- * If the source of the emergency number is associated with country, field ‘mcc’ must be provided;
- * otherwise the field ‘mcc’ must be an empty string.
+ * If the emergency number is associated with country, field ‘mcc’ must be provided, otherwise
+ * field ‘mcc’ must be an empty string. If the emergency number is associated with network
+ * operator, field ‘mcc’ and 'mnc' must be provided, otherwise field ‘mnc’ must be an empty
+ * string. If the emergency number is specified with emergency service category(s), field
+ * 'categories' must be provided, otherwise field 'categories' must be
+ * @1.4::EmergencyServiceCategories::UNSPECIFIED. If the emergency number is specified with
+ * emergency uniform resource names (URN), field 'urns' must be provided, otherwise field 'urns'
+ * must be an empty list.
  *
- * If the source of the emergency number is associated with network operator, field ‘mcc’ and
- * 'mnc' must be provided; otherwise the field ‘mnc’ must be an empty string.
+ * A unique EmergencyNumber has a unique combination of ‘number’, ‘mcc’, 'mnc', 'categories' and
+ * 'urns' fields. Multiple @1.4::EmergencyNumberSource should be merged into one 'sources' field
+ * via bitwise-OR combination for the same EmergencyNumber.
  *
- * A unique EmergencyNumber has a unique combination of ‘number’, ‘mcc’, 'mnc' and 'categories'
- * fields. Multiple @1.4::EmergencyNumberSource should be merged into the bitfield for the same
- * EmergencyNumber.
- *
- * Reference: 3GPP TS 22.101 version 9.1.0 Release 9
+ * Reference: 3gpp 22.101, Section 10 - Emergency Calls;
+ *            3gpp 23.167, Section 6 - Functional description;
+ *            3gpp 24.503, Section 5.1.6.8.1 - General;
+ *            RFC 5031
  */
 struct EmergencyNumber{
     /**
@@ -88,6 +96,10 @@
      */
     bitfield<EmergencyServiceCategory> categories;
     /**
+     * The list of emergency Uniform Resource Names (URN).
+     */
+    vec<string> urns;
+    /**
      * The bitfield of @1.4::EmergencyNumberSource(s). See @1.4::EmergencyNumberSource for the
      * value of each bit.
      */
@@ -1520,15 +1532,15 @@
 
 /** Overwritten from @1.2::CellInfo in order to update the CellInfoLte to 1.4 version. */
 struct CellInfo {
-    /** Cell type for selecting from union CellInfo. */
-    CellInfoType cellInfoType;
-
     /**
      * True if the phone is registered to a mobile network that provides service on this cell and
      * this cell is being used or would be used for network signaling.
      */
     bool isRegistered;
 
+    /** Connection status for the cell. */
+    CellConnectionStatus connectionStatus;
+
     /** CellInfo details, cellInfoType can tell which cell info should be used. */
     safe_union Info {
         CellInfoGsm gsm;
diff --git a/radio/config/1.1/Android.bp b/radio/config/1.1/Android.bp
index 056510c..151a0a3 100644
--- a/radio/config/1.1/Android.bp
+++ b/radio/config/1.1/Android.bp
@@ -7,10 +7,10 @@
         enabled: true,
     },
     srcs: [
+        "types.hal",
         "IRadioConfig.hal",
         "IRadioConfigIndication.hal",
         "IRadioConfigResponse.hal",
-        "types.hal",
     ],
     interfaces: [
         "android.hardware.radio.config@1.0",
@@ -19,6 +19,7 @@
     ],
     types: [
         "ModemInfo",
+        "ModemsConfig",
         "PhoneCapability",
     ],
     gen_java: true,
diff --git a/radio/config/1.1/IRadioConfig.hal b/radio/config/1.1/IRadioConfig.hal
index bc63339..7b0c6b6 100644
--- a/radio/config/1.1/IRadioConfig.hal
+++ b/radio/config/1.1/IRadioConfig.hal
@@ -19,6 +19,7 @@
 import @1.0::IRadioConfig;
 import @1.1::IRadioConfigResponse;
 import @1.1::PhoneCapability;
+import @1.1::ModemsConfig;
 
 /**
  * Note: IRadioConfig 1.1 is an intermediate layer between Android P and Android Q.
@@ -56,4 +57,36 @@
      * Response callback is IRadioConfigResponse.setPreferredDataModemResponse()
      */
     oneway setPreferredDataModem(int32_t serial, uint8_t modemId);
+
+   /**
+     * Set modems configurations by specifying the number of live modems (i.e modems that are
+     * enabled and actively working as part of a working telephony stack).
+     *
+     * Example: this interface can be used to switch to single/multi sim mode by specifying
+     * the number of live modems as 1, 2, etc
+     *
+     * Note: by setting the number of live modems in this API, that number of modems will
+     * subsequently get enabled/disabled
+     *
+     * @param serial serial number of request.
+     * @param modemsConfig ModemsConfig object including the number of live modems
+     *
+     * Response callback is IRadioResponse.setModemsConfigResponse()
+     */
+    oneway setModemsConfig(int32_t serial, ModemsConfig modemsConfig);
+
+   /**
+     * Get modems configurations. This interface is used to get modem configurations
+     * which includes the number of live modems (i.e modems that are
+     * enabled and actively working as part of a working telephony stack)
+     *
+     * Note: in order to get the overall number of modems available on the phone,
+     * refer to getPhoneCapability API
+     *
+     * @param serial Serial number of request.
+     *
+     * Response callback is IRadioResponse.getModemsConfigResponse() which
+     * will return <@1.1::ModemsConfig>.
+     */
+    oneway getModemsConfig(int32_t serial);
 };
diff --git a/radio/config/1.1/IRadioConfigResponse.hal b/radio/config/1.1/IRadioConfigResponse.hal
index 42a31b1..d42ff06 100644
--- a/radio/config/1.1/IRadioConfigResponse.hal
+++ b/radio/config/1.1/IRadioConfigResponse.hal
@@ -19,6 +19,7 @@
 import @1.0::IRadioConfigResponse;
 import @1.1::PhoneCapability;
 import android.hardware.radio@1.0::RadioResponseInfo;
+import @1.1::ModemsConfig;
 
 /**
  * Note: IRadioConfig 1.1 is an intermediate layer between Android P and Android Q.
@@ -50,4 +51,27 @@
      *   RadioError:INVALID_ARGUMENTS
      */
     oneway setPreferredDataModemResponse(RadioResponseInfo info);
+
+    /**
+     * @param info Response info struct containing response type, serial no. and error
+     *
+     * Valid errors returned:
+     *   RadioError:NONE
+     *   RadioError:RADIO_NOT_AVAILABLE
+     *   RadioError:REQUEST_NOT_SUPPORTED
+     *   RadioError:INVALID_ARGUMENTS
+     */
+    oneway setModemsConfigResponse(RadioResponseInfo info);
+
+    /**
+     * @param info Response info struct containing response type, serial no. and error
+     * @param modemsConfig <@1.1::ModemsConfig> it defines all the modems' configurations
+     *        at this time, only the number of live modems
+     *
+     * Valid errors returned:
+     *   RadioError:NONE
+     *   RadioError:RADIO_NOT_AVAILABLE
+     *   RadioError:REQUEST_NOT_SUPPORTED
+     */
+    oneway getModemsConfigResponse(RadioResponseInfo info, ModemsConfig modemsConfig);
 };
diff --git a/radio/config/1.1/types.hal b/radio/config/1.1/types.hal
index a7b9f86..89a4723 100644
--- a/radio/config/1.1/types.hal
+++ b/radio/config/1.1/types.hal
@@ -61,3 +61,11 @@
      */
     vec<ModemInfo> logicalModemList;
 };
+
+struct ModemsConfig {
+    /**
+     * variable to indicate the number of live modems i.e modems that are enabled
+     * and actively working as part of a working connectivity stack
+     */
+    uint8_t numOfLiveModems;
+};
\ No newline at end of file
diff --git a/radio/config/1.1/vts/functional/Android.bp b/radio/config/1.1/vts/functional/Android.bp
new file mode 100644
index 0000000..de909a3
--- /dev/null
+++ b/radio/config/1.1/vts/functional/Android.bp
@@ -0,0 +1,33 @@
+//
+// Copyright (C) 2018 The Android Open Source Project
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+//      http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//
+
+cc_test {
+    name: "VtsHalRadioConfigV1_1TargetTest",
+    defaults: ["VtsHalTargetTestDefaults"],
+    srcs: [
+        "radio_config_hidl_hal_api.cpp",
+        "radio_config_hidl_hal_test.cpp",
+        "radio_config_response.cpp",
+        "VtsHalRadioConfigV1_1TargetTest.cpp",
+    ],
+    static_libs: [
+        "RadioVtsTestUtilBase",
+        "android.hardware.radio.config@1.0",
+        "android.hardware.radio.config@1.1",
+    ],
+    header_libs: ["radio.util.header@1.0"],
+    test_suites: ["general-tests"],
+}
diff --git a/radio/config/1.1/vts/functional/VtsHalRadioConfigV1_1TargetTest.cpp b/radio/config/1.1/vts/functional/VtsHalRadioConfigV1_1TargetTest.cpp
new file mode 100644
index 0000000..2fc6b62
--- /dev/null
+++ b/radio/config/1.1/vts/functional/VtsHalRadioConfigV1_1TargetTest.cpp
@@ -0,0 +1,26 @@
+/*
+ * Copyright (C) 2018 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include <radio_config_hidl_hal_utils.h>
+
+int main(int argc, char** argv) {
+    ::testing::AddGlobalTestEnvironment(RadioConfigHidlEnvironment::Instance());
+    ::testing::InitGoogleTest(&argc, argv);
+    RadioConfigHidlEnvironment::Instance()->init(&argc, argv);
+    int status = RUN_ALL_TESTS();
+    LOG(INFO) << "Test result = " << status;
+    return status;
+}
diff --git a/radio/config/1.1/vts/functional/radio_config_hidl_hal_api.cpp b/radio/config/1.1/vts/functional/radio_config_hidl_hal_api.cpp
new file mode 100644
index 0000000..a1639d8
--- /dev/null
+++ b/radio/config/1.1/vts/functional/radio_config_hidl_hal_api.cpp
@@ -0,0 +1,71 @@
+/*
+ * Copyright (C) 2018 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include <radio_config_hidl_hal_utils.h>
+
+#define ASSERT_OK(ret) ASSERT_TRUE(ret.isOk())
+
+/*
+ * Test IRadioConfig.getModemsConfig()
+ */
+TEST_F(RadioConfigHidlTest, getModemsConfig) {
+    serial = GetRandomSerialNumber();
+    Return<void> res = radioConfig->getModemsConfig(serial);
+    ASSERT_OK(res);
+    EXPECT_EQ(std::cv_status::no_timeout, wait());
+    EXPECT_EQ(RadioResponseType::SOLICITED, radioConfigRsp->rspInfo.type);
+    EXPECT_EQ(serial, radioConfigRsp->rspInfo.serial);
+    ALOGI("getModemsConfig, rspInfo.error = %s\n", toString(radioConfigRsp->rspInfo.error).c_str());
+
+    ASSERT_TRUE(CheckAnyOfErrors(radioConfigRsp->rspInfo.error,
+                                 {RadioError::NONE, RadioError::REQUEST_NOT_SUPPORTED}));
+}
+
+/*
+ * Test IRadioConfig.setModemsConfig()
+ */
+TEST_F(RadioConfigHidlTest, setModemsConfig_invalidArgument) {
+    serial = GetRandomSerialNumber();
+    ModemsConfig* mConfig = new ModemsConfig();
+    Return<void> res = radioConfig->setModemsConfig(serial, *mConfig);
+    ASSERT_OK(res);
+    EXPECT_EQ(std::cv_status::no_timeout, wait());
+    EXPECT_EQ(RadioResponseType::SOLICITED, radioConfigRsp->rspInfo.type);
+    EXPECT_EQ(serial, radioConfigRsp->rspInfo.serial);
+    ALOGI("setModemsConfig, rspInfo.error = %s\n", toString(radioConfigRsp->rspInfo.error).c_str());
+
+    ASSERT_TRUE(
+        CheckAnyOfErrors(radioConfigRsp->rspInfo.error,
+                         {RadioError::INVALID_ARGUMENTS, RadioError::REQUEST_NOT_SUPPORTED}));
+}
+
+/*
+ * Test IRadioConfig.setModemsConfig()
+ */
+TEST_F(RadioConfigHidlTest, setModemsConfig_goodRequest) {
+    serial = GetRandomSerialNumber();
+    ModemsConfig* mConfig = new ModemsConfig();
+    mConfig->numOfLiveModems = 1;
+    Return<void> res = radioConfig->setModemsConfig(serial, *mConfig);
+    ASSERT_OK(res);
+    EXPECT_EQ(std::cv_status::no_timeout, wait());
+    EXPECT_EQ(RadioResponseType::SOLICITED, radioConfigRsp->rspInfo.type);
+    EXPECT_EQ(serial, radioConfigRsp->rspInfo.serial);
+    ALOGI("setModemsConfig, rspInfo.error = %s\n", toString(radioConfigRsp->rspInfo.error).c_str());
+
+    ASSERT_TRUE(CheckAnyOfErrors(radioConfigRsp->rspInfo.error,
+                                 {RadioError::NONE, RadioError::REQUEST_NOT_SUPPORTED}));
+}
diff --git a/radio/config/1.1/vts/functional/radio_config_hidl_hal_test.cpp b/radio/config/1.1/vts/functional/radio_config_hidl_hal_test.cpp
new file mode 100644
index 0000000..a8c257d
--- /dev/null
+++ b/radio/config/1.1/vts/functional/radio_config_hidl_hal_test.cpp
@@ -0,0 +1,69 @@
+/*
+ * Copyright (C) 2018 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include <radio_config_hidl_hal_utils.h>
+
+void RadioConfigHidlTest::SetUp() {
+    radioConfig = ::testing::VtsHalHidlTargetTestBase::getService<IRadioConfig>(
+        RadioConfigHidlEnvironment::Instance()->getServiceName<IRadioConfig>(
+            hidl_string(RADIO_SERVICE_NAME)));
+    if (radioConfig == NULL) {
+        sleep(60);
+        radioConfig = ::testing::VtsHalHidlTargetTestBase::getService<IRadioConfig>(
+            RadioConfigHidlEnvironment::Instance()->getServiceName<IRadioConfig>(
+                hidl_string(RADIO_SERVICE_NAME)));
+    }
+    ASSERT_NE(nullptr, radioConfig.get());
+
+    radioConfigRsp = new (std::nothrow) RadioConfigResponse(*this);
+    ASSERT_NE(nullptr, radioConfigRsp.get());
+
+    count_ = 0;
+
+    radioConfig->setResponseFunctions(radioConfigRsp, nullptr);
+    EXPECT_EQ(RadioResponseType::SOLICITED, radioConfigRsp->rspInfo.type);
+    EXPECT_EQ(serial, radioConfigRsp->rspInfo.serial);
+    EXPECT_EQ(RadioError::NONE, radioConfigRsp->rspInfo.error);
+}
+
+/*
+ * Notify that the response message is received.
+ */
+void RadioConfigHidlTest::notify(int receivedSerial) {
+    std::unique_lock<std::mutex> lock(mtx_);
+    if (serial == receivedSerial) {
+        count_++;
+        cv_.notify_one();
+    }
+}
+
+/*
+ * Wait till the response message is notified or till TIMEOUT_PERIOD.
+ */
+std::cv_status RadioConfigHidlTest::wait() {
+    std::unique_lock<std::mutex> lock(mtx_);
+
+    std::cv_status status = std::cv_status::no_timeout;
+    auto now = std::chrono::system_clock::now();
+    while (count_ == 0) {
+        status = cv_.wait_until(lock, now + std::chrono::seconds(TIMEOUT_PERIOD));
+        if (status == std::cv_status::timeout) {
+            return status;
+        }
+    }
+    count_--;
+    return status;
+}
\ No newline at end of file
diff --git a/radio/config/1.1/vts/functional/radio_config_hidl_hal_utils.h b/radio/config/1.1/vts/functional/radio_config_hidl_hal_utils.h
new file mode 100644
index 0000000..1747ce8
--- /dev/null
+++ b/radio/config/1.1/vts/functional/radio_config_hidl_hal_utils.h
@@ -0,0 +1,115 @@
+/*
+ * Copyright (C) 2018 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include <android-base/logging.h>
+
+#include <VtsHalHidlTargetTestBase.h>
+#include <VtsHalHidlTargetTestEnvBase.h>
+#include <chrono>
+#include <condition_variable>
+#include <mutex>
+
+#include <android/hardware/radio/config/1.1/IRadioConfig.h>
+#include <android/hardware/radio/config/1.1/IRadioConfigResponse.h>
+#include <android/hardware/radio/config/1.1/types.h>
+
+#include "vts_test_util.h"
+
+using namespace ::android::hardware::radio::config::V1_1;
+
+using ::android::sp;
+using ::android::hardware::hidl_string;
+using ::android::hardware::hidl_vec;
+using ::android::hardware::Return;
+using ::android::hardware::Void;
+using ::android::hardware::radio::config::V1_0::SimSlotStatus;
+using ::android::hardware::radio::V1_0::RadioResponseInfo;
+using ::android::hardware::radio::V1_0::RadioResponseType;
+
+#define TIMEOUT_PERIOD 75
+#define RADIO_SERVICE_NAME "slot1"
+
+class RadioConfigHidlTest;
+
+/* Callback class for radio config response */
+class RadioConfigResponse : public IRadioConfigResponse {
+   protected:
+    RadioConfigHidlTest& parent;
+
+   public:
+    RadioResponseInfo rspInfo;
+
+    RadioConfigResponse(RadioConfigHidlTest& parent);
+    virtual ~RadioConfigResponse() = default;
+
+    Return<void> getSimSlotsStatusResponse(
+        const RadioResponseInfo& info,
+        const ::android::hardware::hidl_vec<SimSlotStatus>& slotStatus);
+
+    Return<void> setSimSlotsMappingResponse(const RadioResponseInfo& info);
+
+    Return<void> getPhoneCapabilityResponse(const RadioResponseInfo& info,
+                                            const PhoneCapability& phoneCapability);
+
+    Return<void> setPreferredDataModemResponse(const RadioResponseInfo& info);
+
+    Return<void> getModemsConfigResponse(const RadioResponseInfo& info,
+                                         const ModemsConfig& mConfig);
+
+    Return<void> setModemsConfigResponse(const RadioResponseInfo& info);
+};
+
+// Test environment for Radio HIDL HAL.
+class RadioConfigHidlEnvironment : public ::testing::VtsHalHidlTargetTestEnvBase {
+   public:
+    // get the test environment singleton
+    static RadioConfigHidlEnvironment* Instance() {
+        static RadioConfigHidlEnvironment* instance = new RadioConfigHidlEnvironment;
+        return instance;
+    }
+    virtual void registerTestServices() override { registerTestService<IRadioConfig>(); }
+
+   private:
+    RadioConfigHidlEnvironment() {}
+};
+
+// The main test class for Radio config HIDL.
+class RadioConfigHidlTest : public ::testing::VtsHalHidlTargetTestBase {
+   protected:
+    std::mutex mtx_;
+    std::condition_variable cv_;
+    int count_;
+
+   public:
+    virtual void SetUp() override;
+
+    /* Used as a mechanism to inform the test about data/event callback */
+    void notify(int receivedSerial);
+
+    /* Test code calls this function to wait for response */
+    std::cv_status wait();
+
+    void updateSimCardStatus();
+
+    /* Serial number for radio request */
+    int serial;
+
+    /* radio config service handle */
+    sp<IRadioConfig> radioConfig;
+
+    /* radio config response handle */
+    sp<RadioConfigResponse> radioConfigRsp;
+};
diff --git a/radio/config/1.1/vts/functional/radio_config_response.cpp b/radio/config/1.1/vts/functional/radio_config_response.cpp
new file mode 100644
index 0000000..8c9e4d7
--- /dev/null
+++ b/radio/config/1.1/vts/functional/radio_config_response.cpp
@@ -0,0 +1,50 @@
+/*
+ * Copyright (C) 2018 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include <radio_config_hidl_hal_utils.h>
+
+// SimSlotStatus slotStatus;
+
+RadioConfigResponse::RadioConfigResponse(RadioConfigHidlTest& parent) : parent(parent) {}
+
+Return<void> RadioConfigResponse::getSimSlotsStatusResponse(
+    const RadioResponseInfo& /* info */,
+    const ::android::hardware::hidl_vec<SimSlotStatus>& /* slotStatus */) {
+    return Void();
+}
+
+Return<void> RadioConfigResponse::setSimSlotsMappingResponse(const RadioResponseInfo& /* info */) {
+    return Void();
+}
+
+Return<void> RadioConfigResponse::getPhoneCapabilityResponse(
+    const RadioResponseInfo& /* info */, const PhoneCapability& /* phoneCapability */) {
+    return Void();
+}
+
+Return<void> RadioConfigResponse::setPreferredDataModemResponse(
+    const RadioResponseInfo& /* info */) {
+    return Void();
+}
+
+Return<void> RadioConfigResponse::getModemsConfigResponse(const RadioResponseInfo& /* info */,
+                                                          const ModemsConfig& /* mConfig */) {
+    return Void();
+}
+
+Return<void> RadioConfigResponse::setModemsConfigResponse(const RadioResponseInfo& /* info */) {
+    return Void();
+}
\ No newline at end of file
diff --git a/sensors/2.0/ISensors.hal b/sensors/2.0/ISensors.hal
index 1685a0a..3a9af46 100644
--- a/sensors/2.0/ISensors.hal
+++ b/sensors/2.0/ISensors.hal
@@ -95,11 +95,15 @@
      * The Wake Lock FMQ is used by the framework to notify the HAL when it is
      * safe to release its wake_lock. When the framework receives WAKE_UP events
      * from the Event FMQ and the framework has acquired a wake_lock, the
-     * framework must write a WakeLockEvent to the Wake Lock FMQ with the number
-     * of WAKE_UP events processed. When the HAL reads the WakeLockEvent from
-     * the Wake Lock FMQ, the HAL should decrement its current count of
-     * unprocessed WAKE_UP events and release its wake_lock if the current
-     * count of unprocessed WAKE_UP events is zero.
+     * framework must write the number of WAKE_UP events processed to the Wake
+     * Lock FMQ. When the HAL reads the data from the Wake Lock FMQ, the HAL
+     * decrements its current count of unprocessed WAKE_UP events and releases
+     * its wake_lock if the current count of unprocessed WAKE_UP events is
+     * zero.
+     *
+     * The framework must use the WakeLockQueueFlagBits::DATA_WRITTEN value to
+     * notify the HAL that data has been written to the Wake Lock FMQ and must
+     * be read by HAL.
      *
      * The ISensorsCallback is used by the HAL to notify the framework of
      * asynchronous events, such as a dynamic sensor connection.
diff --git a/sensors/2.0/default/Sensors.cpp b/sensors/2.0/default/Sensors.cpp
index efc8b05..15fe86f 100644
--- a/sensors/2.0/default/Sensors.cpp
+++ b/sensors/2.0/default/Sensors.cpp
@@ -31,6 +31,7 @@
 using ::android::hardware::sensors::V1_0::Result;
 using ::android::hardware::sensors::V1_0::SharedMemInfo;
 using ::android::hardware::sensors::V2_0::SensorTimeout;
+using ::android::hardware::sensors::V2_0::WakeLockQueueFlagBits;
 
 constexpr const char* kWakeLockName = "SensorsHAL_WAKEUP";
 
@@ -86,6 +87,17 @@
     const sp<ISensorsCallback>& sensorsCallback) {
     Result result = Result::OK;
 
+    // Ensure that all sensors are disabled
+    for (auto sensor : mSensors) {
+        sensor.second->activate(false /* enable */);
+    }
+
+    // Stop the Wake Lock thread if it is currently running
+    if (mReadWakeLockQueueRun.load()) {
+        mReadWakeLockQueueRun = false;
+        mWakeLockThread.join();
+    }
+
     // Save a reference to the callback
     mCallback = sensorsCallback;
 
@@ -215,7 +227,9 @@
 
         // Read events from the Wake Lock FMQ. Timeout after a reasonable amount of time to ensure
         // that any held wake lock is able to be released if it is held for too long.
-        mWakeLockQueue->readBlocking(&eventsHandled, 1 /* count */, kReadTimeoutNs);
+        mWakeLockQueue->readBlocking(&eventsHandled, 1 /* count */, 0 /* readNotification */,
+                                     static_cast<uint32_t>(WakeLockQueueFlagBits::DATA_WRITTEN),
+                                     kReadTimeoutNs);
         updateWakeLock(0 /* eventsWritten */, eventsHandled);
     }
 }
diff --git a/sensors/2.0/types.hal b/sensors/2.0/types.hal
index f9defa2..4457544 100644
--- a/sensors/2.0/types.hal
+++ b/sensors/2.0/types.hal
@@ -40,3 +40,11 @@
      */
      EVENTS_READ = 1 << 1,
 };
+
+enum WakeLockQueueFlagBits : uint32_t {
+    /**
+     * Used to notify the HAL that the framework has written data to the Wake
+     * Lock FMQ.
+     */
+     DATA_WRITTEN = 1 << 0,
+};
diff --git a/thermal/2.0/default/Android.bp b/thermal/2.0/default/Android.bp
index f620e6e..dab0d33 100644
--- a/thermal/2.0/default/Android.bp
+++ b/thermal/2.0/default/Android.bp
@@ -14,7 +14,7 @@
 // limitations under the License.
 
 cc_binary {
-    name: "android.hardware.thermal@2.0-service",
+    name: "android.hardware.thermal@2.0-service.mock",
     defaults: ["hidl_defaults"],
     relative_install_path: "hw",
     vendor: true,
diff --git a/thermal/2.0/default/android.hardware.thermal@2.0-service.rc b/thermal/2.0/default/android.hardware.thermal@2.0-service.rc
index de49d20..046c771 100644
--- a/thermal/2.0/default/android.hardware.thermal@2.0-service.rc
+++ b/thermal/2.0/default/android.hardware.thermal@2.0-service.rc
@@ -1,4 +1,4 @@
-service vendor.thermal-hal-2-0-mock /vendor/bin/hw/android.hardware.thermal@2.0-service
+service vendor.thermal-hal-2-0-mock /vendor/bin/hw/android.hardware.thermal@2.0-service.mock
     interface android.hardware.thermal@2.0::IThermal default
     class hal
     user system
diff --git a/wifi/1.3/default/hidl_struct_util.cpp b/wifi/1.3/default/hidl_struct_util.cpp
index a24d048..a102def 100644
--- a/wifi/1.3/default/hidl_struct_util.cpp
+++ b/wifi/1.3/default/hidl_struct_util.cpp
@@ -1253,6 +1253,10 @@
         hidl_request.debugConfigs
             .useSdfInBandVal[(size_t)NanBandIndex::NAN_BAND_5GHZ];
 
+    // disable NANv3 NDPe
+    legacy_request->config_ndpe_attr = 1;
+    legacy_request->use_ndpe_attr = 0;
+
     return true;
 }
 
@@ -1764,6 +1768,10 @@
         hidl_request.bandSpecificConfig[(size_t)NanBandIndex::NAN_BAND_5GHZ]
             .discoveryWindowIntervalVal;
 
+    // disable NANv3 NDPe
+    legacy_request->config_ndpe_attr = 1;
+    legacy_request->use_ndpe_attr = 0;
+
     return true;
 }
 
diff --git a/wifi/hostapd/1.1/IHostapd.hal b/wifi/hostapd/1.1/IHostapd.hal
index 4e59ffc..c144f6a 100644
--- a/wifi/hostapd/1.1/IHostapd.hal
+++ b/wifi/hostapd/1.1/IHostapd.hal
@@ -26,6 +26,64 @@
  */
 interface IHostapd extends @1.0::IHostapd {
     /**
+     * Parameters to specify the channel range for ACS.
+     */
+    struct AcsChannelRange {
+        /**
+         * Channel number (IEEE 802.11) at the start of the range.
+         */
+        uint32_t start;
+        /**
+         * Channel number (IEEE 802.11) at the end of the range.
+         */
+        uint32_t end;
+    };
+
+    /**
+     * Parameters to control the channel selection for the interface.
+     */
+    struct ChannelParams {
+        /**
+         * This option can be used to specify the channels selected by ACS.
+         * If this is an empty list, all channels allowed in selected HW mode
+         * are specified implicitly.
+         * Note: channels may be overridden by firmware.
+         * Note: this option is ignored if ACS is disabled.
+         */
+        vec<AcsChannelRange> acsChannelRanges;
+    };
+
+    /**
+     * Parameters to use for setting up the access point interface.
+     */
+    struct IfaceParams {
+        /**
+         * Baseline information as defined in HAL 1.0.
+         */
+        @1.0::IHostapd.IfaceParams V1_0;
+        /** Additional Channel params for the interface */
+        ChannelParams channelParams;
+    };
+
+    /**
+     * Adds a new access point for hostapd to control.
+     *
+     * This should trigger the setup of an access point with the specified
+     * interface and network params.
+     *
+     * @param ifaceParams AccessPoint Params for the access point.
+     * @param nwParams Network Params for the access point.
+     * @return status Status of the operation.
+     *         Possible status codes:
+     *         |HostapdStatusCode.SUCCESS|,
+     *         |HostapdStatusCode.FAILURE_ARGS_INVALID|,
+     *         |HostapdStatusCode.FAILURE_UNKNOWN|,
+     *         |HostapdStatusCode.FAILURE_IFACE_EXISTS|
+     */
+    addAccessPoint_1_1(IfaceParams ifaceParams, NetworkParams nwParams)
+        generates(HostapdStatus status);
+
+    /**
      * Register for callbacks from the hostapd service.
      *
      * These callbacks are invoked for global events that are not specific
diff --git a/wifi/supplicant/1.2/ISupplicantStaNetwork.hal b/wifi/supplicant/1.2/ISupplicantStaNetwork.hal
index 6c356a4..7c3da6f 100644
--- a/wifi/supplicant/1.2/ISupplicantStaNetwork.hal
+++ b/wifi/supplicant/1.2/ISupplicantStaNetwork.hal
@@ -28,6 +28,12 @@
 interface ISupplicantStaNetwork extends @1.1::ISupplicantStaNetwork {
     /** Possble mask of values for KeyMgmt param. */
     enum KeyMgmtMask : @1.0::ISupplicantStaNetwork.KeyMgmtMask {
+        /** WPA using EAP authentication with stronger SHA256-based algorithms */
+        WPA_EAP_SHA256 = 1 << 7,
+
+        /** WPA pre-shared key with stronger SHA256-based algorithms */
+        WPA_PSK_SHA256 = 1 << 8,
+
         /** WPA3-Personal SAE Key management */
         SAE = 1 << 10,
 
diff --git a/wifi/supplicant/1.2/types.hal b/wifi/supplicant/1.2/types.hal
index 576b4f5..eaf2546 100644
--- a/wifi/supplicant/1.2/types.hal
+++ b/wifi/supplicant/1.2/types.hal
@@ -60,4 +60,5 @@
     BUSY,
     TIMEOUT,
     FAILURE,
+    NOT_SUPPORTED,
 };
diff --git a/wifi/supplicant/1.2/vts/OWNERS b/wifi/supplicant/1.2/vts/OWNERS
new file mode 100644
index 0000000..8bfb148
--- /dev/null
+++ b/wifi/supplicant/1.2/vts/OWNERS
@@ -0,0 +1,2 @@
+rpius@google.com
+etancohen@google.com
diff --git a/wifi/supplicant/1.2/vts/functional/Android.bp b/wifi/supplicant/1.2/vts/functional/Android.bp
new file mode 100644
index 0000000..1b970e1
--- /dev/null
+++ b/wifi/supplicant/1.2/vts/functional/Android.bp
@@ -0,0 +1,88 @@
+//
+// Copyright (C) 2019 The Android Open Source Project
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+//      http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//
+
+cc_library_static {
+    name: "VtsHalWifiSupplicantV1_2TargetTestUtil",
+    defaults: ["VtsHalTargetTestDefaults"],
+    srcs: ["supplicant_hidl_test_utils_1_2.cpp"],
+    export_include_dirs: [
+        "."
+    ],
+    static_libs: [
+        "VtsHalWifiV1_0TargetTestUtil",
+        "VtsHalWifiSupplicantV1_0TargetTestUtil",
+        "VtsHalWifiSupplicantV1_1TargetTestUtil",
+        "android.hardware.wifi.supplicant@1.0",
+        "android.hardware.wifi.supplicant@1.1",
+        "android.hardware.wifi.supplicant@1.2",
+        "android.hardware.wifi@1.0",
+        "libcrypto",
+        "libgmock",
+        "libwifi-system",
+        "libwifi-system-iface",
+    ],
+}
+
+cc_test {
+    name: "VtsHalWifiSupplicantV1_2TargetTest",
+    defaults: ["VtsHalTargetTestDefaults"],
+    srcs: [
+        "VtsHalWifiSupplicantV1_2TargetTest.cpp",
+        "supplicant_sta_iface_hidl_test.cpp",
+        "supplicant_sta_network_hidl_test.cpp",
+    ],
+    static_libs: [
+        "VtsHalWifiV1_0TargetTestUtil",
+        "VtsHalWifiSupplicantV1_0TargetTestUtil",
+        "VtsHalWifiSupplicantV1_1TargetTestUtil",
+        "VtsHalWifiSupplicantV1_2TargetTestUtil",
+        "android.hardware.wifi.supplicant@1.0",
+        "android.hardware.wifi.supplicant@1.1",
+        "android.hardware.wifi.supplicant@1.2",
+        "android.hardware.wifi@1.0",
+        "android.hardware.wifi@1.1",
+        "libcrypto",
+        "libgmock",
+        "libwifi-system",
+        "libwifi-system-iface",
+    ],
+    test_suites: ["general-tests"],
+}
+
+cc_test {
+    name: "VtsHalWifiSupplicantP2pV1_2TargetTest",
+    defaults: ["VtsHalTargetTestDefaults"],
+    srcs: [
+        "VtsHalWifiSupplicantV1_2TargetTest.cpp",
+        "supplicant_p2p_iface_hidl_test.cpp",
+    ],
+    static_libs: [
+        "VtsHalWifiV1_0TargetTestUtil",
+        "VtsHalWifiSupplicantV1_0TargetTestUtil",
+        "VtsHalWifiSupplicantV1_1TargetTestUtil",
+        "VtsHalWifiSupplicantV1_2TargetTestUtil",
+        "android.hardware.wifi.supplicant@1.0",
+        "android.hardware.wifi.supplicant@1.1",
+        "android.hardware.wifi.supplicant@1.2",
+        "android.hardware.wifi@1.0",
+        "android.hardware.wifi@1.1",
+        "libcrypto",
+        "libgmock",
+        "libwifi-system",
+        "libwifi-system-iface",
+    ],
+}
+
diff --git a/wifi/supplicant/1.2/vts/functional/VtsHalWifiSupplicantV1_2TargetTest.cpp b/wifi/supplicant/1.2/vts/functional/VtsHalWifiSupplicantV1_2TargetTest.cpp
new file mode 100644
index 0000000..267fa67
--- /dev/null
+++ b/wifi/supplicant/1.2/vts/functional/VtsHalWifiSupplicantV1_2TargetTest.cpp
@@ -0,0 +1,60 @@
+/*
+ * Copyright (C) 2019 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include <android-base/logging.h>
+#include <android/hardware/wifi/1.1/IWifi.h>
+#include <android/hardware/wifi/supplicant/1.2/ISupplicant.h>
+
+#include "supplicant_hidl_test_utils.h"
+#include "wifi_hidl_test_utils.h"
+
+class WifiSupplicantHidlEnvironment_1_2 : public WifiSupplicantHidlEnvironment {
+   public:
+    // get the test environment singleton
+    static WifiSupplicantHidlEnvironment_1_2* Instance() {
+        static WifiSupplicantHidlEnvironment_1_2* instance =
+            new WifiSupplicantHidlEnvironment_1_2;
+        return instance;
+    }
+    virtual void registerTestServices() override {
+        registerTestService<::android::hardware::wifi::V1_0::IWifi>();
+        registerTestService<::android::hardware::wifi::V1_1::IWifi>();
+        registerTestService<
+            ::android::hardware::wifi::supplicant::V1_0::ISupplicant>();
+        registerTestService<
+            ::android::hardware::wifi::supplicant::V1_1::ISupplicant>();
+        registerTestService<
+            ::android::hardware::wifi::supplicant::V1_2::ISupplicant>();
+    }
+
+   private:
+    WifiSupplicantHidlEnvironment_1_2() {}
+};
+
+WifiSupplicantHidlEnvironment* gEnv =
+    WifiSupplicantHidlEnvironment_1_2::Instance();
+
+int main(int argc, char** argv) {
+    ::testing::AddGlobalTestEnvironment(gEnv);
+    ::testing::InitGoogleTest(&argc, argv);
+    gEnv->init(&argc, argv);
+    int status = gEnv->initFromOptions(argc, argv);
+    if (status == 0) {
+        int status = RUN_ALL_TESTS();
+        LOG(INFO) << "Test result = " << status;
+    }
+    return status;
+}
diff --git a/wifi/supplicant/1.2/vts/functional/supplicant_hidl_test_utils_1_2.cpp b/wifi/supplicant/1.2/vts/functional/supplicant_hidl_test_utils_1_2.cpp
new file mode 100644
index 0000000..f270bff
--- /dev/null
+++ b/wifi/supplicant/1.2/vts/functional/supplicant_hidl_test_utils_1_2.cpp
@@ -0,0 +1,43 @@
+/*
+ * Copyright (C) 2019 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include <VtsHalHidlTargetTestBase.h>
+#include <android-base/logging.h>
+
+#include "supplicant_hidl_test_utils.h"
+#include "supplicant_hidl_test_utils_1_2.h"
+
+using ::android::sp;
+using ::android::hardware::wifi::supplicant::V1_2::ISupplicant;
+using ::android::hardware::wifi::supplicant::V1_2::ISupplicantP2pIface;
+using ::android::hardware::wifi::supplicant::V1_2::ISupplicantStaIface;
+using ::android::hardware::wifi::supplicant::V1_2::ISupplicantStaNetwork;
+
+sp<ISupplicant> getSupplicant_1_2() {
+    return ISupplicant::castFrom(getSupplicant());
+}
+
+sp<ISupplicantStaIface> getSupplicantStaIface_1_2() {
+    return ISupplicantStaIface::castFrom(getSupplicantStaIface());
+}
+
+sp<ISupplicantStaNetwork> createSupplicantStaNetwork_1_2() {
+    return ISupplicantStaNetwork::castFrom(createSupplicantStaNetwork());
+}
+
+sp<ISupplicantP2pIface> getSupplicantP2pIface_1_2() {
+    return ISupplicantP2pIface::castFrom(getSupplicantP2pIface());
+}
diff --git a/wifi/supplicant/1.2/vts/functional/supplicant_hidl_test_utils_1_2.h b/wifi/supplicant/1.2/vts/functional/supplicant_hidl_test_utils_1_2.h
new file mode 100644
index 0000000..8a7ccc5
--- /dev/null
+++ b/wifi/supplicant/1.2/vts/functional/supplicant_hidl_test_utils_1_2.h
@@ -0,0 +1,37 @@
+/*
+ * Copyright (C) 2019 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef SUPPLICANT_HIDL_TEST_UTILS_1_2_H
+#define SUPPLICANT_HIDL_TEST_UTILS_1_2_H
+
+#include <android/hardware/wifi/supplicant/1.2/ISupplicant.h>
+#include <android/hardware/wifi/supplicant/1.2/ISupplicantP2pIface.h>
+#include <android/hardware/wifi/supplicant/1.2/ISupplicantStaIface.h>
+#include <android/hardware/wifi/supplicant/1.2/ISupplicantStaNetwork.h>
+
+android::sp<android::hardware::wifi::supplicant::V1_2::ISupplicant>
+getSupplicant_1_2();
+
+android::sp<android::hardware::wifi::supplicant::V1_2::ISupplicantStaIface>
+getSupplicantStaIface_1_2();
+
+android::sp<android::hardware::wifi::supplicant::V1_2::ISupplicantStaNetwork>
+createSupplicantStaNetwork_1_2();
+
+android::sp<android::hardware::wifi::supplicant::V1_2::ISupplicantP2pIface>
+getSupplicantP2pIface_1_2();
+
+#endif /* SUPPLICANT_HIDL_TEST_UTILS_1_2_H */
diff --git a/wifi/supplicant/1.2/vts/functional/supplicant_p2p_iface_hidl_test.cpp b/wifi/supplicant/1.2/vts/functional/supplicant_p2p_iface_hidl_test.cpp
new file mode 100644
index 0000000..46b4087
--- /dev/null
+++ b/wifi/supplicant/1.2/vts/functional/supplicant_p2p_iface_hidl_test.cpp
@@ -0,0 +1,128 @@
+/*
+ * Copyright (C) 2019 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include <android-base/logging.h>
+
+#include <VtsHalHidlTargetTestBase.h>
+
+#include <android/hardware/wifi/supplicant/1.2/ISupplicantP2pIface.h>
+
+#include "supplicant_hidl_test_utils.h"
+#include "supplicant_hidl_test_utils_1_2.h"
+
+using ::android::sp;
+using ::android::hardware::wifi::supplicant::V1_0::SupplicantStatus;
+using ::android::hardware::wifi::supplicant::V1_0::SupplicantStatusCode;
+using ::android::hardware::wifi::supplicant::V1_2::ISupplicantP2pIface;
+
+namespace {
+constexpr uint8_t kTestSsid[] = {'D', 'I', 'R', 'E', 'C', 'T', '-', 'x',
+                                 'y', '-', 'H', 'E', 'L', 'L', 'O'};
+constexpr char kTestPassphrase[] = "P2pWorld1234";
+constexpr uint8_t kTestZeroMacAddr[] = {[0 ... 5] = 0x0};
+}  // namespace
+
+class SupplicantP2pIfaceHidlTest : public ::testing::VtsHalHidlTargetTestBase {
+   public:
+    virtual void SetUp() override {
+        startSupplicantAndWaitForHidlService();
+        EXPECT_TRUE(turnOnExcessiveLogging());
+        p2p_iface_ = getSupplicantP2pIface_1_2();
+        ASSERT_NE(p2p_iface_.get(), nullptr);
+    }
+
+    virtual void TearDown() override { stopSupplicant(); }
+
+   protected:
+    // ISupplicantP2pIface object used for all tests in this fixture.
+    sp<ISupplicantP2pIface> p2p_iface_;
+};
+
+/*
+ * Verify that AddGroup_1_2 could create a group successfully.
+ */
+TEST_F(SupplicantP2pIfaceHidlTest, AddGroup_1_2_Success) {
+    std::vector<uint8_t> ssid(kTestSsid, kTestSsid + sizeof(kTestSsid));
+    std::string passphrase = kTestPassphrase;
+    int freq = 5;
+    std::array<uint8_t, 6> zero_mac_addr;
+    memcpy(zero_mac_addr.data(), kTestZeroMacAddr, zero_mac_addr.size());
+    bool persistent = false;
+    int is_join = false;
+
+    p2p_iface_->addGroup_1_2(ssid, passphrase, persistent, freq, zero_mac_addr,
+                             is_join, [](const SupplicantStatus& status) {
+                                 EXPECT_EQ(SupplicantStatusCode::SUCCESS,
+                                           status.code);
+                             });
+}
+
+/*
+ * Verify that AddGroup_1_2 fails due to invalid SSID.
+ */
+TEST_F(SupplicantP2pIfaceHidlTest, AddGroup_1_2_FailureInvalidSsid) {
+    std::vector<uint8_t> ssid;
+    std::string passphrase = kTestPassphrase;
+    int freq = 5;
+    std::array<uint8_t, 6> zero_mac_addr;
+    memcpy(zero_mac_addr.data(), kTestZeroMacAddr, zero_mac_addr.size());
+    bool persistent = false;
+    int is_join = false;
+
+    p2p_iface_->addGroup_1_2(
+        ssid, passphrase, persistent, freq, zero_mac_addr, is_join,
+        [](const SupplicantStatus& status) {
+            EXPECT_EQ(SupplicantStatusCode::FAILURE_ARGS_INVALID, status.code);
+        });
+}
+
+/*
+ * Verify that AddGroup_1_2 fails due to invalid passphrase.
+ */
+TEST_F(SupplicantP2pIfaceHidlTest, AddGroup_1_2_FailureInvalidPassphrase) {
+    std::vector<uint8_t> ssid(kTestSsid, kTestSsid + sizeof(kTestSsid));
+    std::string passphrase = "1234";
+    int freq = 5;
+    std::array<uint8_t, 6> zero_mac_addr;
+    memcpy(zero_mac_addr.data(), kTestZeroMacAddr, zero_mac_addr.size());
+    bool persistent = false;
+    int is_join = false;
+
+    p2p_iface_->addGroup_1_2(
+        ssid, passphrase, persistent, freq, zero_mac_addr, is_join,
+        [](const SupplicantStatus& status) {
+            EXPECT_EQ(SupplicantStatusCode::FAILURE_ARGS_INVALID, status.code);
+        });
+}
+
+/*
+ * Verify that AddGroup_1_2 fails due to invalid frequency.
+ */
+TEST_F(SupplicantP2pIfaceHidlTest, AddGroup_1_2_FailureInvalidFrequency) {
+    std::vector<uint8_t> ssid(kTestSsid, kTestSsid + sizeof(kTestSsid));
+    std::string passphrase = kTestPassphrase;
+    int freq = 9999;
+    std::array<uint8_t, 6> zero_mac_addr;
+    memcpy(zero_mac_addr.data(), kTestZeroMacAddr, zero_mac_addr.size());
+    bool persistent = false;
+    int is_join = false;
+
+    p2p_iface_->addGroup_1_2(
+        ssid, passphrase, persistent, freq, zero_mac_addr, is_join,
+        [](const SupplicantStatus& status) {
+            EXPECT_EQ(SupplicantStatusCode::FAILURE_UNKNOWN, status.code);
+        });
+}
diff --git a/wifi/supplicant/1.2/vts/functional/supplicant_sta_iface_hidl_test.cpp b/wifi/supplicant/1.2/vts/functional/supplicant_sta_iface_hidl_test.cpp
new file mode 100644
index 0000000..4425281
--- /dev/null
+++ b/wifi/supplicant/1.2/vts/functional/supplicant_sta_iface_hidl_test.cpp
@@ -0,0 +1,418 @@
+/*
+ * Copyright (C) 2019 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include <VtsHalHidlTargetTestBase.h>
+#include <android/hardware/wifi/supplicant/1.0/ISupplicantStaIfaceCallback.h>
+#include <android/hardware/wifi/supplicant/1.0/types.h>
+#include <android/hardware/wifi/supplicant/1.1/ISupplicantStaIfaceCallback.h>
+#include <android/hardware/wifi/supplicant/1.2/ISupplicantStaIface.h>
+#include <android/hardware/wifi/supplicant/1.2/ISupplicantStaIfaceCallback.h>
+#include <android/hardware/wifi/supplicant/1.2/ISupplicantStaNetwork.h>
+#include <android/hardware/wifi/supplicant/1.2/types.h>
+#include <hidl/HidlSupport.h>
+#include <hidl/Status.h>
+
+#include "supplicant_hidl_test_utils.h"
+#include "supplicant_hidl_test_utils_1_2.h"
+
+using ::android::sp;
+using ::android::hardware::hidl_array;
+using ::android::hardware::hidl_string;
+using ::android::hardware::hidl_vec;
+using ::android::hardware::Return;
+using ::android::hardware::Void;
+using ::android::hardware::wifi::supplicant::V1_0::SupplicantStatus;
+using ::android::hardware::wifi::supplicant::V1_0::SupplicantStatusCode;
+using ::android::hardware::wifi::supplicant::V1_2::DppAkm;
+using ::android::hardware::wifi::supplicant::V1_2::DppFailureCode;
+using ::android::hardware::wifi::supplicant::V1_2::DppNetRole;
+using ::android::hardware::wifi::supplicant::V1_2::DppProgressCode;
+using ::android::hardware::wifi::supplicant::V1_2::DppSuccessCode;
+using ::android::hardware::wifi::supplicant::V1_2::ISupplicantStaIface;
+using ::android::hardware::wifi::supplicant::V1_2::ISupplicantStaIfaceCallback;
+using ::android::hardware::wifi::supplicant::V1_2::ISupplicantStaNetwork;
+
+#define TIMEOUT_PERIOD 60
+class IfaceDppCallback;
+
+class SupplicantStaIfaceHidlTest : public ::testing::VtsHalHidlTargetTestBase {
+   public:
+    virtual void SetUp() override {
+        startSupplicantAndWaitForHidlService();
+        EXPECT_TRUE(turnOnExcessiveLogging());
+        sta_iface_ = getSupplicantStaIface_1_2();
+        ASSERT_NE(sta_iface_.get(), nullptr);
+        count_ = 0;
+    }
+
+    virtual void TearDown() override { stopSupplicant(); }
+
+    enum DppCallbackType {
+        ANY_CALLBACK = -2,
+        INVALID = -1,
+
+        EVENT_SUCCESS = 0,
+        EVENT_SUCCESS_CONFIG_RECEIVED,
+        EVENT_PROGRESS,
+        EVENT_FAILURE,
+    };
+
+    DppCallbackType dppCallbackType;
+    uint32_t code;
+
+    /* Used as a mechanism to inform the test about data/event callback */
+    inline void notify() {
+        std::unique_lock<std::mutex> lock(mtx_);
+        count_++;
+        cv_.notify_one();
+    }
+
+    /* Test code calls this function to wait for data/event callback */
+    inline std::cv_status wait(DppCallbackType waitForCallbackType) {
+        std::unique_lock<std::mutex> lock(mtx_);
+        EXPECT_NE(INVALID, waitForCallbackType);  // can't ASSERT in a
+                                                  // non-void-returning method
+        auto now = std::chrono::system_clock::now();
+        std::cv_status status =
+            cv_.wait_until(lock, now + std::chrono::seconds(TIMEOUT_PERIOD));
+        return status;
+    }
+
+   private:
+    // synchronization objects
+    std::mutex mtx_;
+    std::condition_variable cv_;
+    int count_;
+
+   protected:
+    // ISupplicantStaIface object used for all tests in this fixture.
+    sp<ISupplicantStaIface> sta_iface_;
+    bool isDppSupported() {
+        uint32_t keyMgmtMask = 0;
+
+        // We need to first get the key management capabilities from the device.
+        // If DPP is not supported, we just pass the test.
+        sta_iface_->getKeyMgmtCapabilities(
+            [&](const SupplicantStatus& status, uint32_t keyMgmtMaskInternal) {
+                EXPECT_EQ(SupplicantStatusCode::SUCCESS, status.code);
+
+                keyMgmtMask = keyMgmtMaskInternal;
+            });
+
+        if (!(keyMgmtMask & ISupplicantStaNetwork::KeyMgmtMask::DPP)) {
+            // DPP not supported
+            return false;
+        }
+
+        return true;
+    }
+};
+
+class IfaceCallback : public ISupplicantStaIfaceCallback {
+    Return<void> onNetworkAdded(uint32_t /* id */) override { return Void(); }
+    Return<void> onNetworkRemoved(uint32_t /* id */) override { return Void(); }
+    Return<void> onStateChanged(
+        ISupplicantStaIfaceCallback::State /* newState */,
+        const hidl_array<uint8_t, 6>& /*bssid */, uint32_t /* id */,
+        const hidl_vec<uint8_t>& /* ssid */) override {
+        return Void();
+    }
+    Return<void> onAnqpQueryDone(
+        const hidl_array<uint8_t, 6>& /* bssid */,
+        const ISupplicantStaIfaceCallback::AnqpData& /* data */,
+        const ISupplicantStaIfaceCallback::Hs20AnqpData& /* hs20Data */)
+        override {
+        return Void();
+    }
+    virtual Return<void> onHs20IconQueryDone(
+        const hidl_array<uint8_t, 6>& /* bssid */,
+        const hidl_string& /* fileName */,
+        const hidl_vec<uint8_t>& /* data */) override {
+        return Void();
+    }
+    virtual Return<void> onHs20SubscriptionRemediation(
+        const hidl_array<uint8_t, 6>& /* bssid */,
+        ISupplicantStaIfaceCallback::OsuMethod /* osuMethod */,
+        const hidl_string& /* url*/) override {
+        return Void();
+    }
+    Return<void> onHs20DeauthImminentNotice(
+        const hidl_array<uint8_t, 6>& /* bssid */, uint32_t /* reasonCode */,
+        uint32_t /* reAuthDelayInSec */,
+        const hidl_string& /* url */) override {
+        return Void();
+    }
+    Return<void> onDisconnected(const hidl_array<uint8_t, 6>& /* bssid */,
+                                bool /* locallyGenerated */,
+                                ISupplicantStaIfaceCallback::ReasonCode
+                                /* reasonCode */) override {
+        return Void();
+    }
+    Return<void> onAssociationRejected(
+        const hidl_array<uint8_t, 6>& /* bssid */,
+        ISupplicantStaIfaceCallback::StatusCode /* statusCode */,
+        bool /*timedOut */) override {
+        return Void();
+    }
+    Return<void> onAuthenticationTimeout(
+        const hidl_array<uint8_t, 6>& /* bssid */) override {
+        return Void();
+    }
+    Return<void> onBssidChanged(
+        ISupplicantStaIfaceCallback::BssidChangeReason /* reason */,
+        const hidl_array<uint8_t, 6>& /* bssid */) override {
+        return Void();
+    }
+    Return<void> onEapFailure() override { return Void(); }
+    Return<void> onEapFailure_1_1(
+        ISupplicantStaIfaceCallback::EapErrorCode /* eapErrorCode */) override {
+        return Void();
+    }
+    Return<void> onWpsEventSuccess() override { return Void(); }
+    Return<void> onWpsEventFail(
+        const hidl_array<uint8_t, 6>& /* bssid */,
+        ISupplicantStaIfaceCallback::WpsConfigError /* configError */,
+        ISupplicantStaIfaceCallback::WpsErrorIndication /* errorInd */)
+        override {
+        return Void();
+    }
+    Return<void> onWpsEventPbcOverlap() override { return Void(); }
+    Return<void> onExtRadioWorkStart(uint32_t /* id */) override {
+        return Void();
+    }
+    Return<void> onExtRadioWorkTimeout(uint32_t /* id*/) override {
+        return Void();
+    }
+    Return<void> onDppSuccessConfigReceived(
+        const hidl_vec<uint8_t>& /* ssid */, const hidl_string& /* password */,
+        const hidl_array<uint8_t, 32>& /* psk */,
+        DppAkm /* securityAkm */) override {
+        return Void();
+    }
+    Return<void> onDppSuccess(DppSuccessCode /* code */) override {
+        return Void();
+    }
+    Return<void> onDppProgress(DppProgressCode /* code */) override {
+        return Void();
+    }
+    Return<void> onDppFailure(DppFailureCode /* code */) override {
+        return Void();
+    }
+};
+
+class IfaceDppCallback : public IfaceCallback {
+    SupplicantStaIfaceHidlTest& parent_;
+
+    Return<void> onDppSuccessConfigReceived(
+        const hidl_vec<uint8_t>& /* ssid */, const hidl_string& /* password */,
+        const hidl_array<uint8_t, 32>& /* psk */,
+        DppAkm /* securityAkm */) override {
+        parent_.code = 0;
+        parent_.dppCallbackType = SupplicantStaIfaceHidlTest::DppCallbackType::
+            EVENT_SUCCESS_CONFIG_RECEIVED;
+        parent_.notify();
+        return Void();
+    }
+    Return<void> onDppSuccess(DppSuccessCode code) override {
+        parent_.code = (uint32_t)code;
+        parent_.dppCallbackType =
+            SupplicantStaIfaceHidlTest::DppCallbackType::EVENT_SUCCESS;
+        parent_.notify();
+        return Void();
+    }
+    Return<void> onDppProgress(DppProgressCode code) override {
+        parent_.code = (uint32_t)code;
+        parent_.dppCallbackType =
+            SupplicantStaIfaceHidlTest::DppCallbackType::EVENT_PROGRESS;
+        parent_.notify();
+        return Void();
+    }
+    Return<void> onDppFailure(DppFailureCode code) override {
+        parent_.code = (uint32_t)code;
+        parent_.dppCallbackType =
+            SupplicantStaIfaceHidlTest::DppCallbackType::EVENT_FAILURE;
+        parent_.notify();
+        return Void();
+    }
+
+   public:
+    IfaceDppCallback(SupplicantStaIfaceHidlTest& parent) : parent_(parent){};
+};
+
+/*
+ * RegisterCallback_1_2
+ */
+TEST_F(SupplicantStaIfaceHidlTest, RegisterCallback_1_2) {
+    sta_iface_->registerCallback_1_2(
+        new IfaceCallback(), [](const SupplicantStatus& status) {
+            EXPECT_EQ(SupplicantStatusCode::SUCCESS, status.code);
+        });
+}
+
+/*
+ * GetKeyMgmtCapabilities
+ */
+TEST_F(SupplicantStaIfaceHidlTest, GetKeyMgmtCapabilities) {
+    sta_iface_->getKeyMgmtCapabilities(
+        [&](const SupplicantStatus& status, uint32_t keyMgmtMask) {
+            EXPECT_EQ(SupplicantStatusCode::SUCCESS, status.code);
+
+            // Even though capabilities vary, these two are always set in HAL
+            // v1.2
+            EXPECT_TRUE(keyMgmtMask & ISupplicantStaNetwork::KeyMgmtMask::NONE);
+            EXPECT_TRUE(keyMgmtMask &
+                        ISupplicantStaNetwork::KeyMgmtMask::IEEE8021X);
+        });
+}
+
+/*
+ * AddDppPeerUriAndRomveUri
+ */
+TEST_F(SupplicantStaIfaceHidlTest, AddDppPeerUriAndRomveUri) {
+    // We need to first get the key management capabilities from the device.
+    // If DPP is not supported, we just pass the test.
+    if (!isDppSupported()) {
+        // DPP not supported
+        return;
+    }
+
+    hidl_string uri =
+        "DPP:C:81/1;M:48d6d5bd1de1;I:G1197843;K:MDkwEwYHKoZIzj0CAQYIKoZIzj"
+        "0DAQcDIgAD0edY4X3N//HhMFYsZfMbQJTiNFtNIWF/cIwMB/gzqOM=;;";
+    uint32_t peer_id = 0;
+
+    // Add a peer URI
+    sta_iface_->addDppPeerUri(
+        uri, [&](const SupplicantStatus& status, uint32_t id) {
+            EXPECT_EQ(SupplicantStatusCode::SUCCESS, status.code);
+            EXPECT_NE(0, id);
+            EXPECT_NE(-1, id);
+
+            peer_id = id;
+        });
+
+    // ...and then remove it.
+    sta_iface_->removeDppUri(peer_id, [&](const SupplicantStatus& status) {
+        EXPECT_EQ(SupplicantStatusCode::SUCCESS, status.code);
+    });
+}
+
+/*
+ * StartDppEnrolleeInitiator
+ */
+TEST_F(SupplicantStaIfaceHidlTest, StartDppEnrolleeInitiator) {
+    // We need to first get the key management capabilities from the device.
+    // If DPP is not supported, we just pass the test.
+    if (!isDppSupported()) {
+        // DPP not supported
+        return;
+    }
+
+    hidl_string uri =
+        "DPP:C:81/1;M:48d6d5bd1de1;I:G1197843;K:MDkwEwYHKoZIzj0CAQYIKoZIzj"
+        "0DAQcDIgAD0edY4X3N//HhMFYsZfMbQJTiNFtNIWF/cIwMB/gzqOM=;;";
+    uint32_t peer_id = 0;
+
+    // Register callbacks
+    sta_iface_->registerCallback_1_2(
+        new IfaceDppCallback(*this), [](const SupplicantStatus& status) {
+            EXPECT_EQ(SupplicantStatusCode::SUCCESS, status.code);
+        });
+
+    // Add a peer URI
+    sta_iface_->addDppPeerUri(
+        uri, [&](const SupplicantStatus& status, uint32_t id) {
+            EXPECT_EQ(SupplicantStatusCode::SUCCESS, status.code);
+            EXPECT_NE(0, id);
+            EXPECT_NE(-1, id);
+
+            peer_id = id;
+        });
+
+    // Start DPP as Enrollee-Initiator. Since this operation requires two
+    // devices, we start the operation and expect a timeout.
+    sta_iface_->startDppEnrolleeInitiator(
+        peer_id, 0, [&](const SupplicantStatus& status) {
+            EXPECT_EQ(SupplicantStatusCode::SUCCESS, status.code);
+        });
+
+    // Wait for the timeout callback
+    ASSERT_EQ(std::cv_status::no_timeout,
+              wait(SupplicantStaIfaceHidlTest::DppCallbackType::EVENT_FAILURE));
+    ASSERT_EQ(SupplicantStaIfaceHidlTest::DppCallbackType::EVENT_FAILURE,
+              dppCallbackType);
+
+    // ...and then remove the peer URI.
+    sta_iface_->removeDppUri(peer_id, [&](const SupplicantStatus& status) {
+        EXPECT_EQ(SupplicantStatusCode::SUCCESS, status.code);
+    });
+}
+
+/*
+ * StartDppConfiguratorInitiator
+ */
+TEST_F(SupplicantStaIfaceHidlTest, StartDppConfiguratorInitiator) {
+    // We need to first get the key management capabilities from the device.
+    // If DPP is not supported, we just pass the test.
+    if (!isDppSupported()) {
+        // DPP not supported
+        return;
+    }
+
+    hidl_string uri =
+        "DPP:C:81/1;M:48d6d5bd1de1;I:G1197843;K:MDkwEwYHKoZIzj0CAQYIKoZIzj"
+        "0DAQcDIgAD0edY4X3N//HhMFYsZfMbQJTiNFtNIWF/cIwMB/gzqOM=;;";
+    uint32_t peer_id = 0;
+
+    // Register callbacks
+    sta_iface_->registerCallback_1_2(
+        new IfaceDppCallback(*this), [](const SupplicantStatus& status) {
+            EXPECT_EQ(SupplicantStatusCode::SUCCESS, status.code);
+        });
+
+    // Add a peer URI
+    sta_iface_->addDppPeerUri(
+        uri, [&](const SupplicantStatus& status, uint32_t id) {
+            EXPECT_EQ(SupplicantStatusCode::SUCCESS, status.code);
+            EXPECT_NE(0, id);
+            EXPECT_NE(-1, id);
+
+            peer_id = id;
+        });
+
+    std::string ssid =
+        "6D795F746573745F73736964";  // 'my_test_ssid' encoded in hex
+    std::string password = "746F70736563726574";  // 'topsecret' encoded in hex
+
+    // Start DPP as Configurator-Initiator. Since this operation requires two
+    // devices, we start the operation and expect a timeout.
+    sta_iface_->startDppConfiguratorInitiator(
+        peer_id, 0, ssid, password, NULL, DppNetRole::STA, DppAkm::PSK,
+        [&](const SupplicantStatus& status) {
+            EXPECT_EQ(SupplicantStatusCode::SUCCESS, status.code);
+        });
+
+    // Wait for the timeout callback
+    ASSERT_EQ(std::cv_status::no_timeout,
+              wait(SupplicantStaIfaceHidlTest::DppCallbackType::EVENT_FAILURE));
+    ASSERT_EQ(SupplicantStaIfaceHidlTest::DppCallbackType::EVENT_FAILURE,
+              dppCallbackType);
+
+    // ...and then remove the peer URI.
+    sta_iface_->removeDppUri(peer_id, [&](const SupplicantStatus& status) {
+        EXPECT_EQ(SupplicantStatusCode::SUCCESS, status.code);
+    });
+}
diff --git a/wifi/supplicant/1.2/vts/functional/supplicant_sta_network_hidl_test.cpp b/wifi/supplicant/1.2/vts/functional/supplicant_sta_network_hidl_test.cpp
new file mode 100644
index 0000000..ed421d7
--- /dev/null
+++ b/wifi/supplicant/1.2/vts/functional/supplicant_sta_network_hidl_test.cpp
@@ -0,0 +1,192 @@
+/*
+ * Copyright (C) 2019 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include <android-base/logging.h>
+
+#include <VtsHalHidlTargetTestBase.h>
+#include <android/hardware/wifi/supplicant/1.1/ISupplicantStaNetwork.h>
+
+#include "supplicant_hidl_test_utils.h"
+#include "supplicant_hidl_test_utils_1_2.h"
+
+using ::android::sp;
+using ::android::hardware::hidl_vec;
+using ::android::hardware::wifi::supplicant::V1_0::SupplicantStatus;
+using ::android::hardware::wifi::supplicant::V1_0::SupplicantStatusCode;
+using ::android::hardware::wifi::supplicant::V1_2::ISupplicantStaNetwork;
+// namespace {
+// constexpr uint8_t kTestIdentity[] = {0x45, 0x67, 0x98, 0x67, 0x56};
+// constexpr uint8_t kTestEncryptedIdentity[] = {0x35, 0x37, 0x58, 0x57, 0x26};
+//}  // namespace
+
+class SupplicantStaNetworkHidlTest
+    : public ::testing::VtsHalHidlTargetTestBase {
+   public:
+    virtual void SetUp() override {
+        startSupplicantAndWaitForHidlService();
+        EXPECT_TRUE(turnOnExcessiveLogging());
+        sta_network_ = createSupplicantStaNetwork_1_2();
+        ASSERT_NE(sta_network_.get(), nullptr);
+    }
+
+    virtual void TearDown() override { stopSupplicant(); }
+
+   protected:
+    // ISupplicantStaNetwork object used for all tests in this fixture.
+    sp<ISupplicantStaNetwork> sta_network_;
+};
+
+/*
+ * SetGetSaePassword
+ */
+TEST_F(SupplicantStaNetworkHidlTest, SetGetSaePassword) {
+    std::string password = "topsecret";
+
+    sta_network_->setSaePassword(password, [](const SupplicantStatus &status) {
+        EXPECT_EQ(SupplicantStatusCode::SUCCESS, status.code);
+    });
+
+    sta_network_->getSaePassword(
+        [&password](const SupplicantStatus &status, std::string passwordOut) {
+            EXPECT_EQ(SupplicantStatusCode::SUCCESS, status.code);
+            EXPECT_EQ(passwordOut.compare(password), 0);
+        });
+}
+
+/*
+ * SetGetSaePasswordId
+ */
+TEST_F(SupplicantStaNetworkHidlTest, SetGetSaePasswordId) {
+    std::string passwordId = "id1";
+
+    sta_network_->setSaePasswordId(
+        passwordId, [](const SupplicantStatus &status) {
+            EXPECT_EQ(SupplicantStatusCode::SUCCESS, status.code);
+        });
+
+    sta_network_->getSaePasswordId([&passwordId](const SupplicantStatus &status,
+                                                 std::string passwordIdOut) {
+        EXPECT_EQ(SupplicantStatusCode::SUCCESS, status.code);
+        EXPECT_EQ(passwordIdOut.compare(passwordId), 0);
+    });
+}
+
+/*
+ * SetGetGroupMgmtCipher
+ */
+TEST_F(SupplicantStaNetworkHidlTest, SetGetGroupMgmtCipher) {
+    uint32_t groupMgmtCipher =
+        (uint32_t)ISupplicantStaNetwork::GroupMgmtCipherMask::BIP_GMAC_256;
+
+    sta_network_->setGroupMgmtCipher(
+        groupMgmtCipher, [](const SupplicantStatus &status) {
+            EXPECT_EQ(SupplicantStatusCode::SUCCESS, status.code);
+        });
+
+    sta_network_->getGroupMgmtCipher(
+        [&groupMgmtCipher](const SupplicantStatus &status,
+                           uint32_t groupMgmtCipherOut) {
+            EXPECT_EQ(SupplicantStatusCode::SUCCESS, status.code);
+            EXPECT_EQ(groupMgmtCipherOut, groupMgmtCipher);
+        });
+}
+
+/*
+ * SetGetKeyMgmt_1_2
+ */
+TEST_F(SupplicantStaNetworkHidlTest, SetGetKeyMgmt_1_2) {
+    uint32_t keyMgmt = (uint32_t)ISupplicantStaNetwork::KeyMgmtMask::SAE;
+
+    sta_network_->setKeyMgmt_1_2(keyMgmt, [](const SupplicantStatus &status) {
+        EXPECT_EQ(SupplicantStatusCode::SUCCESS, status.code);
+    });
+
+    sta_network_->getKeyMgmt_1_2(
+        [&keyMgmt](const SupplicantStatus &status, uint32_t keyMgmtOut) {
+            EXPECT_EQ(SupplicantStatusCode::SUCCESS, status.code);
+            EXPECT_EQ(keyMgmtOut, keyMgmt);
+        });
+}
+
+/*
+ * SetGetGroupCipher_1_2
+ */
+TEST_F(SupplicantStaNetworkHidlTest, SetGetGroupCipher_1_2) {
+    uint32_t groupCipher =
+        (uint32_t)ISupplicantStaNetwork::GroupCipherMask::GCMP_256;
+
+    sta_network_->setGroupCipher_1_2(
+        groupCipher, [](const SupplicantStatus &status) {
+            EXPECT_EQ(SupplicantStatusCode::SUCCESS, status.code);
+        });
+
+    sta_network_->getGroupCipher_1_2(
+        [&groupCipher](const SupplicantStatus &status,
+                       uint32_t groupCipherOut) {
+            EXPECT_EQ(SupplicantStatusCode::SUCCESS, status.code);
+            EXPECT_EQ(groupCipherOut, groupCipher);
+        });
+}
+
+/*
+ * SetGetPairwiseCipher_1_2
+ */
+TEST_F(SupplicantStaNetworkHidlTest, SetGetPairwiseCipher_1_2) {
+    uint32_t pairwiseCipher =
+        (uint32_t)ISupplicantStaNetwork::PairwiseCipherMask::GCMP_256;
+
+    sta_network_->setPairwiseCipher_1_2(
+        pairwiseCipher, [](const SupplicantStatus &status) {
+            EXPECT_EQ(SupplicantStatusCode::SUCCESS, status.code);
+        });
+
+    sta_network_->getPairwiseCipher_1_2(
+        [&pairwiseCipher](const SupplicantStatus &status,
+                          uint32_t pairwiseCipherOut) {
+            EXPECT_EQ(SupplicantStatusCode::SUCCESS, status.code);
+            EXPECT_EQ(pairwiseCipherOut, pairwiseCipher);
+        });
+}
+
+/*
+ * EnableSuiteBEapOpenSslCiphers
+ */
+TEST_F(SupplicantStaNetworkHidlTest, EnableSuiteBEapOpenSslCiphers) {
+    sta_network_->enableSuiteBEapOpenSslCiphers(
+        [](const SupplicantStatus &status) {
+            EXPECT_EQ(SupplicantStatusCode::SUCCESS, status.code);
+        });
+
+    sta_network_->enableSuiteBEapOpenSslCiphers(
+        [](const SupplicantStatus &status) {
+            EXPECT_EQ(SupplicantStatusCode::SUCCESS, status.code);
+        });
+}
+
+/*
+ * EnableTlsSuiteBEapPhase1Param
+ */
+TEST_F(SupplicantStaNetworkHidlTest, EnableTlsSuiteBEapPhase1Param) {
+    sta_network_->enableTlsSuiteBEapPhase1Param(
+        true, [](const SupplicantStatus &status) {
+            EXPECT_EQ(SupplicantStatusCode::SUCCESS, status.code);
+        });
+
+    sta_network_->enableTlsSuiteBEapPhase1Param(
+        false, [](const SupplicantStatus &status) {
+            EXPECT_EQ(SupplicantStatusCode::SUCCESS, status.code);
+        });
+}