Merge "Add HAL API for enabling DSDS setModemsConfig and getModemsConfig APIs will allow the framework to set the number of live modems to switch to single/multi sim state"
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/core/all-versions/vts/functional/Android.bp b/audio/core/all-versions/vts/functional/Android.bp
index b04adf7..6498289 100644
--- a/audio/core/all-versions/vts/functional/Android.bp
+++ b/audio/core/all-versions/vts/functional/Android.bp
@@ -22,6 +22,7 @@
         "libaudiopolicycomponents",
         "libicuuc",
         "libicuuc_stubdata",
+        "libandroidicu",
         "libmedia_helper",
         "libxml2",
     ],
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/audio/effect/all-versions/vts/functional/Android.bp b/audio/effect/all-versions/vts/functional/Android.bp
index 88d49d8..de6cad9 100644
--- a/audio/effect/all-versions/vts/functional/Android.bp
+++ b/audio/effect/all-versions/vts/functional/Android.bp
@@ -28,6 +28,7 @@
         "libeffectsconfig",
         "libicuuc",
         "libicuuc_stubdata",
+        "libandroidicu",
         "libxml2",
     ],
     header_libs: [
diff --git a/automotive/OWNERS b/automotive/OWNERS
new file mode 100644
index 0000000..4a94494
--- /dev/null
+++ b/automotive/OWNERS
@@ -0,0 +1,3 @@
+randolphs@google.com
+pirozzoj@google.com
+twasilczyk@google.com
diff --git a/automotive/vehicle/2.0/default/OWNERS b/automotive/vehicle/2.0/default/OWNERS
deleted file mode 100644
index d5d9d4c..0000000
--- a/automotive/vehicle/2.0/default/OWNERS
+++ /dev/null
@@ -1,3 +0,0 @@
-egranata@google.com
-pavelm@google.com
-spaik@google.com
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/automotive/vehicle/2.0/types.hal b/automotive/vehicle/2.0/types.hal
index 4751a76..e874146 100644
--- a/automotive/vehicle/2.0/types.hal
+++ b/automotive/vehicle/2.0/types.hal
@@ -131,6 +131,9 @@
  * When a property's status field is not set to AVAILABLE:
  *  - IVehicle#set may return StatusCode::NOT_AVAILABLE.
  *  - IVehicle#get is not guaranteed to work.
+ *
+ * Properties set to values out of range must be ignored and no action taken
+ * in response to such ill formed requests.
  */
 enum VehicleProperty : int32_t {
 
@@ -243,7 +246,7 @@
      * Fuel door location
      *
      * @change_mode VehiclePropertyChangeMode:STATIC
-     * @data_enum FuelDoorLocationType
+     * @data_enum PortLocationType
      * @access VehiclePropertyAccess:READ
      */
     INFO_FUEL_DOOR_LOCATION = (
@@ -267,6 +270,7 @@
 
     /**
      * Driver's seat location
+     * VHAL implementations must ignore the areaId. Use VehicleArea:GLOBAL.
      *
      * @change_mode VehiclePropertyChangeMode:STATIC
      * @data_enum VehicleAreaSeat
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/default/ExternalCameraDevice.cpp b/camera/device/3.4/default/ExternalCameraDevice.cpp
index b96f574..0f23657 100644
--- a/camera/device/3.4/default/ExternalCameraDevice.cpp
+++ b/camera/device/3.4/default/ExternalCameraDevice.cpp
@@ -378,8 +378,12 @@
     const uint8_t timestampSource = ANDROID_SENSOR_INFO_TIMESTAMP_SOURCE_UNKNOWN;
     UPDATE(ANDROID_SENSOR_INFO_TIMESTAMP_SOURCE, &timestampSource, 1);
 
-    // Orientation probably isn't useful for external facing camera?
-    const int32_t orientation = 0;
+    // Orientation is a bit odd for external camera, but consider it as the orientation
+    // between the external camera sensor (which is usually landscape) and the device's
+    // natural display orientation. For devices with natural landscape display (ex: tablet/TV), the
+    // orientation should be 0. For devices with natural portrait display (phone), the orientation
+    // should be 270.
+    const int32_t orientation = mCfg.orientation;
     UPDATE(ANDROID_SENSOR_ORIENTATION, &orientation, 1);
 
     // android.shading
diff --git a/camera/device/3.4/default/ExternalCameraUtils.cpp b/camera/device/3.4/default/ExternalCameraUtils.cpp
index 680c95a..0941052 100644
--- a/camera/device/3.4/default/ExternalCameraUtils.cpp
+++ b/camera/device/3.4/default/ExternalCameraUtils.cpp
@@ -160,9 +160,11 @@
 namespace common {
 
 namespace {
-    const int  kDefaultJpegBufSize = 5 << 20; // 5MB
-    const int  kDefaultNumVideoBuffer = 4;
-    const int  kDefaultNumStillBuffer = 2;
+    const int kDefaultJpegBufSize = 5 << 20; // 5MB
+    const int kDefaultNumVideoBuffer = 4;
+    const int kDefaultNumStillBuffer = 2;
+    const int kDefaultOrientation = 0; // suitable for natural landscape displays like tablet/TV
+                                       // For phone devices 270 is better
 } // anonymous namespace
 
 const char* ExternalCameraConfig::kDefaultCfgPath = "/vendor/etc/external_camera_config.xml";
@@ -276,10 +278,17 @@
                 minStreamSize->UnsignedAttribute("height", /*Default*/0)};
     }
 
