Merge "wifi/supplicant: Add SHA256 key management definition"
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..0014022 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(),
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/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/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/compatibility_matrices/compatibility_matrix.current.xml b/compatibility_matrices/compatibility_matrix.current.xml
index e1a4203..2fd8861 100644
--- a/compatibility_matrices/compatibility_matrix.current.xml
+++ b/compatibility_matrices/compatibility_matrix.current.xml
@@ -203,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>
@@ -218,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>
diff --git a/gnss/2.0/Android.bp b/gnss/2.0/Android.bp
index 9b6b076..9b04be0 100644
--- a/gnss/2.0/Android.bp
+++ b/gnss/2.0/Android.bp
@@ -19,6 +19,7 @@
     ],
     interfaces: [
         "android.hardware.gnss.measurement_corrections@1.0",
+        "android.hardware.gnss.visibility_control@1.0",
         "android.hardware.gnss@1.0",
         "android.hardware.gnss@1.1",
         "android.hidl.base@1.0",
diff --git a/gnss/2.0/IGnss.hal b/gnss/2.0/IGnss.hal
index e1acd6d..1f1858e 100644
--- a/gnss/2.0/IGnss.hal
+++ b/gnss/2.0/IGnss.hal
@@ -17,6 +17,7 @@
 package android.hardware.gnss@2.0;
 
 import android.hardware.gnss.measurement_corrections@1.0::IMeasurementCorrections;
+import android.hardware.gnss.visibility_control@1.0::IGnssVisibilityControl;
 import @1.1::IGnss;
 
 import IGnssCallback;
@@ -25,7 +26,15 @@
 import IAGnss;
 import IAGnssRil;
 
-/** Represents the standard GNSS (Global Navigation Satellite System) interface. */
+/**
+ * Represents the standard GNSS (Global Navigation Satellite System) interface.
+ *
+ * Due to the introduction of new GNSS HAL package android.hardware.gnss.visibility_control@1.0
+ * the interface @1.0::IGnssNi.hal and @1.0::IGnssNiCallback.hal are deprecated in this version
+ * and are not supported by the framework. The GNSS HAL implementation of this interface
+ * must return nullptr for the following @1.0::IGnss method.
+ *      getExtensionGnssNi() generates (IGnssNi gnssNiIface);
+ */
 interface IGnss extends @1.1::IGnss {
     /**
      * Opens the interface and provides the callback routines to the implementation of this
@@ -76,6 +85,13 @@
      *
      * @return measurementCorrectionsIface Handle to the IMeasurementCorrections interface.
      */
-     getExtensionMeasurementCorrections()
+    getExtensionMeasurementCorrections()
             generates (IMeasurementCorrections measurementCorrectionsIface);
-};
+
+    /**
+     * This method returns the IGnssVisibilityControl interface.
+     *
+     * @return visibilityControlIface Handle to the IGnssVisibilityControl interface.
+     */
+    getExtensionVisibilityControl() generates (IGnssVisibilityControl visibilityControlIface);
+};
\ No newline at end of file
diff --git a/gnss/2.0/default/Android.bp b/gnss/2.0/default/Android.bp
index 92d5c1f..985aa2b 100644
--- a/gnss/2.0/default/Android.bp
+++ b/gnss/2.0/default/Android.bp
@@ -26,6 +26,7 @@
         "AGnssRil.cpp",
         "Gnss.cpp",
         "GnssMeasurement.cpp",
+        "GnssVisibilityControl.cpp",
         "service.cpp"
     ],
     shared_libs: [
@@ -35,6 +36,7 @@
         "liblog",
         "android.hardware.gnss@2.0",
         "android.hardware.gnss.measurement_corrections@1.0",
+        "android.hardware.gnss.visibility_control@1.0",
         "android.hardware.gnss@1.0",
         "android.hardware.gnss@1.1",
     ],
diff --git a/gnss/2.0/default/Gnss.cpp b/gnss/2.0/default/Gnss.cpp
index 5c752d5..217f0f3 100644
--- a/gnss/2.0/default/Gnss.cpp
+++ b/gnss/2.0/default/Gnss.cpp
@@ -22,8 +22,10 @@
 #include "AGnssRil.h"
 #include "GnssConfiguration.h"
 #include "GnssMeasurement.h"
+#include "GnssVisibilityControl.h"
 
 using ::android::hardware::Status;
+using ::android::hardware::gnss::visibility_control::V1_0::implementation::GnssVisibilityControl;
 
 namespace android {
 namespace hardware {
@@ -93,8 +95,8 @@
 }
 
 Return<sp<V1_0::IGnssNi>> Gnss::getExtensionGnssNi() {
-    // TODO implement
-    return sp<V1_0::IGnssNi>{};
+    // The IGnssNi.hal interface is deprecated in 2.0.
+    return nullptr;
 }
 
 Return<sp<V1_0::IGnssMeasurement>> Gnss::getExtensionGnssMeasurement() {
@@ -205,6 +207,11 @@
     return sp<measurement_corrections::V1_0::IMeasurementCorrections>{};
 }
 
+Return<sp<visibility_control::V1_0::IGnssVisibilityControl>> Gnss::getExtensionVisibilityControl() {
+    ALOGD("Gnss::getExtensionVisibilityControl");
+    return new GnssVisibilityControl();
+}
+
 Return<bool> Gnss::setCallback_2_0(const sp<V2_0::IGnssCallback>& callback) {
     ALOGD("Gnss::setCallback_2_0");
     if (callback == nullptr) {
diff --git a/gnss/2.0/default/Gnss.h b/gnss/2.0/default/Gnss.h
index e86158f..890b026 100644
--- a/gnss/2.0/default/Gnss.h
+++ b/gnss/2.0/default/Gnss.h
@@ -79,6 +79,8 @@
     Return<bool> setCallback_2_0(const sp<V2_0::IGnssCallback>& callback) override;
     Return<sp<measurement_corrections::V1_0::IMeasurementCorrections>>
     getExtensionMeasurementCorrections() override;
+    Return<sp<visibility_control::V1_0::IGnssVisibilityControl>> getExtensionVisibilityControl()
+            override;
 
    private:
     static sp<V2_0::IGnssCallback> sGnssCallback_2_0;
diff --git a/gnss/2.0/default/GnssVisibilityControl.cpp b/gnss/2.0/default/GnssVisibilityControl.cpp
new file mode 100644
index 0000000..99b8e34
--- /dev/null
+++ b/gnss/2.0/default/GnssVisibilityControl.cpp
@@ -0,0 +1,57 @@
+/*
+ * Copyright (C) 2019 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#define LOG_TAG "GnssVisibilityControl"
+
+#include "GnssVisibilityControl.h"
+#include <log/log.h>
+
+namespace android {
+namespace hardware {
+namespace gnss {
+namespace visibility_control {
+namespace V1_0 {
+namespace implementation {
+
+// Methods from ::android::hardware::gnss::visibility_control::V1_0::IGnssVisibilityControl follow.
+Return<bool> GnssVisibilityControl::enableNfwLocationAccess(
+        const hidl_vec<hidl_string>& proxyApps) {
+    std::string os;
+    bool first = true;
+    for (const auto& proxyApp : proxyApps) {
+        if (first) {
+            first = false;
+        } else {
+            os += " ";
+        }
+
+        os += proxyApp;
+    }
+
+    ALOGD("enableNfwLocationAccess proxyApps: %s", os.c_str());
+    return true;
+}
+
+Return<bool> GnssVisibilityControl::setCallback(const sp<V1_0::IGnssVisibilityControlCallback>&) {
+    return true;
+}
+
+}  // namespace implementation
+}  // namespace V1_0
+}  // namespace visibility_control
+}  // namespace gnss
+}  // namespace hardware
+}  // namespace android
diff --git a/gnss/2.0/default/GnssVisibilityControl.h b/gnss/2.0/default/GnssVisibilityControl.h
new file mode 100644
index 0000000..45febff
--- /dev/null
+++ b/gnss/2.0/default/GnssVisibilityControl.h
@@ -0,0 +1,53 @@
+/*
+ * Copyright (C) 2019 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef ANDROID_HARDWARE_GNSS_VISIBILITY_CONTROL_V1_0_GNSSVISIBILITYCONTROL_H
+#define ANDROID_HARDWARE_GNSS_VISIBILITY_CONTROL_V1_0_GNSSVISIBILITYCONTROL_H
+
+#include <android/hardware/gnss/visibility_control/1.0/IGnssVisibilityControl.h>
+#include <hidl/MQDescriptor.h>
+#include <hidl/Status.h>
+
+namespace android {
+namespace hardware {
+namespace gnss {
+namespace visibility_control {
+namespace V1_0 {
+namespace implementation {
+
+using ::android::sp;
+using ::android::hardware::hidl_array;
+using ::android::hardware::hidl_memory;
+using ::android::hardware::hidl_string;
+using ::android::hardware::hidl_vec;
+using ::android::hardware::Return;
+using ::android::hardware::Void;
+
+struct GnssVisibilityControl : public IGnssVisibilityControl {
+    // Methods from ::android::hardware::gnss::visibility_control::V1_0::IGnssVisibilityControl
+    // follow.
+    Return<bool> enableNfwLocationAccess(const hidl_vec<hidl_string>& proxyApps) override;
+    Return<bool> setCallback(const sp<V1_0::IGnssVisibilityControlCallback>& callback) override;
+};
+
+}  // namespace implementation
+}  // namespace V1_0
+}  // namespace visibility_control
+}  // namespace gnss
+}  // namespace hardware
+}  // namespace android
+
+#endif  // ANDROID_HARDWARE_GNSS_VISIBILITY_CONTROL_V1_0_GNSSVISIBILITYCONTROL_H
\ No newline at end of file
diff --git a/gnss/2.0/vts/functional/Android.bp b/gnss/2.0/vts/functional/Android.bp
index 894716d..684b381 100644
--- a/gnss/2.0/vts/functional/Android.bp
+++ b/gnss/2.0/vts/functional/Android.bp
@@ -24,6 +24,7 @@
     ],
     static_libs: [
         "android.hardware.gnss.measurement_corrections@1.0",
+        "android.hardware.gnss.visibility_control@1.0",
         "android.hardware.gnss@1.0",
         "android.hardware.gnss@1.1",
         "android.hardware.gnss@2.0",
diff --git a/gnss/2.0/vts/functional/gnss_hal_test_cases.cpp b/gnss/2.0/vts/functional/gnss_hal_test_cases.cpp
index cef06a2..552cf1b 100644
--- a/gnss/2.0/vts/functional/gnss_hal_test_cases.cpp
+++ b/gnss/2.0/vts/functional/gnss_hal_test_cases.cpp
@@ -19,6 +19,7 @@
 #include <VtsHalHidlTargetTestBase.h>
 #include <gnss_hal_test.h>
 
+using android::hardware::hidl_string;
 using android::hardware::hidl_vec;
 
 using IGnssConfiguration_2_0 = android::hardware::gnss::V2_0::IGnssConfiguration;
@@ -30,6 +31,8 @@
 using IAGnss_2_0 = android::hardware::gnss::V2_0::IAGnss;
 using IAGnss_1_0 = android::hardware::gnss::V1_0::IAGnss;
 using IAGnssCallback_2_0 = android::hardware::gnss::V2_0::IAGnssCallback;
+using android::hardware::gnss::V1_0::IGnssNi;
+using android::hardware::gnss::visibility_control::V1_0::IGnssVisibilityControl;
 
 /*
  * SetupTeardownCreateCleanup:
@@ -117,7 +120,7 @@
  * The GNSS HAL 2.0 implementation must support @2.0::IAGnssRil interface due to the deprecation
  * of framework network API methods needed to support the @1.0::IAGnssRil interface.
  *
- * TODO (b/121287858): Enforce gnss@2.0 HAL package is supported on devices launced with Q or later.
+ * TODO (b/121287858): Enforce gnss@2.0 HAL package is supported on devices launched with Q or later
  */
 TEST_F(GnssHalTest, TestAGnssRilExtension) {
     auto agnssRil = gnss_hal_->getExtensionAGnssRil_2_0();
@@ -199,7 +202,7 @@
  * The GNSS HAL 2.0 implementation must support @2.0::IAGnss interface due to the deprecation
  * of framework network API methods needed to support the @1.0::IAGnss interface.
  *
- * TODO (b/121287858): Enforce gnss@2.0 HAL package is supported on devices launced with Q or later.
+ * TODO (b/121287858): Enforce gnss@2.0 HAL package is supported on devices launched with Q or later
  */
 TEST_F(GnssHalTest, TestAGnssExtension) {
     // Verify IAGnss 2.0 is supported.
@@ -218,10 +221,45 @@
  * TestAGnssExtension_1_0_Deprecation:
  * Gets the @1.0::IAGnss extension and verifies that it is a nullptr.
  *
- * TODO (b/121287858): Enforce gnss@2.0 HAL package is supported on devices launced with Q or later.
+ * TODO (b/121287858): Enforce gnss@2.0 HAL package is supported on devices launched with Q or later
  */
 TEST_F(GnssHalTest, TestAGnssExtension_1_0_Deprecation) {
     // Verify IAGnss 1.0 is not supported.
     auto agnss_1_0 = gnss_hal_->getExtensionAGnss();
     ASSERT_TRUE(!agnss_1_0.isOk() || ((sp<IAGnss_1_0>)agnss_1_0) == nullptr);
 }
+
+/*
+ * TestGnssNiExtension_Deprecation:
+ * Gets the @1.0::IGnssNi extension and verifies that it is a nullptr.
+ *
+ * TODO (b/121287858): Enforce gnss@2.0 HAL package is supported on devices launched with Q or later
+ */
+TEST_F(GnssHalTest, TestGnssNiExtension_Deprecation) {
+    // Verify IGnssNi 1.0 is not supported.
+    auto gnssNi = gnss_hal_->getExtensionGnssNi();
+    ASSERT_TRUE(!gnssNi.isOk() || ((sp<IGnssNi>)gnssNi) == nullptr);
+}
+
+/*
+ * TestGnssVisibilityControlExtension:
+ * Gets the GnssVisibilityControlExtension and verifies that it supports the
+ * gnss.visibility_control@1.0::IGnssVisibilityControl interface by invoking a method.
+ *
+ * The GNSS HAL 2.0 implementation must support gnss.visibility_control@1.0::IGnssVisibilityControl.
+ *
+ * TODO (b/121287858): Enforce gnss@2.0 HAL package is supported on devices launched with Q or later
+ */
+TEST_F(GnssHalTest, TestGnssVisibilityControlExtension) {
+    // Verify IGnssVisibilityControl is supported.
+    auto gnssVisibilityControl = gnss_hal_->getExtensionVisibilityControl();
+    ASSERT_TRUE(gnssVisibilityControl.isOk());
+    sp<IGnssVisibilityControl> iGnssVisibilityControl = gnssVisibilityControl;
+    ASSERT_NE(iGnssVisibilityControl, nullptr);
+
+    // Set non-framework proxy apps.
+    hidl_vec<hidl_string> proxyApps{"ims.example.com", "mdt.example.com"};
+    auto result = iGnssVisibilityControl->enableNfwLocationAccess(proxyApps);
+    ASSERT_TRUE(result.isOk());
+    EXPECT_TRUE(result);
+}
diff --git a/gnss/visibility_control/1.0/Android.bp b/gnss/visibility_control/1.0/Android.bp
new file mode 100644
index 0000000..40a28c9
--- /dev/null
+++ b/gnss/visibility_control/1.0/Android.bp
@@ -0,0 +1,18 @@
+// This file is autogenerated by hidl-gen -Landroidbp.
+
+hidl_interface {
+    name: "android.hardware.gnss.visibility_control@1.0",
+    root: "android.hardware",
+    vndk: {
+        enabled: true,
+    },
+    srcs: [
+        "IGnssVisibilityControl.hal",
+        "IGnssVisibilityControlCallback.hal",
+    ],
+    interfaces: [
+        "android.hidl.base@1.0",
+    ],
+    gen_java: true,
+}
+
diff --git a/gnss/visibility_control/1.0/IGnssVisibilityControl.hal b/gnss/visibility_control/1.0/IGnssVisibilityControl.hal
new file mode 100644
index 0000000..9148127
--- /dev/null
+++ b/gnss/visibility_control/1.0/IGnssVisibilityControl.hal
@@ -0,0 +1,83 @@
+/*
+ * Copyright (C) 2018 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.hardware.gnss.visibility_control@1.0;
+
+import IGnssVisibilityControlCallback;
+
+/**
+ * Represents the GNSS location reporting permissions and notification interface.
+ *
+ * This interface is used to tell the GNSS HAL implementation whether the framework user has
+ * granted permission to the GNSS HAL implementation to provide GNSS location information for
+ * non-framework (NFW), non-user initiated emergency use cases, and to notify the framework user
+ * of these GNSS location information deliveries.
+ *
+ * For user initiated emergency cases (and for the configured extended emergency session duration),
+ * the GNSS HAL implementation must serve the emergency location supporting network initiated
+ * location requests immediately irrespective of this permission settings.
+ *
+ * There is no separate need for the GNSS HAL implementation to monitor the global device location
+ * on/off setting. Permission to use GNSS for non-framework use cases is expressly controlled
+ * by the method enableNfwLocationAccess(). The framework monitors the location permission settings
+ * of the configured proxy applications(s), and device location settings, and calls the method
+ * enableNfwLocationAccess() whenever the user control proxy applications have, or do not have,
+ * location permission. The proxy applications are used to provide user visibility and control of
+ * location access by the non-framework on/off device entities they are representing.
+ *
+ * For device user visibility, the GNSS HAL implementation must call the method
+ * IGnssVisibilityControlCallback.nfwNotifyCb() whenever location request is rejected or
+ * location information is provided to non-framework entities (on or off device). This includes
+ * the network initiated location requests for user-initiated emergency use cases as well.
+ *
+ * The HAL implementations that support this interface must not report GNSS location, measurement,
+ * status, or other information that can be used to derive user location to any entity when not
+ * expressly authorized by this HAL. This includes all endpoints for location information
+ * off the device, including carriers, vendors, OEM and others directly or indirectly.
+ */
+interface IGnssVisibilityControl {
+    /**
+     * Enables/disables non-framework entity location access permission in the GNSS HAL.
+     *
+     * The framework will call this method to update GNSS HAL implementation every time the
+     * framework user, through the given proxy application(s) and/or device location settings,
+     * explicitly grants/revokes the location access permission for non-framework, non-user
+     * initiated emergency use cases.
+     *
+     * Whenever the user location information is delivered to non-framework entities, the HAL
+     * implementation must call the method IGnssVisibilityControlCallback.nfwNotifyCb() to notify
+     * the framework for user visibility.
+     *
+     * @param proxyApps Full list of package names of proxy Android applications representing
+     * the non-framework location access entities (on/off the device) for which the framework
+     * user has granted non-framework location access permission. The GNSS HAL implementation
+     * must provide location information only to non-framework entities represented by these
+     * proxy applications.
+     *
+     * The package name of the proxy Android application follows the standard Java language
+     * package naming format. For example, com.example.myapp.
+     *
+     * @return success True if the operation was successful.
+     */
+    enableNfwLocationAccess(vec<string> proxyApps) generates (bool success);
+
+    /**
+     * Registers the callback for HAL implementation to use.
+     *
+     * @param callback Handle to IGnssVisibilityControlCallback interface.
+     */
+    setCallback(IGnssVisibilityControlCallback callback) generates (bool success);
+};
\ No newline at end of file
diff --git a/gnss/visibility_control/1.0/IGnssVisibilityControlCallback.hal b/gnss/visibility_control/1.0/IGnssVisibilityControlCallback.hal
new file mode 100644
index 0000000..5a582c2
--- /dev/null
+++ b/gnss/visibility_control/1.0/IGnssVisibilityControlCallback.hal
@@ -0,0 +1,160 @@
+/*
+ * Copyright (C) 2018 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.hardware.gnss.visibility_control@1.0;
+
+/**
+ * GNSS location reporting permissions and notification callback interface.
+ */
+interface IGnssVisibilityControlCallback {
+    /**
+     * Protocol stack that is requesting the non-framework location information.
+     */
+    enum NfwProtocolStack : uint8_t {
+        /** Cellular control plane requests */
+        CTRL_PLANE                      = 0,
+        /** All types of SUPL requests */
+        SUPL                            = 1,
+
+        /** All types of requests from IMS */
+        IMS                             = 10,
+        /** All types of requests from SIM */
+        SIM                             = 11,
+
+        /** Requests from other protocol stacks */
+        OTHER_PROTOCOL_STACK            = 100
+    };
+
+    /*
+     * Entity that is requesting/receiving the location information.
+     */
+    enum NfwRequestor : uint8_t {
+        /** Wireless service provider */
+        CARRIER                         = 0,
+
+        /** Device manufacturer */
+        OEM                             = 10,
+        /** Modem chipset vendor */
+        MODEM_CHIPSET_VENDOR            = 11,
+        /** GNSS chipset vendor */
+        GNSS_CHIPSET_VENDOR             = 12,
+        /** Other chipset vendor */
+        OTHER_CHIPSET_VENDOR            = 13,
+
+        /** Automobile client */
+        AUTOMOBILE_CLIENT               = 20,
+
+        /** Other sources */
+        OTHER_REQUESTOR                 = 100
+     };
+
+    /**
+     * GNSS response type for non-framework location requests.
+     */
+    enum NfwResponseType : uint8_t {
+        /** Request rejected because framework has not given permission for this use case */
+        REJECTED                        = 0,
+
+        /** Request accepted but could not provide location because of a failure */
+        ACCEPTED_NO_LOCATION_PROVIDED   = 1,
+
+        /** Request accepted and location provided */
+        ACCEPTED_LOCATION_PROVIDED      = 2,
+     };
+
+    /**
+     * Represents a non-framework location information request/response notification.
+     */
+    struct NfwNotification {
+        /**
+         * Package name of the Android proxy application representing the non-framework
+         * entity that requested location. Set to empty string if unknown.
+         */
+        string proxyAppPackageName;
+
+        /** Protocol stack that initiated the non-framework location request. */
+        NfwProtocolStack protocolStack;
+
+        /**
+         * Name of the protocol stack if protocolStack field is set to OTHER_PROTOCOL_STACK.
+         * Otherwise, set to empty string.
+         *
+         * This field is opaque to the framework and used for logging purposes.
+         */
+        string otherProtocolStackName;
+
+        /** Source initiating/receiving the location information. */
+        NfwRequestor requestor;
+
+        /**
+         * Identity of the endpoint receiving the location information. For example, carrier
+         * name, OEM name, SUPL SLP/E-SLP FQDN, chipset vendor name, etc.
+         *
+         * This field is opaque to the framework and used for logging purposes.
+         */
+        string requestorId;
+
+        /** Indicates whether location information was provided for this request. */
+        NfwResponseType responseType;
+
+        /** Is the device in user initiated emergency session. */
+        bool inEmergencyMode;
+
+        /** Is cached location provided */
+        bool isCachedLocation;
+    };
+
+    /**
+     * Callback to report a non-framework delivered location.
+     *
+     * The GNSS HAL implementation must call this method to notify the framework whenever
+     * a non-framework location request is made to the GNSS HAL.
+     *
+     * Non-framework entities like low power sensor hubs that request location from GNSS and
+     * only pass location information through Android framework controls are exempt from this
+     * power-spending reporting. However, low power sensor hubs or other chipsets which may send
+     * the location information to anywhere other than Android framework (which provides user
+     * visibility and control), must report location information use through this API whenever
+     * location information (or events driven by that location such as "home" location detection)
+     * leaves the domain of that low power chipset.
+     *
+     * To avoid overly spamming the framework, high speed location reporting of the exact same
+     * type may be throttled to report location at a lower rate than the actual report rate, as
+     * long as the location is reported with a latency of no more than the larger of 5 seconds,
+     * or the next the Android processor awake time. For example, if an Automotive client is
+     * getting location information from the GNSS location system at 20Hz, this method may be
+     * called at 1Hz. As another example, if a low power processor is getting location from the
+     * GNSS chipset, and the Android processor is asleep, the notification to the Android HAL may
+     * be delayed until the next wake of the Android processor.
+     *
+     * @param notification Non-framework delivered location request/response description.
+     */
+    nfwNotifyCb(NfwNotification notification);
+
+    /**
+     * Tells if the device is currently in an emergency session.
+     *
+     * Emergency session is defined as the device being actively in a user initiated emergency
+     * call or in post emergency call extension time period.
+     *
+     * If the GNSS HAL implementation cannot determine if the device is in emergency session
+     * mode, it must call this method to confirm that the device is in emergency session before
+     * serving network initiated emergency SUPL and Control Plane location requests.
+     *
+     * @return success True if the framework determines that the device is in emergency session.
+     */
+    isInEmergencySession() generates (bool success);
+};
\ No newline at end of file
diff --git a/graphics/allocator/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/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.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.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/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;
+}