+    XMLElement *orientation = deviceCfg->FirstChildElement("Orientation");
+    if (orientation == nullptr) {
+        ALOGI("%s: no sensor orientation specified", __FUNCTION__);
+    } else {
+        ret.orientation = orientation->IntAttribute("degree", /*Default*/kDefaultOrientation);
+    }
+
     ALOGI("%s: external camera cfg loaded: maxJpgBufSize %d,"
-            " num video buffers %d, num still buffers %d",
+            " num video buffers %d, num still buffers %d, orientation %d",
             __FUNCTION__, ret.maxJpegBufSize,
-            ret.numVideoBuffers, ret.numStillBuffers);
+            ret.numVideoBuffers, ret.numStillBuffers, ret.orientation);
     for (const auto& limit : ret.fpsLimits) {
         ALOGI("%s: fpsLimitList: %dx%d@%f", __FUNCTION__,
                 limit.size.width, limit.size.height, limit.fpsUpperBound);
@@ -292,7 +301,8 @@
 ExternalCameraConfig::ExternalCameraConfig() :
         maxJpegBufSize(kDefaultJpegBufSize),
         numVideoBuffers(kDefaultNumVideoBuffer),
-        numStillBuffers(kDefaultNumStillBuffer) {
+        numStillBuffers(kDefaultNumStillBuffer),
+        orientation(kDefaultOrientation) {
     fpsLimits.push_back({/*Size*/{ 640,  480}, /*FPS upper bound*/30.0});
     fpsLimits.push_back({/*Size*/{1280,  720}, /*FPS upper bound*/7.5});
     fpsLimits.push_back({/*Size*/{1920, 1080}, /*FPS upper bound*/5.0});
diff --git a/camera/device/3.4/default/include/ext_device_v3_4_impl/ExternalCameraUtils.h b/camera/device/3.4/default/include/ext_device_v3_4_impl/ExternalCameraUtils.h
index 5754ccb..3b1ac96 100644
--- a/camera/device/3.4/default/include/ext_device_v3_4_impl/ExternalCameraUtils.h
+++ b/camera/device/3.4/default/include/ext_device_v3_4_impl/ExternalCameraUtils.h
@@ -80,6 +80,9 @@
     // Minimum output stream size
     Size minStreamSize;
 
+    // The value of android.sensor.orientation
+    int32_t orientation;
+
 private:
     ExternalCameraConfig();
 };
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/cas/1.0/default/service.cpp b/cas/1.0/default/service.cpp
index 2e6e55d..516acfb 100644
--- a/cas/1.0/default/service.cpp
+++ b/cas/1.0/default/service.cpp
@@ -47,7 +47,7 @@
     android::status_t status;
     if (kLazyService) {
         auto serviceRegistrar = std::make_shared<LazyServiceRegistrar>();
-        status = serviceRegistrar->registerServiceWithCallback(service);
+        status = serviceRegistrar->registerService(service);
     } else {
         status = service->registerAsService();
     }
diff --git a/compatibility_matrices/Android.bp b/compatibility_matrices/Android.bp
index b88d88f..5f56ee9 100644
--- a/compatibility_matrices/Android.bp
+++ b/compatibility_matrices/Android.bp
@@ -70,7 +70,6 @@
         "compatibility_matrix.current.xml",
     ],
     kernel_configs: [
-        "kernel_config_current_4.4",
         "kernel_config_current_4.9",
         "kernel_config_current_4.14",
         "kernel_config_current_4.19",
diff --git a/compatibility_matrices/compatibility_matrix.current.xml b/compatibility_matrices/compatibility_matrix.current.xml
index d4c422d..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>
@@ -240,6 +250,14 @@
             <instance>default</instance>
         </interface>
     </hal>
+    <hal format="hidl" optional="true">
+        <name>android.hardware.input.classifier</name>
+        <version>1.0</version>
+        <interface>
+            <name>IInputClassifier</name>
+            <instance>default</instance>
+        </interface>
+    </hal>
     <hal format="hidl" optional="false">
         <name>android.hardware.keymaster</name>
         <version>3.0</version>
@@ -327,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>
@@ -341,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>
@@ -367,6 +385,7 @@
     <hal format="hidl" optional="true">
         <name>android.hardware.sensors</name>
         <version>1.0</version>
+        <version>2.0</version>
         <interface>
             <name>ISensors</name>
             <instance>default</instance>
@@ -439,7 +458,7 @@
     </hal>
     <hal format="hidl" optional="true">
         <name>android.hardware.vibrator</name>
-        <version>1.0-2</version>
+        <version>1.0-3</version>
         <interface>
             <name>IVibrator</name>
             <instance>default</instance>
@@ -487,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 dab6aa5..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 3f124ae..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,11 +396,12 @@
 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
 1d19720d4fd38b1095f0f555a4bd92b3b12c9b1d0f560b0e9a474cd6dcc20db6 android.hardware.radio@1.2::IRadio
 e78cf871f9fd1c072874e481e06e18e2681763cf2aa38c1fd777d53bab4eb69b android.hardware.sensors@1.0::types
+3d01e29e8129186f7567c4f9c8bee7480a0768e587b1be9b28adb0a6cbec6bf2 android.hardware.tv.cec@1.0::types
 1722ad002317b1fae1400de709e90f442d94ef22864e05f7a12af48c32e8edc8 android.hardware.usb@1.1::types
 29c8da7a13c40d488f569c812441d5754ee45bdcdb8ce6564f524b708d10a057 android.hardware.vibrator@1.1::types
diff --git a/drm/1.0/default/Android.mk b/drm/1.0/default/Android.mk
index 99773be..d66f377 100644
--- a/drm/1.0/default/Android.mk
+++ b/drm/1.0/default/Android.mk
@@ -19,39 +19,23 @@
 LOCAL_PATH := $(call my-dir)
 
 include $(CLEAR_VARS)
+
+include $(LOCAL_PATH)/common_default_service.mk
 LOCAL_MODULE := android.hardware.drm@1.0-service
 LOCAL_INIT_RC := android.hardware.drm@1.0-service.rc
-LOCAL_PROPRIETARY_MODULE := true
-LOCAL_MODULE_RELATIVE_PATH := hw
-LOCAL_SRC_FILES := \
-  service.cpp \
+LOCAL_SRC_FILES := service.cpp
 
-LOCAL_SHARED_LIBRARIES := \
-  android.hardware.drm@1.0 \
-  android.hidl.memory@1.0 \
-  libhidlbase \
-  libhidltransport \
-  libhardware \
-  liblog \
-  libutils \
-  libbinder \
+include $(BUILD_EXECUTABLE)
 
-LOCAL_STATIC_LIBRARIES := \
-  android.hardware.drm@1.0-helper \
+############# Build legacy drm lazy service ############
 
-LOCAL_C_INCLUDES := \
-  hardware/interfaces/drm
+include $(CLEAR_VARS)
 
-LOCAL_HEADER_LIBRARIES := \
-  media_plugin_headers
-
-# TODO(b/18948909) Some legacy DRM plugins only support 32-bit. They need to be
-# migrated to 64-bit. Once all of a device's legacy DRM plugins support 64-bit,
-# that device can turn on TARGET_ENABLE_MEDIADRM_64 to build this service as
-# 64-bit.
-ifneq ($(TARGET_ENABLE_MEDIADRM_64), true)
-LOCAL_32_BIT_ONLY := true
-endif
+include $(LOCAL_PATH)/common_default_service.mk
+LOCAL_MODULE := android.hardware.drm@1.0-service-lazy
+LOCAL_OVERRIDES_MODULES := android.hardware.drm@1.0-service
+LOCAL_INIT_RC := android.hardware.drm@1.0-service-lazy.rc
+LOCAL_SRC_FILES := serviceLazy.cpp
 
 include $(BUILD_EXECUTABLE)
 
diff --git a/drm/1.0/default/android.hardware.drm@1.0-service-lazy.rc b/drm/1.0/default/android.hardware.drm@1.0-service-lazy.rc
new file mode 100644
index 0000000..4b32f7f
--- /dev/null
+++ b/drm/1.0/default/android.hardware.drm@1.0-service-lazy.rc
@@ -0,0 +1,10 @@
+service vendor.drm-hal-1-0 /vendor/bin/hw/android.hardware.drm@1.0-service-lazy
+    interface android.hardware.drm@1.0::ICryptoFactory default
+    interface android.hardware.drm@1.0::IDrmFactory default
+    oneshot
+    disabled
+    class hal
+    user media
+    group mediadrm drmrpc
+    ioprio rt 4
+    writepid /dev/cpuset/foreground/tasks
diff --git a/drm/1.0/default/android.hardware.drm@1.0-service.rc b/drm/1.0/default/android.hardware.drm@1.0-service.rc
index a3457b5..790eded 100644
--- a/drm/1.0/default/android.hardware.drm@1.0-service.rc
+++ b/drm/1.0/default/android.hardware.drm@1.0-service.rc
@@ -1,4 +1,6 @@
 service vendor.drm-hal-1-0 /vendor/bin/hw/android.hardware.drm@1.0-service
+    interface android.hardware.drm@1.0::ICryptoFactory default
+    interface android.hardware.drm@1.0::IDrmFactory default
     class hal
     user media
     group mediadrm drmrpc
diff --git a/drm/1.0/default/common_default_service.mk b/drm/1.0/default/common_default_service.mk
new file mode 100644
index 0000000..28db567
--- /dev/null
+++ b/drm/1.0/default/common_default_service.mk
@@ -0,0 +1,45 @@
+#
+# 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 $(CLEAR_VARS)
+LOCAL_PROPRIETARY_MODULE := true
+LOCAL_MODULE_RELATIVE_PATH := hw
+
+LOCAL_SHARED_LIBRARIES := \
+  android.hardware.drm@1.0 \
+  android.hidl.memory@1.0 \
+  libhidlbase \
+  libhidltransport \
+  libhardware \
+  liblog \
+  libutils \
+  libbinder \
+
+LOCAL_STATIC_LIBRARIES := \
+  android.hardware.drm@1.0-helper \
+
+LOCAL_C_INCLUDES := \
+  hardware/interfaces/drm
+
+LOCAL_HEADER_LIBRARIES := \
+  media_plugin_headers
+
+# TODO(b/18948909) Some legacy DRM plugins only support 32-bit. They need to be
+# migrated to 64-bit. Once all of a device's legacy DRM plugins support 64-bit,
+# that device can turn on TARGET_ENABLE_MEDIADRM_64 to build this service as
+# 64-bit.
+ifneq ($(TARGET_ENABLE_MEDIADRM_64), true)
+LOCAL_32_BIT_ONLY := true
+endif
diff --git a/drm/1.0/default/service.cpp b/drm/1.0/default/service.cpp
index 1a44ce2..98d2c3b 100644
--- a/drm/1.0/default/service.cpp
+++ b/drm/1.0/default/service.cpp
@@ -13,7 +13,6 @@
  * See the License for the specific language governing permissions and
  * limitations under the License.
  */
-#define LOG_TAG "android.hardware.drm@1.0-service"
 
 #include <1.0/default/CryptoFactory.h>
 #include <1.0/default/DrmFactory.h>
@@ -31,15 +30,8 @@
 using android::hardware::drm::V1_0::IDrmFactory;
 
 int main() {
-    ALOGD("android.hardware.drm@1.0-service starting...");
-
-    // The DRM HAL may communicate to other vendor components via
-    // /dev/vndbinder
-    android::ProcessState::initWithDriver("/dev/vndbinder");
-
     configureRpcThreadpool(8, true /* callerWillJoin */);
-    android::status_t status =
-        registerPassthroughServiceImplementation<IDrmFactory>();
+    android::status_t status = registerPassthroughServiceImplementation<IDrmFactory>();
     LOG_ALWAYS_FATAL_IF(
         status != android::OK,
         "Error while registering drm service: %d", status);
diff --git a/drm/1.0/default/serviceLazy.cpp b/drm/1.0/default/serviceLazy.cpp
new file mode 100644
index 0000000..e5068b5
--- /dev/null
+++ b/drm/1.0/default/serviceLazy.cpp
@@ -0,0 +1,40 @@
+/*
+ * 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.
+ */
+
+#include <1.0/default/CryptoFactory.h>
+#include <1.0/default/DrmFactory.h>
+
+#include <hidl/HidlTransportSupport.h>
+#include <hidl/LegacySupport.h>
+
+#include <binder/ProcessState.h>
+
+using android::hardware::configureRpcThreadpool;
+using android::hardware::joinRpcThreadpool;
+using android::hardware::registerLazyPassthroughServiceImplementation;
+
+using android::hardware::drm::V1_0::ICryptoFactory;
+using android::hardware::drm::V1_0::IDrmFactory;
+
+int main() {
+    configureRpcThreadpool(8, true /* callerWillJoin */);
+    android::status_t status = registerLazyPassthroughServiceImplementation<IDrmFactory>();
+    LOG_ALWAYS_FATAL_IF(status != android::OK, "Error while registering drm service: %d", status);
+    status = registerLazyPassthroughServiceImplementation<ICryptoFactory>();
+    LOG_ALWAYS_FATAL_IF(status != android::OK, "Error while registering crypto service: %d",
+                        status);
+    joinRpcThreadpool();
+}
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 200671e..9b04be0 100644
--- a/gnss/2.0/Android.bp
+++ b/gnss/2.0/Android.bp
@@ -13,11 +13,13 @@
         "IAGnssRil.hal",
         "IGnss.hal",
         "IGnssCallback.hal",
+        "IGnssConfiguration.hal",
         "IGnssMeasurement.hal",
         "IGnssMeasurementCallback.hal",
     ],
     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 fb8b040..1f1858e 100644
--- a/gnss/2.0/IGnss.hal
+++ b/gnss/2.0/IGnss.hal
@@ -17,16 +17,26 @@
 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;
+import IGnssConfiguration;
 import IGnssMeasurement;
 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
      * interface.
      *
@@ -37,6 +47,13 @@
     setCallback_2_0(IGnssCallback callback) generates (bool success);
 
     /**
+     * This method returns the IGnssConfiguration interface.
+     *
+     * @return gnssConfigurationIface Handle to the IGnssConfiguration interface.
+     */
+    getExtensionGnssConfiguration_2_0() generates (IGnssConfiguration gnssConfigurationIface);
+
+    /**
      * This method returns the IAGnss Interface.
      *
      * The getExtensionAGnss() must return nullptr as the @1.0::IAGnss interface is
@@ -68,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/IGnssConfiguration.hal b/gnss/2.0/IGnssConfiguration.hal
new file mode 100644
index 0000000..90c376e
--- /dev/null
+++ b/gnss/2.0/IGnssConfiguration.hal
@@ -0,0 +1,45 @@
+/*
+ * 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@2.0;
+
+import @1.1::IGnssConfiguration;
+
+/**
+ * Extended interface for GNSS Configuration support.
+ *
+ * Due to the introduction of new GNSS HAL package android.hardware.gnss.visibility_control@1.0
+ * the following methods in @1.0::IGnssConfiguration are deprecated in this version and not
+ * called by the framework.
+ *
+ * setGpsLock(bitfield<GpsLock> lock) generates (bool success);
+ * setSuplEs(bool enabled) generates (bool success);
+ */
+interface IGnssConfiguration extends @1.1::IGnssConfiguration {
+    /**
+     * This method sets the emergency session extension duration. The GNSS HAL
+     * implementation must serve emergency SUPL and Control Plane network initiated
+     * location requests for this extra duration after the user initiated emergency
+     * session ends.
+     *
+     * @param emergencyExtensionSeconds Number of seconds to extend the emergency
+     * session duration post emergency call.
+     *
+     * @return success True if the GNSS HAL implementation accepts and supports the
+     * extended duration for emergency SUPL and Control Plane location requests.
+     */
+    setEsExtensionSec(uint32_t emergencyExtensionSeconds) generates (bool success);
+};
\ No newline at end of file
diff --git a/gnss/2.0/default/Android.bp b/gnss/2.0/default/Android.bp
index 9119ee4..985aa2b 100644
--- a/gnss/2.0/default/Android.bp
+++ b/gnss/2.0/default/Android.bp
@@ -21,10 +21,12 @@
     vendor: true,
     vintf_fragments: ["android.hardware.gnss@2.0-service.xml"],
     srcs: [
+        "GnssConfiguration.cpp",
         "AGnss.cpp",
         "AGnssRil.cpp",
         "Gnss.cpp",
         "GnssMeasurement.cpp",
+        "GnssVisibilityControl.cpp",
         "service.cpp"
     ],
     shared_libs: [
@@ -34,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 bde904f..217f0f3 100644
--- a/gnss/2.0/default/Gnss.cpp
+++ b/gnss/2.0/default/Gnss.cpp
@@ -20,9 +20,12 @@
 #include <log/log.h>
 #include "AGnss.h"
 #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 {
@@ -92,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() {
@@ -181,6 +184,10 @@
 }
 
 // Methods from V2_0::IGnss follow.
+Return<sp<V2_0::IGnssConfiguration>> Gnss::getExtensionGnssConfiguration_2_0() {
+    return new GnssConfiguration{};
+}
+
 Return<sp<V2_0::IAGnss>> Gnss::getExtensionAGnss_2_0() {
     return new AGnss{};
 }
@@ -200,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 47792cf..890b026 100644
--- a/gnss/2.0/default/Gnss.h
+++ b/gnss/2.0/default/Gnss.h
@@ -72,12 +72,15 @@
     Return<bool> injectBestLocation(const V1_0::GnssLocation& location) override;
 
     // Methods from V2_0::IGnss follow.
+    Return<sp<V2_0::IGnssConfiguration>> getExtensionGnssConfiguration_2_0() override;
     Return<sp<V2_0::IAGnss>> getExtensionAGnss_2_0() override;
     Return<sp<V2_0::IAGnssRil>> getExtensionAGnssRil_2_0() override;
     Return<sp<V2_0::IGnssMeasurement>> getExtensionGnssMeasurement_2_0() override;
     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/GnssConfiguration.cpp b/gnss/2.0/default/GnssConfiguration.cpp
new file mode 100644
index 0000000..4389dd2
--- /dev/null
+++ b/gnss/2.0/default/GnssConfiguration.cpp
@@ -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.
+ */
+
+#define LOG_TAG "GnssConfiguration"
+
+#include "GnssConfiguration.h"
+#include <log/log.h>
+
+namespace android {
+namespace hardware {
+namespace gnss {
+namespace V2_0 {
+namespace implementation {
+
+// Methods from ::android::hardware::gnss::V1_0::IGnssConfiguration follow.
+Return<bool> GnssConfiguration::setSuplEs(bool enable) {
+    ALOGD("setSuplEs enable: %d", enable);
+    // Method deprecated in 2.0 and not expected to be called by the framework.
+    return false;
+}
+
+Return<bool> GnssConfiguration::setSuplVersion(uint32_t) {
+    // TODO implement
+    return bool{};
+}
+
+Return<bool> GnssConfiguration::setSuplMode(hidl_bitfield<SuplMode>) {
+    // TODO implement
+    return bool{};
+}
+
+Return<bool> GnssConfiguration::setGpsLock(hidl_bitfield<GpsLock> gpsLock) {
+    ALOGD("setGpsLock gpsLock: %hhu", static_cast<GpsLock>(gpsLock));
+    // Method deprecated in 2.0 and not expected to be called by the framework.
+    return false;
+}
+
+Return<bool> GnssConfiguration::setLppProfile(hidl_bitfield<LppProfile>) {
+    // TODO implement
+    return bool{};
+}
+
+Return<bool> GnssConfiguration::setGlonassPositioningProtocol(hidl_bitfield<GlonassPosProtocol>) {
+    // TODO implement
+    return bool{};
+}
+
+Return<bool> GnssConfiguration::setEmergencySuplPdn(bool) {
+    // TODO implement
+    return bool{};
+}
+
+// Methods from ::android::hardware::gnss::V1_1::IGnssConfiguration follow.
+Return<bool> GnssConfiguration::setBlacklist(
+    const hidl_vec<V1_1::IGnssConfiguration::BlacklistedSource>&) {
+    // TODO (b/122463906): Reuse 1.1 implementation.
+    return bool{};
+}
+
+// Methods from ::android::hardware::gnss::V2_0::IGnssConfiguration follow.
+Return<bool> GnssConfiguration::setEsExtensionSec(uint32_t emergencyExtensionSeconds) {
+    ALOGD("setEsExtensionSec emergencyExtensionSeconds: %d", emergencyExtensionSeconds);
+    return true;
+}
+
+}  // namespace implementation
+}  // namespace V2_0
+}  // namespace gnss
+}  // namespace hardware
+}  // namespace android
\ No newline at end of file
diff --git a/gnss/2.0/default/GnssConfiguration.h b/gnss/2.0/default/GnssConfiguration.h
new file mode 100644
index 0000000..0c02ccd
--- /dev/null
+++ b/gnss/2.0/default/GnssConfiguration.h
@@ -0,0 +1,62 @@
+/*
+ * Copyright (C) 2018 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef ANDROID_HARDWARE_GNSS_V2_0_GNSSCONFIGURATION_H
+#define ANDROID_HARDWARE_GNSS_V2_0_GNSSCONFIGURATION_H
+
+#include <android/hardware/gnss/2.0/IGnssConfiguration.h>
+#include <hidl/MQDescriptor.h>
+#include <hidl/Status.h>
+
+namespace android {
+namespace hardware {
+namespace gnss {
+namespace V2_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 GnssConfiguration : public IGnssConfiguration {
+    // Methods from ::android::hardware::gnss::V1_0::IGnssConfiguration follow.
+    Return<bool> setSuplEs(bool enabled) override;
+    Return<bool> setSuplVersion(uint32_t version) override;
+    Return<bool> setSuplMode(hidl_bitfield<SuplMode> mode) override;
+    Return<bool> setGpsLock(hidl_bitfield<GpsLock> lock) override;
+    Return<bool> setLppProfile(hidl_bitfield<LppProfile> lppProfile) override;
+    Return<bool> setGlonassPositioningProtocol(hidl_bitfield<GlonassPosProtocol> protocol) override;
+    Return<bool> setEmergencySuplPdn(bool enable) override;
+
+    // Methods from ::android::hardware::gnss::V1_1::IGnssConfiguration follow.
+    Return<bool> setBlacklist(
+        const hidl_vec<V1_1::IGnssConfiguration::BlacklistedSource>& blacklist) override;
+
+    // Methods from ::android::hardware::gnss::V2_0::IGnssConfiguration follow.
+    Return<bool> setEsExtensionSec(uint32_t emergencyExtensionSeconds) override;
+};
+
+}  // namespace implementation
+}  // namespace V2_0
+}  // namespace gnss
+}  // namespace hardware
+}  // namespace android
+
+#endif  // ANDROID_HARDWARE_GNSS_V2_0_GNSSCONFIGURATION_H
\ No newline at end of file
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/VtsHalGnssV2_0TargetTest.cpp b/gnss/2.0/vts/functional/VtsHalGnssV2_0TargetTest.cpp
index ae36c50..a8e40ba 100644
--- a/gnss/2.0/vts/functional/VtsHalGnssV2_0TargetTest.cpp
+++ b/gnss/2.0/vts/functional/VtsHalGnssV2_0TargetTest.cpp
@@ -23,6 +23,7 @@
     ::testing::AddGlobalTestEnvironment(GnssHidlEnvironment::Instance());
     ::testing::InitGoogleTest(&argc, argv);
     GnssHidlEnvironment::Instance()->init(&argc, argv);
+    // TODO (b/122463165): Expand coverage to include 1.1 and 1.0 VTS tests.
     int status = RUN_ALL_TESTS();
     ALOGI("Test result = %d", status);
     return status;
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 ef232c9..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,8 +19,10 @@
 #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;
 using IAGnssRil_2_0 = android::hardware::gnss::V2_0::IAGnssRil;
 using IGnssMeasurement_2_0 = android::hardware::gnss::V2_0::IGnssMeasurement;
 using IGnssMeasurement_1_1 = android::hardware::gnss::V1_1::IGnssMeasurement;
@@ -29,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:
@@ -60,13 +64,63 @@
 }
 
 /*
+ * TestGnssConfigurationExtension:
+ * Gets the GnssConfigurationExtension and verifies that it returns an actual extension by
+ * calling a method.
+ *
+ * The GNSS HAL 2.0 implementation must support @2.0::IGnssConfiguration interface due to
+ * the deprecation of some methods in @1.0::IGnssConfiguration interface.
+ */
+TEST_F(GnssHalTest, TestGnssConfigurationExtension) {
+    auto gnssConfiguration = gnss_hal_->getExtensionGnssConfiguration_2_0();
+    ASSERT_TRUE(gnssConfiguration.isOk());
+    sp<IGnssConfiguration_2_0> iGnssConfiguration = gnssConfiguration;
+    ASSERT_NE(iGnssConfiguration, nullptr);
+
+    auto result = iGnssConfiguration->setEsExtensionSec(180);
+    ASSERT_TRUE(result.isOk());
+    // Expected result can be true or false depending on whether HAL implementation supports
+    // detecting emergency sessions without involving the framework.
+}
+
+/*
+ * TestGnssConfiguration_setSuplEs_Deprecation:
+ * Calls setSuplEs and verifies that it returns false.
+ */
+TEST_F(GnssHalTest, TestGnssConfiguration_setSuplEs_Deprecation) {
+    auto gnssConfiguration = gnss_hal_->getExtensionGnssConfiguration_2_0();
+    ASSERT_TRUE(gnssConfiguration.isOk());
+    sp<IGnssConfiguration_2_0> iGnssConfiguration = gnssConfiguration;
+    ASSERT_NE(iGnssConfiguration, nullptr);
+
+    auto result = iGnssConfiguration->setSuplEs(false);
+    ASSERT_TRUE(result.isOk());
+    EXPECT_FALSE(result);
+}
+
+/*
+ * TestGnssConfiguration_setGpsLock_Deprecation:
+ * Calls setGpsLock and verifies that it returns false.
+ */
+TEST_F(GnssHalTest, TestGnssConfiguration_setGpsLock_Deprecation) {
+    auto gnssConfiguration = gnss_hal_->getExtensionGnssConfiguration_2_0();
+    ASSERT_TRUE(gnssConfiguration.isOk());
+    sp<IGnssConfiguration_2_0> iGnssConfiguration = gnssConfiguration;
+    ASSERT_NE(iGnssConfiguration, nullptr);
+
+    auto result = iGnssConfiguration->setGpsLock(0);
+    ASSERT_TRUE(result.isOk());
+    EXPECT_FALSE(result);
+}
+
+/*
  * TestAGnssRilExtension:
  * Gets the AGnssRilExtension and verifies that it returns an actual extension.
  *
  * 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();
@@ -76,11 +130,11 @@
 }
 
 /*
- * TestAGnssRilUpdateNetworkState_2_0:
+ * TestAGnssRil_UpdateNetworkState_2_0:
  * 1. Updates GNSS HAL that a network has connected.
  * 2. Updates GNSS HAL that network has disconnected.
  */
-TEST_F(GnssHalTest, TestAGnssRilUpdateNetworkState_2_0) {
+TEST_F(GnssHalTest, TestAGnssRil_UpdateNetworkState_2_0) {
     auto agnssRil = gnss_hal_->getExtensionAGnssRil_2_0();
     ASSERT_TRUE(agnssRil.isOk());
     sp<IAGnssRil_2_0> iAGnssRil = agnssRil;
@@ -148,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.
@@ -167,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/composer/2.3/utils/OWNERS b/graphics/composer/2.3/utils/OWNERS
index 234bc75..b3ea6be 100644
--- a/graphics/composer/2.3/utils/OWNERS
+++ b/graphics/composer/2.3/utils/OWNERS
@@ -1,6 +1,7 @@
 # Graphics team
-olv@google.com
+lpy@google.com
 stoza@google.com
+vhau@google.com
 
 # VTS team
 yim@google.com
diff --git a/graphics/composer/2.3/vts/functional/OWNERS b/graphics/composer/2.3/vts/functional/OWNERS
index 234bc75..b3ea6be 100644
--- a/graphics/composer/2.3/vts/functional/OWNERS
+++ b/graphics/composer/2.3/vts/functional/OWNERS
@@ -1,6 +1,7 @@
 # Graphics team
-olv@google.com
+lpy@google.com
 stoza@google.com
+vhau@google.com
 
 # VTS team
 yim@google.com
diff --git a/graphics/composer/2.3/vts/functional/VtsHalGraphicsComposerV2_3TargetTest.cpp b/graphics/composer/2.3/vts/functional/VtsHalGraphicsComposerV2_3TargetTest.cpp
index 535f847..dca7406 100644
--- a/graphics/composer/2.3/vts/functional/VtsHalGraphicsComposerV2_3TargetTest.cpp
+++ b/graphics/composer/2.3/vts/functional/VtsHalGraphicsComposerV2_3TargetTest.cpp
@@ -248,14 +248,47 @@
 }
 
 /**
+ * Test IComposerClient::getHdrCapabilities_2_3
+ */
+TEST_F(GraphicsComposerHidlTest, GetHdrCapabilities_2_3) {
+    float maxLuminance;
+    float maxAverageLuminance;
+    float minLuminance;
+    ASSERT_NO_FATAL_FAILURE(mComposerClient->getHdrCapabilities_2_3(
+        mPrimaryDisplay, &maxLuminance, &maxAverageLuminance, &minLuminance));
+    ASSERT_TRUE(maxLuminance >= minLuminance);
+}
+
+/**
+ * Test IComposerClient::getPerFrameMetadataKeys_2_3
+ */
+TEST_F(GraphicsComposerHidlTest, GetPerFrameMetadataKeys_2_3) {
+    std::vector<IComposerClient::PerFrameMetadataKey> keys;
+    mComposerClient->getRaw()->getPerFrameMetadataKeys_2_3(
+        mPrimaryDisplay, [&](const auto tmpError, const auto outKeys) {
+            if (tmpError != Error::UNSUPPORTED) {
+                ASSERT_EQ(Error::NONE, tmpError);
+                keys = outKeys;
+            }
+        });
+}
+
+/**
  * TestIComposerClient::getReadbackBufferAttributes_2_3
  */
 TEST_F(GraphicsComposerHidlTest, GetReadbackBufferAttributes_2_3) {
     Dataspace dataspace;
     PixelFormat pixelFormat;
 
-    ASSERT_NO_FATAL_FAILURE(mComposerClient->getReadbackBufferAttributes_2_3(
-        mPrimaryDisplay, &pixelFormat, &dataspace));
+    mComposerClient->getRaw()->getReadbackBufferAttributes_2_3(
+        mPrimaryDisplay,
+        [&](const auto tmpError, const auto outPixelFormat, const auto outDataspace) {
+            if (tmpError != Error::UNSUPPORTED) {
+                ASSERT_EQ(Error::NONE, tmpError);
+                dataspace = outDataspace;
+                pixelFormat = outPixelFormat;
+            }
+        });
 }
 
 /**
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/health/1.0/default/android.hardware.health@1.0-service.rc b/health/1.0/default/android.hardware.health@1.0-service.rc
index d74a07e..405784f 100644
--- a/health/1.0/default/android.hardware.health@1.0-service.rc
+++ b/health/1.0/default/android.hardware.health@1.0-service.rc
@@ -2,3 +2,4 @@
     class hal
     user system
     group system
+    capabilities WAKE_ALARM
diff --git a/health/2.0/README.md b/health/2.0/README.md
index 5efc51a..58ea9e3 100644
--- a/health/2.0/README.md
+++ b/health/2.0/README.md
@@ -67,6 +67,7 @@
         class hal
         user system
         group system
+        capabilities WAKE_ALARM
         file /dev/kmsg w
     ```
 
@@ -97,7 +98,7 @@
 1. Storage related APIs:
 
     1. If the device does not implement `IHealth.getDiskStats` and
-        `IHealth.getStorageInfo`, add `libstoragehealthdefault` to `static_libs`.
+        `IHealth.getStorageInfo`, add `libhealthstoragedefault` to `static_libs`.
 
     1. If the device implements one of these two APIs, add and implement the
         following functions in `HealthService.cpp`:
@@ -115,7 +116,7 @@
 
     ```
     # device/<manufacturer>/<device>/sepolicy/vendor/file_contexts
-    /vendor/bin/hw/android\.hardware\.health@2\.0-service.<device> u:object_r:hal_health_default_exec:s0
+    /vendor/bin/hw/android\.hardware\.health@2\.0-service\.<device> u:object_r:hal_health_default_exec:s0
 
     # device/<manufacturer>/<device>/sepolicy/vendor/hal_health_default.te
     # Add device specific permissions to hal_health_default domain, especially
diff --git a/health/storage/1.0/default/android.hardware.health.storage@1.0-service.rc b/health/storage/1.0/default/android.hardware.health.storage@1.0-service.rc
index c6a1425..d5e1a29 100644
--- a/health/storage/1.0/default/android.hardware.health.storage@1.0-service.rc
+++ b/health/storage/1.0/default/android.hardware.health.storage@1.0-service.rc
@@ -1,5 +1,7 @@
 service vendor.health-storage-hal-1-0 /vendor/bin/hw/android.hardware.health.storage@1.0-service
     interface android.hardware.health.storage@1.0::IStorage default
+    oneshot
+    disabled
     class hal
     user system
     group system
diff --git a/health/storage/1.0/default/service.cpp b/health/storage/1.0/default/service.cpp
index a945033..f4296f1 100644
--- a/health/storage/1.0/default/service.cpp
+++ b/health/storage/1.0/default/service.cpp
@@ -14,6 +14,7 @@
  * limitations under the License.
  */
 
+#include <hidl/HidlLazyUtils.h>
 #include <hidl/HidlTransportSupport.h>
 #include "Storage.h"
 
@@ -23,6 +24,7 @@
 using android::UNKNOWN_ERROR;
 using android::hardware::configureRpcThreadpool;
 using android::hardware::joinRpcThreadpool;
+using android::hardware::LazyServiceRegistrar;
 using android::hardware::health::storage::V1_0::IStorage;
 using android::hardware::health::storage::V1_0::implementation::Storage;
 
@@ -30,7 +32,8 @@
     configureRpcThreadpool(1, true);
 
     sp<IStorage> service = new Storage();
-    status_t result = service->registerAsService();
+    LazyServiceRegistrar registrar;
+    status_t result = registrar.registerService(service);
 
     if (result != OK) {
         return result;
diff --git a/input/classifier/1.0/Android.bp b/input/classifier/1.0/Android.bp
new file mode 100644
index 0000000..c3c6fc6
--- /dev/null
+++ b/input/classifier/1.0/Android.bp
@@ -0,0 +1,35 @@
+// This file is autogenerated by hidl-gen -Landroidbp.
+
+hidl_interface {
+    name: "android.hardware.input.classifier@1.0",
+    root: "android.hardware",
+    vndk: {
+        enabled: true,
+    },
+    srcs: [
+        "types.hal",
+        "IInputClassifier.hal",
+    ],
+    interfaces: [
+        "android.hidl.base@1.0",
+    ],
+    types: [
+        "Action",
+        "Axis",
+        "Button",
+        "Classification",
+        "EdgeFlag",
+        "Flag",
+        "Meta",
+        "MotionEvent",
+        "PointerCoords",
+        "PointerProperties",
+        "PolicyFlag",
+        "Source",
+        "SourceClass",
+        "ToolType",
+        "VideoFrame",
+    ],
+    gen_java: true,
+}
+
diff --git a/input/classifier/1.0/IInputClassifier.hal b/input/classifier/1.0/IInputClassifier.hal
new file mode 100644
index 0000000..edc1138
--- /dev/null
+++ b/input/classifier/1.0/IInputClassifier.hal
@@ -0,0 +1,26 @@
+/*
+ * 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.input.classifier@1.0;
+
+interface IInputClassifier {
+
+  /**
+   * Returns the classification for the current sequence of input events.
+   */
+  classify(MotionEvent event) generates (Classification classification);
+
+};
diff --git a/input/classifier/1.0/default/Android.bp b/input/classifier/1.0/default/Android.bp
new file mode 100644
index 0000000..ddd883c
--- /dev/null
+++ b/input/classifier/1.0/default/Android.bp
@@ -0,0 +1,23 @@
+cc_binary {
+    name: "android.hardware.input.classifier@1.0-service-example",
+    init_rc: ["android.hardware.input.classifier@1.0-service-example.rc"],
+    relative_install_path: "hw",
+    vendor: true,
+    vintf_fragments: ["manifest_input.classifier.xml"],
+    srcs: [
+        "InputClassifier.cpp",
+        "service.cpp",
+    ],
+    shared_libs: [
+        "android.hardware.input.classifier@1.0",
+        "libhidlbase",
+        "libhidltransport",
+        "liblog",
+        "libutils",
+    ],
+    cflags: [
+        "-Wall",
+        "-Werror",
+        "-Wextra",
+    ],
+}
diff --git a/input/classifier/1.0/default/InputClassifier.cpp b/input/classifier/1.0/default/InputClassifier.cpp
new file mode 100644
index 0000000..c463361
--- /dev/null
+++ b/input/classifier/1.0/default/InputClassifier.cpp
@@ -0,0 +1,65 @@
+/*
+ * 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 "InputClassifierHAL"
+
+#include "InputClassifier.h"
+#include <inttypes.h>
+#include <log/log.h>
+#include <utils/Timers.h>
+
+using namespace android::hardware::input::classifier::V1_0;
+
+namespace android {
+namespace hardware {
+namespace input {
+namespace classifier {
+namespace V1_0 {
+namespace implementation {
+
+// Methods from ::android::hardware::input::classifier::V1_0::IInputClassifier follow.
+Return<Classification> InputClassifier::classify(const MotionEvent& event) {
+    /**
+     * In this example implementation, we will see how many "pixels" inside the video frame
+     * exceed the value of 250. If more than 6 such pixels are present, then treat the event
+     * as a "DEEP_PRESS".
+     */
+    if (event.frames.size() == 0) {
+        return Classification::NONE;
+    }
+    ALOGI("Frame(O) timestamp = %" PRIu64 ", received %zu frame(s)", event.frames[0].timestamp,
+          event.frames.size());
+    for (const VideoFrame& frame : event.frames) {
+        size_t count = 0;
+        for (size_t i = 0; i < frame.data.size(); i++) {
+            if (frame.data[i] > 250) {
+                count++;
+            }
+        }
+        if (count > 6) {
+            return Classification::DEEP_PRESS;
+        }
+    }
+
+    return Classification::NONE;
+}
+
+}  // namespace implementation
+}  // namespace V1_0
+}  // namespace classifier
+}  // namespace input
+}  // namespace hardware
+}  // namespace android
diff --git a/input/classifier/1.0/default/InputClassifier.h b/input/classifier/1.0/default/InputClassifier.h
new file mode 100644
index 0000000..0858ecb
--- /dev/null
+++ b/input/classifier/1.0/default/InputClassifier.h
@@ -0,0 +1,45 @@
+/*
+ * 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_INPUT_CLASSIFIER_V1_0_INPUTCLASSIFIER_H
+#define ANDROID_HARDWARE_INPUT_CLASSIFIER_V1_0_INPUTCLASSIFIER_H
+
+#include <android/hardware/input/classifier/1.0/IInputClassifier.h>
+#include <hidl/Status.h>
+
+namespace android {
+namespace hardware {
+namespace input {
+namespace classifier {
+namespace V1_0 {
+namespace implementation {
+
+using ::android::hardware::Return;
+
+struct InputClassifier : public IInputClassifier {
+    // Methods from ::android::hardware::input::classifier::V1_0::IInputClassifier follow.
+    Return<Classification> classify(
+        const ::android::hardware::input::classifier::V1_0::MotionEvent& event) override;
+};
+
+}  // namespace implementation
+}  // namespace V1_0
+}  // namespace classifier
+}  // namespace input
+}  // namespace hardware
+}  // namespace android
+
+#endif  // ANDROID_HARDWARE_INPUT_CLASSIFIER_V1_0_INPUTCLASSIFIER_H
diff --git a/input/classifier/1.0/default/android.hardware.input.classifier@1.0-service-example.rc b/input/classifier/1.0/default/android.hardware.input.classifier@1.0-service-example.rc
new file mode 100644
index 0000000..f799bf4
--- /dev/null
+++ b/input/classifier/1.0/default/android.hardware.input.classifier@1.0-service-example.rc
@@ -0,0 +1,9 @@
+service vendor.input.classifier-1-0 /vendor/bin/hw/android.hardware.input.classifier@1.0-service-example
+    # Must be specified if "disabled" is set. This HAL will only start if requested via getService
+    interface android.hardware.input.classifier@1.0::IInputClassifier default
+    class hal
+    user nobody
+    # will not be restarted if it exits until it is requested to be restarted
+    oneshot
+    # will only be started when requested
+    disabled
diff --git a/input/classifier/1.0/default/manifest_input.classifier.xml b/input/classifier/1.0/default/manifest_input.classifier.xml
new file mode 100644
index 0000000..8634169
--- /dev/null
+++ b/input/classifier/1.0/default/manifest_input.classifier.xml
@@ -0,0 +1,11 @@
+<manifest version="1.0" type="device">
+    <hal format="hidl">
+        <name>android.hardware.input.classifier</name>
+        <transport>hwbinder</transport>
+        <version>1.0</version>
+        <interface>
+            <name>IInputClassifier</name>
+            <instance>default</instance>
+        </interface>
+    </hal>
+</manifest>
diff --git a/input/classifier/1.0/default/service.cpp b/input/classifier/1.0/default/service.cpp
new file mode 100644
index 0000000..6ef2118
--- /dev/null
+++ b/input/classifier/1.0/default/service.cpp
@@ -0,0 +1,48 @@
+/*
+ * 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 "android.hardware.input.classifier@1.0"
+
+#include <inttypes.h>
+
+#include <hidl/HidlTransportSupport.h>
+#include <log/log.h>
+
+#include "InputClassifier.h"
+#include "android/hardware/input/classifier/1.0/IInputClassifier.h"
+
+using android::sp;
+using android::status_t;
+using android::hardware::configureRpcThreadpool;
+using android::hardware::joinRpcThreadpool;
+using android::hardware::input::classifier::V1_0::IInputClassifier;
+using android::hardware::input::classifier::V1_0::implementation::InputClassifier;
+
+int main() {
+    sp<IInputClassifier> classifier = new InputClassifier();
+
+    configureRpcThreadpool(1, true);
+    const status_t status = classifier->registerAsService();
+
+    if (status != android::OK) {
+        ALOGE("Could not register InputClassifier HAL!");
+        return EXIT_FAILURE;  // or handle error
+    }
+
+    joinRpcThreadpool();
+    LOG_ALWAYS_FATAL("Under normal operation, joinRpcThreadpool should never return");
+    return EXIT_FAILURE;
+}
diff --git a/input/classifier/1.0/types.hal b/input/classifier/1.0/types.hal
new file mode 100644
index 0000000..244ecd9
--- /dev/null
+++ b/input/classifier/1.0/types.hal
@@ -0,0 +1,829 @@
+/*
+ * 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.input.classifier@1.0;
+
+
+/**
+ * Constants that identify each individual axis of a motion event.
+ */
+enum Axis : uint64_t {
+    /**
+     * Axis constant: X axis of a motion event.
+     *
+     * - For a touch screen, reports the absolute X screen position of the center of
+     * the touch contact area.  The units are display pixels.
+     * - For a touch pad, reports the absolute X surface position of the center of the touch
+     * contact area. The units are device-dependent.
+     * - For a mouse, reports the absolute X screen position of the mouse pointer.
+     * The units are display pixels.
+     * - For a trackball, reports the relative horizontal displacement of the trackball.
+     * The value is normalized to a range from -1.0 (left) to 1.0 (right).
+     * - For a joystick, reports the absolute X position of the joystick.
+     * The value is normalized to a range from -1.0 (left) to 1.0 (right).
+     */
+    X = 0,
+    /**
+     * Axis constant: Y axis of a motion event.
+     *
+     * - For a touch screen, reports the absolute Y screen position of the center of
+     * the touch contact area.  The units are display pixels.
+     * - For a touch pad, reports the absolute Y surface position of the center of the touch
+     * contact area. The units are device-dependent.
+     * - For a mouse, reports the absolute Y screen position of the mouse pointer.
+     * The units are display pixels.
+     * - For a trackball, reports the relative vertical displacement of the trackball.
+     * The value is normalized to a range from -1.0 (up) to 1.0 (down).
+     * - For a joystick, reports the absolute Y position of the joystick.
+     * The value is normalized to a range from -1.0 (up or far) to 1.0 (down or near).
+     */
+    Y = 1,
+    /**
+     * Axis constant: Pressure axis of a motion event.
+     *
+     * - For a touch screen or touch pad, reports the approximate pressure applied to the surface
+     * by a finger or other tool.  The value is normalized to a range from
+     * 0 (no pressure at all) to 1 (normal pressure), although values higher than 1
+     * may be generated depending on the calibration of the input device.
+     * - For a trackball, the value is set to 1 if the trackball button is pressed
+     * or 0 otherwise.
+     * - For a mouse, the value is set to 1 if the primary mouse button is pressed
+     * or 0 otherwise.
+     */
+    PRESSURE = 2,
+    /**
+     * Axis constant: Size axis of a motion event.
+     *
+     * - For a touch screen or touch pad, reports the approximate size of the contact area in
+     * relation to the maximum detectable size for the device.  The value is normalized
+     * to a range from 0 (smallest detectable size) to 1 (largest detectable size),
+     * although it is not a linear scale. This value is of limited use.
+     * To obtain calibrated size information, see
+     * {@link TOUCH_MAJOR} or {@link TOOL_MAJOR}.
+     */
+    SIZE = 3,
+    /**
+     * Axis constant: TouchMajor axis of a motion event.
+     *
+     * - For a touch screen, reports the length of the major axis of an ellipse that
+     * represents the touch area at the point of contact.
+     * The units are display pixels.
+     * - For a touch pad, reports the length of the major axis of an ellipse that
+     * represents the touch area at the point of contact.
+     * The units are device-dependent.
+     */
+    TOUCH_MAJOR = 4,
+    /**
+     * Axis constant: TouchMinor axis of a motion event.
+     *
+     * - For a touch screen, reports the length of the minor axis of an ellipse that
+     * represents the touch area at the point of contact.
+     * The units are display pixels.
+     * - For a touch pad, reports the length of the minor axis of an ellipse that
+     * represents the touch area at the point of contact.
+     * The units are device-dependent.
+     *
+     * When the touch is circular, the major and minor axis lengths will be equal to one another.
+     */
+    TOUCH_MINOR = 5,
+    /**
+     * Axis constant: ToolMajor axis of a motion event.
+     *
+     * - For a touch screen, reports the length of the major axis of an ellipse that
+     * represents the size of the approaching finger or tool used to make contact.
+     * - For a touch pad, reports the length of the major axis of an ellipse that
+     * represents the size of the approaching finger or tool used to make contact.
+     * The units are device-dependent.
+     *
+     * When the touch is circular, the major and minor axis lengths will be equal to one another.
+     *
+     * The tool size may be larger than the touch size since the tool may not be fully
+     * in contact with the touch sensor.
+     */
+    TOOL_MAJOR = 6,
+    /**
+     * Axis constant: ToolMinor axis of a motion event.
+     *
+     * - For a touch screen, reports the length of the minor axis of an ellipse that
+     * represents the size of the approaching finger or tool used to make contact.
+     * - For a touch pad, reports the length of the minor axis of an ellipse that
+     * represents the size of the approaching finger or tool used to make contact.
+     * The units are device-dependent.
+     *
+     * When the touch is circular, the major and minor axis lengths will be equal to one another.
+     *
+     * The tool size may be larger than the touch size since the tool may not be fully
+     * in contact with the touch sensor.
+     */
+    TOOL_MINOR = 7,
+    /**
+     * Axis constant: Orientation axis of a motion event.
+     *
+     * - For a touch screen or touch pad, reports the orientation of the finger
+     * or tool in radians relative to the vertical plane of the device.
+     * An angle of 0 radians indicates that the major axis of contact is oriented
+     * upwards, is perfectly circular or is of unknown orientation.  A positive angle
+     * indicates that the major axis of contact is oriented to the right.  A negative angle
+     * indicates that the major axis of contact is oriented to the left.
+     * The full range is from -PI/2 radians (finger pointing fully left) to PI/2 radians
+     * (finger pointing fully right).
+     * - For a stylus, the orientation indicates the direction in which the stylus
+     * is pointing in relation to the vertical axis of the current orientation of the screen.
+     * The range is from -PI radians to PI radians, where 0 is pointing up,
+     * -PI/2 radians is pointing left, -PI or PI radians is pointing down, and PI/2 radians
+     * is pointing right.  See also {@link TILT}.
+     */
+    ORIENTATION = 8,
+    /**
+     * Axis constant: Vertical Scroll axis of a motion event.
+     *
+     * - For a mouse, reports the relative movement of the vertical scroll wheel.
+     * The value is normalized to a range from -1.0 (down) to 1.0 (up).
+     *
+     * The framework may use this axis to scroll views vertically.
+     */
+    VSCROLL = 9,
+    /**
+     * Axis constant: Horizontal Scroll axis of a motion event.
+     *
+     * - For a mouse, reports the relative movement of the horizontal scroll wheel.
+     * The value is normalized to a range from -1.0 (left) to 1.0 (right).
+     *
+     * The framework may use this axis to scroll views horizontally.
+     */
+    HSCROLL = 10,
+    /**
+     * Axis constant: Z axis of a motion event.
+     *
+     * - For a joystick, reports the absolute Z position of the joystick.
+     * The value is normalized to a range from -1.0 (high) to 1.0 (low).
+     * <em>On game pads with two analog joysticks, this axis is often reinterpreted
+     * to report the absolute X position of the second joystick instead.</em>
+     */
+    Z = 11,
+    /**
+     * Axis constant: X Rotation axis of a motion event.
+     *
+     * - For a joystick, reports the absolute rotation angle about the X axis.
+     * The value is normalized to a range from -1.0 (counter-clockwise) to 1.0 (clockwise).
+     */
+    RX = 12,
+    /**
+     * Axis constant: Y Rotation axis of a motion event.
+     *
+     * - For a joystick, reports the absolute rotation angle about the Y axis.
+     * The value is normalized to a range from -1.0 (counter-clockwise) to 1.0 (clockwise).
+     */
+    RY = 13,
+    /**
+     * Axis constant: Z Rotation axis of a motion event.
+     *
+     * - For a joystick, reports the absolute rotation angle about the Z axis.
+     * The value is normalized to a range from -1.0 (counter-clockwise) to 1.0 (clockwise).
+     * On game pads with two analog joysticks, this axis is often reinterpreted
+     * to report the absolute Y position of the second joystick instead.
+     */
+    RZ = 14,
+    /**
+     * Axis constant: Hat X axis of a motion event.
+     *
+     * - For a joystick, reports the absolute X position of the directional hat control.
+     * The value is normalized to a range from -1.0 (left) to 1.0 (right).
+     */
+    HAT_X = 15,
+    /**
+     * Axis constant: Hat Y axis of a motion event.
+     *
+     * - For a joystick, reports the absolute Y position of the directional hat control.
+     * The value is normalized to a range from -1.0 (up) to 1.0 (down).
+     */
+    HAT_Y = 16,
+    /**
+     * Axis constant: Left Trigger axis of a motion event.
+     *
+     * - For a joystick, reports the absolute position of the left trigger control.
+     * The value is normalized to a range from 0.0 (released) to 1.0 (fully pressed).
+     */
+    LTRIGGER = 17,
+    /**
+     * Axis constant: Right Trigger axis of a motion event.
+     *
+     * - For a joystick, reports the absolute position of the right trigger control.
+     * The value is normalized to a range from 0.0 (released) to 1.0 (fully pressed).
+     */
+    RTRIGGER = 18,
+    /**
+     * Axis constant: Throttle axis of a motion event.
+     *
+     * - For a joystick, reports the absolute position of the throttle control.
+     * The value is normalized to a range from 0.0 (fully open) to 1.0 (fully closed).
+     */
+    THROTTLE = 19,
+    /**
+     * Axis constant: Rudder axis of a motion event.
+     *
+     * - For a joystick, reports the absolute position of the rudder control.
+     * The value is normalized to a range from -1.0 (turn left) to 1.0 (turn right).
+     */
+    RUDDER = 20,
+    /**
+     * Axis constant: Wheel axis of a motion event.
+     *
+     * - For a joystick, reports the absolute position of the steering wheel control.
+     * The value is normalized to a range from -1.0 (turn left) to 1.0 (turn right).
+     */
+    WHEEL = 21,
+    /**
+     * Axis constant: Gas axis of a motion event.
+     *
+     * - For a joystick, reports the absolute position of the gas (accelerator) control.
+     * The value is normalized to a range from 0.0 (no acceleration)
+     * to 1.0 (maximum acceleration).
+     */
+    GAS = 22,
+    /**
+     * Axis constant: Brake axis of a motion event.
+     *
+     * - For a joystick, reports the absolute position of the brake control.
+     * The value is normalized to a range from 0.0 (no braking) to 1.0 (maximum braking).
+     */
+    BRAKE = 23,
+    /**
+     * Axis constant: Distance axis of a motion event.
+     *
+     * - For a stylus, reports the distance of the stylus from the screen.
+     * A value of 0.0 indicates direct contact and larger values indicate increasing
+     * distance from the surface.
+     */
+    DISTANCE = 24,
+    /**
+     * Axis constant: Tilt axis of a motion event.
+     *
+     * - For a stylus, reports the tilt angle of the stylus in radians where
+     * 0 radians indicates that the stylus is being held perpendicular to the
+     * surface, and PI/2 radians indicates that the stylus is being held flat
+     * against the surface.
+     */
+    TILT = 25,
+    /**
+     * Axis constant:  Generic scroll axis of a motion event.
+     *
+     * - This is used for scroll axis motion events that can't be classified as strictly
+     *   vertical or horizontal. The movement of a rotating scroller is an example of this.
+     */
+    SCROLL = 26,
+    /**
+     * Axis constant: The movement of x position of a motion event.
+     *
+     * - For a mouse, reports a difference of x position between the previous position.
+     * This is useful when pointer is captured, in that case the mouse pointer doesn't
+     * change the location but this axis reports the difference which allows the app
+     * to see how the mouse is moved.
+     */
+    RELATIVE_X = 27,
+    /**
+     * Axis constant: The movement of y position of a motion event.
+     *
+     * Same as {@link RELATIVE_X}, but for y position.
+     */
+    RELATIVE_Y = 28,
+    /**
+     * Axis constant: Generic 1 axis of a motion event.
+     * The interpretation of a generic axis is device-specific.
+     */
+    GENERIC_1 = 32,
+    /**
+     * Axis constant: Generic 2 axis of a motion event.
+     * The interpretation of a generic axis is device-specific.
+     */
+    GENERIC_2 = 33,
+    /**
+     * Axis constant: Generic 3 axis of a motion event.
+     * The interpretation of a generic axis is device-specific.
+     */
+    GENERIC_3 = 34,
+    /**
+     * Axis constant: Generic 4 axis of a motion event.
+     * The interpretation of a generic axis is device-specific.
+     */
+    GENERIC_4 = 35,
+    /**
+     * Axis constant: Generic 5 axis of a motion event.
+     * The interpretation of a generic axis is device-specific.
+     */
+    GENERIC_5 = 36,
+    /**
+     * Axis constant: Generic 6 axis of a motion event.
+     * The interpretation of a generic axis is device-specific.
+     */
+    GENERIC_6 = 37,
+    /**
+     * Axis constant: Generic 7 axis of a motion event.
+     * The interpretation of a generic axis is device-specific.
+     */
+    GENERIC_7 = 38,
+    /**
+     * Axis constant: Generic 8 axis of a motion event.
+     * The interpretation of a generic axis is device-specific.
+     */
+    GENERIC_8 = 39,
+    /**
+     * Axis constant: Generic 9 axis of a motion event.
+     * The interpretation of a generic axis is device-specific.
+     */
+    GENERIC_9 = 40,
+    /**
+     * Axis constant: Generic 10 axis of a motion event.
+     * The interpretation of a generic axis is device-specific.
+     */
+    GENERIC_10 = 41,
+    /**
+     * Axis constant: Generic 11 axis of a motion event.
+     * The interpretation of a generic axis is device-specific.
+     */
+    GENERIC_11 = 42,
+    /**
+     * Axis constant: Generic 12 axis of a motion event.
+     * The interpretation of a generic axis is device-specific.
+     */
+    GENERIC_12 = 43,
+    /**
+     * Axis constant: Generic 13 axis of a motion event.
+     * The interpretation of a generic axis is device-specific.
+     */
+    GENERIC_13 = 44,
+    /**
+     * Axis constant: Generic 14 axis of a motion event.
+     * The interpretation of a generic axis is device-specific.
+     */
+    GENERIC_14 = 45,
+    /**
+     * Axis constant: Generic 15 axis of a motion event.
+     * The interpretation of a generic axis is device-specific.
+     */
+    GENERIC_15 = 46,
+    /**
+     * Axis constant: Generic 16 axis of a motion event.
+     * The interpretation of a generic axis is device-specific.
+     */
+    GENERIC_16 = 47,
+};
+
+/**
+ * Tool type of a pointer
+ */
+enum ToolType: uint8_t {
+    UNKNOWN = 0,
+    FINGER = 1,
+    STYLUS = 2,
+    MOUSE = 3,
+    ERASER = 4,
+};
+
+/**
+ * Properties of a particular pointer. Analogous to Android's PointerProperties.
+ */
+struct PointerProperties {
+    /**
+     * A number identifying a specific pointer. When a pointer is lifted,
+     * this value may be reused by another new pointer, even during the
+     * same gesture. For example, if there are two pointers touching the screen
+     * at the same time, they might have pointer ID's of 0 and 1. If the
+     * pointer with id = 0 is lifted, while the pointer with id = 1 remains, and
+     * a new pointer is placed on the screen, then the new pointer may receive
+     * an id of 0. While a pointer is active, it is guaranteed to keep the same
+     * id.
+     */
+    int32_t id;
+    /**
+     * Type of tool used to make contact, such as a finger or stylus, if known.
+     */
+    ToolType toolType;
+};
+
+/**
+ * Pointer coordinate data. Analogous to Android's PointerCoords.
+ */
+struct PointerCoords {
+    /**
+     * Bitfield of axes that are present in this structure.
+     */
+    bitfield<Axis> bits;
+    /**
+     * The values corresponding to each non-zero axis. This vector only
+     * contains non-zero entries. If an axis that is not currently specified
+     * in "bits" is requested, a zero value is returned.
+     * There are only as many values stored here
+     * as there are non-zero bits in the "bits" field.
+     * The values are position-packed. So the first non-zero axis will be
+     * at position 0, the next non-zero axis will be at position 1, and so on.
+     */
+    vec<float> values;
+};
+
+enum SourceClass: uint8_t {
+    NONE = 1 << 0,
+    BUTTON = 1 << 1,
+    POINTER = 1 << 2,
+    NAVIGATION = 1 << 3,
+    POSITION = 1 << 4,
+    JOYSTICK = 1 << 5,
+};
+
+/**
+ * Input sources
+ */
+enum Source: uint32_t {
+    UNKNOWN = 0,
+    KEYBOARD = (1 << 8) | SourceClass:BUTTON,
+    DPAD = (1 << 9) | SourceClass:BUTTON,
+    GAMEPAD = (1 << 10) | SourceClass:BUTTON,
+    TOUCHSCREEN = (1 << 12) | SourceClass:POINTER,
+    MOUSE = (1 << 13) | SourceClass:POINTER,
+    STYLUS = (1 << 14) | SourceClass:POINTER,
+    BLUETOOTH_STYLUS = (1 << 15) | STYLUS,
+    TRACKBALL = (1 << 16) | SourceClass:NAVIGATION,
+    MOUSE_RELATIVE = (1 << 17) | SourceClass:NAVIGATION,
+    TOUCHPAD = (1 << 20) | SourceClass:POSITION,
+    TOUCH_NAVIGATION = (1 << 21) | SourceClass:NONE,
+    ROTARY_ENCODER = (1 << 22) | SourceClass:NONE,
+    JOYSTICK = (1 << 24) | SourceClass:JOYSTICK,
+    ANY = 0xFFFFFF00,
+};
+
+/** Motion event actions */
+enum Action: int32_t {
+    /** A pressed gesture has started, the motion contains the initial starting location. */
+    DOWN = 0,
+    /**
+     * A pressed gesture has finished, the motion contains the final release location
+     * as well as any intermediate points since the last down or move event.
+     */
+    UP = 1,
+    /**
+     * A change has happened during a press gesture (between AMOTION_EVENT_ACTION_DOWN and
+     * AMOTION_EVENT_ACTION_UP). The motion contains the most recent point.
+     */
+    MOVE = 2,
+    /**
+     * The current gesture has been aborted.
+     * You will not receive any more points in it. You must treat this as
+     * an up event, but not perform any action that you normally would.
+     */
+    CANCEL = 3,
+    /**
+     * A movement has happened outside of the normal bounds of the UI element.
+     * This does not provide a full gesture, but only the initial location of the movement/touch.
+     */
+    OUTSIDE = 4,
+    /**
+     * A non-primary pointer has gone down.
+     */
+    POINTER_DOWN = 5,
+    /**
+     * A non-primary pointer has gone up.
+     */
+    POINTER_UP = 6,
+    /**
+     * A change happened but the pointer is not down (unlike AMOTION_EVENT_ACTION_MOVE).
+     * The motion contains the most recent point, as well as any intermediate points since
+     * the last hover move event.
+     */
+    HOVER_MOVE = 7,
+    /**
+     * The motion event contains relative vertical and/or horizontal scroll offsets.
+     * Use getAxisValue to retrieve the information from AMOTION_EVENT_AXIS_VSCROLL
+     * and AMOTION_EVENT_AXIS_HSCROLL.
+     * The pointer may or may not be down when this event is dispatched.
+     * The framework will always deliver this action to the window under the pointer, which
+     * may not be the window currently touched.
+     */
+    SCROLL = 8,
+    /**
+     * The pointer is not down but has entered the boundaries of a window or view.
+     */
+    HOVER_ENTER = 9,
+    /**
+     * The pointer is not down but has exited the boundaries of a window or view.
+     */
+    HOVER_EXIT = 10,
+    /**
+     * One or more buttons have been pressed.
+     */
+    BUTTON_PRESS = 11,
+    /**
+     * One or more buttons have been released.
+     */
+    BUTTON_RELEASE = 12,
+};
+
+/** Edge flags */
+enum EdgeFlag : int32_t {
+    /** No edges are intersected */
+    NONE = 0,
+    /** Motion intersected top edge of the screen */
+    TOP = 1 << 0,
+    /** Motion intersected bottom edge of the screen */
+    BOTTOM = 1 << 1,
+    /** Motion intersected left edge of the screen */
+    LEFT = 1 << 2,
+    /** Motion intersected right edge of the screen */
+    RIGHT = 1 << 3,
+};
+
+/** Policy flags */
+enum PolicyFlag : uint32_t {
+    // The following flags originate in RawEvents
+
+    /** Event should wake the device */
+    WAKE = 1 << 0,
+    /** Key is virtual, and should generate haptic feedback */
+    VIRTUAL = 1 << 1,
+    /** Key is the special function modifier */
+    FUNCTION = 1 << 2,
+    /**
+     * Key represents a special gesture that has been detected
+     * by the touch firmware or driver.
+     */
+    GESTURE = 1 << 3,
+
+    // The following flags may be generated here in the InputClassifier HAL
+    // or in later InputListener stages
+
+    /** Event was injected */
+    INJECTED = 1 << 24,
+    /**
+     * Event comes from a trusted source, such as a directly attached input
+     * device or an application with system-wide event injection permission.
+     */
+    TRUSTED = 1 << 25,
+    /** Event has passed through an input filter. */
+    FILTERED = 1 << 26,
+    /** Disable automatic key repeating behaviour. */
+    DISABLE_KEY_REPEAT = 1 << 27,
+
+    // The following flags are set by the input reader policy as it intercepts each event
+
+    /** Device was in an interactive state when the event was intercepted */
+    INTERACTIVE = 1 << 29,
+    /** Event should be dispatched to applications */
+    PASS_TO_USER = 1 << 30,
+};
+
+/**
+ * Buttons that are associated with motion events.
+ */
+enum Button : int32_t {
+    NONE = 0,
+    PRIMARY = 1 << 0,
+    SECONDARY = 1 << 1,
+    TERTIARY = 1 << 2,
+    BACK = 1 << 3,
+    FORWARD = 1 << 4,
+    STYLUS_PRIMARY = 1 << 5,
+    STYLUS_SECONDARY = 1 << 6,
+};
+
+/**
+ * Meta key / modifier state
+ */
+enum Meta : int32_t {
+    NONE = 0,
+
+    /** One of the ALT meta keys is pressed. */
+    ALT_ON = 1 << 1, // 0x02
+
+    /** The left ALT meta key is pressed. */
+    ALT_LEFT_ON = 1 << 4, // 0x10
+
+    /** The right ALT meta key is pressed. */
+    ALT_RIGHT_ON = 1 << 5, // 0x20
+
+    /** One of the SHIFT meta keys is pressed. */
+    SHIFT_ON = 1 << 0, // 0x01
+
+    /** The left SHIFT meta key is pressed. */
+    SHIFT_LEFT_ON = 1 << 6, // 0x40
+
+    /** The right SHIFT meta key is pressed. */
+    SHIFT_RIGHT_ON = 1 << 7, // 0x80
+
+    /** The SYM meta key is pressed. */
+    SYM_ON = 1 << 2, // 0x04
+
+    /** The FUNCTION meta key is pressed. */
+    FUNCTION_ON = 1 << 3, // 0x08
+
+    /** One of the CTRL meta keys is pressed. */
+    CTRL_ON = 1 << 12, // 0x1000
+
+    /** The left CTRL meta key is pressed. */
+    CTRL_LEFT_ON = 1 << 13, // 0x2000
+
+    /** The right CTRL meta key is pressed. */
+    CTRL_RIGHT_ON = 1 << 14, // 0x4000
+
+    /** One of the META meta keys is pressed. */
+    META_ON = 1 << 16, // 0x10000
+
+    /** The left META meta key is pressed. */
+    META_LEFT_ON = 1 << 17, // 0x20000
+
+    /** The right META meta key is pressed. */
+    META_RIGHT_ON = 1 << 18, //0x40000
+
+    /** The CAPS LOCK meta key is on. */
+    CAPS_LOCK_ON = 1 << 20, // 0x100000
+
+    /** The NUM LOCK meta key is on. */
+    NUM_LOCK_ON = 1 << 21, // 0x200000
+
+    /** The SCROLL LOCK meta key is on. */
+    SCROLL_LOCK_ON = 1 << 22, // 0x400000
+};
+
+/**
+ * Motion event flags
+ */
+enum Flag : int32_t {
+    /**
+     * Indicates that the window that received this motion event is partly
+     * or wholly obscured by another visible window above it. This flag is set to true
+     * even if the event did not directly pass through the obscured area.
+     * A security sensitive application can check this flag to identify situations in which
+     * a malicious application may have covered up part of its content for the purpose
+     * of misleading the user or hijacking touches. An appropriate response might be
+     * to drop the suspect touches or to take additional precautions to confirm the user's
+     * actual intent.
+     */
+    WINDOW_IS_OBSCURED = 1 << 0,
+    /**
+     * This flag indicates that the event has been generated by a gesture generator. It
+     * could be used, for example, to determine whether touch slop should be applied.
+     */
+    IS_GENERATED_GESTURE = 1 << 3, // 0x8
+    /**
+     * Motion event is inconsistent with previously sent motion events.
+     */
+    TAINTED = 1 << 31, // 0x80000000
+};
+
+/**
+ * Touch heatmap.
+ *
+ * The array is a 2-D row-major matrix with dimensions (height, width).
+ * The heatmap data does not rotate when device orientation changes.
+ *
+ * Example:
+ *
+ * If the data in the array is:
+ * data[i] = i for i in 0 .. 59,
+ * then it can be represented as follows:
+ *
+ *  <--    width   -- >
+ *   0  1  2  3  4  5   ^
+ *   6  7  8  9 10 11   |
+ *  12 12 14 15 16 17   |
+ *  18    ...      23   | height
+ *  24    ...      29   |
+ *  30    ...      35   |
+ *  36    ...      41   |
+ *  42    ...      47   |
+ *  48    ...      53   |
+ *  54    ...      59   v
+ *
+ * Looking at the device in standard portrait orientation,
+ * the element "0" is the top left of the screen,
+ * "5" is at the top right, and "59" is the bottom right.
+ * Here width=6, and height=10.
+ */
+struct VideoFrame {
+    /**
+     * Video frame data.
+     * Size of the data is width * height.
+     */
+    vec<int16_t> data;
+    uint32_t width;
+    uint32_t height;
+    /**
+     * Time at which the frame was collected, in nanoseconds.
+     * Measured with the same clock that is used to populate MotionEvent times.
+     */
+    uint64_t timestamp;
+};
+
+/**
+ * Analogous to Android's native MotionEvent / NotifyMotionArgs.
+ * Stores the basic information about pointer movements.
+ */
+struct MotionEvent {
+    // InputEvent fields
+    /**
+     * The id of the device which produced this event.
+     */
+    int32_t deviceId;
+    /**
+     * The source type of this event.
+     */
+    Source source;
+    /**
+     * The display id associated with this event.
+     */
+    int32_t displayId;
+
+    // NotifyMotionArgs fields
+    /**
+     * Time when the initial touch down occurred, in nanoseconds.
+     */
+    int64_t downTime;
+    /**
+     * Time when this event occurred, in nanoseconds.
+     */
+    int64_t eventTime;
+    /**
+     * The kind of action being performed.
+     */
+    Action action;
+    /**
+     * For ACTION_POINTER_DOWN or ACTION_POINTER_UP, this contains the associated pointer index.
+     * The index may be used to get information about the pointer that has gone down or up.
+     */
+    uint8_t actionIndex;
+    /**
+     * The button that has been modified during a press or release action.
+     */
+    Button actionButton;
+    /**
+     * The motion event flags.
+     */
+    bitfield<Flag> flags;
+    /**
+     * The motion event policy flags.
+     */
+    bitfield<PolicyFlag> policyFlags;
+    /**
+     * The edges, if any, that were touched by this motion event.
+     */
+    bitfield<EdgeFlag> edgeFlags;
+    /**
+     * The state of any meta / modifier keys that were in effect when the event was generated.
+     */
+    bitfield<Meta> metaState;
+    /**
+     * The state of buttons that are pressed.
+     */
+    bitfield<Button> buttonState;
+    /**
+     * The precision of the X coordinate being reported.
+     */
+    float xPrecision;
+    /**
+     * The precision of the Y coordinate being reported.
+     */
+    float yPrecision;
+    /**
+     * The properties of each pointer present in this motion event.
+     */
+    vec<PointerProperties> pointerProperties;
+    /**
+     * The coordinates of each pointer.
+     */
+    vec<PointerCoords> pointerCoords;
+
+    // Additional fields from NotifyMotionArgs
+    /**
+     * Device time at which the event occurred, in microseconds.
+     * Will wrap after a little over an hour.
+     */
+    uint32_t deviceTimestamp;
+    /**
+     * The video frames, if any, associated with the current or previous motion events.
+     */
+    vec<VideoFrame> frames;
+};
+
+
+enum Classification : uint8_t {
+    NONE = 0,
+    /**
+     * Too early to classify the gesture, need more events.
+     */
+    AMBIGUOUS_GESTURE = 1,
+    /**
+     * User is force-pressing the screen.
+     */
+    DEEP_PRESS = 2,
+};
diff --git a/keymaster/3.0/vts/functional/keymaster_tags.h b/keymaster/3.0/vts/functional/keymaster_tags.h
index f241ef1..8544bf7 100644
--- a/keymaster/3.0/vts/functional/keymaster_tags.h
+++ b/keymaster/3.0/vts/functional/keymaster_tags.h
@@ -274,7 +274,10 @@
  */
 template <typename ValueT> class NullOr {
     template <typename T> struct reference_initializer {
+#pragma GCC diagnostic push
+#pragma GCC diagnostic ignored "-Wnull-dereference"
         static T&& init() { return *static_cast<std::remove_reference_t<T>*>(nullptr); }
+#pragma GCC diagnostic pop
     };
     template <typename T> struct pointer_initializer {
         static T init() { return nullptr; }
diff --git a/keymaster/4.0/support/include/keymasterV4_0/keymaster_tags.h b/keymaster/4.0/support/include/keymasterV4_0/keymaster_tags.h
index 61c444c..97dab68 100644
--- a/keymaster/4.0/support/include/keymasterV4_0/keymaster_tags.h
+++ b/keymaster/4.0/support/include/keymasterV4_0/keymaster_tags.h
@@ -282,7 +282,10 @@
 class NullOr {
     template <typename T>
     struct reference_initializer {
+#pragma GCC diagnostic push
+#pragma GCC diagnostic ignored "-Wnull-dereference"
         static T&& init() { return *static_cast<std::remove_reference_t<T>*>(nullptr); }
+#pragma GCC diagnostic pop
     };
     template <typename T>
     struct pointer_initializer {
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 7c55cab..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,
@@ -160,6 +160,7 @@
     REDUCE_MIN = 94,
     REDUCE_ANY = 95,
     REDUCE_ALL = 96,
+    INSTANCE_NORMALIZATION = 97,
     /* ADDING A NEW FUNDAMENTAL OPERATION REQUIRES UPDATING THE VALUE OF
      * OperationTypeRange::OPERATION_FUNDAMENTAL_MAX.
      */
@@ -173,7 +174,7 @@
  */
 enum OperationTypeRange : uint32_t {
     OPERATION_FUNDAMENTAL_MIN = 0,
-    OPERATION_FUNDAMENTAL_MAX = 96,
+    OPERATION_FUNDAMENTAL_MAX = 97,
     OPERATION_OEM_MIN = 10000,
     OPERATION_OEM_MAX = 10000,
 };
@@ -233,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
@@ -254,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;
 
@@ -396,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/nfc/1.2/Android.bp b/nfc/1.2/Android.bp
new file mode 100644
index 0000000..c338e02
--- /dev/null
+++ b/nfc/1.2/Android.bp
@@ -0,0 +1,23 @@
+// This file is autogenerated by hidl-gen -Landroidbp.
+
+hidl_interface {
+    name: "android.hardware.nfc@1.2",
+    root: "android.hardware",
+    vndk: {
+        enabled: true,
+    },
+    srcs: [
+        "types.hal",
+        "INfc.hal",
+    ],
+    interfaces: [
+        "android.hardware.nfc@1.0",
+        "android.hardware.nfc@1.1",
+        "android.hidl.base@1.0",
+    ],
+    types: [
+        "NfcConfig",
+    ],
+    gen_java: true,
+}
+
diff --git a/nfc/1.2/INfc.hal b/nfc/1.2/INfc.hal
new file mode 100644
index 0000000..4788fd7
--- /dev/null
+++ b/nfc/1.2/INfc.hal
@@ -0,0 +1,28 @@
+/*
+ * Copyright (C) 2017 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package android.hardware.nfc@1.2;
+
+import @1.1::INfc;
+import @1.2::NfcConfig;
+
+interface INfc extends @1.1::INfc {
+    /**
+     * Fetches vendor specific configurations.
+     * @return config indicates support for certain features and
+     *     populates the vendor specific configs
+     */
+    getConfig_1_2() generates (NfcConfig config);
+};
diff --git a/nfc/1.2/types.hal b/nfc/1.2/types.hal
new file mode 100644
index 0000000..d6db9a8
--- /dev/null
+++ b/nfc/1.2/types.hal
@@ -0,0 +1,32 @@
+/*
+ * Copyright (C) 2017 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package android.hardware.nfc@1.2;
+
+import @1.1::NfcConfig;
+
+struct NfcConfig {
+    @1.1::NfcConfig v1_1;
+
+    /*
+     * NFCEE ID for offhost UICC & eSE secure element.
+     * 0x00 if there aren't any. Refer NCI specification
+     */
+    vec<uint8_t> offHostRouteUicc;
+    vec<uint8_t> offHostRouteEse;
+
+    /** Default IsoDep route. 0x00 if there aren't any. Refer NCI spec */
+    uint8_t defaultIsoDepRoute;
+};
diff --git a/nfc/1.2/vts/functional/Android.bp b/nfc/1.2/vts/functional/Android.bp
new file mode 100644
index 0000000..13b254c
--- /dev/null
+++ b/nfc/1.2/vts/functional/Android.bp
@@ -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.
+//
+
+cc_test {
+    name: "VtsHalNfcV1_2TargetTest",
+    defaults: ["VtsHalTargetTestDefaults"],
+    srcs: ["VtsHalNfcV1_2TargetTest.cpp"],
+    static_libs: [
+        "android.hardware.nfc@1.0",
+        "android.hardware.nfc@1.1",
+        "android.hardware.nfc@1.2",
+    ],
+}
diff --git a/nfc/1.2/vts/functional/VtsHalNfcV1_2TargetTest.cpp b/nfc/1.2/vts/functional/VtsHalNfcV1_2TargetTest.cpp
new file mode 100644
index 0000000..ee4a887
--- /dev/null
+++ b/nfc/1.2/vts/functional/VtsHalNfcV1_2TargetTest.cpp
@@ -0,0 +1,187 @@
+/*
+ * Copyright (C) 2018 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#define LOG_TAG "nfc_hidl_hal_test"
+#include <android-base/logging.h>
+
+#include <android/hardware/nfc/1.1/INfcClientCallback.h>
+#include <android/hardware/nfc/1.2/INfc.h>
+#include <android/hardware/nfc/1.2/types.h>
+#include <hardware/nfc.h>
+
+#include <VtsHalHidlTargetCallbackBase.h>
+#include <VtsHalHidlTargetTestBase.h>
+#include <VtsHalHidlTargetTestEnvBase.h>
+
+using ::android::sp;
+using ::android::hardware::hidl_vec;
+using ::android::hardware::Return;
+using ::android::hardware::Void;
+using ::android::hardware::nfc::V1_0::NfcData;
+using ::android::hardware::nfc::V1_0::NfcStatus;
+using ::android::hardware::nfc::V1_1::INfcClientCallback;
+using ::android::hardware::nfc::V1_1::NfcEvent;
+using ::android::hardware::nfc::V1_2::INfc;
+using ::android::hardware::nfc::V1_2::NfcConfig;
+
+// Range of valid off host route ids
+constexpr unsigned int MIN_OFFHOST_ROUTE_ID = 0x80;
+constexpr unsigned int MAX_OFFHOST_ROUTE_ID = 0xFE;
+
+constexpr char kCallbackNameSendEvent[] = "sendEvent";
+constexpr char kCallbackNameSendData[] = "sendData";
+
+class NfcClientCallbackArgs {
+   public:
+    NfcEvent last_event_;
+    NfcStatus last_status_;
+    NfcData last_data_;
+};
+
+/* Callback class for data & Event. */
+class NfcClientCallback : public ::testing::VtsHalHidlTargetCallbackBase<NfcClientCallbackArgs>,
+                          public INfcClientCallback {
+   public:
+    virtual ~NfcClientCallback() = default;
+
+    /* sendEvent callback function - Records the Event & Status
+     * and notifies the TEST
+     **/
+    Return<void> sendEvent_1_1(NfcEvent event, NfcStatus event_status) override {
+        NfcClientCallbackArgs args;
+        args.last_event_ = event;
+        args.last_status_ = event_status;
+        NotifyFromCallback(kCallbackNameSendEvent, args);
+        return Void();
+    };
+
+    /** NFC 1.1 HAL shouldn't send 1.0 callbacks */
+    Return<void> sendEvent(__attribute__((unused))::android::hardware::nfc::V1_0::NfcEvent event,
+                           __attribute__((unused)) NfcStatus event_status) override {
+        return Void();
+    }
+
+    /* sendData callback function. Records the data and notifies the TEST*/
+    Return<void> sendData(const NfcData& data) override {
+        NfcClientCallbackArgs args;
+        args.last_data_ = data;
+        NotifyFromCallback(kCallbackNameSendData, args);
+        return Void();
+    };
+};
+
+// Test environment for Nfc HIDL HAL.
+class NfcHidlEnvironment : public ::testing::VtsHalHidlTargetTestEnvBase {
+   public:
+    // get the test environment singleton
+    static NfcHidlEnvironment* Instance() {
+        static NfcHidlEnvironment* instance = new NfcHidlEnvironment;
+        return instance;
+    }
+
+    virtual void registerTestServices() override { registerTestService<INfc>(); }
+
+   private:
+    NfcHidlEnvironment() {}
+};
+
+// The main test class for NFC HIDL HAL.
+class NfcHidlTest : public ::testing::VtsHalHidlTargetTestBase {
+   public:
+    virtual void SetUp() override {
+        nfc_ = ::testing::VtsHalHidlTargetTestBase::getService<INfc>();
+        ASSERT_NE(nfc_, nullptr);
+
+        nfc_cb_ = new NfcClientCallback();
+        ASSERT_NE(nfc_cb_, nullptr);
+
+        EXPECT_EQ(NfcStatus::OK, nfc_->open_1_1(nfc_cb_));
+        // Wait for OPEN_CPLT event
+        auto res = nfc_cb_->WaitForCallback(kCallbackNameSendEvent);
+        EXPECT_TRUE(res.no_timeout);
+        EXPECT_EQ(NfcEvent::OPEN_CPLT, res.args->last_event_);
+        EXPECT_EQ(NfcStatus::OK, res.args->last_status_);
+
+        /*
+         * Close the hal and then re-open to make sure we are in a predictable
+         * state for all the tests.
+         */
+        EXPECT_EQ(NfcStatus::OK, nfc_->close());
+        // Wait for CLOSE_CPLT event
+        res = nfc_cb_->WaitForCallback(kCallbackNameSendEvent);
+        EXPECT_TRUE(res.no_timeout);
+        EXPECT_EQ(NfcEvent::CLOSE_CPLT, res.args->last_event_);
+        EXPECT_EQ(NfcStatus::OK, res.args->last_status_);
+
+        EXPECT_EQ(NfcStatus::OK, nfc_->open_1_1(nfc_cb_));
+        // Wait for OPEN_CPLT event
+        res = nfc_cb_->WaitForCallback(kCallbackNameSendEvent);
+        EXPECT_TRUE(res.no_timeout);
+        EXPECT_EQ(NfcEvent::OPEN_CPLT, res.args->last_event_);
+        EXPECT_EQ(NfcStatus::OK, res.args->last_status_);
+    }
+
+    virtual void TearDown() override {
+        EXPECT_EQ(NfcStatus::OK, nfc_->close());
+        // Wait for CLOSE_CPLT event
+        auto res = nfc_cb_->WaitForCallback(kCallbackNameSendEvent);
+        EXPECT_TRUE(res.no_timeout);
+        EXPECT_EQ(NfcEvent::CLOSE_CPLT, res.args->last_event_);
+        EXPECT_EQ(NfcStatus::OK, res.args->last_status_);
+    }
+
+    sp<INfc> nfc_;
+    sp<NfcClientCallback> nfc_cb_;
+};
+
+/*
+ * getConfig:
+ * Calls getConfig()
+ * checks if fields in NfcConfig are populated correctly
+ */
+TEST_F(NfcHidlTest, GetExtendedConfig) {
+    nfc_->getConfig_1_2([](NfcConfig config) {
+        for (uint8_t uicc : config.offHostRouteUicc) {
+            EXPECT_GE(uicc, MIN_OFFHOST_ROUTE_ID);
+            EXPECT_LE(uicc, MAX_OFFHOST_ROUTE_ID);
+        }
+        for (uint8_t ese : config.offHostRouteEse) {
+            EXPECT_GE(ese, MIN_OFFHOST_ROUTE_ID);
+            EXPECT_LE(ese, MAX_OFFHOST_ROUTE_ID);
+        }
+        if (config.defaultIsoDepRoute != 0) {
+            EXPECT_GE(config.defaultIsoDepRoute, MIN_OFFHOST_ROUTE_ID);
+            EXPECT_LE(config.defaultIsoDepRoute, MAX_OFFHOST_ROUTE_ID);
+        }
+    });
+}
+
+int main(int argc, char** argv) {
+    ::testing::AddGlobalTestEnvironment(NfcHidlEnvironment::Instance());
+    ::testing::InitGoogleTest(&argc, argv);
+    NfcHidlEnvironment::Instance()->init(&argc, argv);
+
+    std::system("svc nfc disable"); /* Turn off NFC */
+    sleep(5);
+
+    int status = RUN_ALL_TESTS();
+    LOG(INFO) << "Test result = " << status;
+
+    std::system("svc nfc enable"); /* Turn on NFC */
+    sleep(5);
+
+    return status;
+}
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/Android.bp b/radio/1.4/Android.bp
index ad114f3..32f9712 100644
--- a/radio/1.4/Android.bp
+++ b/radio/1.4/Android.bp
@@ -30,6 +30,7 @@
         "DataConnActiveStatus",
         "DataProfileInfo",
         "DataRegStateResult",
+        "EmergencyCallRouting",
         "EmergencyNumber",
         "EmergencyNumberSource",
         "EmergencyServiceCategory",
diff --git a/radio/1.4/IRadio.hal b/radio/1.4/IRadio.hal
index 8438777..3f4b1a5 100644
--- a/radio/1.4/IRadio.hal
+++ b/radio/1.4/IRadio.hal
@@ -18,9 +18,11 @@
 
 import @1.0::Dial;
 import @1.2::DataRequestReason;
+import @1.2::NetworkScanRequest;
 import @1.3::IRadio;
 import @1.4::AccessNetwork;
 import @1.4::DataProfileInfo;
+import @1.4::EmergencyCallRouting;
 import @1.4::EmergencyServiceCategory;
 import @1.4::RadioAccessFamily;
 
@@ -101,33 +103,60 @@
     oneway setDataProfile_1_4(int32_t serial, vec<DataProfileInfo> profiles);
 
     /**
-     * Initiate emergency voice call, with zero or more emergency service category(s).
+     * 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.
      *
-     * Note this API is the same as IRadio.dial except using the
-     * @1.4::EmergencyServiceCategory as the input param.
+     * 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.
      *
-     * If the number in the 'dialInfo' field is identified as an emergency number in Android,
-     * Android use this request for its emergency call instead of @1.0::IRadio.dial. The
-     * implementation decides how to handle the call (e.g. emergency routing or normal
-     * routing).
+     * 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
+     * @1.4::EmergencyNumberRouting#NORMAL, the implementation must use normal call routing to
+     * handle the call; if it is specified as @1.4::EmergencyNumberRouting#EMERGENCY, the
+     * implementation must use emergency routing to handle the call; if it is
+     * @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; iff either the
-     * 'categories' field is set to @1.4::EmergencyServiceCategory#UNSPECIFIED or the underlying
-     * technology used to request emergency services does not support the emergency service
-     * category, the interpretation of the categories is defined by implementation.
+     * '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);
+            bitfield<EmergencyServiceCategory> categories, vec<string> urns,
+            EmergencyCallRouting routing, bool isTesting);
+
+    /**
+     * Starts a network scan
+     *
+     * @param serial Serial number of request.
+     * @param request Defines the radio networks/bands/channels which need to be scanned.
+     *
+     * Same API as @1.2::IRadio.startNetworkScan_1_2, except using the
+     * @1.4::IRadioResponse.startNetworkScanResponse_1_4 as the response.
+     */
+    oneway startNetworkScan_1_4(int32_t serial, NetworkScanRequest request);
 
     /**
      * Query the preferred network type bitmap.
diff --git a/radio/1.4/IRadioIndication.hal b/radio/1.4/IRadioIndication.hal
index 626b494..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, 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 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.
+     * Radio must report all the valid emergency numbers with known mobile country code, mobile
+     * 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/IRadioResponse.hal b/radio/1.4/IRadioResponse.hal
index df40969..a58a5c1 100644
--- a/radio/1.4/IRadioResponse.hal
+++ b/radio/1.4/IRadioResponse.hal
@@ -50,6 +50,23 @@
 
     /**
      * @param info Response info struct containing response type, serial no. and error
+     *
+     * Same API as @1.1::IRadioResponse.startNetworkScanResponse, except disallowing error codes
+     * OPERATION_NOT_ALLOWED and REQUEST_NOT_SUPPORTED.
+     *
+     * Valid errors returned:
+     *   RadioError:NONE
+     *   RadioError:RADIO_NOT_AVAILABLE
+     *   RadioError:DEVICE_IN_USE
+     *   RadioError:INTERNAL_ERR
+     *   RadioError:NO_MEMORY
+     *   RadioError:MODEM_ERR
+     *   RadioError:INVALID_ARGUMENTS
+     */
+    oneway startNetworkScanResponse_1_4(RadioResponseInfo info);
+
+    /**
+     * @param info Response info struct containing response type, serial no. and error
      * @param cellInfo List of current cell information known to radio
      *
      * Valid errors returned:
diff --git a/radio/1.4/types.hal b/radio/1.4/types.hal
index d0eb0ac..65f6608 100644
--- a/radio/1.4/types.hal
+++ b/radio/1.4/types.hal
@@ -39,6 +39,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;
 
@@ -52,20 +53,27 @@
 };
 
 /**
- * Emergency number contains information of number, one or more service category(s), mobile country
- * code (mcc), 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{
     /**
@@ -87,6 +95,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.
      */
@@ -155,6 +167,25 @@
     DEFAULT = 1 << 3,
 };
 
+/**
+ * Indicates how the implementation should handle the emergency call if it is required by Android.
+ */
+enum EmergencyCallRouting : int32_t {
+    /**
+     * Indicates Android does not require how to handle the corresponding emergency call; it is
+     * decided by implementation.
+     */
+    UNKNOWN = 0,
+    /**
+     * Indicates the implementation must handle the call through emergency routing.
+     */
+    EMERGENCY = 1,
+    /**
+     * Indicates the implementation must handle the call through normal call routing.
+     */
+    NORMAL = 2,
+};
+
 enum RadioTechnology : @1.0::RadioTechnology {
     /** 5G NR. */
     NR = 20,
@@ -1500,15 +1531,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/sensors/2.0/ISensors.hal b/sensors/2.0/ISensors.hal
index 939bf73..3a9af46 100644
--- a/sensors/2.0/ISensors.hal
+++ b/sensors/2.0/ISensors.hal
@@ -77,20 +77,33 @@
      * framework. The Event FMQ is created using the eventQueueDescriptor.
      * Data may only be written to the Event FMQ. Data must not be read from
      * the Event FMQ since the framework is the only reader. Upon receiving
-     * sensor events, the HAL should write the sensor events to the Event FMQ.
+     * sensor events, the HAL writes the sensor events to the Event FMQ.
+     *
      * Once the HAL is finished writing sensor events to the Event FMQ, the HAL
-     * must call the Event FMQ's EventFlag wake() function with the
-     * EventQueueFlagBits::READ_AND_PROCESS mask which notifies the framework
-     * that sensor events are available to be read and processed.
+     * must notify the framework that sensor events are available to be read and
+     * processed. This is accomplished by either:
+     *     1) Calling the Event FMQ’s EventFlag::wake() function with
+              EventQueueFlagBits::READ_AND_PROCESS
+     *     2) Setting the write notification in the Event FMQ’s writeBlocking()
+     *        function to EventQueueFlagBits::READ_AND_PROCESS.
+     *
+     * If the Event FMQ’s writeBlocking() function is used, the read
+     * notification must be set to EventQueueFlagBits::EVENTS_READ in order to
+     * be notified and unblocked when the framework has successfully read events
+     * from the Event FMQ.
      *
      * 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.
@@ -110,6 +123,10 @@
      * any outstanding wake_locks held as a result of WAKE_UP events should be
      * released.
      *
+     * All active sensor requests and direct channels must be closed and
+     * properly cleaned up when initialize is called in order to ensure that the
+     * HAL and framework's state is consistent (e.g. after a runtime restart).
+     *
      * initialize must be thread safe and prevent concurrent calls
      * to initialize from simultaneously modifying state.
      *
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/sensors/2.0/vts/functional/SensorsHidlEnvironmentV2_0.cpp b/sensors/2.0/vts/functional/SensorsHidlEnvironmentV2_0.cpp
index 37b7349..be7415b 100644
--- a/sensors/2.0/vts/functional/SensorsHidlEnvironmentV2_0.cpp
+++ b/sensors/2.0/vts/functional/SensorsHidlEnvironmentV2_0.cpp
@@ -24,10 +24,12 @@
 
 using ::android::hardware::EventFlag;
 using ::android::hardware::hidl_vec;
+using ::android::hardware::Return;
 using ::android::hardware::sensors::V1_0::Result;
 using ::android::hardware::sensors::V1_0::SensorInfo;
 using ::android::hardware::sensors::V2_0::EventQueueFlagBits;
 using ::android::hardware::sensors::V2_0::ISensors;
+using ::android::hardware::sensors::V2_0::ISensorsCallback;
 
 template <typename EnumType>
 constexpr typename std::underlying_type<EnumType>::type asBaseType(EnumType value) {
@@ -36,6 +38,16 @@
 
 constexpr size_t SensorsHidlEnvironmentV2_0::MAX_RECEIVE_BUFFER_EVENT_COUNT;
 
+struct SensorsCallback : ISensorsCallback {
+    Return<void> onDynamicSensorsConnected(const hidl_vec<SensorInfo>& /* sensorInfos */) {
+        return Return<void>();
+    }
+
+    Return<void> onDynamicSensorsDisconnected(const hidl_vec<int32_t>& /* sensorHandles */) {
+        return Return<void>();
+    }
+};
+
 bool SensorsHidlEnvironmentV2_0::resetHal() {
     bool succeed = false;
     do {
@@ -63,7 +75,7 @@
         }
 
         mSensors->initialize(*mEventQueue->getDesc(), *mWakeLockQueue->getDesc(),
-                             nullptr /* TODO: callback */);
+                             new SensorsCallback());
 
         std::vector<SensorInfo> sensorList;
         if (!mSensors->getSensorsList([&](const hidl_vec<SensorInfo>& list) { sensorList = list; })
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/tv/cec/1.0/types.hal b/tv/cec/1.0/types.hal
index c734c4d..ebe65ae 100644
--- a/tv/cec/1.0/types.hal
+++ b/tv/cec/1.0/types.hal
@@ -114,6 +114,8 @@
     VENDOR_COMMAND_WITH_ID = 0xA0,
     CLEAR_EXTERNAL_TIMER = 0xA1,
     SET_EXTERNAL_TIMER = 0xA2,
+    REPORT_SHORT_AUDIO_DESCRIPTOR = 0xA3,
+    REQUEST_SHORT_AUDIO_DESCRIPTOR = 0xA4,
     INITIATE_ARC = 0xC0,
     REPORT_ARC_INITIATED = 0xC1,
     REPORT_ARC_TERMINATED = 0xC2,
diff --git a/vibrator/1.3/Android.bp b/vibrator/1.3/Android.bp
new file mode 100644
index 0000000..28370d6
--- /dev/null
+++ b/vibrator/1.3/Android.bp
@@ -0,0 +1,20 @@
+// This file is autogenerated by hidl-gen -Landroidbp.
+
+hidl_interface {
+    name: "android.hardware.vibrator@1.3",
+    root: "android.hardware",
+    vndk: {
+        enabled: true,
+    },
+    srcs: [
+        "IVibrator.hal",
+    ],
+    interfaces: [
+        "android.hardware.vibrator@1.0",
+        "android.hardware.vibrator@1.1",
+        "android.hardware.vibrator@1.2",
+        "android.hidl.base@1.0",
+    ],
+    gen_java: true,
+}
+
diff --git a/vibrator/1.3/IVibrator.hal b/vibrator/1.3/IVibrator.hal
new file mode 100644
index 0000000..01c2801
--- /dev/null
+++ b/vibrator/1.3/IVibrator.hal
@@ -0,0 +1,44 @@
+/*
+ * 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.vibrator@1.3;
+
+import @1.0::Status;
+import @1.2::IVibrator;
+
+interface IVibrator extends @1.2::IVibrator {
+  /**
+   * Returns whether the vibrator supports control through an alternate interface.
+   */
+  supportsExternalControl() generates (bool supports);
+
+  /**
+   * Enables/disables control override of vibrator to audio.
+   *
+   * When this API is set, the vibrator control should be ceded to audio system
+   * for haptic audio. While this is enabled, issuing of other commands to control
+   * the vibrator is unsupported and the resulting behavior is undefined. Amplitude
+   * control may or may not be supported and is reflected in the return value of
+   * supportsAmplitudeControl() while this is enabled. When this is disabled, the
+   * vibrator should resume to an off state.
+   *
+   * @param enabled Whether external control should be enabled or disabled.
+   * @return status Whether the command was successful or not. Must return
+   *                Status::UNSUPPORTED_OPERATION if external control is
+   *                not supported by the device.
+   */
+  setExternalControl(bool enabled) generates (Status status);
+};
diff --git a/vibrator/1.3/vts/functional/Android.bp b/vibrator/1.3/vts/functional/Android.bp
new file mode 100644
index 0000000..5b4c893
--- /dev/null
+++ b/vibrator/1.3/vts/functional/Android.bp
@@ -0,0 +1,29 @@
+//
+// 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: "VtsHalVibratorV1_3TargetTest",
+    defaults: ["VtsHalTargetTestDefaults"],
+    srcs: ["VtsHalVibratorV1_3TargetTest.cpp"],
+    static_libs: [
+        "android.hardware.vibrator@1.0",
+        "android.hardware.vibrator@1.1",
+        "android.hardware.vibrator@1.2",
+        "android.hardware.vibrator@1.3",
+    ],
+    test_suites: ["general-tests"],
+}
+
diff --git a/vibrator/1.3/vts/functional/VtsHalVibratorV1_3TargetTest.cpp b/vibrator/1.3/vts/functional/VtsHalVibratorV1_3TargetTest.cpp
new file mode 100644
index 0000000..a67d1dc
--- /dev/null
+++ b/vibrator/1.3/vts/functional/VtsHalVibratorV1_3TargetTest.cpp
@@ -0,0 +1,81 @@
+/*
+ * Copyright (C) 2016 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 "vibrator_hidl_hal_test"
+
+#include <VtsHalHidlTargetTestBase.h>
+#include <VtsHalHidlTargetTestEnvBase.h>
+#include <android-base/logging.h>
+#include <android/hardware/vibrator/1.0/types.h>
+#include <android/hardware/vibrator/1.3/IVibrator.h>
+#include <unistd.h>
+
+using ::android::sp;
+using ::android::hardware::vibrator::V1_0::Status;
+using ::android::hardware::vibrator::V1_3::IVibrator;
+
+// Test environment for Vibrator HIDL HAL.
+class VibratorHidlEnvironment : public ::testing::VtsHalHidlTargetTestEnvBase {
+   public:
+    // get the test environment singleton
+    static VibratorHidlEnvironment* Instance() {
+        static VibratorHidlEnvironment* instance = new VibratorHidlEnvironment;
+        return instance;
+    }
+
+    virtual void registerTestServices() override { registerTestService<IVibrator>(); }
+
+   private:
+    VibratorHidlEnvironment() {}
+};
+
+// The main test class for VIBRATOR HIDL HAL 1.3.
+class VibratorHidlTest_1_3 : public ::testing::VtsHalHidlTargetTestBase {
+   public:
+    virtual void SetUp() override {
+        vibrator = ::testing::VtsHalHidlTargetTestBase::getService<IVibrator>(
+            VibratorHidlEnvironment::Instance()->getServiceName<IVibrator>());
+        ASSERT_NE(vibrator, nullptr);
+    }
+
+    virtual void TearDown() override {}
+
+    sp<IVibrator> vibrator;
+};
+
+TEST_F(VibratorHidlTest_1_3, ChangeVibrationalExternalControl) {
+    if (vibrator->supportsExternalControl()) {
+        EXPECT_EQ(Status::OK, vibrator->setExternalControl(true));
+        sleep(1);
+        EXPECT_EQ(Status::OK, vibrator->setExternalControl(false));
+        sleep(1);
+    }
+}
+
+TEST_F(VibratorHidlTest_1_3, SetExternalControlReturnUnsupportedOperationIfNotSupported) {
+    if (!vibrator->supportsExternalControl()) {
+        EXPECT_EQ(Status::UNSUPPORTED_OPERATION, vibrator->setExternalControl(true));
+    }
+}
+
+int main(int argc, char** argv) {
+    ::testing::AddGlobalTestEnvironment(VibratorHidlEnvironment::Instance());
+    ::testing::InitGoogleTest(&argc, argv);
+    VibratorHidlEnvironment::Instance()->init(&argc, argv);
+    int status = RUN_ALL_TESTS();
+    LOG(INFO) << "Test result = " << status;
+    return status;
+}
diff --git a/wifi/1.0/vts/functional/Android.bp b/wifi/1.0/vts/functional/Android.bp
index 3189db4..397ad17 100644
--- a/wifi/1.0/vts/functional/Android.bp
+++ b/wifi/1.0/vts/functional/Android.bp
@@ -45,6 +45,7 @@
     static_libs: [
         "VtsHalWifiV1_0TargetTestUtil",
         "android.hardware.wifi@1.0",
+        "android.hardware.wifi@1.1",
         "android.hardware.wifi@1.2",
         "android.hardware.wifi@1.3",
     ],
diff --git a/wifi/1.0/vts/functional/wifi_chip_hidl_test.cpp b/wifi/1.0/vts/functional/wifi_chip_hidl_test.cpp
index a3fdf27..3555c2e 100644
--- a/wifi/1.0/vts/functional/wifi_chip_hidl_test.cpp
+++ b/wifi/1.0/vts/functional/wifi_chip_hidl_test.cpp
@@ -17,6 +17,7 @@
 #include <android-base/logging.h>
 
 #include <android/hardware/wifi/1.0/IWifiChip.h>
+#include <android/hardware/wifi/1.3/IWifiChip.h>
 
 #include <VtsHalHidlTargetTestBase.h>
 
@@ -87,7 +88,19 @@
 
     uint32_t configureChipForStaIfaceAndGetCapabilities() {
         configureChipForIfaceType(IfaceType::STA, true);
-        const auto& status_and_caps = HIDL_INVOKE(wifi_chip_, getCapabilities);
+
+        sp<::android::hardware::wifi::V1_3::IWifiChip> chip_converted =
+            ::android::hardware::wifi::V1_3::IWifiChip::castFrom(wifi_chip_);
+
+        std::pair<WifiStatus, uint32_t> status_and_caps;
+
+        if (chip_converted != nullptr) {
+            // Call the newer HAL version
+            status_and_caps = HIDL_INVOKE(chip_converted, getCapabilities_1_3);
+        } else {
+            status_and_caps = HIDL_INVOKE(wifi_chip_, getCapabilities);
+        }
+
         if (status_and_caps.first.code != WifiStatusCode::SUCCESS) {
             EXPECT_EQ(WifiStatusCode::ERROR_NOT_SUPPORTED, status_and_caps.first.code);
             return 0;
diff --git a/wifi/1.1/vts/functional/Android.bp b/wifi/1.1/vts/functional/Android.bp
index 78d7a85..6662314 100644
--- a/wifi/1.1/vts/functional/Android.bp
+++ b/wifi/1.1/vts/functional/Android.bp
@@ -24,6 +24,8 @@
         "VtsHalWifiV1_0TargetTestUtil",
         "android.hardware.wifi@1.0",
         "android.hardware.wifi@1.1",
+        "android.hardware.wifi@1.2",
+        "android.hardware.wifi@1.3",
     ],
     test_suites: ["general-tests"],
 }
diff --git a/wifi/1.1/vts/functional/wifi_chip_hidl_test.cpp b/wifi/1.1/vts/functional/wifi_chip_hidl_test.cpp
index d3a983c..6323547 100644
--- a/wifi/1.1/vts/functional/wifi_chip_hidl_test.cpp
+++ b/wifi/1.1/vts/functional/wifi_chip_hidl_test.cpp
@@ -18,6 +18,7 @@
 
 #include <android/hardware/wifi/1.1/IWifi.h>
 #include <android/hardware/wifi/1.1/IWifiChip.h>
+#include <android/hardware/wifi/1.3/IWifiChip.h>
 
 #include <VtsHalHidlTargetTestBase.h>
 
@@ -58,7 +59,19 @@
         ChipModeId mode_id;
         EXPECT_TRUE(configureChipToSupportIfaceType(
             wifi_chip_, IfaceType::STA, &mode_id));
-        const auto& status_and_caps = HIDL_INVOKE(wifi_chip_, getCapabilities);
+
+        sp<::android::hardware::wifi::V1_3::IWifiChip> chip_converted =
+            ::android::hardware::wifi::V1_3::IWifiChip::castFrom(wifi_chip_);
+
+        std::pair<WifiStatus, uint32_t> status_and_caps;
+
+        if (chip_converted != nullptr) {
+            // Call the newer HAL version
+            status_and_caps = HIDL_INVOKE(chip_converted, getCapabilities_1_3);
+        } else {
+            status_and_caps = HIDL_INVOKE(wifi_chip_, getCapabilities);
+        }
+
         EXPECT_EQ(WifiStatusCode::SUCCESS, status_and_caps.first.code);
         return status_and_caps.second;
     }
diff --git a/wifi/1.2/vts/functional/Android.bp b/wifi/1.2/vts/functional/Android.bp
index a969f65..b2956ce 100644
--- a/wifi/1.2/vts/functional/Android.bp
+++ b/wifi/1.2/vts/functional/Android.bp
@@ -27,6 +27,7 @@
         "android.hardware.wifi@1.0",
         "android.hardware.wifi@1.1",
         "android.hardware.wifi@1.2",
+        "android.hardware.wifi@1.3",
     ],
     test_suites: ["general-tests"],
 }
diff --git a/wifi/1.2/vts/functional/wifi_chip_hidl_test.cpp b/wifi/1.2/vts/functional/wifi_chip_hidl_test.cpp
index a5457b7..9d567fe 100644
--- a/wifi/1.2/vts/functional/wifi_chip_hidl_test.cpp
+++ b/wifi/1.2/vts/functional/wifi_chip_hidl_test.cpp
@@ -18,6 +18,7 @@
 
 #include <android/hardware/wifi/1.2/IWifiChip.h>
 #include <android/hardware/wifi/1.2/IWifiChipEventCallback.h>
+#include <android/hardware/wifi/1.3/IWifiChip.h>
 
 #include <VtsHalHidlTargetCallbackBase.h>
 #include <VtsHalHidlTargetTestBase.h>
@@ -104,7 +105,19 @@
     ChipModeId mode_id;
     EXPECT_TRUE(
         configureChipToSupportIfaceType(wifi_chip_, IfaceType::STA, &mode_id));
-    const auto& status_and_caps = HIDL_INVOKE(wifi_chip_, getCapabilities);
+
+    sp<::android::hardware::wifi::V1_3::IWifiChip> chip_converted =
+        ::android::hardware::wifi::V1_3::IWifiChip::castFrom(wifi_chip_);
+
+    std::pair<WifiStatus, uint32_t> status_and_caps;
+
+    if (chip_converted != nullptr) {
+        // Call the newer HAL version
+        status_and_caps = HIDL_INVOKE(chip_converted, getCapabilities_1_3);
+    } else {
+        status_and_caps = HIDL_INVOKE(wifi_chip_, getCapabilities);
+    }
+
     EXPECT_EQ(WifiStatusCode::SUCCESS, status_and_caps.first.code);
     return status_and_caps.second;
   }
diff --git a/wifi/1.3/default/tests/wifi_chip_unit_tests.cpp b/wifi/1.3/default/tests/wifi_chip_unit_tests.cpp
index 32ba760..3fcc39e 100644
--- a/wifi/1.3/default/tests/wifi_chip_unit_tests.cpp
+++ b/wifi/1.3/default/tests/wifi_chip_unit_tests.cpp
@@ -16,6 +16,7 @@
 
 #include <android-base/logging.h>
 #include <android-base/macros.h>
+#include <cutils/properties.h>
 #include <gmock/gmock.h>
 
 #undef NAN  // This is weird, NAN is defined in bionic/libc/include/math.h:38
@@ -117,6 +118,19 @@
             .WillRepeatedly(testing::Return(modes));
     }
 
+    void setup_MultiIfaceCombination() {
+        // clang-format off
+        const hidl_vec<V1_0::IWifiChip::ChipIfaceCombination> combinations = {
+            {{{{IfaceType::STA}, 3}}}
+        };
+        const std::vector<V1_0::IWifiChip::ChipMode> modes = {
+            {feature_flags::chip_mode_ids::kV3, combinations}
+        };
+        // clang-format on
+        EXPECT_CALL(*feature_flags_, getChipModes())
+            .WillRepeatedly(testing::Return(modes));
+    }
+
     void assertNumberOfModes(uint32_t num_modes) {
         chip_->getAvailableModes(
             [num_modes](const WifiStatus& status,
@@ -655,6 +669,58 @@
     ASSERT_TRUE(createIface(IfaceType::AP).empty());
 }
 
+class WifiChip_MultiIfaceTest : public WifiChipTest {
+   public:
+    void SetUp() override {
+        setup_MultiIfaceCombination();
+        WifiChipTest::SetUp();
+    }
+};
+
+TEST_F(WifiChip_MultiIfaceTest, Create3Sta) {
+    findModeAndConfigureForIfaceType(IfaceType::STA);
+    ASSERT_FALSE(createIface(IfaceType::STA).empty());
+    ASSERT_FALSE(createIface(IfaceType::STA).empty());
+    ASSERT_FALSE(createIface(IfaceType::STA).empty());
+    ASSERT_TRUE(createIface(IfaceType::STA).empty());
+}
+
+TEST_F(WifiChip_MultiIfaceTest, CreateStaWithDefaultNames) {
+    property_set("wifi.interface.0", "");
+    property_set("wifi.interface.1", "");
+    property_set("wifi.interface.2", "");
+    property_set("wifi.interface", "");
+    property_set("wifi.concurrent.interface", "");
+    findModeAndConfigureForIfaceType(IfaceType::STA);
+    ASSERT_EQ(createIface(IfaceType::STA), "wlan0");
+    ASSERT_EQ(createIface(IfaceType::STA), "wlan1");
+    ASSERT_EQ(createIface(IfaceType::STA), "wlan2");
+}
+
+TEST_F(WifiChip_MultiIfaceTest, CreateStaWithCustomNames) {
+    property_set("wifi.interface.0", "test0");
+    property_set("wifi.interface.1", "test1");
+    property_set("wifi.interface.2", "test2");
+    property_set("wifi.interface", "bad0");
+    property_set("wifi.concurrent.interface", "bad1");
+    findModeAndConfigureForIfaceType(IfaceType::STA);
+    ASSERT_EQ(createIface(IfaceType::STA), "test0");
+    ASSERT_EQ(createIface(IfaceType::STA), "test1");
+    ASSERT_EQ(createIface(IfaceType::STA), "test2");
+}
+
+TEST_F(WifiChip_MultiIfaceTest, CreateStaWithCustomAltNames) {
+    property_set("wifi.interface.0", "");
+    property_set("wifi.interface.1", "");
+    property_set("wifi.interface.2", "");
+    property_set("wifi.interface", "testA0");
+    property_set("wifi.concurrent.interface", "testA1");
+    findModeAndConfigureForIfaceType(IfaceType::STA);
+    ASSERT_EQ(createIface(IfaceType::STA), "testA0");
+    ASSERT_EQ(createIface(IfaceType::STA), "testA1");
+    ASSERT_EQ(createIface(IfaceType::STA), "wlan2");
+}
+
 }  // namespace implementation
 }  // namespace V1_3
 }  // namespace wifi
diff --git a/wifi/1.3/default/wifi_chip.cpp b/wifi/1.3/default/wifi_chip.cpp
index 1f1aa95..e7ebc3b 100644
--- a/wifi/1.3/default/wifi_chip.cpp
+++ b/wifi/1.3/default/wifi_chip.cpp
@@ -41,6 +41,7 @@
 constexpr uint32_t kMaxRingBufferFileAgeSeconds = 60 * 60 * 10;
 constexpr uint32_t kMaxRingBufferFileNum = 20;
 constexpr char kTombstoneFolderPath[] = "/data/vendor/tombstones/wifi/";
+constexpr unsigned kMaxWlanIfaces = 100;
 
 template <typename Iface>
 void invalidateAndClear(std::vector<sp<Iface>>& ifaces, sp<Iface> iface) {
@@ -78,16 +79,25 @@
     return nullptr;
 }
 
-std::string getWlan0IfaceName() {
-    std::array<char, PROPERTY_VALUE_MAX> buffer;
-    property_get("wifi.interface", buffer.data(), "wlan0");
-    return buffer.data();
-}
+std::string getWlanIfaceName(unsigned idx) {
+    if (idx >= kMaxWlanIfaces) {
+        CHECK(false) << "Requested interface beyond wlan" << kMaxWlanIfaces;
+        return {};
+    }
 
-std::string getWlan1IfaceName() {
     std::array<char, PROPERTY_VALUE_MAX> buffer;
-    property_get("wifi.concurrent.interface", buffer.data(), "wlan1");
-    return buffer.data();
+    std::string propName = "wifi.interface." + std::to_string(idx);
+    auto res = property_get(propName.c_str(), buffer.data(), nullptr);
+    if (res > 0) return buffer.data();
+
+    if (idx == 0 || idx == 1) {
+        const char* altPropName =
+            (idx == 0) ? "wifi.interface" : "wifi.concurrent.interface";
+        res = property_get(altPropName, buffer.data(), nullptr);
+        if (res > 0) return buffer.data();
+    }
+
+    return "wlan" + std::to_string(idx);
 }
 
 std::string getP2pIfaceName() {
@@ -636,13 +646,14 @@
     legacy_hal::wifi_error legacy_status;
     uint32_t legacy_feature_set;
     uint32_t legacy_logger_feature_set;
+    const auto ifname = getWlanIfaceName(0);
     std::tie(legacy_status, legacy_feature_set) =
-        legacy_hal_.lock()->getSupportedFeatureSet(getWlan0IfaceName());
+        legacy_hal_.lock()->getSupportedFeatureSet(ifname);
     if (legacy_status != legacy_hal::WIFI_SUCCESS) {
         return {createWifiStatusFromLegacyError(legacy_status), 0};
     }
     std::tie(legacy_status, legacy_logger_feature_set) =
-        legacy_hal_.lock()->getLoggerSupportedFeatureSet(getWlan0IfaceName());
+        legacy_hal_.lock()->getLoggerSupportedFeatureSet(ifname);
     if (legacy_status != legacy_hal::WIFI_SUCCESS) {
         // some devices don't support querying logger feature set
         legacy_logger_feature_set = 0;
@@ -703,8 +714,9 @@
     IWifiChip::ChipDebugInfo result;
     legacy_hal::wifi_error legacy_status;
     std::string driver_desc;
+    const auto ifname = getWlanIfaceName(0);
     std::tie(legacy_status, driver_desc) =
-        legacy_hal_.lock()->getDriverVersion(getWlan0IfaceName());
+        legacy_hal_.lock()->getDriverVersion(ifname);
     if (legacy_status != legacy_hal::WIFI_SUCCESS) {
         LOG(ERROR) << "Failed to get driver version: "
                    << legacyErrorToString(legacy_status);
@@ -716,7 +728,7 @@
 
     std::string firmware_desc;
     std::tie(legacy_status, firmware_desc) =
-        legacy_hal_.lock()->getFirmwareVersion(getWlan0IfaceName());
+        legacy_hal_.lock()->getFirmwareVersion(ifname);
     if (legacy_status != legacy_hal::WIFI_SUCCESS) {
         LOG(ERROR) << "Failed to get firmware version: "
                    << legacyErrorToString(legacy_status);
@@ -734,7 +746,7 @@
     legacy_hal::wifi_error legacy_status;
     std::vector<uint8_t> driver_dump;
     std::tie(legacy_status, driver_dump) =
-        legacy_hal_.lock()->requestDriverMemoryDump(getWlan0IfaceName());
+        legacy_hal_.lock()->requestDriverMemoryDump(getWlanIfaceName(0));
     if (legacy_status != legacy_hal::WIFI_SUCCESS) {
         LOG(ERROR) << "Failed to get driver debug dump: "
                    << legacyErrorToString(legacy_status);
@@ -749,7 +761,7 @@
     legacy_hal::wifi_error legacy_status;
     std::vector<uint8_t> firmware_dump;
     std::tie(legacy_status, firmware_dump) =
-        legacy_hal_.lock()->requestFirmwareMemoryDump(getWlan0IfaceName());
+        legacy_hal_.lock()->requestFirmwareMemoryDump(getWlanIfaceName(0));
     if (legacy_status != legacy_hal::WIFI_SUCCESS) {
         LOG(ERROR) << "Failed to get firmware debug dump: "
                    << legacyErrorToString(legacy_status);
@@ -809,7 +821,7 @@
         return {createWifiStatus(WifiStatusCode::ERROR_NOT_AVAILABLE), {}};
     }
     // These are still assumed to be based on wlan0.
-    std::string ifname = getWlan0IfaceName();
+    std::string ifname = getWlanIfaceName(0);
     sp<WifiNanIface> iface = new WifiNanIface(ifname, legacy_hal_);
     nan_ifaces_.push_back(iface);
     for (const auto& callback : event_cb_handler_.getCallbacks()) {
@@ -952,7 +964,7 @@
         return {createWifiStatus(WifiStatusCode::ERROR_NOT_AVAILABLE), {}};
     }
     sp<WifiRttController> rtt =
-        new WifiRttController(getWlan0IfaceName(), bound_iface, legacy_hal_);
+        new WifiRttController(getWlanIfaceName(0), bound_iface, legacy_hal_);
     rtt_controllers_.emplace_back(rtt);
     return {createWifiStatus(WifiStatusCode::SUCCESS), rtt};
 }
@@ -963,7 +975,7 @@
     std::vector<legacy_hal::wifi_ring_buffer_status>
         legacy_ring_buffer_status_vec;
     std::tie(legacy_status, legacy_ring_buffer_status_vec) =
-        legacy_hal_.lock()->getRingBuffersStatus(getWlan0IfaceName());
+        legacy_hal_.lock()->getRingBuffersStatus(getWlanIfaceName(0));
     if (legacy_status != legacy_hal::WIFI_SUCCESS) {
         return {createWifiStatusFromLegacyError(legacy_status), {}};
     }
@@ -985,7 +997,7 @@
     }
     legacy_hal::wifi_error legacy_status =
         legacy_hal_.lock()->startRingBufferLogging(
-            getWlan0IfaceName(), ring_name,
+            getWlanIfaceName(0), ring_name,
             static_cast<
                 std::underlying_type<WifiDebugRingBufferVerboseLevel>::type>(
                 verbose_level),
@@ -1002,7 +1014,7 @@
         return status;
     }
     legacy_hal::wifi_error legacy_status =
-        legacy_hal_.lock()->getRingBufferData(getWlan0IfaceName(), ring_name);
+        legacy_hal_.lock()->getRingBufferData(getWlanIfaceName(0), ring_name);
 
     return createWifiStatusFromLegacyError(legacy_status);
 }
@@ -1018,7 +1030,7 @@
 WifiStatus WifiChip::stopLoggingToDebugRingBufferInternal() {
     legacy_hal::wifi_error legacy_status =
         legacy_hal_.lock()->deregisterRingBufferCallbackHandler(
-            getWlan0IfaceName());
+            getWlanIfaceName(0));
     return createWifiStatusFromLegacyError(legacy_status);
 }
 
@@ -1027,7 +1039,7 @@
     legacy_hal::wifi_error legacy_status;
     legacy_hal::WakeReasonStats legacy_stats;
     std::tie(legacy_status, legacy_stats) =
-        legacy_hal_.lock()->getWakeReasonStats(getWlan0IfaceName());
+        legacy_hal_.lock()->getWakeReasonStats(getWlanIfaceName(0));
     if (legacy_status != legacy_hal::WIFI_SUCCESS) {
         return {createWifiStatusFromLegacyError(legacy_status), {}};
     }
@@ -1059,10 +1071,10 @@
             }
         };
         legacy_status = legacy_hal_.lock()->registerErrorAlertCallbackHandler(
-            getWlan0IfaceName(), on_alert_callback);
+            getWlanIfaceName(0), on_alert_callback);
     } else {
         legacy_status = legacy_hal_.lock()->deregisterErrorAlertCallbackHandler(
-            getWlan0IfaceName());
+            getWlanIfaceName(0));
     }
     return createWifiStatusFromLegacyError(legacy_status);
 }
@@ -1070,20 +1082,20 @@
 WifiStatus WifiChip::selectTxPowerScenarioInternal(
     V1_1::IWifiChip::TxPowerScenario scenario) {
     auto legacy_status = legacy_hal_.lock()->selectTxPowerScenario(
-        getWlan0IfaceName(),
+        getWlanIfaceName(0),
         hidl_struct_util::convertHidlTxPowerScenarioToLegacy(scenario));
     return createWifiStatusFromLegacyError(legacy_status);
 }
 
 WifiStatus WifiChip::resetTxPowerScenarioInternal() {
     auto legacy_status =
-        legacy_hal_.lock()->resetTxPowerScenario(getWlan0IfaceName());
+        legacy_hal_.lock()->resetTxPowerScenario(getWlanIfaceName(0));
     return createWifiStatusFromLegacyError(legacy_status);
 }
 
 WifiStatus WifiChip::setLatencyModeInternal(LatencyMode mode) {
     auto legacy_status = legacy_hal_.lock()->setLatencyMode(
-        getWlan0IfaceName(),
+        getWlanIfaceName(0),
         hidl_struct_util::convertHidlLatencyModeToLegacy(mode));
     return createWifiStatusFromLegacyError(legacy_status);
 }
@@ -1099,7 +1111,7 @@
 WifiStatus WifiChip::selectTxPowerScenarioInternal_1_2(
     TxPowerScenario scenario) {
     auto legacy_status = legacy_hal_.lock()->selectTxPowerScenario(
-        getWlan0IfaceName(),
+        getWlanIfaceName(0),
         hidl_struct_util::convertHidlTxPowerScenarioToLegacy_1_2(scenario));
     return createWifiStatusFromLegacyError(legacy_status);
 }
@@ -1179,7 +1191,7 @@
         };
     legacy_hal::wifi_error legacy_status =
         legacy_hal_.lock()->registerRingBufferCallbackHandler(
-            getWlan0IfaceName(), on_ring_buffer_data_callback);
+            getWlanIfaceName(0), on_ring_buffer_data_callback);
 
     if (legacy_status == legacy_hal::WIFI_SUCCESS) {
         debug_ring_buffer_cb_registered_ = true;
@@ -1213,7 +1225,7 @@
         };
     legacy_hal::wifi_error legacy_status =
         legacy_hal_.lock()->registerRadioModeChangeCallbackHandler(
-            getWlan0IfaceName(), on_radio_mode_change_callback);
+            getWlanIfaceName(0), on_radio_mode_change_callback);
     return createWifiStatusFromLegacyError(legacy_status);
 }
 
@@ -1330,22 +1342,17 @@
     return false;
 }
 
-// Return "wlan0", if "wlan0" is not already in use, else return "wlan1".
-// This is based on the assumption that we'll have a max of 2 concurrent
-// AP/STA ifaces.
+// Return the first wlan (wlan0, wlan1 etc.) not already in use.
+// This doesn't check the actual presence of these interfaces.
 std::string WifiChip::allocateApOrStaIfaceName() {
-    auto ap_iface = findUsingName(ap_ifaces_, getWlan0IfaceName());
-    auto sta_iface = findUsingName(sta_ifaces_, getWlan0IfaceName());
-    if (!ap_iface.get() && !sta_iface.get()) {
-        return getWlan0IfaceName();
-    }
-    ap_iface = findUsingName(ap_ifaces_, getWlan1IfaceName());
-    sta_iface = findUsingName(sta_ifaces_, getWlan1IfaceName());
-    if (!ap_iface.get() && !sta_iface.get()) {
-        return getWlan1IfaceName();
+    for (unsigned i = 0; i < kMaxWlanIfaces; i++) {
+        const auto ifname = getWlanIfaceName(i);
+        if (findUsingName(ap_ifaces_, ifname)) continue;
+        if (findUsingName(sta_ifaces_, ifname)) continue;
+        return ifname;
     }
     // This should never happen. We screwed up somewhere if it did.
-    CHECK(0) << "wlan0 and wlan1 in use already!";
+    CHECK(false) << "All wlan interfaces in use already!";
     return {};
 }
 
diff --git a/wifi/1.3/vts/functional/wifi_sta_iface_hidl_test.cpp b/wifi/1.3/vts/functional/wifi_sta_iface_hidl_test.cpp
index e195ade..71e90ac 100644
--- a/wifi/1.3/vts/functional/wifi_sta_iface_hidl_test.cpp
+++ b/wifi/1.3/vts/functional/wifi_sta_iface_hidl_test.cpp
@@ -43,6 +43,13 @@
     virtual void TearDown() override { stopWifi(); }
 
    protected:
+    bool isCapabilitySupported(IWifiStaIface::StaIfaceCapabilityMask cap_mask) {
+        const auto& status_and_caps =
+            HIDL_INVOKE(wifi_sta_iface_, getCapabilities);
+        EXPECT_EQ(WifiStatusCode::SUCCESS, status_and_caps.first.code);
+        return (status_and_caps.second & cap_mask) != 0;
+    }
+
     sp<IWifiStaIface> wifi_sta_iface_;
 };
 
@@ -61,3 +68,30 @@
         EXPECT_NE(0, status_and_mac.second[i]);
     }
 }
+
+/*
+ * GetLinkLayerStats_1_3
+ * Ensures that calls to get link layer stats V1_3 will retrieve a non-empty
+ * StaLinkLayerStats after link layer stats collection is enabled.
+ */
+TEST_F(WifiStaIfaceHidlTest, GetLinkLayerStats_1_3) {
+    if (!isCapabilitySupported(
+            IWifiStaIface::StaIfaceCapabilityMask::LINK_LAYER_STATS)) {
+        // No-op if link layer stats is not supported.
+        return;
+    }
+
+    // Enable link layer stats collection.
+    EXPECT_EQ(WifiStatusCode::SUCCESS,
+              HIDL_INVOKE(wifi_sta_iface_, enableLinkLayerStatsCollection, true)
+                  .code);
+    // Retrieve link layer stats.
+    const auto& status_and_stats =
+        HIDL_INVOKE(wifi_sta_iface_, getLinkLayerStats_1_3);
+    EXPECT_EQ(WifiStatusCode::SUCCESS, status_and_stats.first.code);
+    EXPECT_GT(status_and_stats.second.timeStampInMs, 0u);
+    // Disable link layer stats collection.
+    EXPECT_EQ(
+        WifiStatusCode::SUCCESS,
+        HIDL_INVOKE(wifi_sta_iface_, disableLinkLayerStatsCollection).code);
+}
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/Android.bp b/wifi/supplicant/1.2/Android.bp
index 529dad4..18e1cca 100644
--- a/wifi/supplicant/1.2/Android.bp
+++ b/wifi/supplicant/1.2/Android.bp
@@ -10,13 +10,22 @@
         "ISupplicant.hal",
         "ISupplicantP2pIface.hal",
         "ISupplicantStaIface.hal",
+        "ISupplicantStaIfaceCallback.hal",
         "ISupplicantStaNetwork.hal",
+        "types.hal",
     ],
     interfaces: [
         "android.hardware.wifi.supplicant@1.0",
         "android.hardware.wifi.supplicant@1.1",
         "android.hidl.base@1.0",
     ],
+    types: [
+        "DppAkm",
+        "DppNetRole",
+        "DppSuccessCode",
+        "DppProgressCode",
+        "DppFailureCode",
+    ],
     gen_java: true,
 }
 
diff --git a/wifi/supplicant/1.2/ISupplicantStaIface.hal b/wifi/supplicant/1.2/ISupplicantStaIface.hal
index a338c6a..9152a64 100644
--- a/wifi/supplicant/1.2/ISupplicantStaIface.hal
+++ b/wifi/supplicant/1.2/ISupplicantStaIface.hal
@@ -18,6 +18,7 @@
 
 import @1.0::SupplicantStatus;
 import @1.1::ISupplicantStaIface;
+import @1.2::ISupplicantStaIfaceCallback;
 import @1.2::ISupplicantStaNetwork;
 
 /**
@@ -25,6 +26,24 @@
  * interface (e.g wlan0) it controls.
  */
 interface ISupplicantStaIface extends @1.1::ISupplicantStaIface {
+    /**
+     * Register for callbacks from this interface.
+     *
+     * These callbacks are invoked for events that are specific to this interface.
+     * Registration of multiple callback objects is supported. These objects must
+     * be automatically deleted when the corresponding client process is dead or
+     * if this interface is removed.
+     *
+     * @param callback An instance of the |ISupplicantStaIfaceCallback| HIDL
+     *        interface object.
+     * @return status Status of the operation.
+     *         Possible status codes:
+     *         |SupplicantStatusCode.SUCCESS|,
+     *         |SupplicantStatusCode.FAILURE_UNKNOWN|,
+     *         |SupplicantStatusCode.FAILURE_IFACE_INVALID|
+     */
+    registerCallback_1_2(ISupplicantStaIfaceCallback callback)
+        generates (SupplicantStatus status);
 
     /**
      * Get Key management capabilities of the device
@@ -38,5 +57,84 @@
      */
     getKeyMgmtCapabilities()
         generates (SupplicantStatus status, bitfield<KeyMgmtMask> keyMgmtMask);
-};
 
+    /**
+     * Add a DPP peer URI. URI is acquired externally, e.g. by scanning a QR code
+     *
+     * @param uri Peer's DPP URI.
+     * @return status Status of the operation, and an ID for the URI.
+     *         Possible status codes:
+     *         |SupplicantStatusCode.SUCCESS|,
+     *         |SupplicantStatusCode.FAILURE_ARGS_INVALID|,
+     *         |SupplicantStatusCode.FAILURE_UNKNOWN|,
+     *         |SupplicantStatusCode.FAILURE_NETWORK_INVALID|
+     */
+    addDppPeerUri(string uri)
+        generates (SupplicantStatus status, uint32_t id);
+
+    /**
+     * Remove a DPP peer URI.
+     *
+     * @param id The ID of the URI, as returned by |addDppPeerUri|.
+     * @return status Status of the operation.
+     *         Possible status codes:
+     *         |SupplicantStatusCode.SUCCESS|,
+     *         |SupplicantStatusCode.FAILURE_ARGS_INVALID|,
+     *         |SupplicantStatusCode.FAILURE_UNKNOWN|,
+     *         |SupplicantStatusCode.FAILURE_NETWORK_INVALID|
+     */
+    removeDppUri(uint32_t id)
+        generates (SupplicantStatus status);
+
+    /**
+     * Start DPP in Configurator-Initiator mode.
+     *
+     * @param peerBootstrapId Peer device's URI ID.
+     * @param ownBootstrapId Local device's URI ID (0 for none, optional).
+     * @param ssid Network SSID to send to peer (SAE/PSK mode).
+     * @param password Network password to send to peer (SAE/PSK mode).
+     * @param psk Network PSK to send to peer (PSK mode only). Either password or psk should be set.
+     * @param netRole Role to configure the peer, |DppNetRole.DPP_NET_ROLE_STA| or
+     *        |DppNetRole.DPP_NET_ROLE_AP|.
+     * @param securityAkm Security AKM to use (See DppAkm).
+     * @return status Status of the operation.
+     *         Possible status codes:
+     *         |SupplicantStatusCode.SUCCESS|,
+     *         |SupplicantStatusCode.FAILURE_ARGS_INVALID|,
+     *         |SupplicantStatusCode.FAILURE_UNKNOWN|,
+     *         |SupplicantStatusCode.FAILURE_NETWORK_INVALID|
+     */
+    startDppConfiguratorInitiator(uint32_t peerBootstrapId,
+        uint32_t ownBootstrapId, string ssid, string password,
+        string psk, DppNetRole netRole, DppAkm securityAkm)
+        generates (SupplicantStatus status);
+
+    /**
+     * Start DPP in Enrollee-Initiator mode.
+     *
+     * @param peerBootstrapId Peer device's URI ID.
+     * @param ownBootstrapId Local device's URI ID (0 for none, optional).
+     * @return status Status of the operation.
+     *         Possible status codes:
+     *         |SupplicantStatusCode.SUCCESS|,
+     *         |SupplicantStatusCode.FAILURE_ARGS_INVALID|,
+     *         |SupplicantStatusCode.FAILURE_UNKNOWN|,
+     *         |SupplicantStatusCode.FAILURE_NETWORK_INVALID|
+     */
+    startDppEnrolleeInitiator(uint32_t peerBootstrapId,
+        uint32_t ownBootstrapId)
+        generates (SupplicantStatus status);
+
+    /**
+     * Stop DPP Initiator operation.
+     *
+     * @return status Status of the operation.
+     *         Possible status codes:
+     *         |SupplicantStatusCode.SUCCESS|,
+     *         |SupplicantStatusCode.FAILURE_ARGS_INVALID|,
+     *         |SupplicantStatusCode.FAILURE_UNKNOWN|,
+     *         |SupplicantStatusCode.FAILURE_NETWORK_INVALID|
+     */
+     stopDppInitiator()
+        generates (SupplicantStatus status);
+};
diff --git a/wifi/supplicant/1.2/ISupplicantStaIfaceCallback.hal b/wifi/supplicant/1.2/ISupplicantStaIfaceCallback.hal
new file mode 100644
index 0000000..5d5cccf
--- /dev/null
+++ b/wifi/supplicant/1.2/ISupplicantStaIfaceCallback.hal
@@ -0,0 +1,51 @@
+/*
+ * Copyright 2018 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.hardware.wifi.supplicant@1.2;
+
+import @1.1::ISupplicantStaIfaceCallback;
+import @1.0::Ssid;
+
+/**
+ * Callback Interface exposed by the supplicant service
+ * for each station mode interface (ISupplicantStaIface).
+ *
+ * Clients need to host an instance of this HIDL interface object and
+ * pass a reference of the object to the supplicant via the
+ * corresponding |ISupplicantStaIface.registerCallback_1_2| method.
+ */
+interface ISupplicantStaIfaceCallback extends @1.1::ISupplicantStaIfaceCallback {
+    /**
+     * Indicates DPP configuration received success event (Enrolee mode).
+     */
+    oneway onDppSuccessConfigReceived(Ssid ssid, string password, uint8_t[32] psk,
+        DppAkm securityAkm);
+
+    /**
+     * Indicates DPP configuration sent success event (Configurator mode).
+     */
+    oneway onDppSuccess(DppSuccessCode code);
+
+    /**
+     * Indicates a DPP progress event.
+     */
+    oneway onDppProgress(DppProgressCode code);
+
+    /**
+     * Indicates a DPP failure event.
+     */
+    oneway onDppFailure(DppFailureCode code);
+};
diff --git a/wifi/supplicant/1.2/ISupplicantStaNetwork.hal b/wifi/supplicant/1.2/ISupplicantStaNetwork.hal
index 6fd0d51..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,
 
@@ -36,6 +42,9 @@
 
         /** Enhacned Open (OWE) Key management */
         OWE = 1 << 22,
+
+        /** Easy Connect (DPP) Key management */
+        DPP = 1 << 23,
     };
 
     /** Possble mask of values for PairwiseCipher param. */
diff --git a/wifi/supplicant/1.2/types.hal b/wifi/supplicant/1.2/types.hal
new file mode 100644
index 0000000..eaf2546
--- /dev/null
+++ b/wifi/supplicant/1.2/types.hal
@@ -0,0 +1,64 @@
+/*
+ * Copyright 2018 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.hardware.wifi.supplicant@1.2;
+
+/**
+ * DppAkm: The various AKMs that can be provisioned using DPP.
+ */
+enum DppAkm : uint32_t {
+    PSK,
+    PSK_SAE,
+    SAE,
+    DPP,
+};
+
+/**
+ * DppNetRole: The network role that the configurator offers the enrollee.
+ */
+enum DppNetRole: uint32_t {
+    STA,
+    AP,
+};
+
+/**
+ * DppSuccessCode: Success codes for DPP (Easy Connect)
+ */
+enum DppSuccessCode : uint32_t {
+    CONFIGURATION_SENT,
+};
+
+/**
+ * DppProgressCode: Progress codes for DPP (Easy Connect)
+ */
+enum DppProgressCode : uint32_t {
+    AUTHENTICATION_SUCCESS,
+    RESPONSE_PENDING,
+};
+
+/**
+ * DppFailureCode: Error codes for DPP (Easy Connect)
+ */
+enum DppFailureCode : uint32_t {
+    INVALID_URI,
+    AUTHENTICATION,
+    NOT_COMPATIBLE,
+    CONFIGURATION,
+    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);
+        });
+}